mesa: use gl_shader_variable in program resource list
authorTapani Pälli <tapani.palli@intel.com>
Tue, 12 Jan 2016 06:52:12 +0000 (08:52 +0200)
committerTapani Pälli <tapani.palli@intel.com>
Tue, 12 Jan 2016 07:07:10 +0000 (09:07 +0200)
Patch changes linker to allocate gl_shader_variable instead of using
ir_variable. This makes it possible to get rid of ir_variables and ir
in memory after linking.

v2: check that we do not create duplicate entries with
    packed varyings

v3: document 'patch' bit (Ilia Mirkin)

Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/glsl/linker.cpp
src/mesa/main/mtypes.h
src/mesa/main/shader_query.cpp

index d76cd9068c2175405e7caf40f9b1b1a880ed0bc2..eb1bdc05932c0d1831f44094029c0ee4c30ebe81 100644 (file)
@@ -3362,6 +3362,30 @@ build_stageref(struct gl_shader_program *shProg, const char *name,
    return stages;
 }
 
+/**
+ * Create gl_shader_variable from ir_variable class.
+ */
+static gl_shader_variable *
+create_shader_variable(struct gl_shader_program *shProg, const ir_variable *in)
+{
+   gl_shader_variable *out = ralloc(shProg, struct gl_shader_variable);
+   if (!out)
+      return NULL;
+
+   out->type = in->type;
+   out->name = ralloc_strdup(shProg, in->name);
+
+   if (!out->name)
+      return NULL;
+
+   out->location = in->data.location;
+   out->index = in->data.index;
+   out->patch = in->data.patch;
+   out->mode = in->data.mode;
+
+   return out;
+}
+
 static bool
 add_interface_variables(struct gl_shader_program *shProg,
                         exec_list *ir, GLenum programInterface)
@@ -3413,9 +3437,13 @@ add_interface_variables(struct gl_shader_program *shProg,
       if (strncmp(var->name, "gl_out_FragData", 15) == 0)
          continue;
 
-      if (!add_program_resource(shProg, programInterface, var,
-                                build_stageref(shProg, var->name,
-                                               var->data.mode) | mask))
+      gl_shader_variable *sha_v = create_shader_variable(shProg, var);
+      if (!sha_v)
+         return false;
+
+      if (!add_program_resource(shProg, programInterface, sha_v,
+                                build_stageref(shProg, sha_v->name,
+                                               sha_v->mode) | mask))
          return false;
    }
    return true;
@@ -3445,9 +3473,12 @@ add_packed_varyings(struct gl_shader_program *shProg, int stage, GLenum type)
          }
 
          if (type == iface) {
-            if (!add_program_resource(shProg, iface, var,
-                                      build_stageref(shProg, var->name,
-                                                     var->data.mode)))
+            gl_shader_variable *sha_v = create_shader_variable(shProg, var);
+            if (!sha_v)
+               return false;
+            if (!add_program_resource(shProg, iface, sha_v,
+                                      build_stageref(shProg, sha_v->name,
+                                                     sha_v->mode)))
                return false;
          }
       }
