diff --git a/src/compiler/glsl/link_atomics.cpp b/src/compiler/glsl/link_atomics.cpp deleted file mode 100644 index 1db03ece53b..00000000000 --- a/src/compiler/glsl/link_atomics.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright © 2013 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "glsl_parser_extras.h" -#include "ir.h" -#include "ir_uniform.h" -#include "linker.h" -#include "main/errors.h" -#include "main/macros.h" -#include "main/consts_exts.h" -#include "main/shader_types.h" - -namespace { - /* - * Atomic counter uniform as seen by the program. - */ - struct active_atomic_counter_uniform { - unsigned uniform_loc; - ir_variable *var; - }; - - /* - * Atomic counter buffer referenced by the program. There is a one - * to one correspondence between these and the objects that can be - * queried using glGetActiveAtomicCounterBufferiv(). - */ - struct active_atomic_buffer { - active_atomic_buffer() - : uniforms(0), num_uniforms(0), stage_counter_references(), size(0) - {} - - ~active_atomic_buffer() - { - free(uniforms); - } - - void push_back(unsigned uniform_loc, ir_variable *var) - { - active_atomic_counter_uniform *new_uniforms; - - new_uniforms = (active_atomic_counter_uniform *) - realloc(uniforms, sizeof(active_atomic_counter_uniform) * - (num_uniforms + 1)); - - if (new_uniforms == NULL) { - _mesa_error_no_memory(__func__); - return; - } - - uniforms = new_uniforms; - uniforms[num_uniforms].uniform_loc = uniform_loc; - uniforms[num_uniforms].var = var; - num_uniforms++; - } - - active_atomic_counter_uniform *uniforms; - unsigned num_uniforms; - unsigned stage_counter_references[MESA_SHADER_STAGES]; - unsigned size; - }; - - int - cmp_actives(const void *a, const void *b) - { - const active_atomic_counter_uniform *const first = (active_atomic_counter_uniform *) a; - const active_atomic_counter_uniform *const second = (active_atomic_counter_uniform *) b; - - return int(first->var->data.offset) - int(second->var->data.offset); - } - - bool - check_atomic_counters_overlap(const ir_variable *x, const ir_variable *y) - { - return ((x->data.offset >= y->data.offset && - x->data.offset < y->data.offset + y->type->atomic_size()) || - (y->data.offset >= x->data.offset && - y->data.offset < x->data.offset + x->type->atomic_size())); - } - - void - process_atomic_variable(const glsl_type *t, struct gl_shader_program *prog, - unsigned *uniform_loc, ir_variable *var, - active_atomic_buffer *const buffers, - unsigned *num_buffers, int *offset, - const unsigned shader_stage) - { - /* FIXME: Arrays of arrays get counted separately. For example: - * x1[3][3][2] = 9 uniforms, 18 atomic counters - * x2[3][2] = 3 uniforms, 6 atomic counters - * x3[2] = 1 uniform, 2 atomic counters - * - * However this code marks all the counters as active even when they - * might not be used. - */ - if (t->is_array() && t->fields.array->is_array()) { - for (unsigned i = 0; i < t->length; i++) { - process_atomic_variable(t->fields.array, prog, uniform_loc, - var, buffers, num_buffers, offset, - shader_stage); - } - } else { - active_atomic_buffer *buf = &buffers[var->data.binding]; - gl_uniform_storage *const storage = - &prog->data->UniformStorage[*uniform_loc]; - - /* If this is the first time the buffer is used, increment - * the counter of buffers used. - */ - if (buf->size == 0) - (*num_buffers)++; - - buf->push_back(*uniform_loc, var); - - /* When checking for atomic counters we should count every member in - * an array as an atomic counter reference. - */ - if (t->is_array()) - buf->stage_counter_references[shader_stage] += t->length; - else - buf->stage_counter_references[shader_stage]++; - buf->size = MAX2(buf->size, *offset + t->atomic_size()); - - storage->offset = *offset; - *offset += t->atomic_size(); - - (*uniform_loc)++; - } - } - - active_atomic_buffer * - find_active_atomic_counters(const struct gl_constants *consts, - struct gl_shader_program *prog, - unsigned *num_buffers) - { - active_atomic_buffer *const buffers = - new active_atomic_buffer[consts->MaxAtomicBufferBindings]; - - *num_buffers = 0; - - for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) { - struct gl_linked_shader *sh = prog->_LinkedShaders[i]; - if (sh == NULL) - continue; - - foreach_in_list(ir_instruction, node, sh->ir) { - ir_variable *var = node->as_variable(); - - if (var && var->type->contains_atomic()) { - int offset = var->data.offset; - unsigned uniform_loc = var->data.location; - process_atomic_variable(var->type, prog, &uniform_loc, - var, buffers, num_buffers, &offset, i); - } - } - } - - for (unsigned i = 0; i < consts->MaxAtomicBufferBindings; i++) { - if (buffers[i].size == 0) - continue; - - qsort(buffers[i].uniforms, buffers[i].num_uniforms, - sizeof(active_atomic_counter_uniform), - cmp_actives); - - for (unsigned j = 1; j < buffers[i].num_uniforms; j++) { - /* If an overlapping counter found, it must be a reference to the - * same counter from a different shader stage. - */ - if (check_atomic_counters_overlap(buffers[i].uniforms[j-1].var, - buffers[i].uniforms[j].var) - && strcmp(buffers[i].uniforms[j-1].var->name, - buffers[i].uniforms[j].var->name) != 0) { - linker_error(prog, "Atomic counter %s declared at offset %d " - "which is already in use.", - buffers[i].uniforms[j].var->name, - buffers[i].uniforms[j].var->data.offset); - } - } - } - return buffers; - } -} - -void -link_assign_atomic_counter_resources(const struct gl_constants *consts, - struct gl_shader_program *prog) -{ - unsigned num_buffers; - unsigned num_atomic_buffers[MESA_SHADER_STAGES] = {}; - active_atomic_buffer *abs = - find_active_atomic_counters(consts, prog, &num_buffers); - - prog->data->AtomicBuffers = rzalloc_array(prog->data, gl_active_atomic_buffer, - num_buffers); - prog->data->NumAtomicBuffers = num_buffers; - - unsigned i = 0; - for (unsigned binding = 0; - binding < consts->MaxAtomicBufferBindings; - binding++) { - - /* If the binding was not used, skip. - */ - if (abs[binding].size == 0) - continue; - - active_atomic_buffer &ab = abs[binding]; - gl_active_atomic_buffer &mab = prog->data->AtomicBuffers[i]; - - /* Assign buffer-specific fields. */ - mab.Binding = binding; - mab.MinimumSize = ab.size; - mab.Uniforms = rzalloc_array(prog->data->AtomicBuffers, GLuint, - ab.num_uniforms); - mab.NumUniforms = ab.num_uniforms; - - /* Assign counter-specific fields. */ - for (unsigned j = 0; j < ab.num_uniforms; j++) { - ir_variable *const var = ab.uniforms[j].var; - gl_uniform_storage *const storage = - &prog->data->UniformStorage[ab.uniforms[j].uniform_loc]; - - mab.Uniforms[j] = ab.uniforms[j].uniform_loc; - if (!var->data.explicit_binding) - var->data.binding = i; - - storage->atomic_buffer_index = i; - storage->offset = var->data.offset; - storage->array_stride = (var->type->is_array() ? - var->type->without_array()->atomic_size() : 0); - if (!var->type->is_matrix()) - storage->matrix_stride = 0; - } - - /* Assign stage-specific fields. */ - for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) { - if (ab.stage_counter_references[j]) { - mab.StageReferences[j] = GL_TRUE; - num_atomic_buffers[j]++; - } else { - mab.StageReferences[j] = GL_FALSE; - } - } - - i++; - } - - /* Store a list pointers to atomic buffers per stage and store the index - * to the intra-stage buffer list in uniform storage. - */ - for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) { - if (prog->_LinkedShaders[j] && num_atomic_buffers[j] > 0) { - struct gl_program *gl_prog = prog->_LinkedShaders[j]->Program; - gl_prog->info.num_abos = num_atomic_buffers[j]; - gl_prog->sh.AtomicBuffers = - rzalloc_array(gl_prog, gl_active_atomic_buffer *, - num_atomic_buffers[j]); - - unsigned intra_stage_idx = 0; - for (unsigned i = 0; i < num_buffers; i++) { - struct gl_active_atomic_buffer *atomic_buffer = - &prog->data->AtomicBuffers[i]; - if (atomic_buffer->StageReferences[j]) { - gl_prog->sh.AtomicBuffers[intra_stage_idx] = atomic_buffer; - - for (unsigned u = 0; u < atomic_buffer->NumUniforms; u++) { - prog->data->UniformStorage[atomic_buffer->Uniforms[u]].opaque[j].index = - intra_stage_idx; - prog->data->UniformStorage[atomic_buffer->Uniforms[u]].opaque[j].active = - true; - } - - intra_stage_idx++; - } - } - } - } - - delete [] abs; - assert(i == num_buffers); -} - -void -link_check_atomic_counter_resources(const struct gl_constants *consts, - struct gl_shader_program *prog) -{ - unsigned num_buffers; - active_atomic_buffer *const abs = - find_active_atomic_counters(consts, prog, &num_buffers); - unsigned atomic_counters[MESA_SHADER_STAGES] = {}; - unsigned atomic_buffers[MESA_SHADER_STAGES] = {}; - unsigned total_atomic_counters = 0; - unsigned total_atomic_buffers = 0; - - /* Sum the required resources. Note that this counts buffers and - * counters referenced by several shader stages multiple times - * against the combined limit -- That's the behavior the spec - * requires. - */ - for (unsigned i = 0; i < consts->MaxAtomicBufferBindings; i++) { - if (abs[i].size == 0) - continue; - - for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) { - const unsigned n = abs[i].stage_counter_references[j]; - - if (n) { - atomic_counters[j] += n; - total_atomic_counters += n; - atomic_buffers[j]++; - total_atomic_buffers++; - } - } - } - - /* Check that they are within the supported limits. */ - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - if (atomic_counters[i] > consts->Program[i].MaxAtomicCounters) - linker_error(prog, "Too many %s shader atomic counters", - _mesa_shader_stage_to_string(i)); - - if (atomic_buffers[i] > consts->Program[i].MaxAtomicBuffers) - linker_error(prog, "Too many %s shader atomic counter buffers", - _mesa_shader_stage_to_string(i)); - } - - if (total_atomic_counters > consts->MaxCombinedAtomicCounters) - linker_error(prog, "Too many combined atomic counters"); - - if (total_atomic_buffers > consts->MaxCombinedAtomicBuffers) - linker_error(prog, "Too many combined atomic buffers"); - - delete [] abs; -} diff --git a/src/compiler/glsl/link_uniform_initializers.cpp b/src/compiler/glsl/link_uniform_initializers.cpp deleted file mode 100644 index 4f31a3afd4d..00000000000 --- a/src/compiler/glsl/link_uniform_initializers.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "ir.h" -#include "linker.h" -#include "ir_uniform.h" -#include "string_to_uint_map.h" -#include "main/shader_types.h" - -/* These functions are put in a "private" namespace instead of being marked - * static so that the unit tests can access them. See - * http://code.google.com/p/googletest/wiki/AdvancedGuide#Testing_Private_Code - */ -namespace linker { - -static gl_uniform_storage * -get_storage(struct gl_shader_program *prog, const char *name) -{ - unsigned id; - if (prog->UniformHash->get(id, name)) - return &prog->data->UniformStorage[id]; - - assert(!"No uniform storage found!"); - return NULL; -} - -void -copy_constant_to_storage(union gl_constant_value *storage, - const ir_constant *val, - const enum glsl_base_type base_type, - const unsigned int elements, - unsigned int boolean_true) -{ - for (unsigned int i = 0; i < elements; i++) { - switch (base_type) { - case GLSL_TYPE_UINT: - storage[i].u = val->value.u[i]; - break; - case GLSL_TYPE_INT: - case GLSL_TYPE_SAMPLER: - storage[i].i = val->value.i[i]; - break; - case GLSL_TYPE_FLOAT: - storage[i].f = val->value.f[i]; - break; - case GLSL_TYPE_DOUBLE: - case GLSL_TYPE_UINT64: - case GLSL_TYPE_INT64: - /* XXX need to check on big-endian */ - memcpy(&storage[i * 2].u, &val->value.d[i], sizeof(double)); - break; - case GLSL_TYPE_BOOL: - storage[i].b = val->value.b[i] ? boolean_true : 0; - break; - case GLSL_TYPE_ARRAY: - case GLSL_TYPE_STRUCT: - case GLSL_TYPE_TEXTURE: - case GLSL_TYPE_IMAGE: - case GLSL_TYPE_ATOMIC_UINT: - case GLSL_TYPE_INTERFACE: - case GLSL_TYPE_VOID: - case GLSL_TYPE_SUBROUTINE: - case GLSL_TYPE_FUNCTION: - case GLSL_TYPE_ERROR: - case GLSL_TYPE_UINT16: - case GLSL_TYPE_INT16: - case GLSL_TYPE_UINT8: - case GLSL_TYPE_INT8: - case GLSL_TYPE_FLOAT16: - /* All other types should have already been filtered by other - * paths in the caller. - */ - assert(!"Should not get here."); - break; - } - } -} - -/** - * Initialize an opaque uniform from the value of an explicit binding - * qualifier specified in the shader. Atomic counters are different because - * they have no storage and should be handled elsewhere. - */ -static void -set_opaque_binding(void *mem_ctx, gl_shader_program *prog, - const ir_variable *var, const glsl_type *type, - const char *name, int *binding) -{ - - if (type->is_array() && type->fields.array->is_array()) { - const glsl_type *const element_type = type->fields.array; - - for (unsigned int i = 0; i < type->length; i++) { - const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i); - - set_opaque_binding(mem_ctx, prog, var, element_type, - element_name, binding); - } - } else { - struct gl_uniform_storage *const storage = get_storage(prog, name); - - if (!storage) - return; - - const unsigned elements = MAX2(storage->array_elements, 1); - - /* Section 4.4.6 (Opaque-Uniform Layout Qualifiers) of the GLSL 4.50 spec - * says: - * - * "If the binding identifier is used with an array, the first element - * of the array takes the specified unit and each subsequent element - * takes the next consecutive unit." - */ - for (unsigned int i = 0; i < elements; i++) { - storage->storage[i].i = (*binding)++; - } - - for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) { - gl_linked_shader *shader = prog->_LinkedShaders[sh]; - - if (!shader) - continue; - if (!storage->opaque[sh].active) - continue; - - if (storage->type->is_sampler()) { - for (unsigned i = 0; i < elements; i++) { - const unsigned index = storage->opaque[sh].index + i; - - if (var->data.bindless) { - if (index >= shader->Program->sh.NumBindlessSamplers) - break; - shader->Program->sh.BindlessSamplers[index].unit = - storage->storage[i].i; - shader->Program->sh.BindlessSamplers[index].bound = true; - shader->Program->sh.HasBoundBindlessSampler = true; - } else { - if (index >= ARRAY_SIZE(shader->Program->SamplerUnits)) - break; - shader->Program->SamplerUnits[index] = - storage->storage[i].i; - } - } - } else if (storage->type->is_image()) { - for (unsigned i = 0; i < elements; i++) { - const unsigned index = storage->opaque[sh].index + i; - - - if (var->data.bindless) { - if (index >= shader->Program->sh.NumBindlessImages) - break; - shader->Program->sh.BindlessImages[index].unit = - storage->storage[i].i; - shader->Program->sh.BindlessImages[index].bound = true; - shader->Program->sh.HasBoundBindlessImage = true; - } else { - if (index >= ARRAY_SIZE(shader->Program->sh.ImageUnits)) - break; - shader->Program->sh.ImageUnits[index] = - storage->storage[i].i; - } - } - } - } - } -} - -void -set_uniform_initializer(void *mem_ctx, gl_shader_program *prog, - const char *name, const glsl_type *type, - ir_constant *val, unsigned int boolean_true) -{ - const glsl_type *t_without_array = type->without_array(); - if (type->is_struct()) { - for (unsigned int i = 0; i < type->length; i++) { - const glsl_type *field_type = type->fields.structure[i].type; - const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name, - type->fields.structure[i].name); - set_uniform_initializer(mem_ctx, prog, field_name, - field_type, val->get_record_field(i), - boolean_true); - } - return; - } else if (t_without_array->is_struct() || - (type->is_array() && type->fields.array->is_array())) { - const glsl_type *const element_type = type->fields.array; - - for (unsigned int i = 0; i < type->length; i++) { - const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i); - - set_uniform_initializer(mem_ctx, prog, element_name, - element_type, val->const_elements[i], - boolean_true); - } - return; - } - - struct gl_uniform_storage *const storage = get_storage(prog, name); - - if (!storage) - return; - - if (val->type->is_array()) { - const enum glsl_base_type base_type = - val->const_elements[0]->type->base_type; - const unsigned int elements = val->const_elements[0]->type->components(); - unsigned int idx = 0; - unsigned dmul = glsl_base_type_is_64bit(base_type) ? 2 : 1; - - assert(val->type->length >= storage->array_elements); - for (unsigned int i = 0; i < storage->array_elements; i++) { - copy_constant_to_storage(& storage->storage[idx], - val->const_elements[i], - base_type, - elements, - boolean_true); - - idx += elements * dmul; - } - } else { - copy_constant_to_storage(storage->storage, - val, - val->type->base_type, - val->type->components(), - boolean_true); - - if (storage->type->is_sampler()) { - for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) { - gl_linked_shader *shader = prog->_LinkedShaders[sh]; - - if (shader && storage->opaque[sh].active) { - unsigned index = storage->opaque[sh].index; - - shader->Program->SamplerUnits[index] = storage->storage[0].i; - } - } - } - } -} -} - -void -link_set_uniform_initializers(struct gl_shader_program *prog, - unsigned int boolean_true) -{ - void *mem_ctx = NULL; - - for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) { - struct gl_linked_shader *shader = prog->_LinkedShaders[i]; - - if (shader == NULL) - continue; - - foreach_in_list(ir_instruction, node, shader->ir) { - ir_variable *const var = node->as_variable(); - - if (!var || (var->data.mode != ir_var_uniform && - var->data.mode != ir_var_shader_storage)) - continue; - - if (!mem_ctx) - mem_ctx = ralloc_context(NULL); - - if (var->data.explicit_binding) { - const glsl_type *const type = var->type; - - if (var->is_in_buffer_block()) { - /* This case is handled by link_uniform_blocks (at - * process_block_array_leaf) - */ - } else if (type->without_array()->is_sampler() || - type->without_array()->is_image()) { - int binding = var->data.binding; - linker::set_opaque_binding(mem_ctx, prog, var, var->type, - var->name, &binding); - } else if (type->contains_atomic()) { - /* we don't actually need to do anything. */ - } else { - assert(!"Explicit binding not on a sampler, UBO or atomic."); - } - } else if (var->constant_initializer) { - linker::set_uniform_initializer(mem_ctx, prog, var->name, - var->type, var->constant_initializer, - boolean_true); - } - } - } - - memcpy(prog->data->UniformDataDefaults, prog->data->UniformDataSlots, - sizeof(union gl_constant_value) * prog->data->NumUniformDataSlots); - ralloc_free(mem_ctx); -} diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp index 79d5ae99c4a..a099a7885a9 100644 --- a/src/compiler/glsl/link_uniforms.cpp +++ b/src/compiler/glsl/link_uniforms.cpp @@ -40,224 +40,6 @@ * \author Ian Romanick */ -/** - * Used by linker to indicate uniforms that have no location set. - */ -#define UNMAPPED_UNIFORM_LOC ~0u - -static char* -get_top_level_name(const char *name) -{ - const char *first_dot = strchr(name, '.'); - const char *first_square_bracket = strchr(name, '['); - int name_size = 0; - - /* The ARB_program_interface_query spec says: - * - * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying - * the number of active array elements of the top-level shader storage - * block member containing to the active variable is written to - * . If the top-level block member is not declared as an - * array, the value one is written to . If the top-level block - * member is an array with no declared size, the value zero is written - * to ." - */ - - /* The buffer variable is on top level.*/ - if (!first_square_bracket && !first_dot) - name_size = strlen(name); - else if ((!first_square_bracket || - (first_dot && first_dot < first_square_bracket))) - name_size = first_dot - name; - else - name_size = first_square_bracket - name; - - return strndup(name, name_size); -} - -static char* -get_var_name(const char *name) -{ - const char *first_dot = strchr(name, '.'); - - if (!first_dot) - return strdup(name); - - return strndup(first_dot+1, strlen(first_dot) - 1); -} - -static bool -is_top_level_shader_storage_block_member(const char* name, - const char* interface_name, - const char* field_name) -{ - bool result = false; - - /* If the given variable is already a top-level shader storage - * block member, then return array_size = 1. - * We could have two possibilities: if we have an instanced - * shader storage block or not instanced. - * - * For the first, we check create a name as it was in top level and - * compare it with the real name. If they are the same, then - * the variable is already at top-level. - * - * Full instanced name is: interface name + '.' + var name + - * NULL character - */ - int name_length = strlen(interface_name) + 1 + strlen(field_name) + 1; - char *full_instanced_name = (char *) calloc(name_length, sizeof(char)); - if (!full_instanced_name) { - fprintf(stderr, "%s: Cannot allocate space for name\n", __func__); - return false; - } - - snprintf(full_instanced_name, name_length, "%s.%s", - interface_name, field_name); - - /* Check if its top-level shader storage block member of an - * instanced interface block, or of a unnamed interface block. - */ - if (strcmp(name, full_instanced_name) == 0 || - strcmp(name, field_name) == 0) - result = true; - - free(full_instanced_name); - return result; -} - -static int -get_array_size(struct gl_uniform_storage *uni, const glsl_struct_field *field, - char *interface_name, char *var_name) -{ - /* The ARB_program_interface_query spec says: - * - * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying - * the number of active array elements of the top-level shader storage - * block member containing to the active variable is written to - * . If the top-level block member is not declared as an - * array, the value one is written to . If the top-level block - * member is an array with no declared size, the value zero is written - * to ." - */ - if (is_top_level_shader_storage_block_member(uni->name.string, - interface_name, - var_name)) - return 1; - else if (field->type->is_array()) - return field->type->length; - - return 1; -} - -static int -get_array_stride(struct gl_uniform_storage *uni, const glsl_type *iface, - const glsl_struct_field *field, char *interface_name, - char *var_name, bool use_std430_as_default) -{ - /* The ARB_program_interface_query spec says: - * - * "For the property TOP_LEVEL_ARRAY_STRIDE, a single integer - * identifying the stride between array elements of the top-level - * shader storage block member containing the active variable is - * written to . For top-level block members declared as - * arrays, the value written is the difference, in basic machine units, - * between the offsets of the active variable for consecutive elements - * in the top-level array. For top-level block members not declared as - * an array, zero is written to ." - */ - if (field->type->is_array()) { - const enum glsl_matrix_layout matrix_layout = - glsl_matrix_layout(field->matrix_layout); - bool row_major = matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR; - const glsl_type *array_type = field->type->fields.array; - - if (is_top_level_shader_storage_block_member(uni->name.string, - interface_name, - var_name)) - return 0; - - if (GLSL_INTERFACE_PACKING_STD140 == - iface->get_internal_ifc_packing(use_std430_as_default)) { - if (array_type->is_struct() || array_type->is_array()) - return glsl_align(array_type->std140_size(row_major), 16); - else - return MAX2(array_type->std140_base_alignment(row_major), 16); - } else { - return array_type->std430_array_stride(row_major); - } - } - return 0; -} - -static void -calculate_array_size_and_stride(struct gl_shader_program *shProg, - struct gl_uniform_storage *uni, - bool use_std430_as_default) -{ - if (!uni->is_shader_storage) - return; - - int block_index = uni->block_index; - int array_size = -1; - int array_stride = -1; - char *var_name = get_top_level_name(uni->name.string); - char *interface_name = - get_top_level_name(uni->is_shader_storage ? - shProg->data->ShaderStorageBlocks[block_index].name.string : - shProg->data->UniformBlocks[block_index].name.string); - - if (strcmp(var_name, interface_name) == 0) { - /* Deal with instanced array of SSBOs */ - char *temp_name = get_var_name(uni->name.string); - if (!temp_name) { - linker_error(shProg, "Out of memory during linking.\n"); - goto write_top_level_array_size_and_stride; - } - free(var_name); - var_name = get_top_level_name(temp_name); - free(temp_name); - if (!var_name) { - linker_error(shProg, "Out of memory during linking.\n"); - goto write_top_level_array_size_and_stride; - } - } - - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - const gl_linked_shader *sh = shProg->_LinkedShaders[i]; - if (sh == NULL) - continue; - - foreach_in_list(ir_instruction, node, sh->ir) { - ir_variable *var = node->as_variable(); - if (!var || !var->get_interface_type() || - var->data.mode != ir_var_shader_storage) - continue; - - const glsl_type *iface = var->get_interface_type(); - - if (strcmp(interface_name, iface->name) != 0) - continue; - - for (unsigned i = 0; i < iface->length; i++) { - const glsl_struct_field *field = &iface->fields.structure[i]; - if (strcmp(field->name, var_name) != 0) - continue; - - array_stride = get_array_stride(uni, iface, field, interface_name, - var_name, use_std430_as_default); - array_size = get_array_size(uni, field, interface_name, var_name); - goto write_top_level_array_size_and_stride; - } - } - } -write_top_level_array_size_and_stride: - free(interface_name); - free(var_name); - uni->top_level_array_stride = array_stride; - uni->top_level_array_size = array_size; -} - void program_resource_visitor::process(const glsl_type *type, const char *name, bool use_std430_as_default) @@ -458,170 +240,6 @@ program_resource_visitor::set_record_array_count(unsigned) { } -namespace { - -/** - * Class to help calculate the storage requirements for a set of uniforms - * - * 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 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. - */ -class count_uniform_size : public program_resource_visitor { -public: - count_uniform_size(struct string_to_uint_map *map, - struct string_to_uint_map *hidden_map, - bool use_std430_as_default) - : num_active_uniforms(0), num_hidden_uniforms(0), num_values(0), - num_shader_samplers(0), num_shader_images(0), - num_shader_uniform_components(0), num_shader_subroutines(0), - is_buffer_block(false), is_shader_storage(false), map(map), - hidden_map(hidden_map), current_var(NULL), - use_std430_as_default(use_std430_as_default) - { - /* empty */ - } - - void start_shader() - { - 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->current_var = var; - this->is_buffer_block = var->is_in_buffer_block(); - this->is_shader_storage = var->is_in_shader_storage_block(); - if (var->is_interface_instance()) - program_resource_visitor::process(var->get_interface_type(), - var->get_interface_type()->name, - use_std430_as_default); - else - program_resource_visitor::process(var, use_std430_as_default); - } - - /** - * Total number of active uniforms counted - */ - unsigned num_active_uniforms; - - unsigned num_hidden_uniforms; - - /** - * Number of data values required to back the storage for the active uniforms - */ - unsigned num_values; - - /** - * Number of samplers used - */ - unsigned num_shader_samplers; - - /** - * Number of images used - */ - unsigned num_shader_images; - - /** - * Number of uniforms used in the current shader - */ - unsigned num_shader_uniform_components; - - /** - * Number of subroutine uniforms used - */ - unsigned num_shader_subroutines; - - bool is_buffer_block; - bool is_shader_storage; - - struct string_to_uint_map *map; - -private: - virtual void visit_field(const glsl_type *type, const char *name, - bool /* row_major */, - const glsl_type * /* record_type */, - const enum glsl_interface_packing, - bool /* last_field */) - { - assert(!type->without_array()->is_struct()); - assert(!type->without_array()->is_interface()); - assert(!(type->is_array() && type->fields.array->is_array())); - - /* Count the number of samplers regardless of whether the uniform is - * already in the hash table. The hash table prevents adding the same - * uniform for multiple shader targets, but in this case we want to - * count it for each shader target. - */ - const unsigned values = type->component_slots(); - if (type->contains_subroutine()) { - this->num_shader_subroutines += values; - } else if (type->contains_sampler() && !current_var->data.bindless) { - /* Samplers (bound or bindless) are counted as two components as - * specified by ARB_bindless_texture. */ - this->num_shader_samplers += values / 2; - } else if (type->contains_image() && !current_var->data.bindless) { - /* Images (bound or bindless) are counted as two components as - * specified by ARB_bindless_texture. */ - this->num_shader_images += values / 2; - - /* As drivers are likely to represent image uniforms as - * scalar indices, count them against the limit of uniform - * components in the default block. The spec allows image - * uniforms to use up no more than one scalar slot. - */ - if (!is_shader_storage) - this->num_shader_uniform_components += values; - } else { - /* Accumulate the total number of uniform slots used by this shader. - * Note that samplers do not count against this limit because they - * don't use any storage on current hardware. - */ - if (!is_buffer_block) - this->num_shader_uniform_components += values; - } - - /* If the uniform is already in the map, there's nothing more to do. - */ - unsigned id; - if (this->map->get(id, name)) - return; - - if (this->current_var->data.how_declared == ir_var_hidden) { - this->hidden_map->put(this->num_hidden_uniforms, name); - this->num_hidden_uniforms++; - } else { - this->map->put(this->num_active_uniforms-this->num_hidden_uniforms, - name); - } - - /* Each leaf uniform occupies one entry in the list of active - * uniforms. - */ - this->num_active_uniforms++; - - if(!is_gl_identifier(name) && !is_shader_storage && !is_buffer_block) - this->num_values += values; - } - - struct string_to_uint_map *hidden_map; - - /** - * Current variable being processed. - */ - ir_variable *current_var; - - bool use_std430_as_default; -}; - -} /* anonymous namespace */ - unsigned link_calculate_matrix_stride(const glsl_type *matrix, bool row_major, enum glsl_interface_packing packing) @@ -663,1120 +281,3 @@ link_calculate_matrix_stride(const glsl_type *matrix, bool row_major, ? (items < 3 ? items * N : glsl_align(items * N, 16)) : glsl_align(items * N, 16); } - -/** - * Class to help parcel out pieces of backing storage to uniforms - * - * Each uniform processed has some range of the \c gl_constant_value - * structures associated with it. The association is done by finding - * the uniform in the \c string_to_uint_map and using the value from - * the map to connect that slot in the \c gl_uniform_storage table - * with the next available slot in the \c gl_constant_value array. - * - * \warning - * This class assumes that every uniform that will be processed is - * already in the \c string_to_uint_map. In addition, it assumes that - * the \c gl_uniform_storage and \c gl_constant_value arrays are "big - * enough." - */ -class parcel_out_uniform_storage : public program_resource_visitor { -public: - parcel_out_uniform_storage(struct gl_shader_program *prog, - struct string_to_uint_map *map, - struct gl_uniform_storage *uniforms, - union gl_constant_value *values, - bool use_std430_as_default) - : buffer_block_index(0), ubo_byte_offset(0), - shader_type(MESA_SHADER_NONE), - prog(prog), map(map), uniforms(uniforms), - next_sampler(0), next_bindless_sampler(0), next_image(0), - next_bindless_image(0), next_subroutine(0), - use_std430_as_default(use_std430_as_default), - field_counter(0), current_var(NULL), explicit_location(0), - record_array_count(0), record_next_sampler(NULL), - record_next_image(NULL), record_next_bindless_sampler(NULL), - record_next_bindless_image(NULL), - values(values), - shader_samplers_used(0), shader_shadow_samplers(0), - num_bindless_samplers(0), - bindless_targets(NULL), num_bindless_images(0), - bindless_access(NULL), - shader_storage_blocks_write_access(0) - { - memset(this->targets, 0, sizeof(this->targets)); - } - - virtual ~parcel_out_uniform_storage() - { - free(this->bindless_targets); - free(this->bindless_access); - } - - void start_shader(gl_shader_stage shader_type) - { - assert(shader_type < MESA_SHADER_STAGES); - this->shader_type = shader_type; - - this->shader_samplers_used = 0; - this->shader_shadow_samplers = 0; - this->next_sampler = 0; - this->next_image = 0; - this->next_subroutine = 0; - this->record_array_count = 1; - memset(this->targets, 0, sizeof(this->targets)); - - this->num_bindless_samplers = 0; - this->next_bindless_sampler = 0; - free(this->bindless_targets); - this->bindless_targets = NULL; - - this->num_bindless_images = 0; - this->next_bindless_image = 0; - free(this->bindless_access); - this->bindless_access = NULL; - this->shader_storage_blocks_write_access = 0; - } - - void set_and_process(ir_variable *var) - { - current_var = var; - field_counter = 0; - this->record_next_sampler = new string_to_uint_map; - this->record_next_bindless_sampler = new string_to_uint_map; - this->record_next_image = new string_to_uint_map; - this->record_next_bindless_image = new string_to_uint_map; - - buffer_block_index = -1; - if (var->is_in_buffer_block()) { - struct gl_uniform_block *blks = var->is_in_shader_storage_block() ? - prog->data->ShaderStorageBlocks : prog->data->UniformBlocks; - unsigned num_blks = var->is_in_shader_storage_block() ? - prog->data->NumShaderStorageBlocks : prog->data->NumUniformBlocks; - bool is_interface_array = - var->is_interface_instance() && var->type->is_array(); - - if (is_interface_array) { - unsigned l = strlen(var->get_interface_type()->name); - - for (unsigned i = 0; i < num_blks; i++) { - if (strncmp(var->get_interface_type()->name, blks[i].name.string, l) - == 0 && blks[i].name.string[l] == '[') { - buffer_block_index = i; - break; - } - } - } else { - for (unsigned i = 0; i < num_blks; i++) { - if (strcmp(var->get_interface_type()->name, blks[i].name.string) == 0) { - buffer_block_index = i; - break; - } - } - } - assert(buffer_block_index != -1); - - if (var->is_in_shader_storage_block() && - !var->data.memory_read_only) { - unsigned array_size = is_interface_array ? - var->type->array_size() : 1; - - STATIC_ASSERT(MAX_SHADER_STORAGE_BUFFERS <= 32); - - /* Shaders that use too many SSBOs will fail to compile, which - * we don't care about. - * - * This is true for shaders that do not use too many SSBOs: - */ - if (buffer_block_index + array_size <= 32) { - shader_storage_blocks_write_access |= - u_bit_consecutive(buffer_block_index, array_size); - } - } - - /* Uniform blocks that were specified with an instance name must be - * handled a little bit differently. The name of the variable is the - * name used to reference the uniform block instead of being the name - * of a variable within the block. Therefore, searching for the name - * within the block will fail. - */ - if (var->is_interface_instance()) { - ubo_byte_offset = 0; - process(var->get_interface_type(), - var->get_interface_type()->name, - use_std430_as_default); - } else { - const struct gl_uniform_block *const block = - &blks[buffer_block_index]; - - assert(var->data.location != -1); - - const struct gl_uniform_buffer_variable *const ubo_var = - &block->Uniforms[var->data.location]; - - ubo_byte_offset = ubo_var->Offset; - process(var, use_std430_as_default); - } - } else { - /* Store any explicit location and reset data location so we can - * reuse this variable for storing the uniform slot number. - */ - this->explicit_location = current_var->data.location; - current_var->data.location = -1; - - process(var, use_std430_as_default); - } - delete this->record_next_sampler; - delete this->record_next_bindless_sampler; - delete this->record_next_image; - delete this->record_next_bindless_image; - } - - int buffer_block_index; - int ubo_byte_offset; - gl_shader_stage shader_type; - -private: - bool set_opaque_indices(const glsl_type *base_type, - struct gl_uniform_storage *uniform, - const char *name, unsigned &next_index, - struct string_to_uint_map *record_next_index) - { - assert(base_type->is_sampler() || base_type->is_image()); - - if (this->record_array_count > 1) { - unsigned inner_array_size = MAX2(1, uniform->array_elements); - char *name_copy = ralloc_strdup(NULL, name); - - /* Remove all array subscripts from the sampler/image name */ - char *str_start; - 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 + 1)); - } - - unsigned index = 0; - if (record_next_index->get(index, name_copy)) { - /* In this case, we've already seen this uniform so we just use the - * next sampler/image index recorded the last time we visited. - */ - uniform->opaque[shader_type].index = index; - index = inner_array_size + uniform->opaque[shader_type].index; - record_next_index->put(index, name_copy); - - ralloc_free(name_copy); - /* Return as everything else has already been initialised in a - * previous pass. - */ - return false; - } else { - /* We've never seen this uniform before so we need to allocate - * enough indices to store it. - * - * Nested struct arrays behave like arrays of arrays so we need to - * increase the index by the total number of elements of the - * sampler/image in case there is more than one sampler/image - * inside the structs. This allows the offset to be easily - * calculated for indirect indexing. - */ - uniform->opaque[shader_type].index = next_index; - next_index += inner_array_size * this->record_array_count; - - /* Store the next index for future passes over the struct array - */ - index = uniform->opaque[shader_type].index + inner_array_size; - record_next_index->put(index, name_copy); - ralloc_free(name_copy); - } - } else { - /* Increment the sampler/image by 1 for non-arrays and by the number - * of array elements for arrays. - */ - uniform->opaque[shader_type].index = next_index; - next_index += MAX2(1, uniform->array_elements); - } - return true; - } - - void handle_samplers(const glsl_type *base_type, - struct gl_uniform_storage *uniform, const char *name) - { - if (base_type->is_sampler()) { - uniform->opaque[shader_type].active = true; - - const gl_texture_index target = base_type->sampler_index(); - const unsigned shadow = base_type->sampler_shadow; - - if (current_var->data.bindless) { - if (!set_opaque_indices(base_type, uniform, name, - this->next_bindless_sampler, - this->record_next_bindless_sampler)) - return; - - this->num_bindless_samplers = this->next_bindless_sampler; - - this->bindless_targets = (gl_texture_index *) - realloc(this->bindless_targets, - this->num_bindless_samplers * sizeof(gl_texture_index)); - - for (unsigned i = uniform->opaque[shader_type].index; - i < this->num_bindless_samplers; - i++) { - this->bindless_targets[i] = target; - } - } else { - if (!set_opaque_indices(base_type, uniform, name, - this->next_sampler, - this->record_next_sampler)) - return; - - for (unsigned i = uniform->opaque[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; - } - } - } - } - - void handle_images(const glsl_type *base_type, - struct gl_uniform_storage *uniform, const char *name) - { - if (base_type->is_image()) { - uniform->opaque[shader_type].active = true; - - /* Set image access qualifiers */ - const GLenum access = - current_var->data.memory_read_only ? - (current_var->data.memory_write_only ? GL_NONE : - GL_READ_ONLY) : - (current_var->data.memory_write_only ? GL_WRITE_ONLY : - GL_READ_WRITE); - - if (current_var->data.bindless) { - if (!set_opaque_indices(base_type, uniform, name, - this->next_bindless_image, - this->record_next_bindless_image)) - return; - - this->num_bindless_images = this->next_bindless_image; - - this->bindless_access = (GLenum *) - realloc(this->bindless_access, - this->num_bindless_images * sizeof(GLenum)); - - for (unsigned i = uniform->opaque[shader_type].index; - i < this->num_bindless_images; - i++) { - this->bindless_access[i] = access; - } - } else { - if (!set_opaque_indices(base_type, uniform, name, - this->next_image, - this->record_next_image)) - return; - - for (unsigned i = uniform->opaque[shader_type].index; - i < MIN2(this->next_image, MAX_IMAGE_UNIFORMS); - i++) { - prog->_LinkedShaders[shader_type]->Program->sh.ImageAccess[i] = access; - } - } - } - } - - void handle_subroutines(const glsl_type *base_type, - struct gl_uniform_storage *uniform) - { - if (base_type->is_subroutine()) { - 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. - */ - this->next_subroutine += MAX2(1, uniform->array_elements); - - } - } - - virtual void set_buffer_offset(unsigned offset) - { - this->ubo_byte_offset = offset; - } - - virtual void set_record_array_count(unsigned record_array_count) - { - this->record_array_count = record_array_count; - } - - virtual void enter_record(const glsl_type *type, const char *, - bool row_major, - const enum glsl_interface_packing packing) - { - assert(type->is_struct()); - if (this->buffer_block_index == -1) - return; - if (packing == GLSL_INTERFACE_PACKING_STD430) - this->ubo_byte_offset = glsl_align( - this->ubo_byte_offset, type->std430_base_alignment(row_major)); - else - 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 *, - bool row_major, - const enum glsl_interface_packing packing) - { - assert(type->is_struct()); - if (this->buffer_block_index == -1) - return; - if (packing == GLSL_INTERFACE_PACKING_STD430) - this->ubo_byte_offset = glsl_align( - this->ubo_byte_offset, type->std430_base_alignment(row_major)); - else - 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 */, - const enum glsl_interface_packing packing, - bool /* last_field */) - { - assert(!type->without_array()->is_struct()); - assert(!type->without_array()->is_interface()); - assert(!(type->is_array() && type->fields.array->is_array())); - - unsigned id = 0; - bool found = this->map->get(id, name); - assert(found); - - if (!found) - return; - - const glsl_type *base_type; - if (type->is_array()) { - this->uniforms[id].array_elements = type->length; - base_type = type->fields.array; - } else { - this->uniforms[id].array_elements = 0; - base_type = type; - } - - /* Initialise opaque data */ - this->uniforms[id].opaque[shader_type].index = ~0; - this->uniforms[id].opaque[shader_type].active = false; - - if (current_var->data.used || base_type->is_subroutine()) - this->uniforms[id].active_shader_mask |= 1 << shader_type; - - /* This assigns uniform indices to sampler and image uniforms. */ - handle_samplers(base_type, &this->uniforms[id], name); - handle_images(base_type, &this->uniforms[id], name); - handle_subroutines(base_type, &this->uniforms[id]); - - /* For array of arrays or struct arrays the base location may have - * already been set so don't set it again. - */ - if (buffer_block_index == -1 && current_var->data.location == -1) { - current_var->data.location = id; - } - - /* 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 || this->uniforms[id].builtin) { - return; - } - - /* Assign explicit locations. */ - if (current_var->data.explicit_location) { - /* Set sequential locations for struct fields. */ - if (current_var->type->without_array()->is_struct() || - current_var->type->is_array_of_arrays()) { - const unsigned entries = MAX2(1, this->uniforms[id].array_elements); - this->uniforms[id].remap_location = - this->explicit_location + field_counter; - field_counter += entries; - } else { - this->uniforms[id].remap_location = this->explicit_location; - } - } else { - /* Initialize to to indicate that no location is set */ - this->uniforms[id].remap_location = UNMAPPED_UNIFORM_LOC; - } - - this->uniforms[id].name.string = ralloc_strdup(this->uniforms, name); - resource_name_updated(&this->uniforms[id].name); - this->uniforms[id].type = base_type; - this->uniforms[id].num_driver_storage = 0; - this->uniforms[id].driver_storage = NULL; - 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); - - this->uniforms[id].is_shader_storage = - current_var->is_in_shader_storage_block(); - this->uniforms[id].is_bindless = current_var->data.bindless; - - /* Do not assign storage if the uniform is a builtin or buffer object */ - if (!this->uniforms[id].builtin && - !this->uniforms[id].is_shader_storage && - this->buffer_block_index == -1) - this->uniforms[id].storage = this->values; - - if (this->buffer_block_index != -1) { - this->uniforms[id].block_index = this->buffer_block_index; - - unsigned alignment = type->std140_base_alignment(row_major); - if (packing == GLSL_INTERFACE_PACKING_STD430) - alignment = type->std430_base_alignment(row_major); - this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment); - this->uniforms[id].offset = this->ubo_byte_offset; - if (packing == GLSL_INTERFACE_PACKING_STD430) - this->ubo_byte_offset += type->std430_size(row_major); - else - this->ubo_byte_offset += type->std140_size(row_major); - - if (type->is_array()) { - if (packing == GLSL_INTERFACE_PACKING_STD430) - this->uniforms[id].array_stride = - type->without_array()->std430_array_stride(row_major); - else - this->uniforms[id].array_stride = - glsl_align(type->without_array()->std140_size(row_major), - 16); - } else { - this->uniforms[id].array_stride = 0; - } - - if (type->without_array()->is_matrix()) { - this->uniforms[id].matrix_stride = - link_calculate_matrix_stride(type->without_array(), - row_major, - packing); - this->uniforms[id].row_major = row_major; - } else { - this->uniforms[id].matrix_stride = 0; - this->uniforms[id].row_major = false; - } - } else { - this->uniforms[id].block_index = -1; - this->uniforms[id].offset = -1; - this->uniforms[id].array_stride = -1; - this->uniforms[id].matrix_stride = -1; - this->uniforms[id].row_major = false; - } - - if (!this->uniforms[id].builtin && - !this->uniforms[id].is_shader_storage && - this->buffer_block_index == -1) - this->values += type->component_slots(); - - calculate_array_size_and_stride(prog, &this->uniforms[id], - use_std430_as_default); - } - - /** - * Current program being processed. - */ - struct gl_shader_program *prog; - - struct string_to_uint_map *map; - - struct gl_uniform_storage *uniforms; - unsigned next_sampler; - unsigned next_bindless_sampler; - unsigned next_image; - unsigned next_bindless_image; - unsigned next_subroutine; - - bool use_std430_as_default; - - /** - * Field counter is used to take care that uniform structures - * with explicit locations get sequential locations. - */ - unsigned field_counter; - - /** - * Current variable being processed. - */ - ir_variable *current_var; - - /* Used to store the explicit location from current_var so that we can - * reuse the location field for storing the uniform slot id. - */ - int explicit_location; - - /* Stores total struct array elements including nested structs */ - unsigned record_array_count; - - /* Map for temporarily storing next sampler index when handling samplers in - * struct arrays. - */ - struct string_to_uint_map *record_next_sampler; - - /* Map for temporarily storing next imager index when handling images in - * struct arrays. - */ - struct string_to_uint_map *record_next_image; - - /* Map for temporarily storing next bindless sampler index when handling - * bindless samplers in struct arrays. - */ - struct string_to_uint_map *record_next_bindless_sampler; - - /* Map for temporarily storing next bindless image index when handling - * bindless images in struct arrays. - */ - struct string_to_uint_map *record_next_bindless_image; - -public: - union gl_constant_value *values; - - gl_texture_index targets[MAX_SAMPLERS]; - - /** - * Mask of samplers used by the current shader stage. - */ - unsigned shader_samplers_used; - - /** - * Mask of samplers used by the current shader stage for shadows. - */ - unsigned shader_shadow_samplers; - - /** - * Number of bindless samplers used by the current shader stage. - */ - unsigned num_bindless_samplers; - - /** - * Texture targets for bindless samplers used by the current stage. - */ - gl_texture_index *bindless_targets; - - /** - * Number of bindless images used by the current shader stage. - */ - unsigned num_bindless_images; - - /** - * Access types for bindless images used by the current stage. - */ - GLenum *bindless_access; - - /** - * Bitmask of shader storage blocks not declared as read-only. - */ - unsigned shader_storage_blocks_write_access; -}; - -static bool -variable_is_referenced(ir_array_refcount_visitor &v, ir_variable *var) -{ - ir_array_refcount_entry *const entry = v.get_variable_entry(var); - - return entry->is_referenced; - -} - -/** - * Walks the IR and update the references to uniform blocks in the - * ir_variables to point at linked shader's list (previously, they - * would point at the uniform block list in one of the pre-linked - * shaders). - */ -static void -link_update_uniform_buffer_variables(struct gl_linked_shader *shader, - unsigned stage) -{ - ir_array_refcount_visitor v; - - v.run(shader->ir); - - foreach_in_list(ir_instruction, node, shader->ir) { - ir_variable *const var = node->as_variable(); - - if (var == NULL || !var->is_in_buffer_block()) - continue; - - assert(var->data.mode == ir_var_uniform || - var->data.mode == ir_var_shader_storage); - - unsigned num_blocks = var->data.mode == ir_var_uniform ? - shader->Program->info.num_ubos : shader->Program->info.num_ssbos; - struct gl_uniform_block **blks = var->data.mode == ir_var_uniform ? - shader->Program->sh.UniformBlocks : - shader->Program->sh.ShaderStorageBlocks; - - if (var->is_interface_instance()) { - 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] - * through [n-1]. Unlike for non-interface instances, there will - * not be structure types here, so the only name sentinel that we - * have to worry about is [. - */ - assert(var->type->without_array() == var->get_interface_type()); - const char sentinel = var->type->is_array() ? '[' : '\0'; - - const ptrdiff_t len = strlen(var->get_interface_type()->name); - for (unsigned i = 0; i < num_blocks; i++) { - const char *const begin = blks[i]->name.string; - const char *const end = strchr(begin, sentinel); - - if (end == NULL) - continue; - - if (len != (end - begin)) - continue; - - /* Even when a match is found, do not "break" here. This could - * 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 && - (!var->type->is_array() || - entry->is_linearized_index_referenced(blks[i]->linearized_array_index))) { - blks[i]->stageref |= 1U << stage; - } - } - } - - var->data.location = 0; - continue; - } - - bool found = false; - char sentinel = '\0'; - - if (var->type->is_struct()) { - sentinel = '.'; - } else if (var->type->is_array() && (var->type->fields.array->is_array() - || var->type->without_array()->is_struct())) { - sentinel = '['; - } - - const unsigned l = strlen(var->name); - for (unsigned i = 0; i < num_blocks; i++) { - for (unsigned j = 0; j < blks[i]->NumUniforms; j++) { - if (sentinel) { - const char *begin = blks[i]->Uniforms[j].Name; - const char *end = strchr(begin, sentinel); - - if (end == NULL) - continue; - - if ((ptrdiff_t) l != (end - begin)) - continue; - - found = strncmp(var->name, begin, l) == 0; - } else { - found = strcmp(var->name, blks[i]->Uniforms[j].Name) == 0; - } - - if (found) { - var->data.location = j; - - if (variable_is_referenced(v, var)) - blks[i]->stageref |= 1U << stage; - - break; - } - } - - if (found) - break; - } - assert(found); - } -} - -/** - * Combine the hidden uniform hash map with the uniform hash map so that the - * hidden uniforms will be given indicies at the end of the uniform storage - * array. - */ -static void -assign_hidden_uniform_slot_id(const char *name, unsigned hidden_id, - void *closure) -{ - count_uniform_size *uniform_size = (count_uniform_size *) closure; - unsigned hidden_uniform_start = uniform_size->num_active_uniforms - - uniform_size->num_hidden_uniforms; - - uniform_size->map->put(hidden_uniform_start + hidden_id, name); -} - -static void -link_setup_uniform_remap_tables(const struct gl_constants *consts, - struct gl_shader_program *prog) -{ - 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->data->NumUniformStorage; i++) { - if (prog->data->UniformStorage[i].type->is_subroutine() || - prog->data->UniformStorage[i].is_shader_storage) - continue; - - if (prog->data->UniformStorage[i].remap_location != - UNMAPPED_UNIFORM_LOC) { - /* How many new entries for this uniform? */ - const unsigned entries = - 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->data->UniformStorage[i].remap_location + j; - assert(prog->UniformRemapTable[element_loc] == - INACTIVE_UNIFORM_EXPLICIT_LOCATION); - prog->UniformRemapTable[element_loc] = - &prog->data->UniformStorage[i]; - } - } - } - - /* Reserve locations for rest of the uniforms. */ - 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; - - /* Built-in uniforms should not get any location. */ - if (prog->data->UniformStorage[i].builtin) - continue; - - /* Explicit ones have been set already. */ - if (prog->data->UniformStorage[i].remap_location != UNMAPPED_UNIFORM_LOC) - continue; - - /* how many new entries for this uniform? */ - 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 = link_util_find_empty_block(prog, &prog->data->UniformStorage[i]); - - /* Add new entries to the total amount for checking against MAX_UNIFORM- - * _LOCATIONS. This only applies to the default uniform block (-1), - * because locations of uniform block entries are not assignable. - */ - if (prog->data->UniformStorage[i].block_index == -1) - total_entries += entries; - - if (chosen_location != -1) { - empty_locs -= entries; - } else { - chosen_location = prog->NumUniformRemapTable; - - /* resize remap table to fit new entries */ - prog->UniformRemapTable = - reralloc(prog, - prog->UniformRemapTable, - gl_uniform_storage *, - prog->NumUniformRemapTable + entries); - prog->NumUniformRemapTable += entries; - } - - /* set pointers for this uniform */ - for (unsigned j = 0; j < entries; j++) - prog->UniformRemapTable[chosen_location + j] = - &prog->data->UniformStorage[i]; - - /* set the base location in remap table for the uniform */ - prog->data->UniformStorage[i].remap_location = chosen_location; - } - - /* Verify that total amount of entries for explicit and implicit locations - * is less than MAX_UNIFORM_LOCATIONS. - */ - - if (total_entries > consts->MaxUserAssignableUniformLocations) { - linker_error(prog, "count of uniform locations > MAX_UNIFORM_LOCATIONS" - "(%u > %u)", total_entries, - consts->MaxUserAssignableUniformLocations); - } - - /* Reserve all the explicit locations of the active subroutine uniforms. */ - for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) { - if (!prog->data->UniformStorage[i].type->is_subroutine()) - continue; - - if (prog->data->UniformStorage[i].remap_location == UNMAPPED_UNIFORM_LOC) - continue; - - /* How many new entries for this uniform? */ - 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; - - /* Set remap table entries point to correct gl_uniform_storage. */ - for (unsigned k = 0; k < entries; k++) { - unsigned element_loc = - prog->data->UniformStorage[i].remap_location + k; - assert(p->sh.SubroutineUniformRemapTable[element_loc] == - INACTIVE_UNIFORM_EXPLICIT_LOCATION); - p->sh.SubroutineUniformRemapTable[element_loc] = - &prog->data->UniformStorage[i]; - } - } - } - - /* reserve subroutine locations */ - for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) { - if (!prog->data->UniformStorage[i].type->is_subroutine()) - continue; - - if (prog->data->UniformStorage[i].remap_location != - UNMAPPED_UNIFORM_LOC) - continue; - - 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; - - p->sh.SubroutineUniformRemapTable = - reralloc(p, - p->sh.SubroutineUniformRemapTable, - gl_uniform_storage *, - p->sh.NumSubroutineUniformRemapTable + entries); - - for (unsigned k = 0; k < entries; k++) { - p->sh.SubroutineUniformRemapTable[p->sh.NumSubroutineUniformRemapTable + k] = - &prog->data->UniformStorage[i]; - } - prog->data->UniformStorage[i].remap_location = - p->sh.NumSubroutineUniformRemapTable; - p->sh.NumSubroutineUniformRemapTable += entries; - } - } -} - -static void -link_assign_uniform_storage(const struct gl_constants *consts, - struct gl_shader_program *prog, - const unsigned num_data_slots) -{ - /* On the outside chance that there were no uniforms, bail out. - */ - if (prog->data->NumUniformStorage == 0) - return; - - unsigned int boolean_true = consts->UniformBooleanTrue; - - union gl_constant_value *data; - if (prog->data->UniformStorage == NULL) { - prog->data->UniformStorage = rzalloc_array(prog->data, - struct gl_uniform_storage, - prog->data->NumUniformStorage); - data = rzalloc_array(prog->data->UniformStorage, - union gl_constant_value, num_data_slots); - prog->data->UniformDataDefaults = - 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->data->UniformStorage, data, - consts->UseSTD430AsDefaultPacking); - - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - struct gl_linked_shader *shader = prog->_LinkedShaders[i]; - - if (!shader) - continue; - - parcel.start_shader((gl_shader_stage)i); - - foreach_in_list(ir_instruction, node, shader->ir) { - ir_variable *const var = node->as_variable(); - - if ((var == NULL) || (var->data.mode != ir_var_uniform && - var->data.mode != ir_var_shader_storage)) - continue; - - parcel.set_and_process(var); - } - - shader->Program->SamplersUsed = parcel.shader_samplers_used; - shader->shadow_samplers = parcel.shader_shadow_samplers; - shader->Program->sh.ShaderStorageBlocksWriteAccess = - parcel.shader_storage_blocks_write_access; - - if (parcel.num_bindless_samplers > 0) { - shader->Program->sh.NumBindlessSamplers = parcel.num_bindless_samplers; - shader->Program->sh.BindlessSamplers = - rzalloc_array(shader->Program, gl_bindless_sampler, - parcel.num_bindless_samplers); - for (unsigned j = 0; j < parcel.num_bindless_samplers; j++) { - shader->Program->sh.BindlessSamplers[j].target = - parcel.bindless_targets[j]; - } - } - - if (parcel.num_bindless_images > 0) { - shader->Program->sh.NumBindlessImages = parcel.num_bindless_images; - shader->Program->sh.BindlessImages = - rzalloc_array(shader->Program, gl_bindless_image, - parcel.num_bindless_images); - for (unsigned j = 0; j < parcel.num_bindless_images; j++) { - shader->Program->sh.BindlessImages[j].access = - parcel.bindless_access[j]; - } - } - - STATIC_ASSERT(ARRAY_SIZE(shader->Program->sh.SamplerTargets) == - ARRAY_SIZE(parcel.targets)); - for (unsigned j = 0; j < ARRAY_SIZE(parcel.targets); j++) - shader->Program->sh.SamplerTargets[j] = parcel.targets[j]; - } - -#ifndef NDEBUG - 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(consts, 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, - const struct gl_constants *consts) -{ - ralloc_free(prog->data->UniformStorage); - prog->data->UniformStorage = NULL; - prog->data->NumUniformStorage = 0; - - if (prog->UniformHash != NULL) { - prog->UniformHash->clear(); - } else { - prog->UniformHash = new string_to_uint_map; - } - - /* 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. - * - * Note: this is *NOT* the index that is returned to the application by - * glGetUniformLocation. - */ - struct string_to_uint_map *hiddenUniforms = new string_to_uint_map; - count_uniform_size uniform_size(prog->UniformHash, hiddenUniforms, - consts->UseSTD430AsDefaultPacking); - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - struct gl_linked_shader *sh = prog->_LinkedShaders[i]; - - if (sh == NULL) - continue; - - link_update_uniform_buffer_variables(sh, i); - - /* Reset various per-shader target counts. - */ - uniform_size.start_shader(); - - foreach_in_list(ir_instruction, node, sh->ir) { - ir_variable *const var = node->as_variable(); - - if ((var == NULL) || (var->data.mode != ir_var_uniform && - var->data.mode != ir_var_shader_storage)) - continue; - - uniform_size.process(var); - } - - if (uniform_size.num_shader_samplers > - consts->Program[i].MaxTextureImageUnits) { - linker_error(prog, "Too many %s shader texture samplers\n", - _mesa_shader_stage_to_string(i)); - continue; - } - - if (uniform_size.num_shader_images > - consts->Program[i].MaxImageUniforms) { - linker_error(prog, "Too many %s shader image uniforms (%u > %u)\n", - _mesa_shader_stage_to_string(i), - sh->Program->info.num_images, - consts->Program[i].MaxImageUniforms); - continue; - } - - 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->Program->info.num_ubos; i++) { - sh->num_combined_uniform_components += - sh->Program->sh.UniformBlocks[i]->UniformBufferSize / 4; - } - } - - if (prog->data->LinkStatus == LINKING_FAILURE) { - delete hiddenUniforms; - return; - } - - 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(consts, prog, uniform_size.num_values); -} diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index b60794b1aa4..f963e747801 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -2676,97 +2676,6 @@ link_intrastage_shaders(void *mem_ctx, return linked; } -/** - * Update the sizes of linked shader uniform arrays to the maximum - * array index used. - * - * From page 81 (page 95 of the PDF) of the OpenGL 2.1 spec: - * - * If one or more elements of an array are active, - * GetActiveUniform will return the name of the array in name, - * subject to the restrictions listed above. The type of the array - * is returned in type. The size parameter contains the highest - * array element index used, plus one. The compiler or linker - * determines the highest index used. There will be only one - * active uniform reported by the GL per uniform array. - - */ -static void -update_array_sizes(struct gl_shader_program *prog) -{ - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - if (prog->_LinkedShaders[i] == NULL) - continue; - - bool types_were_updated = false; - - 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) || - !var->type->is_array()) - continue; - - /* GL_ARB_uniform_buffer_object says that std140 uniforms - * will not be eliminated. Since we always do std140, just - * don't resize arrays in UBOs. - * - * Atomic counters are supposed to get deterministic - * locations assigned based on the declaration ordering and - * sizes, array compaction would mess that up. - * - * Subroutine uniforms are not removed. - */ - if (var->is_in_buffer_block() || var->type->contains_atomic() || - var->type->contains_subroutine() || var->constant_initializer) - continue; - - int size = var->data.max_array_access; - for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) { - if (prog->_LinkedShaders[j] == NULL) - continue; - - foreach_in_list(ir_instruction, node2, prog->_LinkedShaders[j]->ir) { - ir_variable *other_var = node2->as_variable(); - if (!other_var) - continue; - - if (strcmp(var->name, other_var->name) == 0 && - other_var->data.max_array_access > size) { - size = other_var->data.max_array_access; - } - } - } - - if (size + 1 != (int)var->type->length) { - /* If this is a built-in uniform (i.e., it's backed by some - * fixed-function state), adjust the number of state slots to - * match the new array size. The number of slots per array entry - * is not known. It seems safe to assume that the total number of - * slots is an integer multiple of the number of array elements. - * Determine the number of slots per array element by dividing by - * the old (total) size. - */ - const unsigned num_slots = var->get_num_state_slots(); - if (num_slots > 0) { - var->set_num_state_slots((size + 1) - * (num_slots / var->type->length)); - } - - var->type = glsl_type::get_array_instance(var->type->fields.array, - size + 1); - types_were_updated = true; - } - } - - /* Update the types of dereferences in case we changed any. */ - if (types_were_updated) { - deref_type_updater v; - v.run(prog->_LinkedShaders[i]->ir); - } - } -} - /** * Resize tessellation evaluation per-vertex inputs to the size of * tessellation control per-vertex outputs. @@ -3421,49 +3330,6 @@ store_fragdepth_layout(struct gl_shader_program *prog) } } -/** - * Validate shader image resources. - */ -static void -check_image_resources(const struct gl_constants *consts, - const struct gl_extensions *exts, - struct gl_shader_program *prog) -{ - unsigned total_image_units = 0; - unsigned fragment_outputs = 0; - unsigned total_shader_storage_blocks = 0; - - if (!consts->MaxCombinedImageUniforms && - !consts->MaxCombinedShaderStorageBlocks) - return; - - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - struct gl_linked_shader *sh = prog->_LinkedShaders[i]; - - if (sh) { - total_image_units += sh->Program->info.num_images; - total_shader_storage_blocks += sh->Program->info.num_ssbos; - - if (i == MESA_SHADER_FRAGMENT) { - foreach_in_list(ir_instruction, node, sh->ir) { - ir_variable *var = node->as_variable(); - if (var && var->data.mode == ir_var_shader_out) - /* since there are no double fs outputs - pass false */ - fragment_outputs += var->type->count_attribute_slots(false); - } - } - } - } - - if (total_image_units > consts->MaxCombinedImageUniforms) - linker_error(prog, "Too many combined image uniforms\n"); - - if (total_image_units + fragment_outputs + total_shader_storage_blocks > - consts->MaxCombinedShaderOutputResources) - linker_error(prog, "Too many combined image uniforms, shader storage " - " buffers and fragment outputs\n"); -} - /** * Initializes explicit location slots to INACTIVE_UNIFORM_EXPLICIT_LOCATION @@ -4498,27 +4364,6 @@ disable_varying_optimizations_for_sso(struct gl_shader_program *prog) } } -static void -link_and_validate_uniforms(const struct gl_constants *consts, - const struct gl_extensions *exts, - struct gl_shader_program *prog) -{ - assert(!consts->UseNIRGLSLLinker); - - update_array_sizes(prog); - link_assign_uniform_locations(prog, consts); - - if (prog->data->LinkStatus == LINKING_FAILURE) - return; - - link_util_calculate_subroutine_compat(prog); - link_util_check_uniform_resources(consts, prog); - link_util_check_subroutine_resources(prog); - check_image_resources(consts, exts, prog); - link_assign_atomic_counter_resources(consts, prog); - link_check_atomic_counter_resources(consts, prog); -} - static bool link_varyings_and_uniforms(unsigned first, unsigned last, const struct gl_constants *consts, @@ -4566,9 +4411,6 @@ link_varyings_and_uniforms(unsigned first, unsigned last, api, mem_ctx)) return false; - if (!consts->UseNIRGLSLLinker) - link_and_validate_uniforms(consts, exts, prog); - if (!prog->data->LinkStatus) return false; diff --git a/src/compiler/glsl/linker.h b/src/compiler/glsl/linker.h index 9c4d1ffc8e7..b8b12c20305 100644 --- a/src/compiler/glsl/linker.h +++ b/src/compiler/glsl/linker.h @@ -38,14 +38,6 @@ link_function_calls(gl_shader_program *prog, gl_linked_shader *main, extern void link_invalidate_variable_locations(exec_list *ir); -extern void -link_assign_uniform_locations(struct gl_shader_program *prog, - const struct gl_constants *consts); - -extern void -link_set_uniform_initializers(struct gl_shader_program *prog, - unsigned int boolean_true); - extern int link_cross_validate_uniform_block(void *mem_ctx, struct gl_uniform_block **linked_blocks, @@ -82,15 +74,6 @@ void validate_interstage_uniform_blocks(struct gl_shader_program *prog, gl_linked_shader **stages); -extern void -link_assign_atomic_counter_resources(const struct gl_constants *consts, - struct gl_shader_program *prog); - -extern void -link_check_atomic_counter_resources(const struct gl_constants *consts, - struct gl_shader_program *prog); - - extern struct gl_linked_shader * link_intrastage_shaders(void *mem_ctx, struct gl_context *ctx, diff --git a/src/compiler/glsl/meson.build b/src/compiler/glsl/meson.build index da233b30539..4aab8767526 100644 --- a/src/compiler/glsl/meson.build +++ b/src/compiler/glsl/meson.build @@ -140,11 +140,9 @@ files_libglsl = files( 'linker.h', 'linker_util.h', 'linker_util.cpp', - 'link_atomics.cpp', 'link_functions.cpp', 'link_interface_blocks.cpp', 'link_uniforms.cpp', - 'link_uniform_initializers.cpp', 'link_uniform_block_active_visitor.cpp', 'link_uniform_block_active_visitor.h', 'link_uniform_blocks.cpp', diff --git a/src/compiler/glsl/tests/copy_constant_to_storage_tests.cpp b/src/compiler/glsl/tests/copy_constant_to_storage_tests.cpp deleted file mode 100644 index f2d2af6465f..00000000000 --- a/src/compiler/glsl/tests/copy_constant_to_storage_tests.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#include -#include "util/compiler.h" -#include "main/macros.h" -#include "util/ralloc.h" -#include "uniform_initializer_utils.h" - -namespace linker { -extern void -copy_constant_to_storage(union gl_constant_value *storage, - const ir_constant *val, - const enum glsl_base_type base_type, - const unsigned int elements, - unsigned int boolean_true); -} - -class copy_constant_to_storage : public ::testing::Test { -public: - void int_test(unsigned rows); - void uint_test(unsigned rows); - void bool_test(unsigned rows); - void sampler_test(); - void float_test(unsigned columns, unsigned rows); - - virtual void SetUp(); - virtual void TearDown(); - - gl_constant_value storage[17]; - void *mem_ctx; -}; - -void -copy_constant_to_storage::SetUp() -{ - glsl_type_singleton_init_or_ref(); - - this->mem_ctx = ralloc_context(NULL); -} - -void -copy_constant_to_storage::TearDown() -{ - ralloc_free(this->mem_ctx); - this->mem_ctx = NULL; - - glsl_type_singleton_decref(); -} - -void -copy_constant_to_storage::int_test(unsigned rows) -{ - ir_constant *val; - generate_data(mem_ctx, GLSL_TYPE_INT, 1, rows, val); - - const unsigned red_zone_size = ARRAY_SIZE(storage) - val->type->components(); - fill_storage_array_with_sentinels(storage, - val->type->components(), - red_zone_size); - - linker::copy_constant_to_storage(storage, - val, - val->type->base_type, - val->type->components(), - 0xF00F); - - verify_data(storage, 0, val, red_zone_size, 0xF00F); -} - -void -copy_constant_to_storage::uint_test(unsigned rows) -{ - ir_constant *val; - generate_data(mem_ctx, GLSL_TYPE_UINT, 1, rows, val); - - const unsigned red_zone_size = ARRAY_SIZE(storage) - val->type->components(); - fill_storage_array_with_sentinels(storage, - val->type->components(), - red_zone_size); - - linker::copy_constant_to_storage(storage, - val, - val->type->base_type, - val->type->components(), - 0xF00F); - - verify_data(storage, 0, val, red_zone_size, 0xF00F); -} - -void -copy_constant_to_storage::float_test(unsigned columns, unsigned rows) -{ - ir_constant *val; - generate_data(mem_ctx, GLSL_TYPE_FLOAT, columns, rows, val); - - const unsigned red_zone_size = ARRAY_SIZE(storage) - val->type->components(); - fill_storage_array_with_sentinels(storage, - val->type->components(), - red_zone_size); - - linker::copy_constant_to_storage(storage, - val, - val->type->base_type, - val->type->components(), - 0xF00F); - - verify_data(storage, 0, val, red_zone_size, 0xF00F); -} - -void -copy_constant_to_storage::bool_test(unsigned rows) -{ - ir_constant *val; - generate_data(mem_ctx, GLSL_TYPE_BOOL, 1, rows, val); - - const unsigned red_zone_size = ARRAY_SIZE(storage) - val->type->components(); - fill_storage_array_with_sentinels(storage, - val->type->components(), - red_zone_size); - - linker::copy_constant_to_storage(storage, - val, - val->type->base_type, - val->type->components(), - 0xF00F); - - verify_data(storage, 0, val, red_zone_size, 0xF00F); -} - -/** - * The only difference between this test and int_test is that the base type - * passed to \c linker::copy_constant_to_storage is hard-coded to \c - * GLSL_TYPE_SAMPLER instead of using the base type from the constant. - */ -void -copy_constant_to_storage::sampler_test(void) -{ - ir_constant *val; - generate_data(mem_ctx, GLSL_TYPE_INT, 1, 1, val); - - const unsigned red_zone_size = ARRAY_SIZE(storage) - val->type->components(); - fill_storage_array_with_sentinels(storage, - val->type->components(), - red_zone_size); - - linker::copy_constant_to_storage(storage, - val, - GLSL_TYPE_SAMPLER, - val->type->components(), - 0xF00F); - - verify_data(storage, 0, val, red_zone_size, 0xF00F); -} - -TEST_F(copy_constant_to_storage, bool_uniform) -{ - bool_test(1); -} - -TEST_F(copy_constant_to_storage, bvec2_uniform) -{ - bool_test(2); -} - -TEST_F(copy_constant_to_storage, bvec3_uniform) -{ - bool_test(3); -} - -TEST_F(copy_constant_to_storage, bvec4_uniform) -{ - bool_test(4); -} - -TEST_F(copy_constant_to_storage, int_uniform) -{ - int_test(1); -} - -TEST_F(copy_constant_to_storage, ivec2_uniform) -{ - int_test(2); -} - -TEST_F(copy_constant_to_storage, ivec3_uniform) -{ - int_test(3); -} - -TEST_F(copy_constant_to_storage, ivec4_uniform) -{ - int_test(4); -} - -TEST_F(copy_constant_to_storage, uint_uniform) -{ - uint_test(1); -} - -TEST_F(copy_constant_to_storage, uvec2_uniform) -{ - uint_test(2); -} - -TEST_F(copy_constant_to_storage, uvec3_uniform) -{ - uint_test(3); -} - -TEST_F(copy_constant_to_storage, uvec4_uniform) -{ - uint_test(4); -} - -TEST_F(copy_constant_to_storage, float_uniform) -{ - float_test(1, 1); -} - -TEST_F(copy_constant_to_storage, vec2_uniform) -{ - float_test(1, 2); -} - -TEST_F(copy_constant_to_storage, vec3_uniform) -{ - float_test(1, 3); -} - -TEST_F(copy_constant_to_storage, vec4_uniform) -{ - float_test(1, 4); -} - -TEST_F(copy_constant_to_storage, mat2x2_uniform) -{ - float_test(2, 2); -} - -TEST_F(copy_constant_to_storage, mat2x3_uniform) -{ - float_test(2, 3); -} - -TEST_F(copy_constant_to_storage, mat2x4_uniform) -{ - float_test(2, 4); -} - -TEST_F(copy_constant_to_storage, mat3x2_uniform) -{ - float_test(3, 2); -} - -TEST_F(copy_constant_to_storage, mat3x3_uniform) -{ - float_test(3, 3); -} - -TEST_F(copy_constant_to_storage, mat3x4_uniform) -{ - float_test(3, 4); -} - -TEST_F(copy_constant_to_storage, mat4x2_uniform) -{ - float_test(4, 2); -} - -TEST_F(copy_constant_to_storage, mat4x3_uniform) -{ - float_test(4, 3); -} - -TEST_F(copy_constant_to_storage, mat4x4_uniform) -{ - float_test(4, 4); -} - -TEST_F(copy_constant_to_storage, sampler_uniform) -{ - sampler_test(); -} diff --git a/src/compiler/glsl/tests/meson.build b/src/compiler/glsl/tests/meson.build index 4a565bb21c8..3188e18ee01 100644 --- a/src/compiler/glsl/tests/meson.build +++ b/src/compiler/glsl/tests/meson.build @@ -36,23 +36,6 @@ test( protocol : gtest_test_protocol, ) -test( - 'uniform_initializer_test', - executable( - 'uniform_initializer_test', - ['copy_constant_to_storage_tests.cpp', 'set_uniform_initializer_tests.cpp', - 'uniform_initializer_utils.cpp', 'uniform_initializer_utils.h', - ir_expression_operation_h], - cpp_args : [cpp_msvc_compat_args], - gnu_symbol_visibility : 'hidden', - include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_glsl], - link_with : [libglsl, libglsl_util], - dependencies : [dep_thread, idep_gtest, idep_mesautil], - ), - suite : ['compiler', 'glsl'], - protocol : gtest_test_protocol, -) - test( 'sampler_types_test', executable( diff --git a/src/compiler/glsl/tests/set_uniform_initializer_tests.cpp b/src/compiler/glsl/tests/set_uniform_initializer_tests.cpp deleted file mode 100644 index 9f777b50f69..00000000000 --- a/src/compiler/glsl/tests/set_uniform_initializer_tests.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#include -#include "util/compiler.h" -#include "main/shader_types.h" -#include "main/macros.h" -#include "util/ralloc.h" -#include "string_to_uint_map.h" -#include "uniform_initializer_utils.h" - -namespace linker { -extern void -set_uniform_initializer(void *mem_ctx, gl_shader_program *prog, - const char *name, const glsl_type *type, - ir_constant *val, unsigned int boolean_true); -} - -class set_uniform_initializer : public ::testing::Test { -public: - virtual void SetUp(); - virtual void TearDown(); - - /** - * Index of the uniform to be tested. - * - * All of the \c set_uniform_initializer tests create several slots for - * unifroms. All but one of the slots is fake. This field holds the index - * of the slot for the uniform being tested. - */ - unsigned actual_index; - - /** - * Name of the uniform to be tested. - */ - const char *name; - - /** - * Shader program used in the test. - */ - struct gl_shader_program *prog; - - /** - * Ralloc memory context used for all temporary allocations. - */ - void *mem_ctx; -}; - -void -set_uniform_initializer::SetUp() -{ - glsl_type_singleton_init_or_ref(); - - this->mem_ctx = ralloc_context(NULL); - this->prog = rzalloc(NULL, struct gl_shader_program); - this->prog->data = rzalloc(this->prog, struct gl_shader_program_data); - - /* Set default values used by the test cases. - */ - this->actual_index = 1; - this->name = "i"; -} - -void -set_uniform_initializer::TearDown() -{ - ralloc_free(this->mem_ctx); - this->mem_ctx = NULL; - - if (this->prog->UniformHash) - string_to_uint_map_dtor(this->prog->UniformHash); - - ralloc_free(this->prog); - this->prog = NULL; - - glsl_type_singleton_decref(); -} - -/** - * Create some uniform storage for a program. - * - * \param prog Program to get some storage - * \param num_storage Total number of storage slots - * \param index_to_set Storage slot that will actually get a value - * \param name Name for the actual storage slot - * \param type Type for the elements of the actual storage slot - * \param array_size Size for the array of the actual storage slot. This - * should be zero for non-arrays. - */ -static unsigned -establish_uniform_storage(struct gl_shader_program *prog, unsigned num_storage, - unsigned index_to_set, const char *name, - const glsl_type *type, unsigned array_size) -{ - const unsigned elements = MAX2(1, array_size); - const unsigned data_components = elements * type->components(); - const unsigned total_components = MAX2(17, (data_components - + type->components())); - const unsigned red_zone_components = total_components - data_components; - - prog->UniformHash = new string_to_uint_map; - prog->data->UniformStorage = rzalloc_array(prog, struct gl_uniform_storage, - num_storage); - prog->data->NumUniformStorage = num_storage; - - prog->data->UniformStorage[index_to_set].name.string = (char *) name; - prog->data->UniformStorage[index_to_set].type = type; - prog->data->UniformStorage[index_to_set].array_elements = array_size; - for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) { - prog->data->UniformStorage[index_to_set].opaque[sh].index = ~0; - prog->data->UniformStorage[index_to_set].opaque[sh].active = false; - } - prog->data->UniformStorage[index_to_set].num_driver_storage = 0; - prog->data->UniformStorage[index_to_set].driver_storage = NULL; - prog->data->UniformStorage[index_to_set].storage = - rzalloc_array(prog, union gl_constant_value, total_components); - - fill_storage_array_with_sentinels(prog->data->UniformStorage[index_to_set].storage, - data_components, - red_zone_components); - - prog->UniformHash->put(index_to_set, - prog->data->UniformStorage[index_to_set].name.string); - - for (unsigned i = 0; i < num_storage; i++) { - if (i == index_to_set) - continue; - - prog->data->UniformStorage[i].name.string = (char *) "invalid slot"; - prog->data->UniformStorage[i].type = glsl_type::void_type; - prog->data->UniformStorage[i].array_elements = 0; - for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) { - prog->data->UniformStorage[i].opaque[sh].index = ~0; - prog->data->UniformStorage[i].opaque[sh].active = false; - } - prog->data->UniformStorage[i].num_driver_storage = 0; - prog->data->UniformStorage[i].driver_storage = NULL; - prog->data->UniformStorage[i].storage = NULL; - } - - return red_zone_components; -} - -static void -non_array_test(void *mem_ctx, struct gl_shader_program *prog, - unsigned actual_index, const char *name, - enum glsl_base_type base_type, - unsigned columns, unsigned rows) -{ - const glsl_type *const type = - glsl_type::get_instance(base_type, rows, columns); - - unsigned red_zone_components = - establish_uniform_storage(prog, 3, actual_index, name, type, 0); - - ir_constant *val; - generate_data(mem_ctx, base_type, columns, rows, val); - - linker::set_uniform_initializer(mem_ctx, prog, name, type, val, 0xF00F); - - verify_data(prog->data->UniformStorage[actual_index].storage, 0, val, - red_zone_components, 0xF00F); -} - -TEST_F(set_uniform_initializer, int_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 1); -} - -TEST_F(set_uniform_initializer, ivec2_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 2); -} - -TEST_F(set_uniform_initializer, ivec3_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 3); -} - -TEST_F(set_uniform_initializer, ivec4_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 4); -} - -TEST_F(set_uniform_initializer, uint_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 1); -} - -TEST_F(set_uniform_initializer, uvec2_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 2); -} - -TEST_F(set_uniform_initializer, uvec3_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 3); -} - -TEST_F(set_uniform_initializer, uvec4_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 4); -} - -TEST_F(set_uniform_initializer, bool_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 1); -} - -TEST_F(set_uniform_initializer, bvec2_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 2); -} - -TEST_F(set_uniform_initializer, bvec3_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 3); -} - -TEST_F(set_uniform_initializer, bvec4_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 4); -} - -TEST_F(set_uniform_initializer, float_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 2); -} - -TEST_F(set_uniform_initializer, vec2_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 2); -} - -TEST_F(set_uniform_initializer, vec3_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 3); -} - -TEST_F(set_uniform_initializer, vec4_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 4); -} - -TEST_F(set_uniform_initializer, mat2x2_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 2); -} - -TEST_F(set_uniform_initializer, mat2x3_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 3); -} - -TEST_F(set_uniform_initializer, mat2x4_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 4); -} - -TEST_F(set_uniform_initializer, mat3x2_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 2); -} - -TEST_F(set_uniform_initializer, mat3x3_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 3); -} - -TEST_F(set_uniform_initializer, mat3x4_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 4); -} - -TEST_F(set_uniform_initializer, mat4x2_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 2); -} - -TEST_F(set_uniform_initializer, mat4x3_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 3); -} - -TEST_F(set_uniform_initializer, mat4x4_uniform) -{ - non_array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 4); -} - -static void -array_test(void *mem_ctx, struct gl_shader_program *prog, - unsigned actual_index, const char *name, - enum glsl_base_type base_type, - unsigned columns, unsigned rows, unsigned array_size, - unsigned excess_data_size) -{ - const glsl_type *const element_type = - glsl_type::get_instance(base_type, rows, columns); - - const unsigned red_zone_components = - establish_uniform_storage(prog, 3, actual_index, name, element_type, - array_size); - - /* The constant value generated may have more array elements than the - * uniform that it initializes. In the real compiler and linker this can - * happen when a uniform array is compacted because some of the tail - * elements are not used. In this case, the type of the uniform will be - * modified, but the initializer will not. - */ - ir_constant *val; - generate_array_data(mem_ctx, base_type, columns, rows, - array_size + excess_data_size, val); - - linker::set_uniform_initializer(mem_ctx, prog, name, element_type, val, - 0xF00F); - - verify_data(prog->data->UniformStorage[actual_index].storage, array_size, - val, red_zone_components, 0xF00F); -} - -TEST_F(set_uniform_initializer, int_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 1, 4, 0); -} - -TEST_F(set_uniform_initializer, ivec2_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 2, 4, 0); -} - -TEST_F(set_uniform_initializer, ivec3_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 3, 4, 0); -} - -TEST_F(set_uniform_initializer, ivec4_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 4, 4, 0); -} - -TEST_F(set_uniform_initializer, uint_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 1, 4, 0); -} - -TEST_F(set_uniform_initializer, uvec2_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 2, 4, 0); -} - -TEST_F(set_uniform_initializer, uvec3_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 3, 4, 0); -} - -TEST_F(set_uniform_initializer, uvec4_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 4, 4, 0); -} - -TEST_F(set_uniform_initializer, bool_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 1, 4, 0); -} - -TEST_F(set_uniform_initializer, bvec2_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 2, 4, 0); -} - -TEST_F(set_uniform_initializer, bvec3_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 3, 4, 0); -} - -TEST_F(set_uniform_initializer, bvec4_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 4, 4, 0); -} - -TEST_F(set_uniform_initializer, float_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 1, 4, 0); -} - -TEST_F(set_uniform_initializer, vec2_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 2, 4, 0); -} - -TEST_F(set_uniform_initializer, vec3_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 3, 4, 0); -} - -TEST_F(set_uniform_initializer, vec4_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 4, 4, 0); -} - -TEST_F(set_uniform_initializer, mat2x2_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 2, 4, 0); -} - -TEST_F(set_uniform_initializer, mat2x3_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 3, 4, 0); -} - -TEST_F(set_uniform_initializer, mat2x4_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 4, 4, 0); -} - -TEST_F(set_uniform_initializer, mat3x2_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 2, 4, 0); -} - -TEST_F(set_uniform_initializer, mat3x3_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 3, 4, 0); -} - -TEST_F(set_uniform_initializer, mat3x4_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 4, 4, 0); -} - -TEST_F(set_uniform_initializer, mat4x2_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 2, 4, 0); -} - -TEST_F(set_uniform_initializer, mat4x3_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 3, 4, 0); -} - -TEST_F(set_uniform_initializer, mat4x4_array_uniform) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 4, 4, 0); -} - -TEST_F(set_uniform_initializer, int_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 1, 4, 5); -} - -TEST_F(set_uniform_initializer, ivec2_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 2, 4, 5); -} - -TEST_F(set_uniform_initializer, ivec3_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 3, 4, 5); -} - -TEST_F(set_uniform_initializer, ivec4_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_INT, 1, 4, 4, 5); -} - -TEST_F(set_uniform_initializer, uint_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 1, 4, 5); -} - -TEST_F(set_uniform_initializer, uvec2_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 2, 4, 5); -} - -TEST_F(set_uniform_initializer, uvec3_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 3, 4, 5); -} - -TEST_F(set_uniform_initializer, uvec4_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_UINT, 1, 4, 4, 5); -} - -TEST_F(set_uniform_initializer, bool_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 1, 4, 5); -} - -TEST_F(set_uniform_initializer, bvec2_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 2, 4, 5); -} - -TEST_F(set_uniform_initializer, bvec3_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 3, 4, 5); -} - -TEST_F(set_uniform_initializer, bvec4_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_BOOL, 1, 4, 4, 5); -} - -TEST_F(set_uniform_initializer, float_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 1, 4, 5); -} - -TEST_F(set_uniform_initializer, vec2_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 2, 4, 5); -} - -TEST_F(set_uniform_initializer, vec3_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 3, 4, 5); -} - -TEST_F(set_uniform_initializer, vec4_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 1, 4, 4, 5); -} - -TEST_F(set_uniform_initializer, mat2x2_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 2, 4, 5); -} - -TEST_F(set_uniform_initializer, mat2x3_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 3, 4, 5); -} - -TEST_F(set_uniform_initializer, mat2x4_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 2, 4, 4, 5); -} - -TEST_F(set_uniform_initializer, mat3x2_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 2, 4, 5); -} - -TEST_F(set_uniform_initializer, mat3x3_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 3, 4, 5); -} - -TEST_F(set_uniform_initializer, mat3x4_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 3, 4, 4, 5); -} - -TEST_F(set_uniform_initializer, mat4x2_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 2, 4, 5); -} - -TEST_F(set_uniform_initializer, mat4x3_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 3, 4, 5); -} - -TEST_F(set_uniform_initializer, mat4x4_array_uniform_excess_initializer) -{ - array_test(mem_ctx, prog, actual_index, name, GLSL_TYPE_FLOAT, 4, 4, 4, 5); -} diff --git a/src/compiler/glsl/tests/uniform_initializer_utils.cpp b/src/compiler/glsl/tests/uniform_initializer_utils.cpp deleted file mode 100644 index 42c52013373..00000000000 --- a/src/compiler/glsl/tests/uniform_initializer_utils.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#include -#include "main/macros.h" -#include "util/ralloc.h" -#include "uniform_initializer_utils.h" -#include - -void -fill_storage_array_with_sentinels(gl_constant_value *storage, - unsigned data_size, - unsigned red_zone_size) -{ - for (unsigned i = 0; i < data_size; i++) - storage[i].u = 0xDEADBEEF; - - for (unsigned i = 0; i < red_zone_size; i++) - storage[data_size + i].u = 0xBADDC0DE; -} - -/** - * Verfiy that markers past the end of the real uniform are unmodified - */ -static ::testing::AssertionResult -red_zone_is_intact(gl_constant_value *storage, - unsigned data_size, - unsigned red_zone_size) -{ - for (unsigned i = 0; i < red_zone_size; i++) { - const unsigned idx = data_size + i; - - if (storage[idx].u != 0xBADDC0DE) - return ::testing::AssertionFailure() - << "storage[" << idx << "].u = " << storage[idx].u - << ", exepected data values = " << data_size - << ", red-zone size = " << red_zone_size; - } - - return ::testing::AssertionSuccess(); -} - -static const int values[] = { - 2, 0, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 -}; - -/** - * Generate a single data element. - * - * This is by both \c generate_data and \c generate_array_data to create the - * data. - */ -static void -generate_data_element(void *mem_ctx, const glsl_type *type, - ir_constant *&val, unsigned data_index_base) -{ - /* Set the initial data values for the generated constant. - */ - ir_constant_data data; - memset(&data, 0, sizeof(data)); - for (unsigned i = 0; i < type->components(); i++) { - const unsigned idx = (i + data_index_base) % ARRAY_SIZE(values); - switch (type->base_type) { - case GLSL_TYPE_UINT: - case GLSL_TYPE_INT: - case GLSL_TYPE_SAMPLER: - case GLSL_TYPE_TEXTURE: - case GLSL_TYPE_IMAGE: - data.i[i] = values[idx]; - break; - case GLSL_TYPE_FLOAT: - data.f[i] = float(values[idx]); - break; - case GLSL_TYPE_BOOL: - data.b[i] = bool(values[idx]); - break; - case GLSL_TYPE_DOUBLE: - data.d[i] = double(values[idx]); - break; - case GLSL_TYPE_UINT64: - data.u64[i] = (uint64_t) values[idx]; - break; - case GLSL_TYPE_INT64: - data.i64[i] = (int64_t) values[idx]; - break; - case GLSL_TYPE_ATOMIC_UINT: - case GLSL_TYPE_STRUCT: - case GLSL_TYPE_ARRAY: - case GLSL_TYPE_VOID: - case GLSL_TYPE_ERROR: - case GLSL_TYPE_INTERFACE: - case GLSL_TYPE_SUBROUTINE: - case GLSL_TYPE_FUNCTION: - case GLSL_TYPE_FLOAT16: - case GLSL_TYPE_UINT16: - case GLSL_TYPE_INT16: - case GLSL_TYPE_UINT8: - case GLSL_TYPE_INT8: - ASSERT_TRUE(false); - break; - } - } - - /* Generate and verify the constant. - */ - val = new(mem_ctx) ir_constant(type, &data); - - for (unsigned i = 0; i < type->components(); i++) { - switch (type->base_type) { - case GLSL_TYPE_UINT: - case GLSL_TYPE_INT: - case GLSL_TYPE_SAMPLER: - case GLSL_TYPE_TEXTURE: - case GLSL_TYPE_IMAGE: - ASSERT_EQ(data.i[i], val->value.i[i]); - break; - case GLSL_TYPE_FLOAT: - ASSERT_EQ(data.f[i], val->value.f[i]); - break; - case GLSL_TYPE_BOOL: - ASSERT_EQ(data.b[i], val->value.b[i]); - break; - case GLSL_TYPE_DOUBLE: - ASSERT_EQ(data.d[i], val->value.d[i]); - break; - case GLSL_TYPE_UINT64: - ASSERT_EQ(data.u64[i], val->value.u64[i]); - break; - case GLSL_TYPE_INT64: - ASSERT_EQ(data.i64[i], val->value.i64[i]); - break; - case GLSL_TYPE_ATOMIC_UINT: - case GLSL_TYPE_STRUCT: - case GLSL_TYPE_ARRAY: - case GLSL_TYPE_VOID: - case GLSL_TYPE_ERROR: - case GLSL_TYPE_INTERFACE: - case GLSL_TYPE_SUBROUTINE: - case GLSL_TYPE_FUNCTION: - case GLSL_TYPE_FLOAT16: - case GLSL_TYPE_UINT16: - case GLSL_TYPE_INT16: - case GLSL_TYPE_UINT8: - case GLSL_TYPE_INT8: - ASSERT_TRUE(false); - break; - } - } -} - -void -generate_data(void *mem_ctx, enum glsl_base_type base_type, - unsigned columns, unsigned rows, - ir_constant *&val) -{ - /* Determine what the type of the generated constant should be. - */ - const glsl_type *const type = - glsl_type::get_instance(base_type, rows, columns); - ASSERT_FALSE(type->is_error()); - - generate_data_element(mem_ctx, type, val, 0); -} - -void -generate_array_data(void *mem_ctx, enum glsl_base_type base_type, - unsigned columns, unsigned rows, unsigned array_size, - ir_constant *&val) -{ - /* Determine what the type of the generated constant should be. - */ - const glsl_type *const element_type = - glsl_type::get_instance(base_type, rows, columns); - ASSERT_FALSE(element_type->is_error()); - - const glsl_type *const array_type = - glsl_type::get_array_instance(element_type, array_size); - ASSERT_FALSE(array_type->is_error()); - - /* Set the initial data values for the generated constant. - */ - exec_list values_for_array; - for (unsigned i = 0; i < array_size; i++) { - ir_constant *element; - - generate_data_element(mem_ctx, element_type, element, i); - values_for_array.push_tail(element); - } - - val = new(mem_ctx) ir_constant(array_type, &values_for_array); -} - -static uint64_t -uint64_storage(union gl_constant_value *storage) -{ - uint64_t val; - memcpy(&val, &storage->i, sizeof(uint64_t)); - return val; -} - -static uint64_t -double_storage(union gl_constant_value *storage) -{ - double val; - memcpy(&val, &storage->i, sizeof(double)); - return val; -} - -/** - * Verify that the data stored for the uniform matches the initializer - * - * \param storage Backing storage for the uniform - * \param storage_array_size Array size of the backing storage. This must be - * less than or equal to the array size of the type - * of \c val. If \c val is not an array, this must - * be zero. - * \param val Value of the initializer for the unifrom. - * \param red_zone - */ -void -verify_data(gl_constant_value *storage, unsigned storage_array_size, - ir_constant *val, unsigned red_zone_size, - unsigned int boolean_true) -{ - if (val->type->is_array()) { - const glsl_type *const element_type = val->const_elements[0]->type; - - for (unsigned i = 0; i < storage_array_size; i++) { - verify_data(storage + (i * element_type->components()), 0, - val->const_elements[i], 0, boolean_true); - } - - const unsigned components = element_type->components(); - - if (red_zone_size > 0) { - EXPECT_TRUE(red_zone_is_intact(storage, - storage_array_size * components, - red_zone_size)); - } - } else { - ASSERT_EQ(0u, storage_array_size); - for (unsigned i = 0; i < val->type->components(); i++) { - switch (val->type->base_type) { - case GLSL_TYPE_UINT: - case GLSL_TYPE_INT: - case GLSL_TYPE_SAMPLER: - case GLSL_TYPE_TEXTURE: - case GLSL_TYPE_IMAGE: - EXPECT_EQ(val->value.i[i], storage[i].i); - break; - case GLSL_TYPE_FLOAT: - EXPECT_EQ(val->value.f[i], storage[i].f); - break; - case GLSL_TYPE_BOOL: - EXPECT_EQ(val->value.b[i] ? boolean_true : 0, storage[i].i); - break; - case GLSL_TYPE_DOUBLE: - EXPECT_EQ(val->value.d[i], double_storage(&storage[i*2])); - break; - case GLSL_TYPE_UINT64: - EXPECT_EQ(val->value.u64[i], uint64_storage(&storage[i*2])); - break; - case GLSL_TYPE_INT64: - EXPECT_EQ(val->value.i64[i], uint64_storage(&storage[i*2])); - break; - case GLSL_TYPE_ATOMIC_UINT: - case GLSL_TYPE_STRUCT: - case GLSL_TYPE_ARRAY: - case GLSL_TYPE_VOID: - case GLSL_TYPE_ERROR: - case GLSL_TYPE_INTERFACE: - case GLSL_TYPE_SUBROUTINE: - case GLSL_TYPE_FUNCTION: - case GLSL_TYPE_FLOAT16: - case GLSL_TYPE_UINT16: - case GLSL_TYPE_INT16: - case GLSL_TYPE_UINT8: - case GLSL_TYPE_INT8: - ASSERT_TRUE(false); - break; - } - } - - if (red_zone_size > 0) { - EXPECT_TRUE(red_zone_is_intact(storage, - val->type->components(), - red_zone_size)); - } - } -} diff --git a/src/compiler/glsl/tests/uniform_initializer_utils.h b/src/compiler/glsl/tests/uniform_initializer_utils.h deleted file mode 100644 index f65254cdc88..00000000000 --- a/src/compiler/glsl/tests/uniform_initializer_utils.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef GLSL_UNIFORM_INITIALIZER_UTILS_H -#define GLSL_UNIFORM_INITIALIZER_UTILS_H - -#include "program/prog_parameter.h" -#include "ir.h" -#include "ir_uniform.h" - -extern void -fill_storage_array_with_sentinels(gl_constant_value *storage, - unsigned data_size, - unsigned red_zone_size); - -extern void -generate_data(void *mem_ctx, enum glsl_base_type base_type, - unsigned columns, unsigned rows, - ir_constant *&val); - -extern void -generate_array_data(void *mem_ctx, enum glsl_base_type base_type, - unsigned columns, unsigned rows, unsigned array_size, - ir_constant *&val); - -extern void -verify_data(gl_constant_value *storage, unsigned storage_array_size, - ir_constant *val, unsigned red_zone_size, - unsigned int boolean_true); - -#endif /* GLSL_UNIFORM_INITIALIZER_UTILS_H */ diff --git a/src/mesa/main/consts_exts.h b/src/mesa/main/consts_exts.h index 279ad201ada..20fc47af5ab 100644 --- a/src/mesa/main/consts_exts.h +++ b/src/mesa/main/consts_exts.h @@ -953,9 +953,6 @@ struct gl_constants /** Is the drivers uniform storage packed or padded to 16 bytes. */ bool PackedDriverUniformStorage; - /** Does the driver make use of the NIR based GLSL linker */ - bool UseNIRGLSLLinker; - /** Wether or not glBitmap uses red textures rather than alpha */ bool BitmapUsesRed; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 3172f427ae1..f306eea9237 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -699,14 +699,11 @@ st_create_context_priv(struct gl_context *ctx, struct pipe_context *pipe, ctx->Const.ShaderCompilerOptions[MESA_SHADER_TESS_EVAL].PositionAlwaysPrecise = options->vs_position_always_precise; - ctx->Const.UseNIRGLSLLinker = true; - /* NIR drivers that support tess shaders and compact arrays need to use * GLSLTessLevelsAsInputs / PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS. The NIR * linker doesn't support linking these as compat arrays of sysvals. */ assert(ctx->Const.GLSLTessLevelsAsInputs || - !ctx->Const.UseNIRGLSLLinker || !screen->get_param(screen, PIPE_CAP_NIR_COMPACT_ARRAYS) || !ctx->Extensions.ARB_tessellation_shader);