From d00dd5a2bc0bd361e8b0f1b67d9ac790dc750a36 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Wed, 9 Jun 2021 20:22:24 +0300 Subject: [PATCH] [GPU] Disable primitive reset for non-list types in primitive processor --- src/xenia/gpu/d3d12/pipeline_cache.cc | 1 - src/xenia/gpu/primitive_processor.cc | 38 ++++++++++++++++++++------- src/xenia/gpu/primitive_processor.h | 3 ++- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index 97606a3cf..b28369d54 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -1340,7 +1340,6 @@ bool PipelineCache::GetCurrentStateDescription( break; case xenos::PrimitiveType::kLineList: case xenos::PrimitiveType::kLineStrip: - case xenos::PrimitiveType::kLineLoop: // Quads are emulated as line lists with adjacency. case xenos::PrimitiveType::kQuadList: case xenos::PrimitiveType::k2DLineStrip: diff --git a/src/xenia/gpu/primitive_processor.cc b/src/xenia/gpu/primitive_processor.cc index 62864a256..b00e4ce50 100644 --- a/src/xenia/gpu/primitive_processor.cc +++ b/src/xenia/gpu/primitive_processor.cc @@ -458,16 +458,34 @@ bool PrimitiveProcessor::Process(ProcessingResult& result_out) { } } else { if (regs.Get().multi_prim_ib_ena) { - guest_primitive_reset_index_guest_endian = xenos::GpuSwap( - regs.Get().reset_indx, - guest_index_endian); - // - VGT, what does the guest say about its primitive reset index? - // - It's over 0xFFFF!!! - // - What!? 0xFFFF!? There's no way that can be stored in 16 bits! - guest_primitive_reset_enabled = - guest_index_format == xenos::IndexFormat::kInt16 - ? guest_primitive_reset_index_guest_endian <= UINT16_MAX - : true; + switch (guest_primitive_type) { + case xenos::PrimitiveType::kLineStrip: + case xenos::PrimitiveType::kTriangleFan: + case xenos::PrimitiveType::kTriangleStrip: + case xenos::PrimitiveType::kLineLoop: + case xenos::PrimitiveType::kQuadStrip: + case xenos::PrimitiveType::kPolygon: + case xenos::PrimitiveType::k2DLineStrip: + case xenos::PrimitiveType::k2DTriStrip: + guest_primitive_reset_index_guest_endian = xenos::GpuSwap( + regs.Get().reset_indx, + guest_index_endian); + // - VGT, what does the guest say about its primitive reset index? + // - It's over 0xFFFF!!! + // - What!? 0xFFFF!? There's no way that can be stored in 16 bits! + guest_primitive_reset_enabled = + guest_index_format == xenos::IndexFormat::kInt16 + ? guest_primitive_reset_index_guest_endian <= UINT16_MAX + : true; + break; + default: + // Vulkan explicitly disallows primitive restart index for "list" + // topologies. In Direct3D 12, it's valid for non-strips, but has + // implementation-defined behavior. Make backend usage simpler by + // explicitly filtering lists out, and hope the guest never uses + // primitive reset for lists. + break; + } } } diff --git a/src/xenia/gpu/primitive_processor.h b/src/xenia/gpu/primitive_processor.h index 762b7f1f9..046928738 100644 --- a/src/xenia/gpu/primitive_processor.h +++ b/src/xenia/gpu/primitive_processor.h @@ -138,7 +138,8 @@ class PrimitiveProcessor { xenos::IndexFormat host_index_format; xenos::Endian host_index_endian; // The reset index, if enabled, is always 0xFFFF for host_index_format - // kInt16 and 0xFFFFFFFF for kInt32. + // kInt16 and 0xFFFFFFFF for kInt32. Never enabled for "list" primitive + // types, thus safe for direct usage on Vulkan. bool host_primitive_reset_enabled; // Backend-specific handle for the index buffer valid for the current draw, // only valid for index_buffer_type kHostConverted and kHostBuiltin.