mesa/subroutines: start adding per-context subroutine index support (v1.1)
authorDave Airlie <airlied@redhat.com>
Tue, 7 Jun 2016 05:25:55 +0000 (15:25 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 23 Aug 2016 01:03:45 +0000 (11:03 +1000)
One piece of ARB_shader_subroutine I ignored was the fact that it
needs to store the subroutine index data per context and not per
shader program.

There is one CTS test that tests this:
GL45-CTS.shader_subroutine.multiple_contexts

However the test only does a write to context and readback,
it never renders using the values, so this is enough to fix the
test however not enough to do what the spec says.

So with this patch the info is now stored per context, but
it gets updated into the program at UseProgram and when the
values are inserted into the context, which won't help if
multiple contexts are in use in multiple threads.

v1.1: cleanups and nit-picks (Andres)

Signed-off-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Andres Gomez <agomez@igalia.com>
src/mesa/main/mtypes.h
src/mesa/main/pipelineobj.c
src/mesa/main/shaderapi.c
src/mesa/main/shaderapi.h

index 5b02fadf3cd8532b84003e668b85e9cf02a6065b..10f52349c915162cc6c70a7208775cd9e0694115 100644 (file)
@@ -4314,6 +4314,15 @@ struct gl_atomic_buffer_binding
    GLsizeiptr Size;
 };
 
+/**
+ * Shader subroutines storage
+ */
+struct gl_subroutine_index_binding
+{
+   GLuint NumIndex;
+   GLuint *IndexPtr;
+};
+
 /**
  * Mesa rendering context.
  *
@@ -4552,6 +4561,7 @@ struct gl_context
     */
    struct gl_image_unit ImageUnits[MAX_IMAGE_UNITS];
 
+   struct gl_subroutine_index_binding SubroutineIndex[MESA_SHADER_STAGES];
    /*@}*/
 
    struct gl_meta_state *Meta;  /**< for "meta" operations */
index cd8b0a775b6ea8b73405b4beab514bf710177703..82298409ee19db4cc01add3a54b556c524d57556 100644 (file)
@@ -469,7 +469,7 @@ _mesa_bind_pipeline(struct gl_context *ctx,
       FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
 
       for (i = 0; i < MESA_SHADER_STAGES; i++)
-         _mesa_shader_program_init_subroutine_defaults(ctx->_Shader->CurrentProgram[i]);
+         _mesa_shader_program_init_subroutine_defaults(ctx, ctx->_Shader->CurrentProgram[i]);
    }
 }
 
index 4f29cd974d039ef977208a1e88ee502da74f1e48..6631f1ea47978dba022676ec84fb75ba7f42773a 100644 (file)
@@ -65,6 +65,7 @@
 #define PATH_MAX _MAX_PATH
 #endif
 
+static void _mesa_shader_write_subroutine_index(struct gl_context *ctx, struct gl_linked_shader *sh);
 /**
  * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
  */
@@ -1208,7 +1209,7 @@ use_shader_program(struct gl_context *ctx, gl_shader_stage stage,
       shProg = NULL;
 
    if (shProg)
-      _mesa_shader_program_init_subroutine_defaults(shProg);
+      _mesa_shader_program_init_subroutine_defaults(ctx, shProg);
 
    if (*target != shProg) {
       /* Program is current, flush it */
@@ -2648,27 +2649,15 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
             _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
             return;
          }
+
+         ctx->SubroutineIndex[sh->Stage].IndexPtr[j] = indices[j];
       }
       i += uni_count;
    } while(i < count);
 
    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
-   i = 0;
-   do {
-      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i];
-      if (uni == NULL) {
-         i++;
-         continue;
-      }
-
-      int uni_count = uni->array_elements ? uni->array_elements : 1;
-
-      memcpy(&uni->storage[0], &indices[i],
-             sizeof(GLuint) * uni_count);
 
-      _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count);
-      i += uni_count;
-   } while(i < count);
+   _mesa_shader_write_subroutine_index(ctx, sh);
 }
 
 
