Module: Mesa Branch: main Commit: 72ad0db505669835842158123f09646b8039b8ad URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=72ad0db505669835842158123f09646b8039b8ad
Author: Timothy Arceri <tarc...@itsqueeze.com> Date: Wed Dec 6 13:20:48 2023 +1100 glsl: remove now unused GLSL IR block linker This is now done in the NIR linker instead. Reviewed-by: Alejandro Piñeiro <apinhe...@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26534> --- .../glsl/link_uniform_block_active_visitor.cpp | 294 ------------- .../glsl/link_uniform_block_active_visitor.h | 82 ---- src/compiler/glsl/link_uniform_blocks.cpp | 457 --------------------- src/compiler/glsl/link_uniforms.cpp | 284 ------------- src/compiler/glsl/linker.h | 126 ------ src/compiler/glsl/meson.build | 3 - 6 files changed, 1246 deletions(-) diff --git a/src/compiler/glsl/link_uniform_block_active_visitor.cpp b/src/compiler/glsl/link_uniform_block_active_visitor.cpp deleted file mode 100644 index bd22e91145d..00000000000 --- a/src/compiler/glsl/link_uniform_block_active_visitor.cpp +++ /dev/null @@ -1,294 +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 "link_uniform_block_active_visitor.h" -#include "program.h" -#include "linker_util.h" - -static link_uniform_block_active * -process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var) -{ - const hash_entry *const existing_block = - _mesa_hash_table_search(ht, glsl_get_type_name(var->get_interface_type())); - - const glsl_type *const block_type = var->is_interface_instance() - ? var->type : var->get_interface_type(); - - - /* If a block with this block-name has not previously been seen, add it. - * If a block with this block-name has been seen, it must be identical to - * the block currently being examined. - */ - if (existing_block == NULL) { - link_uniform_block_active *const b = - rzalloc(mem_ctx, struct link_uniform_block_active); - - b->type = block_type; - b->has_instance_name = var->is_interface_instance(); - b->is_shader_storage = var->data.mode == ir_var_shader_storage; - - if (var->data.explicit_binding) { - b->has_binding = true; - b->binding = var->data.binding; - } else { - b->has_binding = false; - b->binding = 0; - } - - _mesa_hash_table_insert(ht, glsl_get_type_name(var->get_interface_type()), (void *) b); - return b; - } else { - link_uniform_block_active *const b = - (link_uniform_block_active *) existing_block->data; - - if (b->type != block_type - || b->has_instance_name != var->is_interface_instance()) - return NULL; - else - return b; - } - - assert(!"Should not get here."); - return NULL; -} - -/* For arrays of arrays this function will give us a middle ground between - * detecting inactive uniform blocks and structuring them in a way that makes - * it easy to calculate the offset for indirect indexing. - * - * For example given the shader: - * - * uniform ArraysOfArraysBlock - * { - * vec4 a; - * } i[3][4][5]; - * - * void main() - * { - * vec4 b = i[0][1][1].a; - * gl_Position = i[2][2][3].a + b; - * } - * - * There are only 2 active blocks above but for the sake of indirect indexing - * and not over complicating the code we will end up with a count of 8. Here - * each dimension has 2 different indices counted so we end up with 2*2*2 - */ -static struct uniform_block_array_elements ** -process_arrays(void *mem_ctx, ir_dereference_array *ir, - struct link_uniform_block_active *block) -{ - if (ir) { - struct uniform_block_array_elements **ub_array_ptr = - process_arrays(mem_ctx, ir->array->as_dereference_array(), block); - if (*ub_array_ptr == NULL) { - *ub_array_ptr = rzalloc(mem_ctx, struct uniform_block_array_elements); - (*ub_array_ptr)->ir = ir; - (*ub_array_ptr)->aoa_size = - ir->array->type->arrays_of_arrays_size(); - } - - struct uniform_block_array_elements *ub_array = *ub_array_ptr; - ir_constant *c = ir->array_index->as_constant(); - if (c) { - /* Index is a constant, so mark just that element used, if not - * already. - */ - const unsigned idx = c->get_uint_component(0); - - unsigned i; - for (i = 0; i < ub_array->num_array_elements; i++) { - if (ub_array->array_elements[i] == idx) - break; - } - - assert(i <= ub_array->num_array_elements); - - if (i == ub_array->num_array_elements) { - ub_array->array_elements = reralloc(mem_ctx, - ub_array->array_elements, - unsigned, - ub_array->num_array_elements + 1); - - ub_array->array_elements[ub_array->num_array_elements] = idx; - - ub_array->num_array_elements++; - } - } else { - /* The array index is not a constant, so mark the entire array used. */ - assert(ir->array->type->is_array()); - if (ub_array->num_array_elements < ir->array->type->length) { - ub_array->num_array_elements = ir->array->type->length; - ub_array->array_elements = reralloc(mem_ctx, - ub_array->array_elements, - unsigned, - ub_array->num_array_elements); - - for (unsigned i = 0; i < ub_array->num_array_elements; i++) { - ub_array->array_elements[i] = i; - } - } - } - - return &ub_array->array; - } else { - return &block->array; - } -} - -ir_visitor_status -link_uniform_block_active_visitor::visit(ir_variable *var) -{ - if (!var->is_in_buffer_block()) - return visit_continue; - - /* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec says: - * - * "All members of a named uniform block declared with a shared or - * std140 layout qualifier are considered active, even if they are not - * referenced in any shader in the program. The uniform block itself is - * also considered active, even if no member of the block is - * referenced." - */ - if (var->get_interface_type_packing() == GLSL_INTERFACE_PACKING_PACKED) - return visit_continue; - - /* Process the block. Bail if there was an error. */ - link_uniform_block_active *const b = - process_block(this->mem_ctx, this->ht, var); - if (b == NULL) { - linker_error(this->prog, - "uniform block `%s' has mismatching definitions", - glsl_get_type_name(var->get_interface_type())); - this->success = false; - return visit_stop; - } - - assert(b->array == NULL); - assert(b->type != NULL); - assert(!b->type->is_array() || b->has_instance_name); - - /* For uniform block arrays declared with a shared or std140 layout - * qualifier, mark all its instances as used. - */ - const glsl_type *type = b->type; - struct uniform_block_array_elements **ub_array = &b->array; - while (type->is_array()) { - assert(b->type->length > 0); - - *ub_array = rzalloc(this->mem_ctx, struct uniform_block_array_elements); - (*ub_array)->num_array_elements = type->length; - (*ub_array)->array_elements = reralloc(this->mem_ctx, - (*ub_array)->array_elements, - unsigned, - (*ub_array)->num_array_elements); - (*ub_array)->aoa_size = type->arrays_of_arrays_size(); - - for (unsigned i = 0; i < (*ub_array)->num_array_elements; i++) { - (*ub_array)->array_elements[i] = i; - } - ub_array = &(*ub_array)->array; - type = type->fields.array; - } - - return visit_continue; -} - -ir_visitor_status -link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir) -{ - /* cycle through arrays of arrays */ - ir_dereference_array *base_ir = ir; - while (base_ir->array->ir_type == ir_type_dereference_array) - base_ir = base_ir->array->as_dereference_array(); - - ir_dereference_variable *const d = - base_ir->array->as_dereference_variable(); - ir_variable *const var = (d == NULL) ? NULL : d->var; - - /* If the r-value being dereferenced is not a variable (e.g., a field of a - * structure) or is not a uniform block instance, continue. - * - * WARNING: It is not enough for the variable to be part of uniform block. - * It must represent the entire block. Arrays (or matrices) inside blocks - * that lack an instance name are handled by the ir_dereference_variable - * function. - */ - if (var == NULL - || !var->is_in_buffer_block() - || !var->is_interface_instance()) - return visit_continue; - - /* Process the block. Bail if there was an error. */ - link_uniform_block_active *const b = - process_block(this->mem_ctx, this->ht, var); - if (b == NULL) { - linker_error(prog, - "uniform block `%s' has mismatching definitions", - glsl_get_type_name(var->get_interface_type())); - this->success = false; - return visit_stop; - } - - /* Block arrays must be declared with an instance name. - */ - assert(b->has_instance_name); - assert(b->type != NULL); - - /* If the block array was declared with a shared or std140 layout - * qualifier, all its instances have been already marked as used in - * link_uniform_block_active_visitor::visit(ir_variable *). - */ - if (var->get_interface_type_packing() == GLSL_INTERFACE_PACKING_PACKED) { - b->var = var; - process_arrays(this->mem_ctx, ir, b); - } - - return visit_continue_with_parent; -} - -ir_visitor_status -link_uniform_block_active_visitor::visit(ir_dereference_variable *ir) -{ - ir_variable *var = ir->var; - - if (!var->is_in_buffer_block()) - return visit_continue; - - assert(!var->is_interface_instance() || !var->type->is_array()); - - /* Process the block. Bail if there was an error. */ - link_uniform_block_active *const b = - process_block(this->mem_ctx, this->ht, var); - if (b == NULL) { - linker_error(this->prog, - "uniform block `%s' has mismatching definitions", - glsl_get_type_name(var->get_interface_type())); - this->success = false; - return visit_stop; - } - - assert(b->array == NULL); - assert(b->type != NULL); - - return visit_continue; -} diff --git a/src/compiler/glsl/link_uniform_block_active_visitor.h b/src/compiler/glsl/link_uniform_block_active_visitor.h deleted file mode 100644 index fed81684403..00000000000 --- a/src/compiler/glsl/link_uniform_block_active_visitor.h +++ /dev/null @@ -1,82 +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. - */ - -#ifndef LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H -#define LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H - -#include "ir.h" -#include "util/hash_table.h" - -struct uniform_block_array_elements { - unsigned *array_elements; - unsigned num_array_elements; - /** - * Size of the array before array-trimming optimizations. - * - * Locations are only assigned to active array elements, but the location - * values are calculated as if all elements are active. The total number - * of elements in an array including the elements in arrays of arrays before - * inactive elements are removed is needed to be perform that calculation. - */ - unsigned aoa_size; - - ir_dereference_array *ir; - - struct uniform_block_array_elements *array; -}; - -struct link_uniform_block_active { - const glsl_type *type; - ir_variable *var; - - struct uniform_block_array_elements *array; - - unsigned binding; - - bool has_instance_name; - bool has_binding; - bool is_shader_storage; -}; - -class link_uniform_block_active_visitor : public ir_hierarchical_visitor { -public: - link_uniform_block_active_visitor(void *mem_ctx, struct hash_table *ht, - struct gl_shader_program *prog) - : success(true), prog(prog), ht(ht), mem_ctx(mem_ctx) - { - /* empty */ - } - - virtual ir_visitor_status visit_enter(ir_dereference_array *); - virtual ir_visitor_status visit(ir_dereference_variable *); - virtual ir_visitor_status visit(ir_variable *); - - bool success; - -private: - struct gl_shader_program *prog; - struct hash_table *ht; - void *mem_ctx; -}; - -#endif /* LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H */ diff --git a/src/compiler/glsl/link_uniform_blocks.cpp b/src/compiler/glsl/link_uniform_blocks.cpp index 67482819c5f..0da7ec43dfd 100644 --- a/src/compiler/glsl/link_uniform_blocks.cpp +++ b/src/compiler/glsl/link_uniform_blocks.cpp @@ -22,464 +22,7 @@ */ #include "ir.h" -#include "linker.h" -#include "ir_uniform.h" -#include "link_uniform_block_active_visitor.h" -#include "util/hash_table.h" -#include "util/u_math.h" -#include "program.h" -#include "main/errors.h" #include "main/shader_types.h" -#include "main/consts_exts.h" - -namespace { - -class ubo_visitor : public program_resource_visitor { -public: - ubo_visitor(void *mem_ctx, gl_uniform_buffer_variable *variables, - unsigned num_variables, struct gl_shader_program *prog, - bool use_std430_as_default) - : index(0), offset(0), buffer_size(0), variables(variables), - num_variables(num_variables), mem_ctx(mem_ctx), - is_array_instance(false), prog(prog), - use_std430_as_default(use_std430_as_default) - { - /* empty */ - } - - void process(const glsl_type *type, const char *name) - { - this->offset = 0; - this->buffer_size = 0; - this->is_array_instance = strchr(name, ']') != NULL; - this->program_resource_visitor::process(type, name, - use_std430_as_default); - } - - unsigned index; - unsigned offset; - unsigned buffer_size; - gl_uniform_buffer_variable *variables; - unsigned num_variables; - void *mem_ctx; - bool is_array_instance; - struct gl_shader_program *prog; - -private: - virtual void enter_record(const glsl_type *type, const char *, - bool row_major, - const enum glsl_interface_packing packing) - { - assert(type->is_struct()); - if (packing == GLSL_INTERFACE_PACKING_STD430) - this->offset = align( - this->offset, type->std430_base_alignment(row_major)); - else - this->offset = align( - this->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 is the last field of a structure, apply rule #9. The - * ARB_uniform_buffer_object spec says: - * - * The structure may have padding at the end; the base offset of the - * member following the sub-structure is rounded up to the next - * multiple of the base alignment of the structure. - */ - if (packing == GLSL_INTERFACE_PACKING_STD430) - this->offset = align( - this->offset, type->std430_base_alignment(row_major)); - else - this->offset = align( - this->offset, type->std140_base_alignment(row_major)); - } - - virtual void set_buffer_offset(unsigned offset) - { - this->offset = offset; - } - - virtual void visit_field(const glsl_type *type, const char *name, - bool row_major, const glsl_type *, - const enum glsl_interface_packing packing, - bool last_field) - { - assert(this->index < this->num_variables); - - gl_uniform_buffer_variable *v = &this->variables[this->index++]; - - v->Name = ralloc_strdup(mem_ctx, name); - v->Type = type; - v->RowMajor = type->without_array()->is_matrix() && row_major; - - if (this->is_array_instance) { - v->IndexName = ralloc_strdup(mem_ctx, name); - - char *open_bracket = strchr(v->IndexName, '['); - assert(open_bracket != NULL); - - char *close_bracket = strchr(open_bracket, '.') - 1; - assert(close_bracket != NULL); - - /* Length of the tail without the ']' but with the NUL. - */ - unsigned len = strlen(close_bracket + 1) + 1; - - memmove(open_bracket, close_bracket + 1, len); - } else { - v->IndexName = v->Name; - } - - unsigned alignment = 0; - unsigned size = 0; - - /* The ARB_program_interface_query spec says: - * - * If the final member of an active shader storage block is array - * with no declared size, the minimum buffer size is computed - * assuming the array was declared as an array with one element. - * - * For that reason, we use the base type of the unsized array to - * calculate its size. We don't need to check if the unsized array is - * the last member of a shader storage block (that check was already - * done by the parser). - */ - const glsl_type *type_for_size = type; - if (type->is_unsized_array()) { - if (!last_field) { - linker_error(prog, "unsized array `%s' definition: " - "only last member of a shader storage block " - "can be defined as unsized array", - name); - } - - type_for_size = type->without_array(); - } - - if (packing == GLSL_INTERFACE_PACKING_STD430) { - alignment = type->std430_base_alignment(v->RowMajor); - size = type_for_size->std430_size(v->RowMajor); - } else { - alignment = type->std140_base_alignment(v->RowMajor); - size = type_for_size->std140_size(v->RowMajor); - } - - this->offset = align(this->offset, alignment); - v->Offset = this->offset; - - this->offset += size; - - /* The ARB_uniform_buffer_object spec says: - * - * For uniform blocks laid out according to [std140] rules, the - * minimum buffer object size returned by the UNIFORM_BLOCK_DATA_SIZE - * query is derived by taking the offset of the last basic machine - * unit consumed by the last uniform of the uniform block (including - * any end-of-array or end-of-structure padding), adding one, and - * rounding up to the next multiple of the base alignment required - * for a vec4. - */ - this->buffer_size = align(this->offset, 16); - } - - bool use_std430_as_default; -}; - -class count_block_size : public program_resource_visitor { -public: - count_block_size() : num_active_uniforms(0) - { - /* empty */ - } - - unsigned num_active_uniforms; - -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 */) - { - this->num_active_uniforms++; - } -}; - -} /* anonymous namespace */ - -struct block { - const glsl_type *type; - bool has_instance_name; -}; - -static void process_block_array_leaf(const char *name, gl_uniform_block *blocks, - ubo_visitor *parcel, - gl_uniform_buffer_variable *variables, - const struct link_uniform_block_active *const b, - unsigned *block_index, - unsigned binding_offset, - unsigned linearized_index, - const struct gl_constants *consts, - struct gl_shader_program *prog); - -/** - * - * \param first_index Value of \c block_index for the first element of the - * array. - */ -static void -process_block_array(struct uniform_block_array_elements *ub_array, char **name, - size_t name_length, gl_uniform_block *blocks, - ubo_visitor *parcel, gl_uniform_buffer_variable *variables, - const struct link_uniform_block_active *const b, - unsigned *block_index, unsigned binding_offset, - const struct gl_constants *consts, - struct gl_shader_program *prog, - unsigned first_index) -{ - for (unsigned j = 0; j < ub_array->num_array_elements; j++) { - size_t new_length = name_length; - - unsigned int element_idx = ub_array->array_elements[j]; - /* Append the subscript to the current variable name */ - ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", element_idx); - - if (ub_array->array) { - unsigned binding_stride = binding_offset + (element_idx * - ub_array->array->aoa_size); - process_block_array(ub_array->array, name, new_length, blocks, - parcel, variables, b, block_index, - binding_stride, consts, prog, first_index); - } else { - process_block_array_leaf(*name, blocks, - parcel, variables, b, block_index, - binding_offset + element_idx, - *block_index - first_index, consts, prog); - } - } -} - -static void -process_block_array_leaf(const char *name, - gl_uniform_block *blocks, - ubo_visitor *parcel, gl_uniform_buffer_variable *variables, - const struct link_uniform_block_active *const b, - unsigned *block_index, unsigned binding_offset, - unsigned linearized_index, - const struct gl_constants *consts, - struct gl_shader_program *prog) -{ - unsigned i = *block_index; - const glsl_type *type = b->type->without_array(); - - blocks[i].name.string = ralloc_strdup(blocks, name); - resource_name_updated(&blocks[i].name); - blocks[i].Uniforms = &variables[(*parcel).index]; - - /* The ARB_shading_language_420pack spec says: - * - * If the binding identifier is used with a uniform block instanced as - * an array then the first element of the array takes the specified - * block binding and each subsequent element takes the next consecutive - * uniform block binding point. - */ - blocks[i].Binding = (b->has_binding) ? b->binding + binding_offset : 0; - - blocks[i].UniformBufferSize = 0; - blocks[i]._Packing = glsl_interface_packing(type->interface_packing); - blocks[i]._RowMajor = type->get_interface_row_major(); - blocks[i].linearized_array_index = linearized_index; - - parcel->process(type, b->has_instance_name ? blocks[i].name.string : ""); - - blocks[i].UniformBufferSize = parcel->buffer_size; - - /* Check SSBO size is lower than maximum supported size for SSBO */ - if (b->is_shader_storage && - parcel->buffer_size > consts->MaxShaderStorageBlockSize) { - linker_error(prog, "shader storage block `%s' has size %d, " - "which is larger than the maximum allowed (%d)", - glsl_get_type_name(b->type), - parcel->buffer_size, - consts->MaxShaderStorageBlockSize); - } - blocks[i].NumUniforms = - (unsigned)(ptrdiff_t)(&variables[parcel->index] - blocks[i].Uniforms); - - *block_index = *block_index + 1; -} - -/* This function resizes the array types of the block so that later we can use - * this new size to correctly calculate the offest for indirect indexing. - */ -static const glsl_type * -resize_block_array(const glsl_type *type, - struct uniform_block_array_elements *ub_array) -{ - if (type->is_array()) { - struct uniform_block_array_elements *child_array = - type->fields.array->is_array() ? ub_array->array : NULL; - const glsl_type *new_child_type = - resize_block_array(type->fields.array, child_array); - - const glsl_type *new_type = - glsl_type::get_array_instance(new_child_type, - ub_array->num_array_elements); - ub_array->ir->array->type = new_type; - return new_type; - } else { - return type; - } -} - -static void -create_buffer_blocks(void *mem_ctx, const struct gl_constants *consts, - struct gl_shader_program *prog, - struct gl_uniform_block **out_blks, unsigned num_blocks, - struct hash_table *block_hash, unsigned num_variables, - bool create_ubo_blocks) -{ - if (num_blocks == 0) { - assert(num_variables == 0); - return; - } - - assert(num_variables != 0); - - /* Allocate storage to hold all of the information related to uniform - * blocks that can be queried through the API. - */ - struct gl_uniform_block *blocks = - rzalloc_array(mem_ctx, gl_uniform_block, num_blocks); - gl_uniform_buffer_variable *variables = - ralloc_array(blocks, gl_uniform_buffer_variable, num_variables); - - /* Add each variable from each uniform block to the API tracking - * structures. - */ - ubo_visitor parcel(blocks, variables, num_variables, prog, - consts->UseSTD430AsDefaultPacking); - - unsigned i = 0; - hash_table_foreach (block_hash, entry) { - const struct link_uniform_block_active *const b = - (const struct link_uniform_block_active *) entry->data; - const glsl_type *block_type = b->type; - - if ((create_ubo_blocks && !b->is_shader_storage) || - (!create_ubo_blocks && b->is_shader_storage)) { - - if (b->array != NULL) { - char *name = ralloc_strdup(NULL, - glsl_get_type_name(block_type->without_array())); - size_t name_length = strlen(name); - - assert(b->has_instance_name); - process_block_array(b->array, &name, name_length, blocks, &parcel, - variables, b, &i, 0, consts, prog, - i); - ralloc_free(name); - } else { - process_block_array_leaf(glsl_get_type_name(block_type), blocks, &parcel, - variables, b, &i, 0, - 0, consts, prog); - } - } - } - - *out_blks = blocks; - - assert(parcel.index == num_variables); -} - -void -link_uniform_blocks(void *mem_ctx, - const struct gl_constants *consts, - struct gl_shader_program *prog, - struct gl_linked_shader *shader, - struct gl_uniform_block **ubo_blocks, - unsigned *num_ubo_blocks, - struct gl_uniform_block **ssbo_blocks, - unsigned *num_ssbo_blocks) -{ - /* This hash table will track all of the uniform blocks that have been - * encountered. Since blocks with the same block-name must be the same, - * the hash is organized by block-name. - */ - struct hash_table *block_hash = - _mesa_hash_table_create(mem_ctx, _mesa_hash_string, - _mesa_key_string_equal); - - if (block_hash == NULL) { - _mesa_error_no_memory(__func__); - linker_error(prog, "out of memory\n"); - return; - } - - /* Determine which uniform blocks are active. */ - link_uniform_block_active_visitor v(mem_ctx, block_hash, prog); - visit_list_elements(&v, shader->ir); - - /* Count the number of active uniform blocks. Count the total number of - * active slots in those uniform blocks. - */ - unsigned num_ubo_variables = 0; - unsigned num_ssbo_variables = 0; - count_block_size block_size; - - hash_table_foreach (block_hash, entry) { - struct link_uniform_block_active *const b = - (struct link_uniform_block_active *) entry->data; - - assert((b->array != NULL) == b->type->is_array()); - - if (b->array != NULL && - (b->type->without_array()->interface_packing == - GLSL_INTERFACE_PACKING_PACKED)) { - b->type = resize_block_array(b->type, b->array); - b->var->type = b->type; - b->var->data.max_array_access = b->type->length - 1; - } - - block_size.num_active_uniforms = 0; - block_size.process(b->type->without_array(), "", - consts->UseSTD430AsDefaultPacking); - - if (b->array != NULL) { - unsigned aoa_size = b->type->arrays_of_arrays_size(); - if (b->is_shader_storage) { - *num_ssbo_blocks += aoa_size; - num_ssbo_variables += aoa_size * block_size.num_active_uniforms; - } else { - *num_ubo_blocks += aoa_size; - num_ubo_variables += aoa_size * block_size.num_active_uniforms; - } - } else { - if (b->is_shader_storage) { - (*num_ssbo_blocks)++; - num_ssbo_variables += block_size.num_active_uniforms; - } else { - (*num_ubo_blocks)++; - num_ubo_variables += block_size.num_active_uniforms; - } - } - - } - - create_buffer_blocks(mem_ctx, consts, prog, ubo_blocks, *num_ubo_blocks, - block_hash, num_ubo_variables, true); - create_buffer_blocks(mem_ctx, consts, prog, ssbo_blocks, *num_ssbo_blocks, - block_hash, num_ssbo_variables, false); - - _mesa_hash_table_destroy(block_hash, NULL); -} static bool link_uniform_blocks_are_compatible(const gl_uniform_block *a, diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp deleted file mode 100644 index ed0677b5513..00000000000 --- a/src/compiler/glsl/link_uniforms.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright © 2011 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 "glsl_symbol_table.h" -#include "program.h" -#include "string_to_uint_map.h" -#include "ir_array_refcount.h" - -#include "main/shader_types.h" -#include "main/consts_exts.h" -#include "util/strndup.h" -#include "util/u_math.h" - -/** - * \file link_uniforms.cpp - * Assign locations for GLSL uniforms. - * - * \author Ian Romanick <ian.d.roman...@intel.com> - */ - -void -program_resource_visitor::process(const glsl_type *type, const char *name, - bool use_std430_as_default) -{ - assert(type->without_array()->is_struct() - || type->without_array()->is_interface()); - - unsigned record_array_count = 1; - char *name_copy = ralloc_strdup(NULL, name); - - enum glsl_interface_packing packing = - type->get_internal_ifc_packing(use_std430_as_default); - - recursion(type, &name_copy, strlen(name), false, NULL, packing, false, - record_array_count, NULL); - ralloc_free(name_copy); -} - -void -program_resource_visitor::process(ir_variable *var, bool use_std430_as_default) -{ - const glsl_type *t = - var->data.from_named_ifc_block ? var->get_interface_type() : var->type; - process(var, t, use_std430_as_default); -} - -void -program_resource_visitor::process(ir_variable *var, const glsl_type *var_type, - bool use_std430_as_default) -{ - unsigned record_array_count = 1; - const bool row_major = - var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR; - - enum glsl_interface_packing packing = var->get_interface_type() ? - var->get_interface_type()-> - get_internal_ifc_packing(use_std430_as_default) : - var->type->get_internal_ifc_packing(use_std430_as_default); - - const glsl_type *t = var_type; - const glsl_type *t_without_array = t->without_array(); - - /* false is always passed for the row_major parameter to the other - * processing functions because no information is available to do - * otherwise. See the warning in linker.h. - */ - if (t_without_array->is_struct() || - (t->is_array() && t->fields.array->is_array())) { - char *name = ralloc_strdup(NULL, var->name); - recursion(var->type, &name, strlen(name), row_major, NULL, packing, - false, record_array_count, NULL); - ralloc_free(name); - } else if (t_without_array->is_interface()) { - char *name = ralloc_strdup(NULL, glsl_get_type_name(t_without_array)); - const glsl_struct_field *ifc_member = var->data.from_named_ifc_block ? - &t_without_array-> - fields.structure[t_without_array->field_index(var->name)] : NULL; - - recursion(t, &name, strlen(name), row_major, NULL, packing, - false, record_array_count, ifc_member); - ralloc_free(name); - } else { - this->set_record_array_count(record_array_count); - this->visit_field(t, var->name, row_major, NULL, packing, false); - } -} - -void -program_resource_visitor::recursion(const glsl_type *t, char **name, - size_t name_length, bool row_major, - const glsl_type *record_type, - const enum glsl_interface_packing packing, - bool last_field, - unsigned record_array_count, - const glsl_struct_field *named_ifc_member) -{ - /* Records need to have each field processed individually. - * - * Arrays of records need to have each array element processed - * individually, then each field of the resulting array elements processed - * individually. - */ - if (t->is_interface() && named_ifc_member) { - ralloc_asprintf_rewrite_tail(name, &name_length, ".%s", - named_ifc_member->name); - recursion(named_ifc_member->type, name, name_length, row_major, NULL, - packing, false, record_array_count, NULL); - } else if (t->is_struct() || t->is_interface()) { - if (record_type == NULL && t->is_struct()) - record_type = t; - - if (t->is_struct()) - this->enter_record(t, *name, row_major, packing); - - for (unsigned i = 0; i < t->length; i++) { - const char *field = t->fields.structure[i].name; - size_t new_length = name_length; - - if (t->is_interface() && t->fields.structure[i].offset != -1) - this->set_buffer_offset(t->fields.structure[i].offset); - - /* Append '.field' to the current variable name. */ - if (name_length == 0) { - ralloc_asprintf_rewrite_tail(name, &new_length, "%s", field); - } else { - ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", field); - } - - /* The layout of structures at the top level of the block is set - * during parsing. For matrices contained in multiple levels of - * structures in the block, the inner structures have no layout. - * These cases must potentially inherit the layout from the outer - * levels. - */ - bool field_row_major = row_major; - const enum glsl_matrix_layout matrix_layout = - glsl_matrix_layout(t->fields.structure[i].matrix_layout); - if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { - field_row_major = true; - } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { - field_row_major = false; - } - - recursion(t->fields.structure[i].type, name, new_length, - field_row_major, - record_type, - packing, - (i + 1) == t->length, record_array_count, NULL); - - /* Only the first leaf-field of the record gets called with the - * record type pointer. - */ - record_type = NULL; - } - - if (t->is_struct()) { - (*name)[name_length] = '\0'; - this->leave_record(t, *name, row_major, packing); - } - } else if (t->without_array()->is_struct() || - t->without_array()->is_interface() || - (t->is_array() && t->fields.array->is_array())) { - if (record_type == NULL && t->fields.array->is_struct()) - record_type = t->fields.array; - - unsigned length = t->length; - - /* Shader storage block unsized arrays: add subscript [0] to variable - * names. - */ - if (t->is_unsized_array()) - length = 1; - - record_array_count *= length; - - for (unsigned i = 0; i < length; i++) { - size_t new_length = name_length; - - /* Append the subscript to the current variable name */ - ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i); - - recursion(t->fields.array, name, new_length, row_major, - record_type, - packing, - (i + 1) == t->length, record_array_count, - named_ifc_member); - - /* Only the first leaf-field of the record gets called with the - * record type pointer. - */ - record_type = NULL; - } - } else { - this->set_record_array_count(record_array_count); - this->visit_field(t, *name, row_major, record_type, packing, last_field); - } -} - -void -program_resource_visitor::enter_record(const glsl_type *, const char *, bool, - const enum glsl_interface_packing) -{ -} - -void -program_resource_visitor::leave_record(const glsl_type *, const char *, bool, - const enum glsl_interface_packing) -{ -} - -void -program_resource_visitor::set_buffer_offset(unsigned) -{ -} - -void -program_resource_visitor::set_record_array_count(unsigned) -{ -} - -unsigned -link_calculate_matrix_stride(const glsl_type *matrix, bool row_major, - enum glsl_interface_packing packing) -{ - const unsigned N = matrix->is_double() ? 8 : 4; - const unsigned items = - row_major ? matrix->matrix_columns : matrix->vector_elements; - - assert(items <= 4); - - /* Matrix stride for std430 mat2xY matrices are not rounded up to - * vec4 size. - * - * Section 7.6.2.2 "Standard Uniform Block Layout" of the OpenGL 4.3 spec - * says: - * - * 2. If the member is a two- or four-component vector with components - * consuming N basic machine units, the base alignment is 2N or 4N, - * respectively. - * ... - * 4. If the member is an array of scalars or vectors, the base - * alignment and array stride are set to match the base alignment of - * a single array element, according to rules (1), (2), and (3), and - * rounded up to the base alignment of a vec4. - * ... - * 7. If the member is a row-major matrix with C columns and R rows, the - * matrix is stored identically to an array of R row vectors with C - * components each, according to rule (4). - * ... - * - * When using the std430 storage layout, shader storage blocks will be - * laid out in buffer storage identically to uniform and shader storage - * blocks using the std140 layout, except that the base alignment and - * stride of arrays of scalars and vectors in rule 4 and of structures - * in rule 9 are not rounded up a multiple of the base alignment of a - * vec4. - */ - return packing == GLSL_INTERFACE_PACKING_STD430 - ? (items < 3 ? items * N : align(items * N, 16)) - : align(items * N, 16); -} diff --git a/src/compiler/glsl/linker.h b/src/compiler/glsl/linker.h index 25112274577..ca201684a6e 100644 --- a/src/compiler/glsl/linker.h +++ b/src/compiler/glsl/linker.h @@ -41,16 +41,6 @@ link_cross_validate_uniform_block(void *mem_ctx, unsigned int *num_linked_blocks, struct gl_uniform_block *new_block); -extern void -link_uniform_blocks(void *mem_ctx, - const struct gl_constants *consts, - struct gl_shader_program *prog, - struct gl_linked_shader *shader, - struct gl_uniform_block **ubo_blocks, - unsigned *num_ubo_blocks, - struct gl_uniform_block **ssbo_blocks, - unsigned *num_ssbo_blocks); - bool validate_intrastage_arrays(struct gl_shader_program *prog, ir_variable *const var, @@ -79,120 +69,4 @@ link_intrastage_shaders(void *mem_ctx, unsigned num_shaders, bool allow_missing_main); -extern unsigned -link_calculate_matrix_stride(const glsl_type *matrix, bool row_major, - enum glsl_interface_packing packing); - -/** - * Class for processing all of the leaf fields of a variable that corresponds - * to a program resource. - * - * The leaf fields are all the parts of the variable that the application - * could query using \c glGetProgramResourceIndex (or that could be returned - * by \c glGetProgramResourceName). - * - * Classes my derive from this class to implement specific functionality. - * This class only provides the mechanism to iterate over the leaves. Derived - * classes must implement \c ::visit_field and may override \c ::process. - */ -class program_resource_visitor { -public: - /** - * Begin processing a variable - * - * Classes that overload this function should call \c ::process from the - * base class to start the recursive processing of the variable. - * - * \param var The variable that is to be processed - * - * Calls \c ::visit_field for each leaf of the variable. - * - * \warning - * When processing a uniform block, this entry should only be used in cases - * where the row / column ordering of matrices in the block does not - * matter. For example, enumerating the names of members of the block, but - * not for determining the offsets of members. - */ - void process(ir_variable *var, bool use_std430_as_default); - - /** - * Begin processing a variable - * - * Classes that overload this function should call \c ::process from the - * base class to start the recursive processing of the variable. - * - * \param var The variable that is to be processed - * \param var_type The glsl_type reference of the variable - * - * Calls \c ::visit_field for each leaf of the variable. - * - * \warning - * When processing a uniform block, this entry should only be used in cases - * where the row / column ordering of matrices in the block does not - * matter. For example, enumerating the names of members of the block, but - * not for determining the offsets of members. - */ - void process(ir_variable *var, const glsl_type *var_type, - bool use_std430_as_default); - - /** - * Begin processing a variable of a structured type. - * - * This flavor of \c process should be used to handle structured types - * (i.e., structures, interfaces, or arrays there of) that need special - * name handling. A common usage is to handle cases where the block name - * (instead of the instance name) is used for an interface block. - * - * \param type Type that is to be processed, associated with \c name - * \param name Base name of the structured variable being processed - * - * \note - * \c type must be \c GLSL_TYPE_RECORD, \c GLSL_TYPE_INTERFACE, or an array - * there of. - */ - void process(const glsl_type *type, const char *name, - bool use_std430_as_default); - -protected: - /** - * Method invoked for each leaf of the variable - * - * \param type Type of the field. - * \param name Fully qualified name of the field. - * \param row_major For a matrix type, is it stored row-major. - * \param record_type Type of the record containing the field. - * \param last_field Set if \c name is the last field of the structure - * containing it. This will always be false for items - * not contained in a structure or interface block. - */ - 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) = 0; - - virtual void enter_record(const glsl_type *type, const char *name, - bool row_major, const enum glsl_interface_packing packing); - - virtual void leave_record(const glsl_type *type, const char *name, - bool row_major, const enum glsl_interface_packing packing); - - virtual void set_buffer_offset(unsigned offset); - - virtual void set_record_array_count(unsigned record_array_count); - -private: - /** - * \param name_length Length of the current name \b not including the - * terminating \c NUL character. - * \param last_field Set if \c name is the last field of the structure - * containing it. This will always be false for items - * not contained in a structure or interface block. - */ - void recursion(const glsl_type *t, char **name, size_t name_length, - bool row_major, const glsl_type *record_type, - const enum glsl_interface_packing packing, - bool last_field, unsigned record_array_count, - const glsl_struct_field *named_ifc_member); -}; - #endif /* GLSL_LINKER_H */ diff --git a/src/compiler/glsl/meson.build b/src/compiler/glsl/meson.build index cdb79ae134e..416a29ff70f 100644 --- a/src/compiler/glsl/meson.build +++ b/src/compiler/glsl/meson.build @@ -190,9 +190,6 @@ files_libglsl = files( 'linker_util.cpp', 'link_functions.cpp', 'link_interface_blocks.cpp', - 'link_uniforms.cpp', - 'link_uniform_block_active_visitor.cpp', - 'link_uniform_block_active_visitor.h', 'link_uniform_blocks.cpp', 'list.h', 'lower_builtins.cpp',