From 7e6dac11866d264c21a108b9623114943d6e88ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tapani=20P=C3=A4lli?= Date: Thu, 5 Nov 2015 12:52:26 +0200 Subject: mesa: validate precision of varyings during ValidateProgramPipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes following failing ES3.1 CTS tests: ES31-CTS.sepshaderobjs.InterfacePrecisionMatchingFloat ES31-CTS.sepshaderobjs.InterfacePrecisionMatchingInt ES31-CTS.sepshaderobjs.InterfacePrecisionMatchingUInt Signed-off-by: Tapani Pälli Reviewed-by: Iago Toral Quiroga --- src/mesa/main/pipelineobj.c | 15 ++++++++++ src/mesa/main/shader_query.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++ src/mesa/main/shaderobj.h | 3 ++ 3 files changed, 80 insertions(+) (limited to 'src') diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c index 699a2ae..90dff13 100644 --- a/src/mesa/main/pipelineobj.c +++ b/src/mesa/main/pipelineobj.c @@ -907,6 +907,21 @@ _mesa_ValidateProgramPipeline(GLuint pipeline) _mesa_validate_program_pipeline(ctx, pipe, (ctx->_Shader->Name == pipe->Name)); + + /* Validate inputs against outputs, this cannot be done during linking + * since programs have been linked separately from each other. + * + * From OpenGL 4.5 Core spec: + * "Separable program objects may have validation failures that cannot be + * detected without the complete program pipeline. Mismatched interfaces, + * improper usage of program objects together, and the same + * state-dependent failures can result in validation errors for such + * program objects." + * + * OpenGL ES 3.1 specification has the same text. + */ + if (!_mesa_validate_pipeline_io(pipe)) + pipe->Validated = GL_FALSE; } void GLAPIENTRY diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index 5cb877b..58ba041 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -1359,3 +1359,65 @@ _mesa_get_program_resourceiv(struct gl_shader_program *shProg, if (length) *length = amount; } + +static bool +validate_io(const struct gl_shader *input_stage, + const struct gl_shader *output_stage) +{ + assert(input_stage && output_stage); + + /* For each output in a, find input in b and do any required checks. */ + foreach_in_list(ir_instruction, out, input_stage->ir) { + ir_variable *out_var = out->as_variable(); + if (!out_var || out_var->data.mode != ir_var_shader_out) + continue; + + foreach_in_list(ir_instruction, in, output_stage->ir) { + ir_variable *in_var = in->as_variable(); + if (!in_var || in_var->data.mode != ir_var_shader_in) + continue; + + if (strcmp(in_var->name, out_var->name) == 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 (in_var->data.precision != out_var->data.precision) + return false; + } + } + } + return true; +} + +/** + * Validate inputs against outputs in a program pipeline. + */ +extern "C" bool +_mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline) +{ + struct gl_shader_program **shProg = + (struct gl_shader_program **) pipeline->CurrentProgram; + + /* Find first active stage in pipeline. */ + unsigned idx, prev = 0; + for (idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) { + if (shProg[idx]) { + prev = idx; + break; + } + } + + for (idx = prev + 1; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) { + if (shProg[idx]) { + if (!validate_io(shProg[prev]->_LinkedShaders[prev], + shProg[idx]->_LinkedShaders[idx])) + return false; + prev = idx; + } + } + return true; +} diff --git a/src/mesa/main/shaderobj.h b/src/mesa/main/shaderobj.h index 796de47..be80752 100644 --- a/src/mesa/main/shaderobj.h +++ b/src/mesa/main/shaderobj.h @@ -234,6 +234,9 @@ _mesa_shader_stage_to_subroutine_uniform(gl_shader_stage stage) } } +extern bool +_mesa_validate_pipeline_io(struct gl_pipeline_object *); + #ifdef __cplusplus } #endif -- cgit v1.1