Support triangle fans in PS5 geometry shaders
Keep the fan center across subgroups and reuse the existing index fetch.
This commit is contained in:
parent
957452d6f9
commit
7c9148dd47
|
|
@ -1102,26 +1102,32 @@ IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph&
|
||||||
entry_ir.BitwiseOr(wave_info, entry_ir.BitwiseOr(entry_ir.ShiftLeftLogical(
|
entry_ir.BitwiseOr(wave_info, entry_ir.BitwiseOr(entry_ir.ShiftLeftLogical(
|
||||||
primitive_count, u32(8)),
|
primitive_count, u32(8)),
|
||||||
vertex_count)));
|
vertex_count)));
|
||||||
// GS adjacency addresses local ES records in LDS. Strip winding alternates
|
// GS adjacency addresses local ES records in LDS. Fans retain the draw's
|
||||||
// with the global primitive number, including across subgroup boundaries.
|
// center in every subgroup; strip winding follows the global primitive.
|
||||||
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 vertex = entry_ir.IMul(local, step);
|
||||||
const auto first = entry_ir.IAdd(vertex, parity);
|
auto first = vertex;
|
||||||
const auto second = mesh.InputPrimitiveSize() >= 2u
|
auto second = u32(0);
|
||||||
? entry_ir.ISub(entry_ir.IAdd(vertex, u32(1)), parity)
|
auto third = u32(0);
|
||||||
: u32(0);
|
if (mesh.InputPrimitiveSize() >= 2u) {
|
||||||
const auto third = mesh.InputPrimitiveSize() == 3u
|
second = entry_ir.IAdd(vertex, u32(1));
|
||||||
? entry_ir.IAdd(vertex, u32(2))
|
}
|
||||||
: u32(0);
|
if (mesh.InputPrimitiveSize() == 3u) {
|
||||||
|
third = entry_ir.IAdd(vertex, u32(2));
|
||||||
|
}
|
||||||
|
auto input_vertex = entry_ir.IAdd(chunk, local);
|
||||||
|
if (mesh.input_primitive == static_cast<uint32_t>(Prospero::PrimitiveType::kTriFan)) {
|
||||||
|
first = u32(0);
|
||||||
|
input_vertex = entry_ir.Select(entry_ir.IEqual(local, u32(0)), u32(0), input_vertex);
|
||||||
|
} else if (mesh.input_primitive == static_cast<uint32_t>(Prospero::PrimitiveType::kTriStrip)) {
|
||||||
|
const auto parity = entry_ir.BitwiseAnd(entry_ir.IAdd(primitive_chunk, local), u32(1));
|
||||||
|
first = entry_ir.IAdd(first, parity);
|
||||||
|
second = entry_ir.ISub(second, parity);
|
||||||
|
}
|
||||||
entry_ir.SetVectorReg(static_cast<IR::VectorReg>(0),
|
entry_ir.SetVectorReg(static_cast<IR::VectorReg>(0),
|
||||||
entry_ir.BitwiseOr(entry_ir.ShiftLeftLogical(first, u32(2)),
|
entry_ir.BitwiseOr(entry_ir.ShiftLeftLogical(first, u32(2)),
|
||||||
entry_ir.ShiftLeftLogical(second, u32(18))));
|
entry_ir.ShiftLeftLogical(second, u32(18))));
|
||||||
entry_ir.SetVectorReg(static_cast<IR::VectorReg>(1),
|
entry_ir.SetVectorReg(static_cast<IR::VectorReg>(1),
|
||||||
entry_ir.ShiftLeftLogical(third, 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 index_bytes = draw(3);
|
||||||
const auto indexed = entry_ir.INotEqual(index_bytes, u32(0));
|
const auto indexed = entry_ir.INotEqual(index_bytes, u32(0));
|
||||||
const auto index_low = draw(4);
|
const auto index_low = draw(4);
|
||||||
|
|
|
||||||
|
|
@ -797,6 +797,7 @@ ShaderParams PrepareProgram(const HW::VertexShaderInfo& regs, const HW::Context&
|
||||||
const auto& group = user_config.GetGeControl();
|
const auto& group = user_config.GetGeControl();
|
||||||
if ((user_config.GetPrimType() != Prospero::PrimitiveType::kPointList &&
|
if ((user_config.GetPrimType() != Prospero::PrimitiveType::kPointList &&
|
||||||
user_config.GetPrimType() != Prospero::PrimitiveType::kLineList &&
|
user_config.GetPrimType() != Prospero::PrimitiveType::kLineList &&
|
||||||
|
user_config.GetPrimType() != Prospero::PrimitiveType::kTriFan &&
|
||||||
user_config.GetPrimType() != Prospero::PrimitiveType::kTriStrip &&
|
user_config.GetPrimType() != Prospero::PrimitiveType::kTriStrip &&
|
||||||
user_config.GetPrimType() != Prospero::PrimitiveType::kTriList) ||
|
user_config.GetPrimType() != Prospero::PrimitiveType::kTriList) ||
|
||||||
sh.m_vgtGsOutPrimType != 2u || sh.m_vgtGsMaxVertOut < 3u ||
|
sh.m_vgtGsOutPrimType != 2u || sh.m_vgtGsMaxVertOut < 3u ||
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,11 @@ struct ShaderMeshInputInfo: ShaderWorkgroupInputInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[[nodiscard]] constexpr uint32_t InputPrimitiveStep() const {
|
[[nodiscard]] constexpr uint32_t InputPrimitiveStep() const {
|
||||||
return input_primitive == static_cast<uint32_t>(Prospero::PrimitiveType::kTriStrip)
|
switch (static_cast<Prospero::PrimitiveType>(input_primitive)) {
|
||||||
? 1u : InputPrimitiveSize();
|
case Prospero::PrimitiveType::kTriFan:
|
||||||
|
case Prospero::PrimitiveType::kTriStrip: return 1u;
|
||||||
|
default: return InputPrimitiveSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
[[nodiscard]] constexpr uint32_t InputPrimitiveCount(uint32_t vertices) const {
|
[[nodiscard]] constexpr uint32_t InputPrimitiveCount(uint32_t vertices) const {
|
||||||
const auto size = InputPrimitiveSize();
|
const auto size = InputPrimitiveSize();
|
||||||
|
|
|
||||||
|
|
@ -9606,6 +9606,15 @@ void TestMergedShaderUserDataSnapshot() {
|
||||||
params.user_data.begin() + 8),
|
params.user_data.begin() + 8),
|
||||||
"monolithic NGG shader used stale GS-back state or lost its s8 user data");
|
"monolithic NGG shader used stale GS-back state or lost its s8 user data");
|
||||||
}
|
}
|
||||||
|
context.SetMaxOutputPerSubgroup(256);
|
||||||
|
context.SetGsMaxVertOut(8);
|
||||||
|
user_config.SetPrimitiveType(Prospero::PrimitiveType::kTriFan);
|
||||||
|
user_config.SetGeControl({32, 32});
|
||||||
|
ShaderVertexInputInfo fan_input{};
|
||||||
|
PrepareProgram(regs, context, user_config, fan_input);
|
||||||
|
Check(fan_input.mesh.primitives_per_group == 30 && fan_input.mesh.vertices_per_group == 32 &&
|
||||||
|
fan_input.mesh.max_vertices == 256 && fan_input.mesh.max_primitives == 192,
|
||||||
|
"captured triangle-fan GS configuration lost its subgroup assembly limits");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEmbeddedFetchPreservesSharedScalarLoad() {
|
void TestEmbeddedFetchPreservesSharedScalarLoad() {
|
||||||
|
|
@ -9791,6 +9800,18 @@ void TestMeshInputAssembly() {
|
||||||
0x40000305, 1, 2, 3, 0, 15, false},
|
0x40000305, 1, 2, 3, 0, 15, false},
|
||||||
{Prospero::PrimitiveType::kTriStrip, 5, 8, 0, 1, 0, 0, 11,
|
{Prospero::PrimitiveType::kTriStrip, 5, 8, 0, 1, 0, 0, 11,
|
||||||
0x40000305, 2, 1, 3, 0, 12, false},
|
0x40000305, 2, 1, 3, 0, 12, false},
|
||||||
|
{Prospero::PrimitiveType::kTriFan, 32, 6, 0, 3, 2, 0x1002, 0,
|
||||||
|
0x40000406, 0, 4, 5, 8, 0x0123, true},
|
||||||
|
{Prospero::PrimitiveType::kTriFan, 5, 8, 1, 0, 2, 0x1002, 0,
|
||||||
|
0x40000305, 0, 1, 2, 0, 0xabcd, true},
|
||||||
|
{Prospero::PrimitiveType::kTriFan, 5, 8, 1, 1, 0, 0, 11,
|
||||||
|
0x40000305, 0, 2, 3, 0, 15, false},
|
||||||
|
{Prospero::PrimitiveType::kTriFan, 5, 7, 1, 3, 2, 0x1002, 11,
|
||||||
|
0x40000204, 0, 4, 5, 12, 0xabd8, true},
|
||||||
|
{Prospero::PrimitiveType::kTriFan, 5, 7, 1, 4, 2, 0x1002, 0,
|
||||||
|
0x40000204, 0, 5, 6, 16, 0, false},
|
||||||
|
{Prospero::PrimitiveType::kTriFan, 5, 8, 1, 64, 4, 0x1000, 0,
|
||||||
|
0x41000000, 0, 65, 66, 268, 0, false},
|
||||||
{Prospero::PrimitiveType::kLineList, 5, 17, 3, 0, 0, 0, 11,
|
{Prospero::PrimitiveType::kLineList, 5, 17, 3, 0, 0, 0, 11,
|
||||||
0x40000204, 0, 1, 0, 0, 23, false},
|
0x40000204, 0, 1, 0, 0, 23, false},
|
||||||
{Prospero::PrimitiveType::kLineList, 6, 17, 2, 4, 2, 0x1002, 11,
|
{Prospero::PrimitiveType::kLineList, 6, 17, 2, 4, 2, 0x1002, 11,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue