[Mesa-dev] glsl: validate invariance between builtin variables

Submitted by Tapani Pälli on Nov. 7, 2014, 11:25 a.m.

Details

Message ID 1415359549-6849-1-git-send-email-tapani.palli@intel.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Tapani Pälli Nov. 7, 2014, 11:25 a.m.
Patch adds additional validation for GLSL ES 1.00 that specifies
cross stage variance requirements for a set of specified builtins.

Fixes failures in WebGL conformance test 'shaders-with-invariance'.

Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
---
 src/glsl/linker.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

Patch hide | download patch | download mbox

diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index bd2aa3c..57082a4 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -695,10 +695,29 @@  cross_validate_globals(struct gl_shader_program *prog,
     * them.
     */
    glsl_symbol_table variables;
+
+   ir_variable *gl_fcoord = NULL, *gl_position = NULL,
+               *gl_pcoord = NULL, *gl_psize = NULL,
+               *gl_frontf = NULL;
+
    for (unsigned i = 0; i < num_shaders; i++) {
       if (shader_list[i] == NULL)
 	 continue;
 
+      /* For GLSL ES 1.00, store builtin variables that require
+       * cross stage validation.
+       */
+      if (prog->IsES && prog->Version < 300) {
+         if (shader_list[i]->Stage == MESA_SHADER_VERTEX) {
+            gl_position = shader_list[i]->symbols->get_variable("gl_Position");
+            gl_psize = shader_list[i]->symbols->get_variable("gl_PointSize");
+         } else if (shader_list[i]->Stage == MESA_SHADER_FRAGMENT) {
+            gl_fcoord = shader_list[i]->symbols->get_variable("gl_FragCoord");
+            gl_pcoord = shader_list[i]->symbols->get_variable("gl_PointCoord");
+            gl_frontf =  shader_list[i]->symbols->get_variable("gl_FrontFacing");
+         }
+      }
+
       foreach_in_list(ir_instruction, node, shader_list[i]->ir) {
 	 ir_variable *const var = node->as_variable();
 
@@ -904,6 +923,30 @@  cross_validate_globals(struct gl_shader_program *prog,
 	    variables.add_variable(var);
       }
    }
+
+   /* GLSL ES 1.00 specification, Section "Invariance and Linkage" says:
+    *
+    *     "For the built-in special variables, gl_FragCoord can only be
+    *     declared invariant if and only if gl_Position is declared invariant.
+    *     Similarly gl_PointCoord can only be declared invariant if and only
+    *     if gl_PointSize is declared invariant. It is an error to declare
+    *     gl_FrontFacing as invariant. The invariance of gl_FrontFacing is the
+    *     same as the invariance of gl_Position."
+    */
+   if (prog->IsES && prog->Version < 300) {
+      if (gl_fcoord && gl_position)
+         if (gl_fcoord->data.invariant && !gl_position->data.invariant)
+            linker_error(prog, "gl_FragCoord declared invariant "
+                         "while gl_Position is declared variant.");
+
+      if (gl_pcoord && gl_psize)
+         if (gl_pcoord->data.invariant && !gl_psize->data.invariant)
+            linker_error(prog, "gl_PointCoord declared invariant "
+                         "while gl_PointSize is declared variant.");
+
+      if (gl_frontf && gl_frontf->data.invariant)
+         linker_error(prog, "gl_FrontFacing cannot be declared invariant.");
+   }
 }