diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index 8d2b9d569..decceaaf3 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -7,6 +8,7 @@ #include "shader_recompiler/backend/glasm/glasm_emit_context.h" #include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/profile.h" +#include "shader_recompiler/runtime_info.h" #include "shader_recompiler/shader_info.h" namespace Shader::Backend::GLASM { @@ -403,6 +405,8 @@ void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) { void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst) { switch (ctx.stage) { case Stage::TessellationControl: + ctx.Add("SHL.U {}.x,primitive.vertexcount,16;", inst); + break; case Stage::TessellationEval: ctx.Add("SHL.U {}.x,primitive.vertexcount,16;", inst); break; @@ -410,7 +414,47 @@ void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst) { // Return sample mask in upper 16 bits ctx.Add("SHL.U {}.x,fragment.samplemask,16;", inst); break; + case Stage::Geometry: { + // Return vertex count in upper 16 bits based on input topology + // Using a lookup table approach for vertex counts + const std::array vertex_counts = { + 1, // Points + 2, // Lines + 4, // LinesAdjacency + 3, // Triangles + 6 // TrianglesAdjacency + }; + + // Map the input topology to an index in our lookup table + u32 topology_index = 0; + switch (ctx.runtime_info.input_topology) { + case Shader::InputTopology::Lines: + topology_index = 1; + break; + case Shader::InputTopology::LinesAdjacency: + topology_index = 2; + break; + case Shader::InputTopology::Triangles: + topology_index = 3; + break; + case Shader::InputTopology::TrianglesAdjacency: + topology_index = 4; + break; + case Shader::InputTopology::Points: + default: + topology_index = 0; + break; + } + + // Get the vertex count from the lookup table and shift it + const u32 result = vertex_counts[topology_index] << 16; + ctx.Add("MOV.S {}.x,0x{:x};", inst, result); + break; + } case Stage::Compute: + // Return standard format (0x00ff0000) + ctx.Add("MOV.S {}.x,0x00ff0000;", inst); + break; default: // Return standard format (0x00ff0000) ctx.Add("MOV.S {}.x,0x00ff0000;", inst); diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index fea325df9..ae10a830c 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -423,6 +424,8 @@ void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) { void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst) { switch (ctx.stage) { case Stage::TessellationControl: + ctx.AddU32("{}=uint(gl_PatchVerticesIn)<<16;", inst); + break; case Stage::TessellationEval: ctx.AddU32("{}=uint(gl_PatchVerticesIn)<<16;", inst); break; @@ -430,7 +433,46 @@ void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst) { // Return sample mask in upper 16 bits ctx.AddU32("{}=uint(gl_SampleMaskIn[0])<<16;", inst); break; + case Stage::Geometry: { + // Return vertex count in upper 16 bits based on input topology + // Using a lookup table approach for vertex counts + ctx.AddU32("{}=uint(", inst); + + // Define vertex counts for each topology in a comment for clarity + ctx.Add("// Vertex counts: Points=1, Lines=2, LinesAdj=4, Triangles=3, TrianglesAdj=6\n"); + + // Use a lookup table approach in the generated GLSL code + ctx.Add("("); + + // Generate a conditional expression that acts like a lookup table + switch (ctx.runtime_info.input_topology) { + case InputTopology::Points: + ctx.Add("1"); // Points + break; + case InputTopology::Lines: + ctx.Add("2"); // Lines + break; + case InputTopology::LinesAdjacency: + ctx.Add("4"); // LinesAdjacency + break; + case InputTopology::Triangles: + ctx.Add("3"); // Triangles + break; + case InputTopology::TrianglesAdjacency: + ctx.Add("6"); // TrianglesAdjacency + break; + default: + ctx.Add("1"); // Default to Points + break; + } + + ctx.Add(")<<16);"); + break; + } case Stage::Compute: + // Return standard format (0x00ff0000) + ctx.AddU32("{}=0x00ff0000u;", inst); + break; default: // Return standard format (0x00ff0000) ctx.AddU32("{}=0x00ff0000u;", inst); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 64f828107..f3c15cfc2 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -553,6 +554,42 @@ Id EmitInvocationInfo(EmitContext& ctx) { // Return sample mask in upper 16 bits return ctx.OpShiftLeftLogical(ctx.U32[1], ctx.OpLoad(ctx.U32[1], ctx.sample_mask), ctx.Const(16u)); + case Stage::Geometry: { + // Return vertex count in upper 16 bits based on input topology + // Using a lookup table approach for vertex counts + const std::array vertex_counts = { + 1, // Points + 2, // Lines + 4, // LinesAdjacency + 3, // Triangles + 6 // TrianglesAdjacency + }; + + // Map the input topology to an index in our lookup table + u32 topology_index = 0; + switch (ctx.runtime_info.input_topology) { + case InputTopology::Lines: + topology_index = 1; + break; + case InputTopology::LinesAdjacency: + topology_index = 2; + break; + case InputTopology::Triangles: + topology_index = 3; + break; + case InputTopology::TrianglesAdjacency: + topology_index = 4; + break; + case InputTopology::Points: + default: + topology_index = 0; + break; + } + + // Get the vertex count from the lookup table and shift it + const u32 vertex_count = vertex_counts[topology_index]; + return ctx.OpShiftLeftLogical(ctx.U32[1], ctx.Const(vertex_count), ctx.Const(16u)); + } case Stage::Compute: // For compute shaders, return standard format since we can't access workgroup size directly return ctx.Const(0x00ff0000u);