@@ -3467,7 +3498,10 @@ add_fragdata_arrays(struct gl_shader_program *shProg)
       ir_variable *var = node->as_variable();
       if (var) {
          assert(var->data.mode == ir_var_shader_out);
-         if (!add_program_resource(shProg, GL_PROGRAM_OUTPUT, var,
+         gl_shader_variable *sha_v = create_shader_variable(shProg, var);
+         if (!sha_v)
+            return false;
+         if (!add_program_resource(shProg, GL_PROGRAM_OUTPUT, sha_v,
                                    1 << MESA_SHADER_FRAGMENT))
             return false;
       }
@@ -3718,8 +3752,14 @@ build_program_resource_list(struct gl_shader_program *shProg)
    if (shProg->SeparateShader) {
       if (!add_packed_varyings(shProg, input_stage, GL_PROGRAM_INPUT))
          return;
-      if (!add_packed_varyings(shProg, output_stage, GL_PROGRAM_OUTPUT))
-         return;
+
+      /* Only when dealing with multiple stages, otherwise we would have
+       * duplicate gl_shader_variable entries.
+       */
+      if (input_stage != output_stage) {
+         if (!add_packed_varyings(shProg, output_stage, GL_PROGRAM_OUTPUT))
+            return;
+      }
    }
 
    if (!add_fragdata_arrays(shProg))
index 8951774e7148160c248060b47cd2401bfbf85570..0992d4d30f0456e26c93647d9309d5d3d187876c 100644 (file)
@@ -2524,6 +2524,67 @@ struct gl_active_atomic_buffer
    GLboolean StageReferences[MESA_SHADER_STAGES];
 };
 
+/**
+ * Data container for shader queries. This holds only the minimal
+ * amount of required information for resource queries to work.
+ */
+struct gl_shader_variable
+{
+   /**
+    * Declared type of the variable
+    */
+   const struct glsl_type *type;
+
+   /**
+    * Declared name of the variable
+    */
+   char *name;
+
+   /**
+    * Storage location of the base of this variable
+    *
+    * The precise meaning of this field depends on the nature of the variable.
+    *
+    *   - Vertex shader input: one of the values from \c gl_vert_attrib.
+    *   - Vertex shader output: one of the values from \c gl_varying_slot.
+    *   - Geometry shader input: one of the values from \c gl_varying_slot.
+    *   - Geometry shader output: one of the values from \c gl_varying_slot.
+    *   - Fragment shader input: one of the values from \c gl_varying_slot.
+    *   - Fragment shader output: one of the values from \c gl_frag_result.
+    *   - Uniforms: Per-stage uniform slot number for default uniform block.
+    *   - Uniforms: Index within the uniform block definition for UBO members.
+    *   - Non-UBO Uniforms: explicit location until linking then reused to
+    *     store uniform slot number.
+    *   - Other: This field is not currently used.
+    *
+    * If the variable is a uniform, shader input, or shader output, and the
+    * slot has not been assigned, the value will be -1.
+    */
+   int location;
+
+   /**
+    * Output index for dual source blending.
+    *
+    * \note
+    * The GLSL spec only allows the values 0 or 1 for the index in \b dual
+    * source blending.
+    */
+   unsigned index:1;
+
+   /**
+    * Specifies whether a shader input/output is per-patch in tessellation
+    * shader stages.
+    */
+   unsigned patch:1;
+
+   /**
+    * Storage class of the variable.
+    *
+    * \sa (n)ir_variable_mode
+    */
+   unsigned mode:4;
+};
+
 /**
  * Active resource in a gl_shader_program
  */
index b25732a2e3b59cbb41e5380ac944af263e2ec06c..014977b28ca061c3313c2b43cea2700d4fd41bf3 100644 (file)
@@ -56,7 +56,7 @@ const type * RESOURCE_ ## name (gl_program_resource *res) { \
    return (type *) res->Data; \
 }
 
-DECL_RESOURCE_FUNC(VAR, ir_variable);
+DECL_RESOURCE_FUNC(VAR, gl_shader_variable);
 DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
 DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
 DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
@@ -101,14 +101,14 @@ _mesa_BindAttribLocation(GLhandleARB program, GLuint index,
 }
 
 static bool
