mesa/sso: Add _mesa_sampler_uniforms_pipeline_are_valid

This is much like _mesa_sampler_uniforms_are_valid, but it operates
across an entire pipeline object.

This function differs from _mesa_sampler_uniforms_are_valid in that it
directly creates the gl_pipeline_object::InfoLog instead of writing to
some temporary buffer.

This was originally included in another patch, but it was split out by
Ian Romanick.

v2 (idr): Fix the loop bounds.  shProg isn't an array, so
ARRAY_SIZE(shProg) was 1, so only the vertex program was validated.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
Gregory Hainaut
2013-06-28 19:26:27 -07:00
committed by Ian Romanick
parent aa46ad26b1
commit 95426b28ac
2 changed files with 79 additions and 0 deletions
+77
View File
@@ -1089,3 +1089,80 @@ _mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
return true;
}
extern "C" bool
_mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline)
{
/* Section 2.11.11 (Shader Execution), subheading "Validation," of the
* OpenGL 4.1 spec says:
*
* "[INVALID_OPERATION] is generated by any command that transfers
* vertices to the GL if:
*
* ...
*
* - Any two active samplers in the current program object are of
* different types, but refer to the same texture image unit.
*
* - The number of active samplers in the program exceeds the
* maximum number of texture image units allowed."
*/
unsigned active_samplers = 0;
const struct gl_shader_program **shProg =
(const struct gl_shader_program **) pipeline->CurrentProgram;
const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
memset(unit_types, 0, sizeof(unit_types));
for (unsigned idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
if (!shProg[idx])
continue;
for (unsigned i = 0; i < shProg[idx]->NumUserUniformStorage; i++) {
const struct gl_uniform_storage *const storage =
&shProg[idx]->UniformStorage[i];
const glsl_type *const t = (storage->type->is_array())
? storage->type->fields.array : storage->type;
if (!t->is_sampler())
continue;
active_samplers++;
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) {
pipeline->InfoLog =
ralloc_asprintf(pipeline,
"Texture unit %d is accessed both as %s "
"and %s",
unit, unit_types[unit]->name, t->name);
return false;
}
}
}
}
if (active_samplers > MAX_COMBINED_TEXTURE_IMAGE_UNITS) {
pipeline->InfoLog =
ralloc_asprintf(pipeline,
"the number of active samplers %d exceed the "
"maximum %d",
active_samplers, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
return false;
}
return true;
}
+2
View File
@@ -300,6 +300,8 @@ _mesa_update_shader_textures_used(struct gl_shader_program *shProg,
extern bool
_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
char *errMsg, size_t errMsgLength);
extern bool
_mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *);
extern const struct gl_program_parameter *
get_uniform_parameter(struct gl_shader_program *shProg, GLint index);