*/
bool initialized;
- /**
- * Base sampler index
- *
- * If \c ::base_type is \c GLSL_TYPE_SAMPLER, this represents the index of
- * this sampler. If \c ::array_elements is not zero, the array will use
- * sampler indexes \c ::sampler through \c ::sampler + \c ::array_elements
- * - 1, inclusive.
- */
- uint8_t sampler;
+ struct {
+ /**
+ * Base sampler index
+ *
+ * If \c ::base_type is \c GLSL_TYPE_SAMPLER, this represents the index
+ * of this sampler. If \c ::array_elements is not zero, the array will
+ * use sampler indices \c ::sampler through \c ::sampler +
+ * \c ::array_elements - 1, inclusive.
+ *
+ * Note that the index may be different in each shader stage.
+ */
+ uint8_t index;
+
+ /**
+ * Whether this sampler is used in this shader stage.
+ */
+ bool active;
+ } sampler[MESA_SHADER_TYPES];
/**
* Storage used by the driver for the uniform
}
if (base_type == GLSL_TYPE_SAMPLER) {
- for (unsigned int i = 0; i < storage->array_elements; i++) {
- prog->SamplerUnits[storage->sampler + i] = storage->storage[i].i;
+ for (int sh = 0; sh < MESA_SHADER_TYPES; sh++) {
+ gl_shader *shader = prog->_LinkedShaders[sh];
+
+ if (shader && storage->sampler[sh].active) {
+ for (unsigned i = 0; i < storage->array_elements; i++) {
+ unsigned index = storage->sampler[sh].index + i;
+
+ shader->SamplerUnits[index] = storage->storage[i].i;
+ }
+ }
}
}
} else {
val->type->base_type,
val->type->components());
- if (storage->type->is_sampler())
- prog->SamplerUnits[storage->sampler] = storage->storage[0].i;
+ if (storage->type->is_sampler()) {
+ for (int sh = 0; sh < MESA_SHADER_TYPES; sh++) {
+ gl_shader *shader = prog->_LinkedShaders[sh];
+
+ if (shader && storage->sampler[sh].active) {
+ unsigned index = storage->sampler[sh].index;
+
+ shader->SamplerUnits[index] = storage->storage[0].i;
+ }
+ }
+ }
}
storage->initialized = true;
parcel_out_uniform_storage(struct string_to_uint_map *map,
struct gl_uniform_storage *uniforms,
union gl_constant_value *values)
- : map(map), uniforms(uniforms), next_sampler(0), values(values)
+ : map(map), uniforms(uniforms), values(values)
{
- memset(this->targets, 0, sizeof(this->targets));
}
- void start_shader()
+ void start_shader(gl_shader_type shader_type)
{
+ assert(shader_type < MESA_SHADER_TYPES);
+ this->shader_type = shader_type;
+
this->shader_samplers_used = 0;
this->shader_shadow_samplers = 0;
+ this->next_sampler = 0;
+ memset(this->targets, 0, sizeof(this->targets));
}
void set_and_process(struct gl_shader_program *prog,
int ubo_block_index;
int ubo_byte_offset;
bool ubo_row_major;
+ gl_shader_type shader_type;
private:
+ void handle_samplers(const glsl_type *base_type,
+ struct gl_uniform_storage *uniform)
+ {
+ if (base_type->is_sampler()) {
+ uniform->sampler[shader_type].index = this->next_sampler;
+ uniform->sampler[shader_type].active = true;
+
+ /* Increment the sampler by 1 for non-arrays and by the number of
+ * array elements for arrays.
+ */
+ this->next_sampler +=
+ MAX2(1, uniform->array_elements);
+
+ const gl_texture_index target = base_type->sampler_index();
+ const unsigned shadow = base_type->sampler_shadow;
+ for (unsigned i = uniform->sampler[shader_type].index;
+ i < MIN2(this->next_sampler, MAX_SAMPLERS);
+ i++) {
+ this->targets[i] = target;
+ this->shader_samplers_used |= 1U << i;
+ this->shader_shadow_samplers |= shadow << i;
+ }
+ } else {
+ uniform->sampler[shader_type].index = ~0;
+ uniform->sampler[shader_type].active = false;
+ }
+ }
+
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major)
{
if (!found)
return;
- /* If there is already storage associated with this uniform, it means
- * that it was set while processing an earlier shader stage. For
- * example, we may be processing the uniform in the fragment shader, but
- * the uniform was already processed in the vertex shader.
- */
- if (this->uniforms[id].storage != NULL) {
- /* If the uniform already has storage set from another shader stage,
- * mark the samplers used for this shader stage.
- */
- if (type->contains_sampler()) {
- const unsigned count = MAX2(1, this->uniforms[id].array_elements);
- const unsigned shadow = (type->is_array())
- ? type->fields.array->sampler_shadow : type->sampler_shadow;
-
- for (unsigned i = 0; i < count; i++) {
- const unsigned s = this->uniforms[id].sampler + i;
-
- this->shader_samplers_used |= 1U << s;
- this->shader_shadow_samplers |= shadow << s;
- }
- }
-
- return;
- }
-
const glsl_type *base_type;
if (type->is_array()) {
this->uniforms[id].array_elements = type->length;
base_type = type;
}
- if (base_type->is_sampler()) {
- this->uniforms[id].sampler = this->next_sampler;
+ /* This assigns sampler uniforms to sampler units. */
+ handle_samplers(base_type, &this->uniforms[id]);
- /* Increment the sampler by 1 for non-arrays and by the number of
- * array elements for arrays.
- */
- this->next_sampler += MAX2(1, this->uniforms[id].array_elements);
-
- const gl_texture_index target = base_type->sampler_index();
- const unsigned shadow = base_type->sampler_shadow;
- for (unsigned i = this->uniforms[id].sampler
- ; i < MIN2(this->next_sampler, MAX_SAMPLERS)
- ; i++) {
- this->targets[i] = target;
- this->shader_samplers_used |= 1U << i;
- this->shader_shadow_samplers |= shadow << i;
- }
-
- } else {
- this->uniforms[id].sampler = ~0;
+ /* If there is already storage associated with this uniform, it means
+ * that it was set while processing an earlier shader stage. For
+ * example, we may be processing the uniform in the fragment shader, but
+ * the uniform was already processed in the vertex shader.
+ */
+ if (this->uniforms[id].storage != NULL) {
+ return;
}
this->uniforms[id].name = ralloc_strdup(this->uniforms, name);
prog->UniformHash = new string_to_uint_map;
}
- /* Uniforms that lack an initializer in the shader code have an initial
- * value of zero. This includes sampler uniforms.
- *
- * Page 24 (page 30 of the PDF) of the GLSL 1.20 spec says:
- *
- * "The link time initial value is either the value of the variable's
- * initializer, if present, or 0 if no initializer is present. Sampler
- * types cannot have initializers."
- */
- memset(prog->SamplerUnits, 0, sizeof(prog->SamplerUnits));
-
/* First pass: Count the uniform resources used by the user-defined
* uniforms. While this happens, each active uniform will have an index
* assigned to it.
if (prog->_LinkedShaders[i] == NULL)
continue;
+ /* Uniforms that lack an initializer in the shader code have an initial
+ * value of zero. This includes sampler uniforms.
+ *
+ * Page 24 (page 30 of the PDF) of the GLSL 1.20 spec says:
+ *
+ * "The link time initial value is either the value of the variable's
+ * initializer, if present, or 0 if no initializer is present. Sampler
+ * types cannot have initializers."
+ */
+ memset(prog->_LinkedShaders[i]->SamplerUnits, 0,
+ sizeof(gl_shader::SamplerUnits));
+
link_update_uniform_buffer_variables(prog->_LinkedShaders[i]);
/* Reset various per-shader target counts.
if (prog->_LinkedShaders[i] == NULL)
continue;
- /* Reset various per-shader target counts.
- */
- parcel.start_shader();
+ parcel.start_shader((gl_shader_type)i);
foreach_list(node, prog->_LinkedShaders[i]->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
prog->_LinkedShaders[i]->active_samplers = parcel.shader_samplers_used;
prog->_LinkedShaders[i]->shadow_samplers = parcel.shader_shadow_samplers;
- }
- assert(sizeof(prog->SamplerTargets) == sizeof(parcel.targets));
- memcpy(prog->SamplerTargets, parcel.targets, sizeof(prog->SamplerTargets));
+ assert(sizeof(gl_shader::SamplerTargets) == sizeof(parcel.targets));
+ memcpy(prog->_LinkedShaders[i]->SamplerTargets, parcel.targets,
+ sizeof(gl_shader::SamplerTargets));
+ }
#ifndef NDEBUG
for (unsigned i = 0; i < num_user_uniforms; i++) {
prog->UniformStorage[index_to_set].type = type;
prog->UniformStorage[index_to_set].array_elements = array_size;
prog->UniformStorage[index_to_set].initialized = false;
- prog->UniformStorage[index_to_set].sampler = ~0;
+ for (int sh = 0; sh < MESA_SHADER_TYPES; sh++) {
+ prog->UniformStorage[index_to_set].sampler[sh].index = ~0;
+ prog->UniformStorage[index_to_set].sampler[sh].active = false;
+ }
prog->UniformStorage[index_to_set].num_driver_storage = 0;
prog->UniformStorage[index_to_set].driver_storage = NULL;
prog->UniformStorage[index_to_set].storage =
prog->UniformStorage[i].type = glsl_type::void_type;
prog->UniformStorage[i].array_elements = 0;
prog->UniformStorage[i].initialized = false;
- prog->UniformStorage[i].sampler = ~0;
+ for (int sh = 0; sh < MESA_SHADER_TYPES; sh++) {
+ prog->UniformStorage[i].sampler[sh].index = ~0;
+ prog->UniformStorage[i].sampler[sh].active = false;
+ }
prog->UniformStorage[i].num_driver_storage = 0;
prog->UniformStorage[i].driver_storage = NULL;
prog->UniformStorage[i].storage = NULL;
GLbitfield shadow_samplers; /**< Samplers used for shadow sampling. */
/*@}*/
+ /**
+ * 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.
*
*/
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? */
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.
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;
}
}
memcpy(prog->SamplerUnits,
- shProg->SamplerUnits,
- sizeof(shProg->SamplerUnits));
+ sh->SamplerUnits,
+ sizeof(sh->SamplerUnits));
_mesa_update_shader_textures_used(shProg, prog);
if (ctx->Driver.SamplerUniformChange)
#include "main/enums.h"
#include "ir_uniform.h"
#include "glsl_types.h"
+#include "program/program.h"
/**
* Update the vertex/fragment program's TexturesUsed array.
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);
class add_uniform_to_shader : public program_resource_visitor {
public:
add_uniform_to_shader(struct gl_shader_program *shader_program,
- struct gl_program_parameter_list *params)
- : shader_program(shader_program), params(params), idx(-1)
+ struct gl_program_parameter_list *params,
+ gl_shader_type shader_type)
+ : shader_program(shader_program), params(params), idx(-1),
+ shader_type(shader_type)
{
/* empty */
}
struct gl_shader_program *shader_program;
struct gl_program_parameter_list *params;
int idx;
+ gl_shader_type shader_type;
};
void
struct gl_uniform_storage *storage =
&this->shader_program->UniformStorage[location];
+ assert(storage->sampler[shader_type].active);
+
for (unsigned int j = 0; j < size / 4; j++)
- params->ParameterValues[index + j][0].f = storage->sampler + j;
+ params->ParameterValues[index + j][0].f =
+ storage->sampler[shader_type].index + j;
}
}
struct gl_program_parameter_list
*params)
{
- add_uniform_to_shader add(shader_program, params);
+ add_uniform_to_shader add(shader_program, params,
+ _mesa_shader_type_to_index(sh->Type));
foreach_list(node, sh->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
#include "main/compiler.h"
#include "main/mtypes.h"
#include "program/prog_parameter.h"
+#include "program/program.h"
}
class get_sampler_name : public ir_hierarchical_visitor
ir_dereference *last;
};
-extern "C" {
-int
+
+extern "C" int
_mesa_get_sampler_uniform_value(class ir_dereference *sampler,
struct gl_shader_program *shader_program,
const struct gl_program *prog)
{
get_sampler_name getname(sampler, shader_program);
+ GLuint shader = _mesa_program_target_to_index(prog->Target);
+
sampler->accept(&getname);
unsigned location;
return 0;
}
- return shader_program->UniformStorage[location].sampler + getname.offset;
-}
+ if (!shader_program->UniformStorage[location].sampler[shader].active) {
+ assert(0 && "cannot return a sampler");
+ linker_error(shader_program,
+ "cannot return a sampler named %s, because it is not "
+ "used in this shader stage. This is a driver bug.\n",
+ getname.name);
+ return 0;
+ }
+
+ return shader_program->UniformStorage[location].sampler[shader].index +
+ getname.offset;
}