mesa: validate sampler uniforms during gluniform calls
Patch fixes 'glsl-2types-of-textures-on-same-unit' in WebGL conformance test suite. No Piglit regressions, fixes gl-2.0-active-sampler-conflict. To avoid adding potentially heavy check during draw (valid_to_render), check is done during uniform updates by inspecting TexturesUsed mask. A new boolean variable is introduced to cache validation state. v2: take into account case where 2 uniforms use same unit (curro) also do the check only when SSO is not in use, SSO has own path for sampler validation. Signed-off-by: Tapani Pälli <tapani.palli@intel.com> Reviewed-by: Francisco Jerez <currojerez@riseup.net>
This commit is contained in:
parent
01d94193ac
commit
953a0af8e3
|
@ -133,6 +133,7 @@
|
|||
#include "program/prog_print.h"
|
||||
#include "math/m_matrix.h"
|
||||
#include "main/dispatch.h" /* for _gloffset_COUNT */
|
||||
#include "uniforms.h"
|
||||
|
||||
#ifdef USE_SPARC_ASM
|
||||
#include "sparc/sparc.h"
|
||||
|
@ -1949,6 +1950,17 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
|
|||
}
|
||||
}
|
||||
|
||||
/* If a program is active and SSO not in use, check if validation of
|
||||
* samplers succeeded for the active program. */
|
||||
if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) {
|
||||
char errMsg[100];
|
||||
if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram,
|
||||
errMsg, 100)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
|
||||
"%s(incomplete framebuffer)", where);
|
||||
|
|
|
@ -2884,6 +2884,7 @@ struct gl_shader_program
|
|||
GLboolean LinkStatus; /**< GL_LINK_STATUS */
|
||||
GLboolean Validated;
|
||||
GLboolean _Used; /**< Ever used for drawing? */
|
||||
GLboolean SamplersValidated; /**< Samplers validated against texture units? */
|
||||
GLchar *InfoLog;
|
||||
|
||||
unsigned Version; /**< GLSL version used for linking */
|
||||
|
|
|
@ -1064,42 +1064,16 @@ 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];
|
||||
/* Shader does not have samplers. */
|
||||
if (shProg->NumUserUniformStorage == 0)
|
||||
return true;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!shProg->SamplersValidated) {
|
||||
_mesa_snprintf(errMsg, errMsgLength,
|
||||
"active samplers with a different type "
|
||||
"refer to the same texture image unit");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,12 +75,26 @@ _mesa_update_shader_textures_used(struct gl_shader_program *shProg,
|
|||
memcpy(prog->SamplerUnits, shader->SamplerUnits, sizeof(prog->SamplerUnits));
|
||||
memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
|
||||
|
||||
shProg->SamplersValidated = GL_TRUE;
|
||||
|
||||
for (s = 0; s < MAX_SAMPLERS; s++) {
|
||||
if (prog->SamplersUsed & (1 << s)) {
|
||||
GLuint unit = shader->SamplerUnits[s];
|
||||
GLuint tgt = shader->SamplerTargets[s];
|
||||
assert(unit < Elements(prog->TexturesUsed));
|
||||
assert(tgt < NUM_TEXTURE_TARGETS);
|
||||
|
||||
/* 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 (prog->TexturesUsed[unit] & ~(1 << tgt))
|
||||
shProg->SamplersValidated = GL_FALSE;
|
||||
|
||||
prog->TexturesUsed[unit] |= (1 << tgt);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue