summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2011-11-14 12:11:46 -0800
committerIan Romanick <[email protected]>2012-01-11 12:51:24 -0800
commit195ee502c3196607e3a74075aefade9770a08a67 (patch)
treef1471a5acefee33601908b051791e02418a5ddf7 /src
parentb527dd65c830a2b008816cf390d5be906e29bb23 (diff)
mesa: Validate sampler settings using uniform storage
Rather than looking at the settings in individual assembly programs, look at the settings in the top-level uniform values. The old code was flawed because examining each shader stage in isolation could allow inconsitent usage across stages (e.g., bind unit 0 to a sampler2D in the vertex shader and sampler1DShadow in the fragment shader). Signed-off-by: Ian Romanick <[email protected]> Reviewed-by: Eric Anholt <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/mesa/main/shaderapi.c64
-rw-r--r--src/mesa/main/uniform_query.cpp43
-rw-r--r--src/mesa/main/uniforms.h3
3 files changed, 48 insertions, 62 deletions
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index f3f13a02645..5bfe217ae86 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -927,62 +927,6 @@ _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
ctx->Driver.UseProgram(ctx, shProg);
}
-
-/**
- * Validate a program's samplers.
- * Specifically, check that there aren't two samplers of different types
- * pointing to the same texture unit.
- * \return GL_TRUE if valid, GL_FALSE if invalid
- */
-static GLboolean
-validate_samplers(const struct gl_program *prog, char *errMsg)
-{
- static const char *targetName[] = {
- "TEXTURE_BUFFER",
- "TEXTURE_2D_ARRAY",
- "TEXTURE_1D_ARRAY",
- "TEXTURE_EXTERNAL",
- "TEXTURE_CUBE",
- "TEXTURE_3D",
- "TEXTURE_RECT",
- "TEXTURE_2D",
- "TEXTURE_1D",
- };
- GLint targetUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
- GLbitfield samplersUsed = prog->SamplersUsed;
- GLuint i;
-
- STATIC_ASSERT(Elements(targetName) == NUM_TEXTURE_TARGETS);
-
- if (samplersUsed == 0x0)
- return GL_TRUE;
-
- for (i = 0; i < Elements(targetUsed); i++)
- targetUsed[i] = -1;
-
- /* walk over bits which are set in 'samplers' */
- while (samplersUsed) {
- GLuint unit;
- gl_texture_index target;
- GLint sampler = _mesa_ffs(samplersUsed) - 1;
- assert(sampler >= 0);
- assert(sampler < Elements(prog->SamplerUnits));
- unit = prog->SamplerUnits[sampler];
- target = prog->SamplerTargets[sampler];
- if (targetUsed[unit] != -1 && targetUsed[unit] != (int) target) {
- _mesa_snprintf(errMsg, 100,
- "Texture unit %d is accessed both as %s and %s",
- unit, targetName[targetUsed[unit]], targetName[target]);
- return GL_FALSE;
- }
- targetUsed[unit] = target;
- samplersUsed ^= (1 << sampler);
- }
-
- return GL_TRUE;
-}
-
-
/**
* Do validation of the given shader program.
* \param errMsg returns error message if validation fails.
@@ -1018,12 +962,8 @@ validate_shader_program(const struct gl_shader_program *shProg,
* Check: any two active samplers in the current program object are of
* different types, but refer to the same texture image unit,
*/
- for (i = 0; i < Elements(shProg->_LinkedShaders); i++) {
- if (shProg->_LinkedShaders[i]
- && !validate_samplers(shProg->_LinkedShaders[i]->Program, errMsg)) {
- return GL_FALSE;
- }
- }
+ if (!_mesa_sampler_uniforms_are_valid(shProg, errMsg, 100))
+ return GL_FALSE;
return GL_TRUE;
}
diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
index f3d6a16eef9..a5a85cd9c13 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -933,3 +933,46 @@ _mesa_get_uniform_location(struct gl_context *ctx,
return _mesa_uniform_merge_location_offset(location, offset);
}
+
+extern "C" bool
+_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
+ char *errMsg, size_t errMsgLength)
+{
+ const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
+
+ memset(unit_types, 0, sizeof(unit_types));
+
+ for (unsigned i = 0; i < shProg->NumUserUniformStorage; i++) {
+ const struct gl_uniform_storage *const storage =
+ &shProg->UniformStorage[i];
+ const glsl_type *const t = (storage->type->is_array())
+ ? storage->type->fields.array : storage->type;
+
+ if (!t->is_sampler())
+ continue;
+
+ const unsigned count = MAX2(1, storage->type->array_size());
+ for (unsigned j = 0; j < count; j++) {
+ const unsigned unit = storage->storage[j].i;
+
+ /* The types of the samplers associated with a particular texture
+ * unit must be an exact match. Page 74 (page 89 of the PDF) of the
+ * OpenGL 3.3 core spec says:
+ *
+ * "It is not allowed to have variables of different sampler
+ * types pointing to the same texture image unit within a program
+ * object."
+ */
+ if (unit_types[unit] == NULL) {
+ unit_types[unit] = t;
+ } else if (unit_types[unit] != t) {
+ _mesa_snprintf(errMsg, errMsgLength,
+ "Texture unit %d is accessed both as %s and %s",
+ unit, unit_types[unit]->name, t->name);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index 123d7b95423..f796f82766e 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -214,6 +214,9 @@ _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
extern void
_mesa_update_shader_textures_used(struct gl_program *prog);
+extern bool
+_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
+ char *errMsg, size_t errMsgLength);
extern void
_mesa_init_shader_uniform_dispatch(struct _glapi_table *exec);