From 1fd07c2c8390bd1432966eb3d5bc4b215f7185e0 Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 7 Sep 2026 05:04:15 +0400 Subject: [PATCH] shader: assemble point inputs for merged geometry shaders --- .../recompiler/frontend/translate/Translate.cpp | 17 ++++++++++++----- src/graphics/shader/shader.cpp | 6 ++++-- src/graphics/shader/shader.h | 8 ++++++-- tests/shaderCfgTests.cpp | 12 +++++++++++- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp index 978ba8ed1..c9a574952 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp @@ -1082,13 +1082,14 @@ IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& const auto primitive_chunk = entry_ir.IMul(builtin(IR::StageInputKind::WorkgroupId, 0), u32(mesh.primitives_per_group)); const auto step = u32(mesh.InputPrimitiveStep()); + const auto size = u32(mesh.InputPrimitiveSize()); const auto chunk = entry_ir.IMul(primitive_chunk, step); const auto vertices = minimum(subtract_saturate(draw(0), chunk), u32(mesh.vertices_per_group)); const auto primitives = entry_ir.Select( - entry_ir.ULessThan(vertices, u32(3)), u32(0), + entry_ir.ULessThan(vertices, size), u32(0), entry_ir.IAdd(IR::U32(entry_ir.Emit(IR::ValueOpcode::UDiv32, - {subtract_saturate(vertices, u32(3)), step})), + {subtract_saturate(vertices, size), step})), u32(1))); const auto wave = entry_ir.ShiftRightLogical(local, u32(6)); const auto wave_base = entry_ir.BitwiseAnd(local, u32(~63u)); @@ -1103,17 +1104,23 @@ IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& vertex_count))); // GS adjacency addresses local ES records in LDS. Strip winding alternates // with the global primitive number, including across subgroup boundaries. - const auto parity = mesh.InputPrimitiveStep() == 1u + const auto parity = mesh.input_primitive == + static_cast(Prospero::PrimitiveType::kTriStrip) ? entry_ir.BitwiseAnd(entry_ir.IAdd(primitive_chunk, local), u32(1)) : u32(0); const auto vertex = entry_ir.IMul(local, step); const auto first = entry_ir.IAdd(vertex, parity); - const auto second = entry_ir.ISub(entry_ir.IAdd(vertex, u32(1)), parity); + const auto second = mesh.InputPrimitiveSize() == 3u + ? entry_ir.ISub(entry_ir.IAdd(vertex, u32(1)), parity) + : u32(0); + const auto third = mesh.InputPrimitiveSize() == 3u + ? entry_ir.IAdd(vertex, u32(2)) + : u32(0); entry_ir.SetVectorReg(static_cast(0), entry_ir.BitwiseOr(entry_ir.ShiftLeftLogical(first, u32(2)), entry_ir.ShiftLeftLogical(second, u32(18)))); entry_ir.SetVectorReg(static_cast(1), - entry_ir.ShiftLeftLogical(entry_ir.IAdd(vertex, u32(2)), u32(2))); + entry_ir.ShiftLeftLogical(third, u32(2))); const auto input_vertex = entry_ir.IAdd(chunk, local); const auto index_bytes = draw(3); const auto indexed = entry_ir.INotEqual(index_bytes, u32(0)); diff --git a/src/graphics/shader/shader.cpp b/src/graphics/shader/shader.cpp index 24c9a0b65..a1868cae3 100644 --- a/src/graphics/shader/shader.cpp +++ b/src/graphics/shader/shader.cpp @@ -781,9 +781,11 @@ ShaderParams PrepareProgram(const HW::VertexShaderInfo& regs, const HW::Context& EXIT_NOT_IMPLEMENTED(regs.gs_regs.rsrc1.gs_vgpr_component_count != 3u || regs.gs_regs.rsrc2.es_vgpr_component_count != 3u); const auto& group = user_config.GetGeControl(); - if ((user_config.GetPrimType() != Prospero::PrimitiveType::kTriStrip && + if ((user_config.GetPrimType() != Prospero::PrimitiveType::kPointList && + user_config.GetPrimType() != Prospero::PrimitiveType::kTriStrip && user_config.GetPrimType() != Prospero::PrimitiveType::kTriList) || - sh.m_vgtGsOutPrimType != 2u || sh.m_vgtGsMaxVertOut < 3u || group.vertex_group_size < 3u || + sh.m_vgtGsOutPrimType != 2u || sh.m_vgtGsMaxVertOut < 3u || + group.vertex_group_size < mesh.InputPrimitiveSize() || mesh.max_vertices == 0u) { EXIT("unsupported GS assembly: input=%u output=%u vertices=%u GE=%u/%u max_output=%u\n", mesh.input_primitive, sh.m_vgtGsOutPrimType, sh.m_vgtGsMaxVertOut, diff --git a/src/graphics/shader/shader.h b/src/graphics/shader/shader.h index 78cd98c21..72e7e0fa0 100644 --- a/src/graphics/shader/shader.h +++ b/src/graphics/shader/shader.h @@ -79,14 +79,18 @@ struct ShaderMeshInputInfo: ShaderWorkgroupInputInfo { uint32_t max_primitives = 0; uint32_t provoking_vertex = 0; + [[nodiscard]] constexpr uint32_t InputPrimitiveSize() const { + return input_primitive == static_cast(Prospero::PrimitiveType::kPointList) ? 1u : 3u; + } [[nodiscard]] constexpr uint32_t InputPrimitiveStep() const { return input_primitive == static_cast(Prospero::PrimitiveType::kTriList) ? 3u : 1u; } [[nodiscard]] constexpr uint32_t InputPrimitiveCount(uint32_t vertices) const { - return vertices < 3u ? 0u : (vertices - 3u) / InputPrimitiveStep() + 1u; + const auto size = InputPrimitiveSize(); + return vertices < size ? 0u : (vertices - size) / InputPrimitiveStep() + 1u; } [[nodiscard]] constexpr uint32_t InputVertexCount(uint32_t primitives) const { - return primitives == 0u ? 0u : (primitives - 1u) * InputPrimitiveStep() + 3u; + return primitives == 0u ? 0u : (primitives - 1u) * InputPrimitiveStep() + InputPrimitiveSize(); } }; diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index e85aa2274..5b3d21de6 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -9471,6 +9471,16 @@ void TestMeshInputAssembly() { 0x40000305, 1, 2, 3, 0, 15, false}, {Prospero::PrimitiveType::kTriStrip, 5, 8, 0, 1, 0, 0, 11, 0x40000305, 2, 1, 3, 0, 12, false}, + {Prospero::PrimitiveType::kPointList, 12, 265, 22, 0, 2, 0x1002, 0, + 0x40000101, 0, 0, 0, 528, 0xabcd, true}, + {Prospero::PrimitiveType::kPointList, 12, 265, 22, 1, 2, 0x1002, 0, + 0x40000101, 1, 0, 0, 532, 0, false}, + {Prospero::PrimitiveType::kPointList, 1, 1, 0, 0, 0, 0, 11, + 0x40000101, 0, 0, 0, 0, 11, false}, + {Prospero::PrimitiveType::kPointList, 12, 265, 1, 1, 4, 0x1000, 5, + 0x40000c0c, 1, 0, 0, 52, 0xabcd0128, true}, + {Prospero::PrimitiveType::kPointList, 12, 265, 1, 64, 4, 0x1000, 0, + 0x41000000, 64, 0, 0, 304, 0, false}, }; for (const auto &test : cases) { ShaderVertexInputInfo input{}; @@ -9532,7 +9542,7 @@ void TestMeshInputAssembly() { } Check(sgpr3 == test.wave_info && vgprs[0] == ((test.first << 2) | (test.second << 18)) && vgprs[1] == test.third * 4 && vgprs[5] == test.vertex_id && vgprs[8] == 9, - "mesh prolog changed triangle assembly, wave counts, vertex ID, or instance ID"); + "mesh prolog changed input assembly, wave counts, vertex ID, or instance ID"); } }