st/mesa: decrease the size of st_vertex_program
[mesa.git] / src / glsl / linker.cpp
index 9d419ac9d39c04d65e1061ec87f613bc729f69da..a97b4ef0a32d11e43268fe94a2b058bdd1eb8c8d 100644 (file)
@@ -1187,7 +1187,7 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
       for (unsigned int j = 0; j < sh->NumUniformBlocks; j++) {
         int index = link_cross_validate_uniform_block(prog,
                                                       &prog->UniformBlocks,
-                                                      &prog->NumUniformBlocks,
+                                                      &prog->NumBufferInterfaceBlocks,
                                                       &sh->UniformBlocks[j]);
 
         if (index == -1) {
@@ -2132,7 +2132,7 @@ link_intrastage_shaders(void *mem_ctx,
 
 
    if (!ok) {
-      ctx->Driver.DeleteShader(ctx, linked);
+      _mesa_delete_shader(ctx, linked);
       return NULL;
    }
 
@@ -2802,7 +2802,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
    unsigned shader_blocks[MESA_SHADER_STAGES] = {0};
    unsigned total_shader_storage_blocks = 0;
 
-   for (unsigned i = 0; i < prog->NumUniformBlocks; i++) {
+   for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) {
       /* Don't check SSBOs for Uniform Block Size */
       if (!prog->UniformBlocks[i].IsShaderStorage &&
           prog->UniformBlocks[i].UniformBufferSize > ctx->Const.MaxUniformBlockSize) {
@@ -2836,7 +2836,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
 
       if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) {
         linker_error(prog, "Too many combined uniform blocks (%d/%d)\n",
-                     prog->NumUniformBlocks,
+                     total_uniform_blocks,
                      ctx->Const.MaxCombinedUniformBlocks);
       } else {
         for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
@@ -2939,7 +2939,7 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog)
 
          total_image_units += sh->NumImages;
 
-         for (unsigned j = 0; j < prog->NumUniformBlocks; j++) {
+         for (unsigned j = 0; j < prog->NumBufferInterfaceBlocks; j++) {
             int stage_index = prog->UniformBlockStageIndex[i][j];
             if (stage_index != -1 && sh->UniformBlocks[stage_index].IsShaderStorage)
                total_shader_storage_blocks++;
@@ -3133,6 +3133,60 @@ check_explicit_uniform_locations(struct gl_context *ctx,
    delete uniform_map;
 }
 
+static bool
+should_add_buffer_variable(struct gl_shader_program *shProg,
+                           GLenum type, const char *name)
+{
+   bool found_interface = false;
+   const char *block_name = NULL;
+
+   /* These rules only apply to buffer variables. So we return
+    * true for the rest of types.
+    */
+   if (type != GL_BUFFER_VARIABLE)
+      return true;
+
+   for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
+      block_name = shProg->UniformBlocks[i].Name;
+      if (strncmp(block_name, name, strlen(block_name)) == 0) {
+         found_interface = true;
+         break;
+      }
+   }
+
+   /* We remove the interface name from the buffer variable name,
+    * including the dot that follows it.
+    */
+   if (found_interface)
+      name = name + strlen(block_name) + 1;
+
+   /* From: ARB_program_interface_query extension:
+    *
+    *  "For an active shader storage block member declared as an array, an
+    *   entry will be generated only for the first array element, regardless
+    *   of its type.  For arrays of aggregate types, the enumeration rules are
+    *   applied recursively for the single enumerated array element.
+    */
+   const char *first_dot = strchr(name, '.');
+   const char *first_square_bracket = strchr(name, '[');
+
+   /* The buffer variable is on top level and it is not an array */
+   if (!first_square_bracket) {
+      return true;
+   /* The shader storage block member is a struct, then generate the entry */
+   } else if (first_dot && first_dot < first_square_bracket) {
+      return true;
+   } else {
+      /* Shader storage block member is an array, only generate an entry for the
+       * first array element.
+       */
+      if (strncmp(first_square_bracket, "[0]", 3) == 0)
+         return true;
+   }
+
+   return false;
+}
+
 static bool
 add_program_resource(struct gl_shader_program *prog, GLenum type,
                      const void *data, uint8_t stages)
@@ -3319,8 +3373,12 @@ add_packed_varyings(struct gl_shader_program *shProg, int stage)
          switch (var->data.mode) {
          case ir_var_shader_in:
             iface = GL_PROGRAM_INPUT;
+            break;
          case ir_var_shader_out:
             iface = GL_PROGRAM_OUTPUT;
+            break;
+         default:
+            unreachable("unexpected type");
          }
          if (!add_program_resource(shProg, iface, var,
                                    build_stageref(shProg, var->name,
@@ -3363,10 +3421,13 @@ build_program_resource_list(struct gl_shader_program *shProg)
    if (input_stage == MESA_SHADER_STAGES && output_stage == 0)
       return;
 
-   if (!add_packed_varyings(shProg, input_stage))
-      return;
-   if (!add_packed_varyings(shProg, output_stage))
-      return;
+   /* Program interface needs to expose varyings in case of SSO. */
+   if (shProg->SeparateShader) {
+      if (!add_packed_varyings(shProg, input_stage))
+         return;
+      if (!add_packed_varyings(shProg, output_stage))
+         return;
+   }
 
    /* Add inputs and outputs to the resource list. */
    if (!add_interface_variables(shProg, shProg->_LinkedShaders[input_stage]->ir,
@@ -3408,13 +3469,17 @@ build_program_resource_list(struct gl_shader_program *shProg)
 
       bool is_shader_storage =  shProg->UniformStorage[i].is_shader_storage;
       GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM;
+      if (!should_add_buffer_variable(shProg, type,
+                                      shProg->UniformStorage[i].name))
+         continue;
+
       if (!add_program_resource(shProg, type,
                                 &shProg->UniformStorage[i], stageref))
          return;
    }
 
    /* Add program uniform blocks and shader storage blocks. */
-   for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) {
+   for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
       bool is_shader_storage = shProg->UniformBlocks[i].IsShaderStorage;
       GLenum type = is_shader_storage ? GL_SHADER_STORAGE_BLOCK : GL_UNIFORM_BLOCK;
       if (!add_program_resource(shProg, type,
@@ -3435,7 +3500,7 @@ build_program_resource_list(struct gl_shader_program *shProg)
          continue;
 
       for (int j = MESA_SHADER_VERTEX; j < MESA_SHADER_STAGES; j++) {
-         if (!shProg->UniformStorage[i].subroutine[j].active)
+         if (!shProg->UniformStorage[i].opaque[j].active)
             continue;
 
          type = _mesa_shader_stage_to_subroutine_uniform((gl_shader_stage)j);
@@ -3670,7 +3735,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
 
    for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
       if (prog->_LinkedShaders[i] != NULL)
-        ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+        _mesa_delete_shader(ctx, prog->_LinkedShaders[i]);
 
       prog->_LinkedShaders[i] = NULL;
    }
@@ -3685,7 +3750,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
 
          if (!prog->LinkStatus) {
             if (sh)
-               ctx->Driver.DeleteShader(ctx, sh);
+               _mesa_delete_shader(ctx, sh);
             goto done;
          }
 
@@ -3708,7 +3773,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
          }
          if (!prog->LinkStatus) {
             if (sh)
-               ctx->Driver.DeleteShader(ctx, sh);
+               _mesa_delete_shader(ctx, sh);
             goto done;
          }