summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/main/mtypes.h10
-rw-r--r--src/mesa/main/pipelineobj.c2
-rw-r--r--src/mesa/main/shaderapi.c78
-rw-r--r--src/mesa/main/shaderapi.h3
4 files changed, 61 insertions, 32 deletions
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 5b02fadf3cd..10f52349c91 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -4315,6 +4315,15 @@ struct gl_atomic_buffer_binding
};
/**
+ * Shader subroutines storage
+ */
+struct gl_subroutine_index_binding
+{
+ GLuint NumIndex;
+ GLuint *IndexPtr;
+};
+
+/**
* Mesa rendering context.
*
* This is the central context data structure for Mesa. Almost all
@@ -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 */
diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c
index cd8b0a775b6..82298409ee1 100644
--- a/src/mesa/main/pipelineobj.c
+++ b/src/mesa/main/pipelineobj.c
@@ -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]);
}
}
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 4f29cd974d0..6631f1ea479 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -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]);
}
}
diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
index 09b9525e402..b3de5fab1e7 100644
--- a/src/mesa/main/shaderapi.h
+++ b/src/mesa/main/shaderapi.h
@@ -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,