diff options
Diffstat (limited to 'mesalib/src/mesa/main/uniform_query.cpp')
-rw-r--r-- | mesalib/src/mesa/main/uniform_query.cpp | 58 |
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; +} |