[Mesa-dev] [PATCH 05/10] mesa: Additional SSO validation using program_interface_query data
Ian Romanick
idr at freedesktop.org
Fri May 20 07:26:00 UTC 2016
From: Ian Romanick <ian.d.romanick at intel.com>
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
Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
I'm experimenting with different formatting of spec quotations. This is
something new-ish based on the list discussion with Ken and Matt earlier
this week.
src/mesa/main/shader_query.cpp | 172 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 172 insertions(+)
diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp
index a120cb4..5fa611f 100644
--- a/src/mesa/main/shader_query.cpp
+++ b/src/mesa/main/shader_query.cpp
@@ -1470,6 +1470,175 @@ 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;
+
+ 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);
+
+ 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;
+
+ /* 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(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.
*/
@@ -1501,6 +1670,9 @@ _mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
if (!validate_io(shProg[prev]->_LinkedShaders[prev],
shProg[idx]->_LinkedShaders[idx]))
return false;
+
+ if (!validate_io(shProg[prev], shProg[idx]))
+ return false;
}
prev = idx;
--
2.5.5
More information about the mesa-dev
mailing list