*
* As uniforms are added to the active set the number of active uniforms and
* the storage requirements for those uniforms are accumulated. The active
- * uniforms are added the the hash table supplied to the constructor.
+ * uniforms are added to the hash table supplied to the constructor.
*
* If the same uniform is added multiple times (i.e., once for each shader
* target), it will only be accounted once.
count_uniform_size(struct string_to_uint_map *map)
: num_active_uniforms(0), num_values(0), num_shader_samplers(0),
num_shader_images(0), num_shader_uniform_components(0),
+ num_shader_subroutines(0),
is_ubo_var(false), map(map)
{
/* empty */
this->num_shader_samplers = 0;
this->num_shader_images = 0;
this->num_shader_uniform_components = 0;
+ this->num_shader_subroutines = 0;
}
void process(ir_variable *var)
{
- this->is_ubo_var = var->is_in_uniform_block();
+ this->is_ubo_var = var->is_in_buffer_block();
if (var->is_interface_instance())
program_resource_visitor::process(var->get_interface_type(),
var->get_interface_type()->name);
*/
unsigned num_shader_uniform_components;
+ /**
+ * Number of subroutine uniforms used
+ */
+ unsigned num_shader_subroutines;
+
bool is_ubo_var;
private:
* count it for each shader target.
*/
const unsigned values = values_for_type(type);
- if (type->contains_sampler()) {
+ if (type->contains_subroutine()) {
+ this->num_shader_subroutines += values;
+ } else if (type->contains_sampler()) {
this->num_shader_samplers += values;
} else if (type->contains_image()) {
this->num_shader_images += values;
this->shader_shadow_samplers = 0;
this->next_sampler = 0;
this->next_image = 0;
+ this->next_subroutine = 0;
memset(this->targets, 0, sizeof(this->targets));
}
field_counter = 0;
ubo_block_index = -1;
- if (var->is_in_uniform_block()) {
+ if (var->is_in_buffer_block()) {
if (var->is_interface_instance() && var->type->is_array()) {
unsigned l = strlen(var->get_interface_type()->name);
}
}
+ void handle_subroutines(const glsl_type *base_type,
+ struct gl_uniform_storage *uniform)
+ {
+ if (base_type->is_subroutine()) {
+ uniform->subroutine[shader_type].index = this->next_subroutine;
+ uniform->subroutine[shader_type].active = true;
+
+ /* Increment the subroutine index by 1 for non-arrays and by the
+ * number of array elements for arrays.
+ */
+ this->next_subroutine += MAX2(1, uniform->array_elements);
+
+ } else {
+ uniform->subroutine[shader_type].index = ~0;
+ uniform->subroutine[shader_type].active = false;
+ }
+ }
+
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major)
{
assert(!"Should not get here.");
}
- virtual void enter_record(const glsl_type *type, const char *name,
+ virtual void enter_record(const glsl_type *type, const char *,
bool row_major) {
+ assert(type->is_record());
+ if (this->ubo_block_index == -1)
+ return;
this->ubo_byte_offset = glsl_align(
this->ubo_byte_offset, type->std140_base_alignment(row_major));
}
- virtual void leave_record(const glsl_type *type, const char *name,
+ virtual void leave_record(const glsl_type *type, const char *,
bool row_major) {
+ assert(type->is_record());
+ if (this->ubo_block_index == -1)
+ return;
this->ubo_byte_offset = glsl_align(
this->ubo_byte_offset, type->std140_base_alignment(row_major));
}
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major, const glsl_type *record_type,
- bool last_field)
+ bool /* last_field */)
{
assert(!type->without_array()->is_record());
assert(!type->without_array()->is_interface());
/* This assigns uniform indices to sampler and image uniforms. */
handle_samplers(base_type, &this->uniforms[id]);
handle_images(base_type, &this->uniforms[id]);
+ handle_subroutines(base_type, &this->uniforms[id]);
- /* 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 there is already storage associated with this uniform or if the
+ * uniform is set as builtin, 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 (this->uniforms[id].storage != NULL || this->uniforms[id].builtin) {
return;
}
this->uniforms[id].initialized = 0;
this->uniforms[id].num_driver_storage = 0;
this->uniforms[id].driver_storage = NULL;
- this->uniforms[id].storage = this->values;
this->uniforms[id].atomic_buffer_index = -1;
this->uniforms[id].hidden =
current_var->data.how_declared == ir_var_hidden;
+ this->uniforms[id].builtin = is_gl_identifier(name);
+
+ /* Do not assign storage if the uniform is builtin */
+ if (!this->uniforms[id].builtin)
+ this->uniforms[id].storage = this->values;
+
if (this->ubo_block_index != -1) {
this->uniforms[id].block_index = this->ubo_block_index;
struct gl_uniform_storage *uniforms;
unsigned next_sampler;
unsigned next_image;
+ unsigned next_subroutine;
public:
union gl_constant_value *values;
foreach_in_list(ir_instruction, node, shader->ir) {
ir_variable *const var = node->as_variable();
- if ((var == NULL) || !var->is_in_uniform_block())
+ if ((var == NULL) || !var->is_in_buffer_block())
continue;
- assert(var->data.mode == ir_var_uniform);
+ assert(var->data.mode == ir_var_uniform ||
+ var->data.mode == ir_var_shader_storage);
if (var->is_interface_instance()) {
var->data.location = 0;
{
ralloc_free(prog->UniformStorage);
prog->UniformStorage = NULL;
- prog->NumUserUniformStorage = 0;
+ prog->NumUniformStorage = 0;
if (prog->UniformHash != NULL) {
prog->UniformHash->clear();
foreach_in_list(ir_instruction, node, sh->ir) {
ir_variable *const var = node->as_variable();
- if ((var == NULL) || (var->data.mode != ir_var_uniform))
+ if ((var == NULL) || (var->data.mode != ir_var_uniform &&
+ var->data.mode != ir_var_shader_storage))
continue;
- /* FINISHME: Update code to process built-in uniforms!
- */
- if (is_gl_identifier(var->name)) {
- uniform_size.num_shader_uniform_components +=
- var->type->component_slots();
- continue;
- }
-
uniform_size.process(var);
}
sh->num_samplers = uniform_size.num_shader_samplers;
sh->NumImages = uniform_size.num_shader_images;
sh->num_uniform_components = uniform_size.num_shader_uniform_components;
-
sh->num_combined_uniform_components = sh->num_uniform_components;
+
for (unsigned i = 0; i < sh->NumUniformBlocks; i++) {
sh->num_combined_uniform_components +=
sh->UniformBlocks[i].UniformBufferSize / 4;
}
}
- const unsigned num_user_uniforms = uniform_size.num_active_uniforms;
+ const unsigned num_uniforms = uniform_size.num_active_uniforms;
const unsigned num_data_slots = uniform_size.num_values;
/* On the outside chance that there were no uniforms, bail out.
*/
- if (num_user_uniforms == 0)
+ if (num_uniforms == 0)
return;
struct gl_uniform_storage *uniforms =
- rzalloc_array(prog, struct gl_uniform_storage, num_user_uniforms);
+ rzalloc_array(prog, struct gl_uniform_storage, num_uniforms);
union gl_constant_value *data =
rzalloc_array(uniforms, union gl_constant_value, num_data_slots);
#ifndef NDEBUG
foreach_in_list(ir_instruction, node, prog->_LinkedShaders[i]->ir) {
ir_variable *const var = node->as_variable();
- if ((var == NULL) || (var->data.mode != ir_var_uniform))
- continue;
-
- /* FINISHME: Update code to process built-in uniforms!
- */
- if (is_gl_identifier(var->name))
+ if ((var == NULL) || (var->data.mode != ir_var_uniform && var->data.mode != ir_var_shader_storage))
continue;
parcel.set_and_process(prog, var);
}
const unsigned hidden_uniforms =
- move_hidden_uniforms_to_end(prog, uniforms, num_user_uniforms);
+ move_hidden_uniforms_to_end(prog, uniforms, num_uniforms);
/* Reserve all the explicit locations of the active uniforms. */
- for (unsigned i = 0; i < num_user_uniforms; i++) {
+ for (unsigned i = 0; i < num_uniforms; i++) {
+ if (uniforms[i].type->is_subroutine())
+ continue;
+
if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC) {
/* How many new entries for this uniform? */
const unsigned entries = MAX2(1, uniforms[i].array_elements);
}
/* Reserve locations for rest of the uniforms. */
- for (unsigned i = 0; i < num_user_uniforms; i++) {
+ for (unsigned i = 0; i < num_uniforms; i++) {
+
+ if (uniforms[i].type->is_subroutine())
+ continue;
+ /* Built-in uniforms should not get any location. */
+ if (uniforms[i].builtin)
+ continue;
/* Explicit ones have been set already. */
if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC)
prog->NumUniformRemapTable += entries;
}
+ /* Reserve all the explicit locations of the active subroutine uniforms. */
+ for (unsigned i = 0; i < num_uniforms; i++) {
+ if (!uniforms[i].type->is_subroutine())
+ continue;
+
+ if (uniforms[i].remap_location == UNMAPPED_UNIFORM_LOC)
+ continue;
+
+ for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+ struct gl_shader *sh = prog->_LinkedShaders[j];
+ if (!sh)
+ continue;
+
+ if (!uniforms[i].subroutine[j].active)
+ continue;
+
+ /* How many new entries for this uniform? */
+ const unsigned entries = MAX2(1, uniforms[i].array_elements);
+
+ /* Set remap table entries point to correct gl_uniform_storage. */
+ for (unsigned k = 0; k < entries; k++) {
+ unsigned element_loc = uniforms[i].remap_location + k;
+ assert(sh->SubroutineUniformRemapTable[element_loc] ==
+ INACTIVE_UNIFORM_EXPLICIT_LOCATION);
+ sh->SubroutineUniformRemapTable[element_loc] = &uniforms[i];
+ }
+ }
+ }
+
+ /* reserve subroutine locations */
+ for (unsigned i = 0; i < num_uniforms; i++) {
+
+ if (!uniforms[i].type->is_subroutine())
+ continue;
+ const unsigned entries = MAX2(1, uniforms[i].array_elements);
+
+ if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC)
+ continue;
+ for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+ struct gl_shader *sh = prog->_LinkedShaders[j];
+ if (!sh)
+ continue;
+
+ if (!uniforms[i].subroutine[j].active)
+ continue;
+
+ sh->SubroutineUniformRemapTable =
+ reralloc(sh,
+ sh->SubroutineUniformRemapTable,
+ gl_uniform_storage *,
+ sh->NumSubroutineUniformRemapTable + entries);
+
+ for (unsigned k = 0; k < entries; k++)
+ sh->SubroutineUniformRemapTable[sh->NumSubroutineUniformRemapTable + k] = &uniforms[i];
+ uniforms[i].remap_location = sh->NumSubroutineUniformRemapTable;
+ sh->NumSubroutineUniformRemapTable += entries;
+ }
+ }
+
#ifndef NDEBUG
- for (unsigned i = 0; i < num_user_uniforms; i++) {
- assert(uniforms[i].storage != NULL);
+ for (unsigned i = 0; i < num_uniforms; i++) {
+ assert(uniforms[i].storage != NULL || uniforms[i].builtin);
}
assert(parcel.values == data_end);
#endif
- prog->NumUserUniformStorage = num_user_uniforms;
+ prog->NumUniformStorage = num_uniforms;
prog->NumHiddenUniforms = hidden_uniforms;
prog->UniformStorage = uniforms;