diff options
Diffstat (limited to 'src/mesa/main/shader_query.cpp')
-rw-r--r-- | src/mesa/main/shader_query.cpp | 115 |
1 files changed, 88 insertions, 27 deletions
diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index ced10a93b1d..e526119db19 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -1373,46 +1373,107 @@ _mesa_get_program_resourceiv(struct gl_shader_program *shProg, } static bool -validate_io(const struct gl_shader *input_stage, - const struct gl_shader *output_stage, bool isES) +validate_io(const struct gl_shader *producer, + const struct gl_shader *consumer, bool isES) { - assert(input_stage && output_stage); + assert(producer && consumer); + unsigned inputs = 0, outputs = 0; + + /* From OpenGL ES 3.1 spec (Interface matching): + * + * "An output variable is considered to match an input variable in the + * subsequent shader if: + * + * - the two variables match in name, type, and qualification; or + * - the two variables are declared with the same location qualifier and + * match in type and qualification. + * + * ... + * + * At an interface between program objects, the set of inputs and outputs + * are considered to match exactly if and only if: + * + * - Every declared input variable has a matching output, as described + * above. + * + * - There are no user-defined output variables declared without a + * matching input variable declaration. + * + * - All matched input and output variables have identical precision + * qualification. + * + * When the set of inputs and outputs on an interface between programs + * matches exactly, all inputs are well-defined except when the + * corresponding outputs were not written in the previous shader. However, + * any mismatch between inputs and outputs will result in a validation + * failure." + * + * OpenGL Core 4.5 spec includes same paragraph as above but without check + * for precision and the last 'validation failure' clause. Therefore + * behaviour is more relaxed, input and output amount is not required by the + * spec to be validated. + * + * FIXME: Update once Khronos spec bug #15331 is resolved. + * FIXME: Add validation by type, currently information loss during varying + * packing makes this challenging. + */ + + /* Currently no matching done for desktop. */ + if (!isES) + return true; /* For each output in a, find input in b and do any required checks. */ - foreach_in_list(ir_instruction, out, input_stage->ir) { + foreach_in_list(ir_instruction, out, producer->ir) { ir_variable *out_var = out->as_variable(); - if (!out_var || out_var->data.mode != ir_var_shader_out) + if (!out_var || out_var->data.mode != ir_var_shader_out || + is_gl_identifier(out_var->name)) continue; - foreach_in_list(ir_instruction, in, output_stage->ir) { + outputs++; + + inputs = 0; + foreach_in_list(ir_instruction, in, consumer->ir) { ir_variable *in_var = in->as_variable(); - if (!in_var || in_var->data.mode != ir_var_shader_in) + if (!in_var || in_var->data.mode != ir_var_shader_in || + is_gl_identifier(in_var->name)) + continue; + + inputs++; + + /* Match by location qualifier and precision. + * + * FIXME: Add explicit location matching validation here. Be careful + * not to match varyings with explicit locations to varyings without + * explicit locations. + */ + if ((in_var->data.explicit_location && + out_var->data.explicit_location) && + in_var->data.location == out_var->data.location && + in_var->data.precision == out_var->data.precision) continue; - if (strcmp(in_var->name, out_var->name) == 0) { - /* Since we now only validate precision, we can skip this step for - * desktop GLSL shaders, there precision qualifier is ignored. - * - * From OpenGL 4.50 Shading Language spec, section 4.7: - * "For the purposes of determining if an output from one - * shader stage matches an input of the next stage, the - * precision qualifier need not match." + unsigned len = strlen(in_var->name); + + /* Handle input swizzle in variable name. */ + const char *dot = strchr(in_var->name, '.'); + if (dot) + len = dot - in_var->name; + + /* Match by name and precision. */ + if (strncmp(in_var->name, out_var->name, len) == 0) { + /* From OpenGL ES 3.1 spec: + * "When both shaders are in separate programs, mismatched + * precision qualifiers will result in a program interface + * mismatch that will result in program pipeline validation + * failures, as described in section 7.4.1 (“Shader Interface + * Matching”) of the OpenGL ES 3.1 Specification." */ - if (isES) { - /* From OpenGL ES 3.1 spec: - * "When both shaders are in separate programs, mismatched - * precision qualifiers will result in a program interface - * mismatch that will result in program pipeline validation - * failures, as described in section 7.4.1 (“Shader Interface - * Matching”) of the OpenGL ES 3.1 Specification." - */ - if (in_var->data.precision != out_var->data.precision) - return false; - } + if (in_var->data.precision != out_var->data.precision) + return false; } } } - return true; + return inputs == outputs; } /** |