#include "glsl_symbol_table.h"
#include "program.h"
#include "util/string_to_uint_map.h"
-#include "ir_variable_refcount.h"
+#include "ir_array_refcount.h"
/**
* \file link_uniforms.cpp
/**
* Count the backing storage requirements for a type
*/
-static unsigned
+unsigned
values_for_type(const glsl_type *type)
{
if (type->is_sampler()) {
record_type = t->fields.array;
unsigned length = t->length;
+
/* Shader storage block unsized arrays: add subscript [0] to variable
- * names */
+ * names.
+ */
if (t->is_unsized_array())
length = 1;
buffer_block_index = -1;
if (var->is_in_buffer_block()) {
struct gl_uniform_block *blks = var->is_in_shader_storage_block() ?
- prog->ShaderStorageBlocks : prog->UniformBlocks;
+ prog->data->ShaderStorageBlocks : prog->data->UniformBlocks;
unsigned num_blks = var->is_in_shader_storage_block() ?
- prog->NumShaderStorageBlocks : prog->NumUniformBlocks;
+ prog->data->NumShaderStorageBlocks : prog->data->NumUniformBlocks;
if (var->is_interface_instance() && var->type->is_array()) {
unsigned l = strlen(var->get_interface_type()->name);
}
} else {
for (unsigned i = 0; i < num_blks; i++) {
- if (strcmp(var->get_interface_type()->name, blks[i].Name) ==
- 0) {
+ if (strcmp(var->get_interface_type()->name, blks[i].Name) == 0) {
buffer_block_index = i;
break;
}
const char *str_end;
while((str_start = strchr(name_copy, '[')) &&
(str_end = strchr(name_copy, ']'))) {
- memmove(str_start, str_end + 1, 1 + strlen(str_end));
+ memmove(str_start, str_end + 1, 1 + strlen(str_end + 1));
}
unsigned index = 0;
this->next_image += MAX2(1, uniform->array_elements);
for (unsigned i = first; i < MIN2(next_image, MAX_IMAGE_UNIFORMS); i++)
- prog->_LinkedShaders[shader_type]->ImageAccess[i] = access;
+ prog->_LinkedShaders[shader_type]->Program->sh.ImageAccess[i] = access;
}
}
uniform->opaque[shader_type].index = this->next_subroutine;
uniform->opaque[shader_type].active = true;
+ prog->_LinkedShaders[shader_type]->Program->sh.NumSubroutineUniforms++;
+
/* Increment the subroutine index by 1 for non-arrays and by the
* number of array elements for arrays.
*/
};
static bool
-variable_is_referenced(ir_variable_refcount_visitor &v, ir_variable *var)
+variable_is_referenced(ir_array_refcount_visitor &v, ir_variable *var)
{
- ir_variable_refcount_entry *const entry = v.get_variable_entry(var);
+ ir_array_refcount_entry *const entry = v.get_variable_entry(var);
- return entry->referenced_count > 0;
+ return entry->is_referenced;
}
link_update_uniform_buffer_variables(struct gl_linked_shader *shader,
unsigned stage)
{
- ir_variable_refcount_visitor v;
+ ir_array_refcount_visitor v;
v.run(shader->ir);
var->data.mode == ir_var_shader_storage);
unsigned num_blocks = var->data.mode == ir_var_uniform ?
- shader->NumUniformBlocks : shader->NumShaderStorageBlocks;
+ shader->Program->info.num_ubos : shader->Program->info.num_ssbos;
struct gl_uniform_block **blks = var->data.mode == ir_var_uniform ?
- shader->UniformBlocks : shader->ShaderStorageBlocks;
+ shader->Program->sh.UniformBlocks :
+ shader->Program->sh.ShaderStorageBlocks;
if (var->is_interface_instance()) {
- if (variable_is_referenced(v, var)) {
+ const ir_array_refcount_entry *const entry = v.get_variable_entry(var);
+
+ if (entry->is_referenced) {
/* Since this is an interface instance, the instance type will be
* same as the array-stripped variable type. If the variable type
* is an array, then the block names will be suffixed with [0]
* be an array of instances, and all elements of the array need
* to be marked as referenced.
*/
- if (strncmp(begin, var->get_interface_type()->name, len) == 0) {
+ if (strncmp(begin, var->get_interface_type()->name, len) == 0 &&
+ (!var->type->is_array() ||
+ entry->is_linearized_index_referenced(blks[i]->linearized_array_index))) {
blks[i]->stageref |= 1U << stage;
}
}
static void
link_setup_uniform_remap_tables(struct gl_context *ctx,
- struct gl_shader_program *prog,
- unsigned num_explicit_uniform_locs)
+ struct gl_shader_program *prog)
{
- unsigned total_entries = num_explicit_uniform_locs;
- unsigned empty_locs =
- prog->NumUniformRemapTable - num_explicit_uniform_locs;
+ unsigned total_entries = prog->NumExplicitUniformLocations;
+ unsigned empty_locs = prog->NumUniformRemapTable - total_entries;
/* Reserve all the explicit locations of the active uniforms. */
- for (unsigned i = 0; i < prog->NumUniformStorage; i++) {
- if (prog->UniformStorage[i].type->is_subroutine() ||
- prog->UniformStorage[i].is_shader_storage)
+ for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
+ if (prog->data->UniformStorage[i].type->is_subroutine() ||
+ prog->data->UniformStorage[i].is_shader_storage)
continue;
- if (prog->UniformStorage[i].remap_location != UNMAPPED_UNIFORM_LOC) {
+ if (prog->data->UniformStorage[i].remap_location !=
+ UNMAPPED_UNIFORM_LOC) {
/* How many new entries for this uniform? */
const unsigned entries =
- MAX2(1, prog->UniformStorage[i].array_elements);
+ MAX2(1, prog->data->UniformStorage[i].array_elements);
/* Set remap table entries point to correct gl_uniform_storage. */
for (unsigned j = 0; j < entries; j++) {
- unsigned element_loc = prog->UniformStorage[i].remap_location + j;
+ unsigned element_loc =
+ prog->data->UniformStorage[i].remap_location + j;
assert(prog->UniformRemapTable[element_loc] ==
INACTIVE_UNIFORM_EXPLICIT_LOCATION);
- prog->UniformRemapTable[element_loc] = &prog->UniformStorage[i];
+ prog->UniformRemapTable[element_loc] =
+ &prog->data->UniformStorage[i];
}
}
}
/* Reserve locations for rest of the uniforms. */
- for (unsigned i = 0; i < prog->NumUniformStorage; i++) {
+ for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
- if (prog->UniformStorage[i].type->is_subroutine() ||
- prog->UniformStorage[i].is_shader_storage)
+ if (prog->data->UniformStorage[i].type->is_subroutine() ||
+ prog->data->UniformStorage[i].is_shader_storage)
continue;
/* Built-in uniforms should not get any location. */
- if (prog->UniformStorage[i].builtin)
+ if (prog->data->UniformStorage[i].builtin)
continue;
/* Explicit ones have been set already. */
- if (prog->UniformStorage[i].remap_location != UNMAPPED_UNIFORM_LOC)
+ if (prog->data->UniformStorage[i].remap_location != UNMAPPED_UNIFORM_LOC)
continue;
/* how many new entries for this uniform? */
- const unsigned entries = MAX2(1, prog->UniformStorage[i].array_elements);
+ const unsigned entries =
+ MAX2(1, prog->data->UniformStorage[i].array_elements);
/* Find UniformRemapTable for empty blocks where we can fit this uniform. */
int chosen_location = -1;
if (empty_locs)
- chosen_location = find_empty_block(prog, &prog->UniformStorage[i]);
+ chosen_location = find_empty_block(prog, &prog->data->UniformStorage[i]);
/* Add new entries to the total amount of entries. */
total_entries += entries;
/* set pointers for this uniform */
for (unsigned j = 0; j < entries; j++)
prog->UniformRemapTable[chosen_location + j] =
- &prog->UniformStorage[i];
+ &prog->data->UniformStorage[i];
/* set the base location in remap table for the uniform */
- prog->UniformStorage[i].remap_location = chosen_location;
+ prog->data->UniformStorage[i].remap_location = chosen_location;
}
/* Verify that total amount of entries for explicit and implicit locations
}
/* Reserve all the explicit locations of the active subroutine uniforms. */
- for (unsigned i = 0; i < prog->NumUniformStorage; i++) {
- if (!prog->UniformStorage[i].type->is_subroutine())
+ for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
+ if (!prog->data->UniformStorage[i].type->is_subroutine())
continue;
- if (prog->UniformStorage[i].remap_location == UNMAPPED_UNIFORM_LOC)
+ if (prog->data->UniformStorage[i].remap_location == UNMAPPED_UNIFORM_LOC)
continue;
- for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
- struct gl_linked_shader *sh = prog->_LinkedShaders[j];
- if (!sh)
- continue;
+ /* How many new entries for this uniform? */
+ const unsigned entries =
+ MAX2(1, prog->data->UniformStorage[i].array_elements);
- if (!prog->UniformStorage[i].opaque[j].active)
- continue;
+ unsigned mask = prog->data->linked_stages;
+ while (mask) {
+ const int j = u_bit_scan(&mask);
+ struct gl_program *p = prog->_LinkedShaders[j]->Program;
- /* How many new entries for this uniform? */
- const unsigned entries =
- MAX2(1, prog->UniformStorage[i].array_elements);
+ if (!prog->data->UniformStorage[i].opaque[j].active)
+ continue;
/* Set remap table entries point to correct gl_uniform_storage. */
for (unsigned k = 0; k < entries; k++) {
- unsigned element_loc = prog->UniformStorage[i].remap_location + k;
- assert(sh->SubroutineUniformRemapTable[element_loc] ==
+ unsigned element_loc =
+ prog->data->UniformStorage[i].remap_location + k;
+ assert(p->sh.SubroutineUniformRemapTable[element_loc] ==
INACTIVE_UNIFORM_EXPLICIT_LOCATION);
- sh->SubroutineUniformRemapTable[element_loc] =
- &prog->UniformStorage[i];
+ p->sh.SubroutineUniformRemapTable[element_loc] =
+ &prog->data->UniformStorage[i];
}
}
}
/* reserve subroutine locations */
- for (unsigned i = 0; i < prog->NumUniformStorage; i++) {
-
- if (!prog->UniformStorage[i].type->is_subroutine())
+ for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
+ if (!prog->data->UniformStorage[i].type->is_subroutine())
continue;
- const unsigned entries = MAX2(1, prog->UniformStorage[i].array_elements);
- if (prog->UniformStorage[i].remap_location != UNMAPPED_UNIFORM_LOC)
+ if (prog->data->UniformStorage[i].remap_location !=
+ UNMAPPED_UNIFORM_LOC)
continue;
- for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
- struct gl_linked_shader *sh = prog->_LinkedShaders[j];
- if (!sh)
- continue;
- if (!prog->UniformStorage[i].opaque[j].active)
+ const unsigned entries =
+ MAX2(1, prog->data->UniformStorage[i].array_elements);
+
+ unsigned mask = prog->data->linked_stages;
+ while (mask) {
+ const int j = u_bit_scan(&mask);
+ struct gl_program *p = prog->_LinkedShaders[j]->Program;
+
+ if (!prog->data->UniformStorage[i].opaque[j].active)
continue;
- sh->SubroutineUniformRemapTable =
- reralloc(sh,
- sh->SubroutineUniformRemapTable,
+ p->sh.SubroutineUniformRemapTable =
+ reralloc(p,
+ p->sh.SubroutineUniformRemapTable,
gl_uniform_storage *,
- sh->NumSubroutineUniformRemapTable + entries);
+ p->sh.NumSubroutineUniformRemapTable + entries);
for (unsigned k = 0; k < entries; k++) {
- sh->SubroutineUniformRemapTable[sh->NumSubroutineUniformRemapTable + k] =
- &prog->UniformStorage[i];
+ p->sh.SubroutineUniformRemapTable[p->sh.NumSubroutineUniformRemapTable + k] =
+ &prog->data->UniformStorage[i];
}
- prog->UniformStorage[i].remap_location =
- sh->NumSubroutineUniformRemapTable;
- sh->NumSubroutineUniformRemapTable += entries;
+ prog->data->UniformStorage[i].remap_location =
+ p->sh.NumSubroutineUniformRemapTable;
+ p->sh.NumSubroutineUniformRemapTable += entries;
}
}
}
static void
link_assign_uniform_storage(struct gl_context *ctx,
struct gl_shader_program *prog,
- const unsigned num_data_slots,
- unsigned num_explicit_uniform_locs)
+ const unsigned num_data_slots)
{
/* On the outside chance that there were no uniforms, bail out.
*/
- if (prog->NumUniformStorage == 0)
+ if (prog->data->NumUniformStorage == 0)
return;
unsigned int boolean_true = ctx->Const.UniformBooleanTrue;
- prog->UniformStorage = rzalloc_array(prog, struct gl_uniform_storage,
- prog->NumUniformStorage);
- union gl_constant_value *data = rzalloc_array(prog->UniformStorage,
- union gl_constant_value,
- num_data_slots);
+ union gl_constant_value *data;
+ if (prog->data->UniformStorage == NULL) {
+ prog->data->UniformStorage = rzalloc_array(prog,
+ struct gl_uniform_storage,
+ prog->data->NumUniformStorage);
+ data = rzalloc_array(prog->data->UniformStorage,
+ union gl_constant_value, num_data_slots);
+ } else {
+ data = prog->data->UniformDataSlots;
+ }
+
#ifndef NDEBUG
union gl_constant_value *data_end = &data[num_data_slots];
#endif
parcel_out_uniform_storage parcel(prog, prog->UniformHash,
- prog->UniformStorage, data);
+ prog->data->UniformStorage, data);
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
parcel.set_and_process(var);
}
- prog->_LinkedShaders[i]->active_samplers = parcel.shader_samplers_used;
+ prog->_LinkedShaders[i]->Program->SamplersUsed =
+ parcel.shader_samplers_used;
prog->_LinkedShaders[i]->shadow_samplers = parcel.shader_shadow_samplers;
- STATIC_ASSERT(sizeof(prog->_LinkedShaders[i]->SamplerTargets) ==
+ STATIC_ASSERT(sizeof(prog->_LinkedShaders[i]->Program->sh.SamplerTargets) ==
sizeof(parcel.targets));
- memcpy(prog->_LinkedShaders[i]->SamplerTargets, parcel.targets,
- sizeof(prog->_LinkedShaders[i]->SamplerTargets));
+ memcpy(prog->_LinkedShaders[i]->Program->sh.SamplerTargets,
+ parcel.targets,
+ sizeof(prog->_LinkedShaders[i]->Program->sh.SamplerTargets));
}
+ /* If this is a fallback compile for a cache miss we already have the
+ * correct uniform mappings and we don't want to reinitialise uniforms so
+ * just return now.
+ */
+ if (prog->data->cache_fallback)
+ return;
+
#ifndef NDEBUG
- for (unsigned i = 0; i < prog->NumUniformStorage; i++) {
- assert(prog->UniformStorage[i].storage != NULL ||
- prog->UniformStorage[i].builtin ||
- prog->UniformStorage[i].is_shader_storage ||
- prog->UniformStorage[i].block_index != -1);
+ for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
+ assert(prog->data->UniformStorage[i].storage != NULL ||
+ prog->data->UniformStorage[i].builtin ||
+ prog->data->UniformStorage[i].is_shader_storage ||
+ prog->data->UniformStorage[i].block_index != -1);
}
assert(parcel.values == data_end);
#endif
- link_setup_uniform_remap_tables(ctx, prog, num_explicit_uniform_locs);
+ link_setup_uniform_remap_tables(ctx, prog);
+
+ /* Set shader cache fields */
+ prog->data->NumUniformDataSlots = num_data_slots;
+ prog->data->UniformDataSlots = data;
link_set_uniform_initializers(prog, boolean_true);
}
void
link_assign_uniform_locations(struct gl_shader_program *prog,
- struct gl_context *ctx,
- unsigned int num_explicit_uniform_locs)
+ struct gl_context *ctx)
{
- ralloc_free(prog->UniformStorage);
- prog->UniformStorage = NULL;
- prog->NumUniformStorage = 0;
+ if (!prog->data->cache_fallback) {
+ ralloc_free(prog->data->UniformStorage);
+ prog->data->UniformStorage = NULL;
+ prog->data->NumUniformStorage = 0;
+ }
if (prog->UniformHash != NULL) {
prog->UniformHash->clear();
if (sh == 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(sh->SamplerUnits, 0, sizeof(sh->SamplerUnits));
- memset(sh->ImageUnits, 0, sizeof(sh->ImageUnits));
-
link_update_uniform_buffer_variables(sh, i);
/* Reset various per-shader target counts.
uniform_size.process(var);
}
- sh->num_samplers = uniform_size.num_shader_samplers;
- sh->NumImages = uniform_size.num_shader_images;
+ sh->Program->info.num_textures = uniform_size.num_shader_samplers;
+ sh->Program->info.num_images = 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++) {
+ for (unsigned i = 0; i < sh->Program->info.num_ubos; i++) {
sh->num_combined_uniform_components +=
- sh->UniformBlocks[i]->UniformBufferSize / 4;
+ sh->Program->sh.UniformBlocks[i]->UniformBufferSize / 4;
}
}
- prog->NumUniformStorage = uniform_size.num_active_uniforms;
- prog->NumHiddenUniforms = uniform_size.num_hidden_uniforms;
+ prog->data->NumUniformStorage = uniform_size.num_active_uniforms;
+ prog->data->NumHiddenUniforms = uniform_size.num_hidden_uniforms;
/* assign hidden uniforms a slot id */
hiddenUniforms->iterate(assign_hidden_uniform_slot_id, &uniform_size);
delete hiddenUniforms;
- link_assign_uniform_storage(ctx, prog, uniform_size.num_values,
- num_explicit_uniform_locs);
+ link_assign_uniform_storage(ctx, prog, uniform_size.num_values);
}