@@ -2710,12 +2699,7 @@ _mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location,
       return;
    }
 
-   {
-      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[location];
-      int offset = location - uni->opaque[stage].index;
-      memcpy(params, &uni->storage[offset],
-            sizeof(GLuint));
-   }
+   *params = ctx->SubroutineIndex[sh->Stage].IndexPtr[location];
 }
 
 
@@ -2824,29 +2808,63 @@ find_compat_subroutine(struct gl_linked_shader *sh,
 }
 
 static void
-_mesa_shader_init_subroutine_defaults(struct gl_linked_shader *sh)
+_mesa_shader_write_subroutine_index(struct gl_context *ctx,
+                                    struct gl_linked_shader *sh)
 {
    int i, j;
 
-   for (i = 0; i < sh->NumSubroutineUniformRemapTable; i++) {
+   if (sh->NumSubroutineUniformRemapTable == 0)
+      return;
+
+   i = 0;
+   do {
       struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i];
       int uni_count;
       int val;
 
-      if (!uni)
+      if (!uni) {
+         i++;
          continue;
-      uni_count = uni->array_elements ? uni->array_elements : 1;
-      val = find_compat_subroutine(sh, uni->type);
+      }
 
-      for (j = 0; j < uni_count; j++)
+      uni_count = uni->array_elements ? uni->array_elements : 1;
+      for (j = 0; j < uni_count; j++) {
+         val = ctx->SubroutineIndex[sh->Stage].IndexPtr[i + j];
          memcpy(&uni->storage[j], &val, sizeof(int));
+      }
 
       _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count);
+      i += uni_count;
+   } while(i < sh->NumSubroutineUniformRemapTable);
+}
+
+static void
+_mesa_shader_init_subroutine_defaults(struct gl_context *ctx,
+                                      struct gl_linked_shader *sh)
+{
+   int i;
+   struct gl_subroutine_index_binding *binding = &ctx->SubroutineIndex[sh->Stage];
+   if (binding->NumIndex != sh->NumSubroutineUniformRemapTable) {
+      binding->IndexPtr = realloc(binding->IndexPtr,
+                                  sh->NumSubroutineUniformRemapTable * (sizeof(GLuint)));
+      binding->NumIndex = sh->NumSubroutineUniformRemapTable;
+   }
+
+   for (i = 0; i < sh->NumSubroutineUniformRemapTable; i++) {
+      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i];
+
+      if (!uni)
+         continue;
+
+      binding->IndexPtr[i] = find_compat_subroutine(sh, uni->type);
    }
+
+   _mesa_shader_write_subroutine_index(ctx, sh);
 }
 
 void
-_mesa_shader_program_init_subroutine_defaults(struct gl_shader_program *shProg)
+_mesa_shader_program_init_subroutine_defaults(struct gl_context *ctx,
+                                              struct gl_shader_program *shProg)
 {
    int i;
 
@@ -2857,6 +2875,6 @@ _mesa_shader_program_init_subroutine_defaults(struct gl_shader_program *shProg)
       if (!shProg->_LinkedShaders[i])
          continue;
 
-      _mesa_shader_init_subroutine_defaults(shProg->_LinkedShaders[i]);
+      _mesa_shader_init_subroutine_defaults(ctx, shProg->_LinkedShaders[i]);
    }
 }
index 09b9525e402a2a026e662ae5a12bdb5544620a31..b3de5fab1e7f89ca33c78696f50e66d08b3c96f6 100644 (file)
@@ -286,7 +286,8 @@ _mesa_PatchParameterfv(GLenum pname, const GLfloat *values);
 
 /* GL_ARB_shader_subroutine */
 void
-_mesa_shader_program_init_subroutine_defaults(struct gl_shader_program *shProg);
+_mesa_shader_program_init_subroutine_defaults(struct gl_context *ctx,
+                                              struct gl_shader_program *shProg);
 
 extern GLint GLAPIENTRY
 _mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype,