glsl: Fix prorgram interface query locations biasing for SSO.
authorKenneth Graunke <kenneth@whitecape.org>
Tue, 29 Mar 2016 21:15:14 +0000 (14:15 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Sat, 2 Apr 2016 05:05:20 +0000 (22:05 -0700)
With SSO, the GL_PROGRAM_INPUT and GL_PROGRAM_OUTPUT interfaces refer to
the first and last shader stage linked into a program.  This may not be
the vertex and fragment shader stages.

So, subtracting VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 is bogus.
We need to subtract VERT_ATTRIB_GENERIC0 for VS inputs,
FRAG_RESULT_DATA0 for FS outputs, and VARYING_SLOT_VAR0 for other cases.

Note that built-in variables get a location of -1.

Fixes 4 dEQP-GLES31.functional.program_interface_query tests:
- program_input.location.separable_fragment.var_explicit_location
- program_input.location.separable_fragment.var_array_explicit_location
- program_output.location.separable_vertex.var_array_explicit_location
- program_output.location.separable_vertex.var_array_explicit_location

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Timothy Arceri <timothy.arceri@collabora.com>
src/compiler/glsl/linker.cpp
src/mesa/main/shader_query.cpp

index 71dbddd8763d39b6f3754fecb232927b49a23799..736852e78094f125e40b20e96733b2b692c454e7 100644 (file)
@@ -3498,7 +3498,8 @@ build_stageref(struct gl_shader_program *shProg, const char *name,
  */
 static gl_shader_variable *
 create_shader_variable(struct gl_shader_program *shProg,
-                       const ir_variable *in, bool use_implicit_location)
+                       const ir_variable *in, bool use_implicit_location,
+                       int location_bias)
 {
    gl_shader_variable *out = ralloc(shProg, struct gl_shader_variable);
    if (!out)
@@ -3536,7 +3537,7 @@ create_shader_variable(struct gl_shader_program *shProg,
        !(in->data.explicit_location || use_implicit_location)) {
       out->location = -1;
    } else {
-      out->location = in->data.location;
+      out->location = in->data.location - location_bias;
    }
 
    out->type = in->type;
@@ -3559,15 +3560,21 @@ add_interface_variables(struct gl_shader_program *shProg,
       if (!var || var->data.how_declared == ir_var_hidden)
          continue;
 
+      int loc_bias;
+
       switch (var->data.mode) {
       case ir_var_system_value:
       case ir_var_shader_in:
          if (programInterface != GL_PROGRAM_INPUT)
             continue;
+         loc_bias = (stage == MESA_SHADER_VERTEX) ? int(VERT_ATTRIB_GENERIC0)
+                                                  : int(VARYING_SLOT_VAR0);
          break;
       case ir_var_shader_out:
          if (programInterface != GL_PROGRAM_OUTPUT)
             continue;
+         loc_bias = (stage == MESA_SHADER_FRAGMENT) ? int(FRAG_RESULT_DATA0)
+                                                    : int(VARYING_SLOT_VAR0);
          break;
       default:
          continue;
@@ -3590,7 +3597,7 @@ add_interface_variables(struct gl_shader_program *shProg,
          (stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_out);
 
       gl_shader_variable *sha_v =
-         create_shader_variable(shProg, var, vs_input_or_fs_output);
+         create_shader_variable(shProg, var, vs_input_or_fs_output, loc_bias);
       if (!sha_v)
          return false;
 
@@ -3625,7 +3632,7 @@ add_packed_varyings(struct gl_shader_program *shProg, int stage, GLenum type)
 
          if (type == iface) {
             gl_shader_variable *sha_v =
-               create_shader_variable(shProg, var, false);
+               create_shader_variable(shProg, var, false, VARYING_SLOT_VAR0);
             if (!sha_v)
                return false;
             if (!add_program_resource(shProg, iface, sha_v,
@@ -3650,7 +3657,8 @@ add_fragdata_arrays(struct gl_shader_program *shProg)
       ir_variable *var = node->as_variable();
       if (var) {
          assert(var->data.mode == ir_var_shader_out);
-         gl_shader_variable *sha_v = create_shader_variable(shProg, var, true);
+         gl_shader_variable *sha_v =
+            create_shader_variable(shProg, var, true, FRAG_RESULT_DATA0);
          if (!sha_v)
             return false;
          if (!add_program_resource(shProg, GL_PROGRAM_OUTPUT, sha_v,
index 190f63879878fab3f91a0b83797b42ca2d4fbd62..4650a5c9ef17d7ca171365e46c07f676c1069df0 100644 (file)
@@ -780,10 +780,6 @@ program_resource_location(struct gl_shader_program *shProg,
                           struct gl_program_resource *res, const char *name,
                           unsigned array_index)
 {
-   /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these
-    * offsets are used internally to differentiate between built-in attributes
-    * and user-defined attributes.
-    */
    switch (res->Type) {
    case GL_PROGRAM_INPUT: {
       const gl_shader_variable *var = RESOURCE_VAR(res);
@@ -796,9 +792,8 @@ program_resource_location(struct gl_shader_program *shProg,
           && array_index >= var->type->length) {
          return -1;
       }
-      return (var->location +
-             (array_index * var->type->without_array()->matrix_columns) -
-             VERT_ATTRIB_GENERIC0);
+      return var->location +
+            (array_index * var->type->without_array()->matrix_columns);
    }
    case GL_PROGRAM_OUTPUT:
       if (RESOURCE_VAR(res)->location == -1)
@@ -809,7 +804,7 @@ program_resource_location(struct gl_shader_program *shProg,
           && array_index >= RESOURCE_VAR(res)->type->length) {
          return -1;
       }
-      return RESOURCE_VAR(res)->location + array_index - FRAG_RESULT_DATA0;
+      return RESOURCE_VAR(res)->location + array_index;
    case GL_UNIFORM:
       /* If the uniform is built-in, fail. */
       if (RESOURCE_UNI(res)->builtin)