diff options
author | Marek Olšák <[email protected]> | 2013-05-13 15:46:49 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2013-05-28 13:05:30 +0200 |
commit | d4a06d77f5898726e2453ef32795a2183c033c05 (patch) | |
tree | b72e6a5743f0f7abd7d63d30151759970f67246d /src/mesa/main | |
parent | b4cb857dbfeb89d56ac0eb67ba1d7d5f65e336d4 (diff) |
mesa: fix GLSL program objects with more than 16 samplers combined
The problem is the sampler units are allocated from the same pool for all
shader stages, so if a vertex shader uses 12 samplers (0..11), the fragment
shader samplers start at index 12, leaving only 4 sampler units
for the fragment shader. The main cause is probably the fact that samplers
(texture unit -> sampler unit mapping, etc.) are tracked globally
for an entire program object.
This commit adapts the GLSL linker and core Mesa such that the sampler units
are assigned to sampler uniforms for each shader stage separately
(if a sampler uniform is used in all shader stages, it may occupy a different
sampler unit in each, and vice versa, an i-th sampler unit may refer to
a different sampler uniform in each shader stage), and the sampler-specific
variables are moved from gl_shader_program to gl_shader.
This doesn't require any driver changes, and it fixes piglit/max-samplers
for gallium and classic swrast. It also works with any number of shader
stages.
v2: - converted tabs to spaces
- added an assertion to _mesa_get_sampler_uniform_value
Reviewed-by: Ian Romanick <[email protected]>
Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src/mesa/main')
-rw-r--r-- | src/mesa/main/mtypes.h | 22 | ||||
-rw-r--r-- | src/mesa/main/uniform_query.cpp | 24 | ||||
-rw-r--r-- | src/mesa/main/uniforms.c | 11 |
3 files changed, 31 insertions, 26 deletions
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 40ffb929617..e0e188606c5 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2132,6 +2132,17 @@ struct gl_shader /*@}*/ /** + * Map from sampler unit to texture unit (set by glUniform1i()) + * + * A sampler unit is associated with each sampler uniform by the linker. + * The sampler unit associated with each uniform is stored in the + * \c gl_uniform_storage::sampler field. + */ + GLubyte SamplerUnits[MAX_SAMPLERS]; + /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */ + gl_texture_index SamplerTargets[MAX_SAMPLERS]; + + /** * Number of uniform components used by this shader. * * This field is only set post-linking. @@ -2335,17 +2346,6 @@ struct gl_shader_program */ struct string_to_uint_map *UniformHash; - /** - * Map from sampler unit to texture unit (set by glUniform1i()) - * - * A sampler unit is associated with each sampler uniform by the linker. - * The sampler unit associated with each uniform is stored in the - * \c gl_uniform_storage::sampler field. - */ - GLubyte SamplerUnits[MAX_SAMPLERS]; - /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */ - gl_texture_index SamplerTargets[MAX_SAMPLERS]; - GLboolean LinkStatus; /**< GL_LINK_STATUS */ GLboolean Validated; GLboolean _Used; /**< Ever used for drawing? */ diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index b7f25e031da..ec3104936e4 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -778,24 +778,24 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, if (uni->type->is_sampler()) { int i; - for (i = 0; i < count; i++) { - shProg->SamplerUnits[uni->sampler + offset + i] = - ((unsigned *) values)[i]; - } - bool flushed = false; for (i = 0; i < MESA_SHADER_TYPES; i++) { struct gl_shader *const sh = shProg->_LinkedShaders[i]; + int j; - /* If the shader stage doesn't use any samplers, don't bother - * checking if any samplers have changed. + /* If the shader stage doesn't use the sampler uniform, skip this. */ - if (sh == NULL || sh->active_samplers == 0) + if (sh == NULL || !uni->sampler[i].active) continue; + for (j = 0; j < count; j++) { + sh->SamplerUnits[uni->sampler[i].index + offset + j] = + ((unsigned *) values)[j]; + } + struct gl_program *const prog = sh->Program; - assert(sizeof(prog->SamplerUnits) == sizeof(shProg->SamplerUnits)); + assert(sizeof(prog->SamplerUnits) == sizeof(sh->SamplerUnits)); /* Determine if any of the samplers used by this shader stage have * been modified. @@ -803,7 +803,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 ((sh->active_samplers & (1U << j)) != 0 - && (prog->SamplerUnits[j] != shProg->SamplerUnits[j])) { + && (prog->SamplerUnits[j] != sh->SamplerUnits[j])) { changed = true; break; } @@ -816,8 +816,8 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, } memcpy(prog->SamplerUnits, - shProg->SamplerUnits, - sizeof(shProg->SamplerUnits)); + sh->SamplerUnits, + sizeof(sh->SamplerUnits)); _mesa_update_shader_textures_used(shProg, prog); if (ctx->Driver.SamplerUniformChange) diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index f0d80f0c812..6d79df6835f 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -45,6 +45,7 @@ #include "main/enums.h" #include "ir_uniform.h" #include "glsl_types.h" +#include "program/program.h" /** * Update the vertex/fragment program's TexturesUsed array. @@ -66,14 +67,18 @@ _mesa_update_shader_textures_used(struct gl_shader_program *shProg, struct gl_program *prog) { GLuint s; + struct gl_shader *shader = + shProg->_LinkedShaders[_mesa_program_target_to_index(prog->Target)]; - memcpy(prog->SamplerUnits, shProg->SamplerUnits, sizeof(prog->SamplerUnits)); + assert(shader); + + memcpy(prog->SamplerUnits, shader->SamplerUnits, sizeof(prog->SamplerUnits)); memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed)); for (s = 0; s < MAX_SAMPLERS; s++) { if (prog->SamplersUsed & (1 << s)) { - GLuint unit = shProg->SamplerUnits[s]; - GLuint tgt = shProg->SamplerTargets[s]; + GLuint unit = shader->SamplerUnits[s]; + GLuint tgt = shader->SamplerTargets[s]; assert(unit < Elements(prog->TexturesUsed)); assert(tgt < NUM_TEXTURE_TARGETS); prog->TexturesUsed[unit] |= (1 << tgt); |