-is_active_attrib(const ir_variable *var)
+is_active_attrib(const gl_shader_variable *var)
 {
    if (!var)
       return false;
 
-   switch (var->data.mode) {
+   switch (var->mode) {
    case ir_var_shader_in:
-      return var->data.location != -1;
+      return var->location != -1;
 
    case ir_var_system_value:
       /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes):
@@ -116,9 +116,9 @@ is_active_attrib(const ir_variable *var)
        * are enumerated, including the special built-in inputs gl_VertexID
        * and gl_InstanceID."
        */
-      return var->data.location == SYSTEM_VALUE_VERTEX_ID ||
-             var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE ||
-             var->data.location == SYSTEM_VALUE_INSTANCE_ID;
+      return var->location == SYSTEM_VALUE_VERTEX_ID ||
+             var->location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE ||
+             var->location == SYSTEM_VALUE_INSTANCE_ID;
 
    default:
       return false;
@@ -163,7 +163,7 @@ _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index,
       return;
    }
 
-   const ir_variable *const var = RESOURCE_VAR(res);
+   const gl_shader_variable *const var = RESOURCE_VAR(res);
 
    if (!is_active_attrib(var))
       return;
@@ -174,8 +174,8 @@ _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index,
     * consider gl_VertexIDMESA as gl_VertexID for purposes of checking
     * active attributes.
     */
-   if (var->data.mode == ir_var_system_value &&
-       var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
+   if (var->mode == ir_var_system_value &&
+       var->location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
       var_name = "gl_VertexID";
    }
 
@@ -427,7 +427,7 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
 const char*
 _mesa_program_resource_name(struct gl_program_resource *res)
 {
-   const ir_variable *var;
+   const gl_shader_variable *var;
    switch (res->Type) {
    case GL_UNIFORM_BLOCK:
    case GL_SHADER_STORAGE_BLOCK:
@@ -437,8 +437,8 @@ _mesa_program_resource_name(struct gl_program_resource *res)
    case GL_PROGRAM_INPUT:
       var = RESOURCE_VAR(res);
       /* Special case gl_VertexIDMESA -> gl_VertexID. */
-      if (var->data.mode == ir_var_system_value &&
-          var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
+      if (var->mode == ir_var_system_value &&
+          var->location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
          return "gl_VertexID";
       }
    /* fallthrough */
@@ -857,14 +857,14 @@ program_resource_location(struct gl_shader_program *shProg,
     */
    switch (res->Type) {
    case GL_PROGRAM_INPUT: {
-      const ir_variable *var = RESOURCE_VAR(res);
+      const gl_shader_variable *var = RESOURCE_VAR(res);
 
       /* If the input is an array, fail if the index is out of bounds. */
       if (array_index > 0
           && array_index >= var->type->length) {
          return -1;
       }
-      return (var->data.location +
+      return (var->location +
              (array_index * var->type->without_array()->matrix_columns) -
              VERT_ATTRIB_GENERIC0);
    }
@@ -874,7 +874,7 @@ program_resource_location(struct gl_shader_program *shProg,
           && array_index >= RESOURCE_VAR(res)->type->length) {
          return -1;
       }
-      return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0;
+      return RESOURCE_VAR(res)->location + array_index - FRAG_RESULT_DATA0;
    case GL_UNIFORM:
       /* If the uniform is built-in, fail. */
       if (RESOURCE_UNI(res)->builtin)
@@ -954,7 +954,7 @@ _mesa_program_resource_location_index(struct gl_shader_program *shProg,
    if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
       return -1;
 
-   return RESOURCE_VAR(res)->data.index;
+   return RESOURCE_VAR(res)->index;
 }
 
 static uint8_t
@@ -1252,7 +1252,7 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
    case GL_LOCATION_INDEX:
       if (res->Type != GL_PROGRAM_OUTPUT)
          goto invalid_operation;
-      *val = RESOURCE_VAR(res)->data.index;
+      *val = RESOURCE_VAR(res)->index;
       return 1;
 
    case GL_NUM_COMPATIBLE_SUBROUTINES:
@@ -1309,7 +1309,7 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
       switch (res->Type) {
       case GL_PROGRAM_INPUT:
       case GL_PROGRAM_OUTPUT:
-         *val = RESOURCE_VAR(res)->data.patch;
+         *val = RESOURCE_VAR(res)->patch;
          return 1;
       default:
          goto invalid_operation;