From 953a0af8e3f73ce0a42a5dc2bf25355453d7a7b0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tapani=20P=C3=A4lli?= Date: Tue, 14 Oct 2014 12:39:54 +0300 Subject: [PATCH] mesa: validate sampler uniforms during gluniform calls MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Francisco Jerez --- src/mesa/main/context.c | 12 +++++++++ src/mesa/main/mtypes.h | 1 + src/mesa/main/uniform_query.cpp | 44 +++++++-------------------------- src/mesa/main/uniforms.c | 14 +++++++++++ 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 5a8f7184ad9..25b9bfc4cf6 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -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); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 9f44edac63b..051a85f6a00 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -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 */ diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index 1592c9bfd24..c2776c087a5 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -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]; - - 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; - } - } + /* Shader does not have samplers. */ + if (shProg->NumUserUniformStorage == 0) + return true; + + if (!shProg->SamplersValidated) { + _mesa_snprintf(errMsg, errMsgLength, + "active samplers with a different type " + "refer to the same texture image unit"); + return false; } - return true; } diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index 0d0cbf57eb7..598b4d4538f 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -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); } } -- 2.30.2