[Mesa-dev] [PATCH 05/10] mesa: Additional SSO validation using program_interface_query data
Alejandro PiƱeiro
apinheiro at igalia.com
Fri May 20 09:38:36 UTC 2016
On 20/05/16 09:26, Ian Romanick wrote:
> 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 you are going to add a spec quote to justify why built-ins are
skipped, probably it would be better to do it the first time you do it,
when filling outputs on the producer loop, just before.
> + 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;
More information about the mesa-dev
mailing list