aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main/uniform_query.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main/uniform_query.cpp')
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp58
1 files changed, 49 insertions, 9 deletions
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index f3d6a16ee..869f7d373 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -691,19 +691,16 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
bool flushed = false;
for (i = 0; i < MESA_SHADER_TYPES; i++) {
- struct gl_program *prog;
-
- if (shProg->_LinkedShaders[i] == NULL)
- continue;
-
- prog = shProg->_LinkedShaders[i]->Program;
+ struct gl_shader *const sh = shProg->_LinkedShaders[i];
/* If the shader stage doesn't use any samplers, don't bother
* checking if any samplers have changed.
*/
- if (prog->SamplersUsed == 0)
+ if (sh == NULL || sh->active_samplers == 0)
continue;
+ struct gl_program *const prog = sh->Program;
+
assert(sizeof(prog->SamplerUnits) == sizeof(shProg->SamplerUnits));
/* Determine if any of the samplers used by this shader stage have
@@ -711,7 +708,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
*/
bool changed = false;
for (unsigned j = 0; j < Elements(prog->SamplerUnits); j++) {
- if ((prog->SamplersUsed & (1U << j)) != 0
+ if ((sh->active_samplers & (1U << j)) != 0
&& (prog->SamplerUnits[j] != shProg->SamplerUnits[j])) {
changed = true;
break;
@@ -728,7 +725,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
shProg->SamplerUnits,
sizeof(shProg->SamplerUnits));
- _mesa_update_shader_textures_used(prog);
+ _mesa_update_shader_textures_used(shProg, prog);
(void) ctx->Driver.ProgramStringNotify(ctx, prog->Target, prog);
}
}
@@ -933,3 +930,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;
+}