summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesa/main/pipelineobj.c15
-rw-r--r--src/mesa/main/shader_query.cpp62
-rw-r--r--src/mesa/main/shaderobj.h3
3 files changed, 80 insertions, 0 deletions
diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c
index 699a2ae47eb..90dff13485b 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 5cb877b0104..58ba04153e6 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 796de470735..be80752d7f2 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