glsl: additional interface redeclaration check for SSO programs
authorTapani Pälli <tapani.palli@intel.com>
Tue, 5 Nov 2019 13:00:25 +0000 (15:00 +0200)
committerTapani Pälli <tapani.palli@intel.com>
Wed, 4 Dec 2019 15:27:41 +0000 (15:27 +0000)
Patch adds additional linker check for SSO programs to make sure they
are redeclaring built-in blocks as required by the desktop spec.

This fixes following Piglit tests:
   arb_separate_shader_objects/linker/pervertex-*

Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
src/compiler/glsl/link_interface_blocks.cpp

index 29c5c6f97aeac70f457eec07778abe8ad1605e18..deb544e3ce6d0156023aa2e7b0f7fe9b6ebb6529 100644 (file)
@@ -401,12 +401,56 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog,
       return;
    }
 
+   /* Desktop OpenGL requires redeclaration of the built-in interfaces for
+    * SSO programs. Passes above implement following rules:
+    *
+    * From Section 7.4 (Program Pipeline Objects) of the OpenGL 4.6 Core
+    * spec:
+    *
+    *    "To use any built-in input or output in the gl_PerVertex and
+    *     gl_PerFragment blocks in separable program objects, shader code
+    *     must redeclare those blocks prior to use.  A separable program
+    *     will fail to link if:
+    *
+    *     it contains multiple shaders of a single type with different
+    *     redeclarations of these built-in input and output blocks; or
+    *
+    *     any shader uses a built-in block member not found in the
+    *     redeclaration of that block."
+    *
+    * ARB_separate_shader_objects issues section (issue #28) states that
+    * redeclaration is not required for GLSL shaders using #version 140 or
+    * earlier (since interface blocks are not possible with older versions).
+    *
+    * From Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1
+    * spec:
+    *
+    *    "Built-in inputs or outputs do not affect interface matching."
+    *
+    * GL_OES_shader_io_blocks adds following:
+    *
+    *    "When using any built-in input or output in the gl_PerVertex block
+    *     in separable program objects, shader code may redeclare that block
+    *     prior to use. If the shader does not redeclare the block, the
+    *     intrinsically declared definition of that block will be used."
+    */
+
    /* Add output interfaces from the producer to the symbol table. */
    foreach_in_list(ir_instruction, node, producer->ir) {
       ir_variable *var = node->as_variable();
       if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_out)
          continue;
 
+      /* Built-in interface redeclaration check. */
+      if (prog->SeparateShader && !prog->IsES && prog->data->Version >= 150 &&
+          var->data.how_declared == ir_var_declared_implicitly &&
+          var->data.used && !producer_iface) {
+         linker_error(prog, "missing output builtin block %s redeclaration "
+                      "in separable shader program",
+                      var->get_interface_type()->name);
+         return;
+      }
+
       definitions.store(var);
    }
 
@@ -418,6 +462,16 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog,
 
       ir_variable *producer_def = definitions.lookup(var);
 
+      /* Built-in interface redeclaration check. */
+      if (prog->SeparateShader && !prog->IsES && prog->data->Version >= 150 &&
+          var->data.how_declared == ir_var_declared_implicitly &&
+          var->data.used && !producer_iface) {
+         linker_error(prog, "missing input builtin block %s redeclaration "
+                      "in separable shader program",
+                      var->get_interface_type()->name);
+         return;
+      }
+
       /* The producer doesn't generate this input: fail to link. Skip built-in
        * 'gl_in[]' since that may not be present if the producer does not
        * write to any of the pre-defined outputs (e.g. if the vertex shader