summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/shader_query.cpp
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2016-05-19 10:28:25 -0700
committerIan Romanick <[email protected]>2016-05-26 16:21:01 -0700
commitbd3f15cffdbbec6d1ea5b7db2fcddaf8b7ae4524 (patch)
treea72ba305e8bf727695576392cc92dedf423ecfd1 /src/mesa/main/shader_query.cpp
parentcfff74629765d1d06313705f5ca80138c2182ef0 (diff)
mesa: Additional SSO validation using program_interface_query data
Fixes the following dEQP tests on SKL: dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_qualifier_vertex_smooth_fragment_flat dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_array_element_type dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_qualifier_vertex_flat_fragment_none dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_order dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_qualifier_vertex_centroid_fragment_flat dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_array_length dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_type dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_explicit_location_type dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_qualifier_vertex_flat_fragment_centroid dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_explicit_location dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_qualifier_vertex_flat_fragment_smooth dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name It regresses one test: dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names Hoever, this test is based on language in the OpenGL ES 3.1 spec that I believe is incorrect. I have already submitted a spec bug: https://www.khronos.org/bugzilla/show_bug.cgi?id=1500 v2: Move spec quote about built-in variables to the first place where it's relevant. Suggested by Alejandro. v3: Move patch earlier in series, fix rebase issues. Signed-off-by: Ian Romanick <[email protected]> Reviewed-by: Alejandro PiƱeiro <[email protected]> [v2] Reviewed-by: Timothy Arceri <[email protected]> [v2]
Diffstat (limited to 'src/mesa/main/shader_query.cpp')
-rw-r--r--src/mesa/main/shader_query.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp
index 9e18a1c6b7c..80e92748b59 100644
--- a/src/mesa/main/shader_query.cpp
+++ b/src/mesa/main/shader_query.cpp
@@ -1474,6 +1474,178 @@ validate_io(const struct gl_shader *producer,
return inputs == outputs;
}
+static bool
+validate_io(struct gl_shader_program *producer,
+ struct gl_shader_program *consumer)
+{
+ if (producer == consumer)
+ return true;
+
+ if (!producer->IsES && !consumer->IsES)
+ return true;
+
+ bool valid = true;
+
+ gl_shader_variable const **outputs =
+ (gl_shader_variable const **) calloc(producer->NumProgramResourceList,
+ sizeof(gl_shader_variable *));
+ if (outputs == NULL)
+ return false;
+
+ /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
+ * says:
+ *
+ * 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.
+ *
+ * Every input has an output, and every output has an input. Scan the list
+ * of producer resources once, and generate the list of outputs. As inputs
+ * and outputs are matched, remove the matched outputs from the set. At
+ * the end, the set must be empty. If the set is not empty, then there is
+ * some output that did not have an input.
+ */
+ unsigned num_outputs = 0;
+ for (unsigned i = 0; i < producer->NumProgramResourceList; i++) {
+ struct gl_program_resource *res = &producer->ProgramResourceList[i];
+
+ if (res->Type != GL_PROGRAM_OUTPUT)
+ continue;
+
+ gl_shader_variable const *const var = RESOURCE_VAR(res);
+
+ /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
+ * says:
+ *
+ * Built-in inputs or outputs do not affect interface matching.
+ */
+ if (is_gl_identifier(var->name))
+ continue;
+
+ outputs[num_outputs++] = var;
+ }
+
+ unsigned match_index = 0;
+ for (unsigned i = 0; i < consumer->NumProgramResourceList; i++) {
+ struct gl_program_resource *res = &consumer->ProgramResourceList[i];
+
+ if (res->Type != GL_PROGRAM_INPUT)
+ continue;
+
+ gl_shader_variable const *const consumer_var = RESOURCE_VAR(res);
+ gl_shader_variable const *producer_var = NULL;
+
+ if (is_gl_identifier(consumer_var->name))
+ continue;
+
+ /* Inputs with explicit locations match other outputs with explicit
+ * locations by location instead of by name.
+ */
+ if (consumer_var->explicit_location) {
+ for (unsigned j = 0; j < num_outputs; j++) {
+ const gl_shader_variable *const var = outputs[j];
+
+ if (var->explicit_location &&
+ consumer_var->location == var->location) {
+ producer_var = var;
+ match_index = j;
+ break;
+ }
+ }
+ } else {
+ for (unsigned j = 0; j < num_outputs; j++) {
+ const gl_shader_variable *const var = outputs[j];
+
+ if (!var->explicit_location &&
+ strcmp(consumer_var->name, var->name) == 0) {
+ producer_var = var;
+ match_index = j;
+ break;
+ }
+ }
+ }
+
+ /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
+ * says:
+ *
+ * - 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.
+ */
+ if (producer_var == NULL) {
+ valid = false;
+ goto out;
+ }
+
+ /* An output cannot match more than one input, so remove the output from
+ * the set of possible outputs.
+ */
+ outputs[match_index] = NULL;
+ num_outputs--;
+ if (match_index < num_outputs)
+ outputs[match_index] = outputs[num_outputs];
+
+ /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
+ *
+ * Qualifier Class| Qualifier |in/out
+ * ---------------+-------------+------
+ * Storage | in |
+ * | out | N/A
+ * | uniform |
+ * ---------------+-------------+------
+ * Auxiliary | centroid | No
+ * ---------------+-------------+------
+ * | location | Yes
+ * | Block layout| N/A
+ * | binding | N/A
+ * | offset | N/A
+ * | format | N/A
+ * ---------------+-------------+------
+ * Interpolation | smooth |
+ * | flat | Yes
+ * ---------------+-------------+------
+ * | lowp |
+ * Precision | mediump | Yes
+ * | highp |
+ * ---------------+-------------+------
+ * Variance | invariant | No
+ * ---------------+-------------+------
+ * Memory | all | N/A
+ *
+ * Note that location mismatches are detected by the loops above that
+ * find the producer variable that goes with the consumer variable.
+ */
+ if (producer_var->type != consumer_var->type ||
+ producer_var->interpolation != consumer_var->interpolation ||
+ producer_var->precision != consumer_var->precision) {
+ valid = false;
+ goto out;
+ }
+
+ if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) {
+ valid = false;
+ goto out;
+ }
+
+ if (producer_var->interface_type != consumer_var->interface_type) {
+ valid = false;
+ goto out;
+ }
+ }
+
+ out:
+ free(outputs);
+ return valid && num_outputs == 0;
+}
+
/**
* Validate inputs against outputs in a program pipeline.
*/
@@ -1505,6 +1677,10 @@ _mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
shProg[idx]->_LinkedShaders[idx],
shProg[prev]->IsES || shProg[idx]->IsES))
return false;
+
+ if (!validate_io(shProg[prev], shProg[idx]))
+ return false;
+
prev = idx;
}
}