shader_recompiler: Pad number of TES passthrough outputs to fragment inputs if needed (#4471)

This commit is contained in:
squidbus 2026-05-25 05:13:30 -07:00 committed by GitHub
parent 86a64fb980
commit 19381b30e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -25,9 +25,11 @@ struct QuadRectListEmitter : public Sirit::Module {
vec3_id = TypeVector(float_id, 3); vec3_id = TypeVector(float_id, 3);
vec4_id = TypeVector(float_id, 4); vec4_id = TypeVector(float_id, 4);
float_zero = Constant(float_id, 0.0f);
float_one = Constant(float_id, 1.0f); float_one = Constant(float_id, 1.0f);
float_min_one = Constant(float_id, -1.0f); float_min_one = Constant(float_id, -1.0f);
int_zero = Constant(int_id, 0); int_zero = Constant(int_id, 0);
vec4_zero = ConstantComposite(vec4_id, float_zero, float_zero, float_zero, float_zero);
const Id float_arr{TypeArray(float_id, Constant(uint_id, 1U))}; const Id float_arr{TypeArray(float_id, Constant(uint_id, 1U))};
gl_per_vertex_type = TypeStruct(vec4_id, float_id, float_arr, float_arr); gl_per_vertex_type = TypeStruct(vec4_id, float_id, float_arr, float_arr);
@ -190,8 +192,14 @@ struct QuadRectListEmitter : public Sirit::Module {
OpStore(OpAccessChain(output_vec4, gl_per_vertex, Int(0)), position); OpStore(OpAccessChain(output_vec4, gl_per_vertex, Int(0)), position);
// out_paramN = in_paramN[index]; // out_paramN = in_paramN[index];
for (int i = 0; i < inputs.size(); i++) { for (int i = 0; i < outputs.size(); i++) {
const Id param{OpLoad(vec4_id, OpAccessChain(input_vec4, inputs[i], index))}; Id param;
if (i < inputs.size()) {
param = OpLoad(vec4_id, OpAccessChain(input_vec4, inputs[i], index));
} else {
// Not enough inputs to forward, use dummy value.
param = vec4_zero;
}
OpStore(outputs[i], param); OpStore(outputs[i], param);
} }
@ -237,6 +245,7 @@ private:
} }
void DefineOutputs(spv::ExecutionModel model) { void DefineOutputs(spv::ExecutionModel model) {
auto num_forwards = vs_info.num_exports;
if (model == spv::ExecutionModel::TessellationControl) { if (model == spv::ExecutionModel::TessellationControl) {
const Id gl_per_vertex_array{TypeArray(gl_per_vertex_type, Constant(uint_id, 4U))}; const Id gl_per_vertex_array{TypeArray(gl_per_vertex_type, Constant(uint_id, 4U))};
gl_out = AddOutput(gl_per_vertex_array); gl_out = AddOutput(gl_per_vertex_array);
@ -252,8 +261,10 @@ private:
Decorate(gl_tess_level_outer, spv::Decoration::Patch); Decorate(gl_tess_level_outer, spv::Decoration::Patch);
} else { } else {
gl_per_vertex = AddOutput(gl_per_vertex_type); gl_per_vertex = AddOutput(gl_per_vertex_type);
// Tessellation eval stage comes before fragment, output number of forwards it will
// actually accept.
num_forwards = fs_info.num_inputs;
} }
const auto num_forwards = std::min(vs_info.num_exports, fs_info.num_inputs);
outputs.reserve(num_forwards); outputs.reserve(num_forwards);
for (int i = 0; i < num_forwards; i++) { for (int i = 0; i < num_forwards; i++) {
const auto& input = fs_info.inputs[i]; const auto& input = fs_info.inputs[i];
@ -279,7 +290,7 @@ private:
gl_in = AddInput(gl_per_vertex_array); gl_in = AddInput(gl_per_vertex_array);
const Id float_arr{TypeArray(vec4_id, Int(32))}; const Id float_arr{TypeArray(vec4_id, Int(32))};
const auto num_forwards = std::min(vs_info.num_exports, fs_info.num_inputs); const auto num_forwards = vs_info.num_exports;
inputs.reserve(num_forwards); inputs.reserve(num_forwards);
for (int i = 0; i < num_forwards; i++) { for (int i = 0; i < num_forwards; i++) {
const auto& input = fs_info.inputs[i]; const auto& input = fs_info.inputs[i];
@ -304,9 +315,11 @@ private:
Id vec2_id; Id vec2_id;
Id vec3_id; Id vec3_id;
Id vec4_id; Id vec4_id;
Id float_zero;
Id float_one; Id float_one;
Id float_min_one; Id float_min_one;
Id int_zero; Id int_zero;
Id vec4_zero;
Id gl_per_vertex_type; Id gl_per_vertex_type;
Id gl_in; Id gl_in;
union { union {