[Mesa-dev] [PATCH 69/77] glsl/i965: make a copy of the shader source and use it at fallback
Timothy Arceri
timothy.arceri at collabora.com
Mon Oct 3 06:05:28 UTC 2016
A number of things can happen that change the shader source after it is
compiled or linked.
For example:
- Source changed after it is first compiled
- Source changed after linking
- Shader detached after linking
In order to be able to fallback to a full rebuild on a cache miss we
make a copy of the shader source it into the new FallbackShaders
field when linking.
---
src/compiler/glsl/linker.cpp | 27 +++++++++++++++-----------
src/compiler/glsl/shader_cache.cpp | 29 ++++++++++++++++++++++++++++
src/mesa/drivers/dri/i965/brw_shader_cache.c | 26 +++++++++++++++++++------
src/mesa/main/mtypes.h | 3 +++
src/mesa/main/shaderobj.c | 6 ++++++
src/mesa/program/ir_to_mesa.cpp | 16 +++++++++++----
6 files changed, 86 insertions(+), 21 deletions(-)
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index 6e05cad..fca65cb 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -4623,7 +4623,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog,
* fixed-function. This applies to the case where all stages are
* missing.
*/
- if (prog->NumShaders == 0) {
+ unsigned shader_count = is_cache_fallback ?
+ prog->NumFallbackShaders : prog->NumShaders;
+ if (shader_count == 0) {
if (ctx->API != API_OPENGL_COMPAT)
linker_error(prog, "no shaders attached to the program\n");
return;
@@ -4665,44 +4667,47 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog,
struct gl_shader **shader_list[MESA_SHADER_STAGES];
unsigned num_shaders[MESA_SHADER_STAGES];
+ struct gl_shader **shaders = is_cache_fallback ?
+ prog->FallbackShaders : prog->Shaders;
+
for (int i = 0; i < MESA_SHADER_STAGES; i++) {
shader_list[i] = (struct gl_shader **)
- calloc(prog->NumShaders, sizeof(struct gl_shader *));
+ calloc(shader_count, sizeof(struct gl_shader *));
num_shaders[i] = 0;
}
unsigned min_version = UINT_MAX;
unsigned max_version = 0;
- for (unsigned i = 0; i < prog->NumShaders; i++) {
- min_version = MIN2(min_version, prog->Shaders[i]->Version);
- max_version = MAX2(max_version, prog->Shaders[i]->Version);
+ for (unsigned i = 0; i < shader_count; i++) {
+ min_version = MIN2(min_version, shaders[i]->Version);
+ max_version = MAX2(max_version, shaders[i]->Version);
- if (prog->Shaders[i]->IsES != prog->Shaders[0]->IsES) {
+ if (shaders[i]->IsES != shaders[0]->IsES) {
linker_error(prog, "all shaders must use same shading "
"language version\n");
goto done;
}
- if (prog->Shaders[i]->info.ARB_fragment_coord_conventions_enable) {
+ if (shaders[i]->info.ARB_fragment_coord_conventions_enable) {
prog->ARB_fragment_coord_conventions_enable = true;
}
- gl_shader_stage shader_type = prog->Shaders[i]->Stage;
- shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i];
+ gl_shader_stage shader_type = shaders[i]->Stage;
+ shader_list[shader_type][num_shaders[shader_type]] = shaders[i];
num_shaders[shader_type]++;
}
/* In desktop GLSL, different shader versions may be linked together. In
* GLSL ES, all shader versions must be the same.
*/
- if (prog->Shaders[0]->IsES && min_version != max_version) {
+ if (shaders[0]->IsES && min_version != max_version) {
linker_error(prog, "all shaders must use same shading "
"language version\n");
goto done;
}
prog->Version = max_version;
- prog->IsES = prog->Shaders[0]->IsES;
+ prog->IsES = shaders[0]->IsES;
/* Some shaders have to be linked with some other shaders present.
*/
diff --git a/src/compiler/glsl/shader_cache.cpp b/src/compiler/glsl/shader_cache.cpp
index 18a338c..95e932a 100644
--- a/src/compiler/glsl/shader_cache.cpp
+++ b/src/compiler/glsl/shader_cache.cpp
@@ -1265,6 +1265,35 @@ shader_cache_read_program_metadata(struct gl_context *ctx,
if (!cache)
return false;
+ /* Free previous fallback information */
+ if (prog->FallbackShaders == NULL) {
+ prog->NumFallbackShaders = 0;
+ for (unsigned i = 0; i < prog->NumFallbackShaders; i++) {
+ ralloc_free(prog->FallbackShaders);
+ prog->FallbackShaders = NULL;
+ }
+ }
+
+ /* Shaders could be recompiled using different source code after linking,
+ * or the shader could be detached from the program so store some
+ * information about the shader to be used in case of fallback.
+ */
+ prog->NumFallbackShaders = prog->NumShaders;
+ prog->FallbackShaders = (struct gl_shader **)
+ reralloc(NULL, prog->FallbackShaders, struct gl_shader *,
+ prog->NumShaders);
+ for (unsigned i = 0; i < prog->NumShaders; i++) {
+ prog->FallbackShaders[i] = rzalloc(prog->FallbackShaders,
+ struct gl_shader);
+ memcpy(prog->FallbackShaders[i]->sha1, prog->Shaders[i]->sha1,
+ sizeof(prog->Shaders[i]->sha1));
+ prog->FallbackShaders[i]->Stage = prog->Shaders[i]->Stage;
+ prog->FallbackShaders[i]->Source =
+ ralloc_strdup(prog->FallbackShaders, prog->Shaders[i]->Source);
+ prog->FallbackShaders[i]->InfoLog =
+ ralloc_strdup(prog->FallbackShaders, "");
+ }
+
for (unsigned i = 0; i < prog->NumShaders; i++) {
if (prog->Shaders[i]->Stage == MESA_SHADER_COMPUTE) {
compile_shaders(ctx, prog);
diff --git a/src/mesa/drivers/dri/i965/brw_shader_cache.c b/src/mesa/drivers/dri/i965/brw_shader_cache.c
index c4ef567..7d0e8a0 100644
--- a/src/mesa/drivers/dri/i965/brw_shader_cache.c
+++ b/src/mesa/drivers/dri/i965/brw_shader_cache.c
@@ -118,12 +118,19 @@ fallback_to_full_recompile(struct brw_context *brw,
if (fp)
fp->cache_fallback = true;
- for (unsigned i = 0; i < shProg->NumShaders; i++) {
- _mesa_glsl_compile_shader(&brw->ctx, shProg->Shaders[i], false,
- false, true);
+ for (unsigned i = 0; i < shProg->NumFallbackShaders; i++) {
+ _mesa_glsl_compile_shader(&brw->ctx, shProg->FallbackShaders[i],
+ false, false, true);
}
_mesa_glsl_link_shader(&brw->ctx, shProg, true);
+ /* We should never get here again so free the shaders */
+ shProg->NumFallbackShaders = 0;
+ for (unsigned i = 0; i < shProg->NumFallbackShaders; i++) {
+ ralloc_free(shProg->FallbackShaders);
+ shProg->FallbackShaders = NULL;
+ }
+
vp->cache_fallback = false;
if (tcp)
tcp->cache_fallback = true;
@@ -144,12 +151,19 @@ fallback_to_full_recompile(struct brw_context *brw,
fp->cache_fallback = true;
- for (unsigned i = 0; i < shProg->NumShaders; i++) {
- _mesa_glsl_compile_shader(&brw->ctx, shProg->Shaders[i], false,
- false, true);
+ for (unsigned i = 0; i < shProg->NumFallbackShaders; i++) {
+ _mesa_glsl_compile_shader(&brw->ctx, shProg->FallbackShaders[i],
+ false, false, true);
}
_mesa_glsl_link_shader(&brw->ctx, shProg, true);
+ /* We should never get here again so free the shaders */
+ shProg->NumFallbackShaders = 0;
+ for (unsigned i = 0; i < shProg->NumFallbackShaders; i++) {
+ ralloc_free(shProg->FallbackShaders);
+ shProg->FallbackShaders = NULL;
+ }
+
fp->cache_fallback = false;
}
}
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 94c6fc4..0b2e5ec 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2734,6 +2734,9 @@ struct gl_shader_program
GLuint NumShaders; /**< number of attached shaders */
struct gl_shader **Shaders; /**< List of attached the shaders */
+ GLuint NumFallbackShaders;
+ struct gl_shader **FallbackShaders; /**< Shaders used for cache fallback */
+
/**
* User-defined attribute bindings
*
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 7f94c1c..005756a 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -377,10 +377,16 @@ _mesa_free_shader_program_data(struct gl_context *ctx,
_mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
}
shProg->NumShaders = 0;
+ shProg->NumFallbackShaders = 0;
free(shProg->Shaders);
shProg->Shaders = NULL;
+ if (shProg->FallbackShaders){
+ ralloc_free(shProg->FallbackShaders);
+ shProg->FallbackShaders = NULL;
+ }
+
/* Transform feedback varying vars */
for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
free(shProg->TransformFeedback.VaryingNames[i]);
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 210cecc..7ff7323 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -3060,9 +3060,11 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog,
prog->LinkStatus = GL_TRUE;
- for (i = 0; i < prog->NumShaders; i++) {
- if (!prog->Shaders[i]->CompileStatus) {
- linker_error(prog, "linking with uncompiled shader");
+ if (!is_cache_fallback) {
+ for (i = 0; i < prog->NumShaders; i++) {
+ if (!prog->Shaders[i]->CompileStatus) {
+ linker_error(prog, "linking with uncompiled shader");
+ }
}
}
@@ -3096,8 +3098,14 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog,
}
#ifdef ENABLE_SHADER_CACHE
- if (prog->LinkStatus)
+ if (prog->LinkStatus && !is_cache_fallback) {
+ if (prog->FallbackShaders) {
+ prog->NumFallbackShaders = 0;
+ ralloc_free(prog->FallbackShaders);
+ prog->FallbackShaders = NULL;
+ }
shader_cache_write_program_metadata(ctx, prog);
+ }
#endif
}
--
2.7.4
More information about the mesa-dev
mailing list