shader: assemble point inputs for merged geometry shaders

This commit is contained in:
nmzik
2026-09-07 05:04:15 +04:00
parent f880c58ccc
commit 1fd07c2c83
4 changed files with 33 additions and 10 deletions
@@ -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<uint32_t>(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<IR::VectorReg>(0),
entry_ir.BitwiseOr(entry_ir.ShiftLeftLogical(first, u32(2)),
entry_ir.ShiftLeftLogical(second, u32(18))));
entry_ir.SetVectorReg(static_cast<IR::VectorReg>(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));
+4 -2
View File
@@ -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,
+6 -2
View File
@@ -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<uint32_t>(Prospero::PrimitiveType::kPointList) ? 1u : 3u;
}
[[nodiscard]] constexpr uint32_t InputPrimitiveStep() const {
return input_primitive == static_cast<uint32_t>(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();
}
};
+11 -1
View File
@@ -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");
}
}