From f1293b2f9bc3a45c71941931edb5148d7b5f5a27 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sun, 3 Apr 2016 12:44:33 +1000 Subject: [PATCH] glsl: fully split apart buffer block arrays MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit With this change we create the UBO and SSBO arrays separately from the beginning rather than putting them into a combined array and splitting it apart later. A bug is with UBO and SSBO stage reference querying is also fixed as we now use the block index to lookup the references in the separate arrays not the combined buffer block array. Reviewed-by: Samuel Iglesias Gonsálvez --- src/compiler/glsl/link_uniform_blocks.cpp | 204 +++++++++------- .../glsl/link_uniform_initializers.cpp | 17 +- src/compiler/glsl/link_uniforms.cpp | 32 +-- src/compiler/glsl/linker.cpp | 225 ++++++++---------- src/compiler/glsl/linker.h | 7 +- src/compiler/glsl/standalone_scaffolding.cpp | 4 - src/mesa/main/mtypes.h | 50 +--- src/mesa/main/shader_query.cpp | 7 +- src/mesa/main/shaderapi.c | 2 +- src/mesa/main/shaderobj.c | 10 +- src/mesa/main/uniforms.c | 8 +- 11 files changed, 270 insertions(+), 296 deletions(-) diff --git a/src/compiler/glsl/link_uniform_blocks.cpp b/src/compiler/glsl/link_uniform_blocks.cpp index c8fa181a15d..586363d4f12 100644 --- a/src/compiler/glsl/link_uniform_blocks.cpp +++ b/src/compiler/glsl/link_uniform_blocks.cpp @@ -291,13 +291,105 @@ resize_block_array(const glsl_type *type, } } -unsigned +static void +create_buffer_blocks(void *mem_ctx, struct gl_context *ctx, + 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 = ralloc_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); + + STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD140) + == unsigned(ubo_packing_std140)); + STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_SHARED) + == unsigned(ubo_packing_shared)); + STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_PACKED) + == unsigned(ubo_packing_packed)); + STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD430) + == unsigned(ubo_packing_std430)); + + unsigned i = 0; + struct hash_entry *entry; + 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) { + unsigned binding_offset = 0; + char *name = ralloc_strdup(NULL, + block_type->without_array()->name); + size_t name_length = strlen(name); + + assert(b->has_instance_name); + process_block_array(b->array, &name, name_length, blocks, &parcel, + variables, b, &i, &binding_offset, ctx, prog); + ralloc_free(name); + } else { + blocks[i].Name = ralloc_strdup(blocks, block_type->name); + blocks[i].Uniforms = &variables[parcel.index]; + blocks[i].Binding = (b->has_binding) ? b->binding : 0; + blocks[i].UniformBufferSize = 0; + blocks[i]._Packing = + gl_uniform_block_packing(block_type->interface_packing); + + parcel.process(block_type, + b->has_instance_name ? block_type->name : ""); + + 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 > ctx->Const.MaxShaderStorageBlockSize) { + linker_error(prog, "shader storage block `%s' has size %d, " + "which is larger than than the maximum allowed (%d)", + block_type->name, parcel.buffer_size, + ctx->Const.MaxShaderStorageBlockSize); + } + blocks[i].NumUniforms = (unsigned)(ptrdiff_t) + (&variables[parcel.index] - blocks[i].Uniforms); + i++; + } + } + } + + *out_blks = blocks; + + assert(parcel.index == num_variables); +} + +void link_uniform_blocks(void *mem_ctx, struct gl_context *ctx, struct gl_shader_program *prog, struct gl_shader **shader_list, unsigned num_shaders, - struct gl_uniform_block **blocks_ret) + 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, @@ -310,7 +402,7 @@ link_uniform_blocks(void *mem_ctx, if (block_hash == NULL) { _mesa_error_no_memory(__func__); linker_error(prog, "out of memory\n"); - return 0; + return; } /* Determine which uniform blocks are active. @@ -323,8 +415,8 @@ link_uniform_blocks(void *mem_ctx, /* Count the number of active uniform blocks. Count the total number of * active slots in those uniform blocks. */ - unsigned num_blocks = 0; - unsigned num_variables = 0; + unsigned num_ubo_variables = 0; + unsigned num_ssbo_variables = 0; count_block_size block_size; struct hash_entry *entry; @@ -346,97 +438,31 @@ link_uniform_blocks(void *mem_ctx, if (b->array != NULL) { unsigned aoa_size = b->type->arrays_of_arrays_size(); - num_blocks += aoa_size; - num_variables += aoa_size * block_size.num_active_uniforms; - } else { - num_blocks++; - num_variables += block_size.num_active_uniforms; - } - - } - - if (num_blocks == 0) { - assert(num_variables == 0); - _mesa_hash_table_destroy(block_hash, NULL); - return 0; - } - - assert(num_variables != 0); - - /* Allocate storage to hold all of the informatation related to uniform - * blocks that can be queried through the API. - */ - gl_uniform_block *blocks = - ralloc_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. - */ - unsigned i = 0; - ubo_visitor parcel(blocks, variables, num_variables); - - STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD140) - == unsigned(ubo_packing_std140)); - STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_SHARED) - == unsigned(ubo_packing_shared)); - STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_PACKED) - == unsigned(ubo_packing_packed)); - STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD430) - == unsigned(ubo_packing_std430)); - - 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 (b->array != NULL) { - unsigned binding_offset = 0; - char *name = ralloc_strdup(NULL, block_type->without_array()->name); - size_t name_length = strlen(name); - - assert(b->has_instance_name); - process_block_array(b->array, &name, name_length, blocks, &parcel, - variables, b, &i, &binding_offset, ctx, prog); - ralloc_free(name); + 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 { - blocks[i].Name = ralloc_strdup(blocks, block_type->name); - blocks[i].Uniforms = &variables[parcel.index]; - blocks[i].Binding = (b->has_binding) ? b->binding : 0; - blocks[i].UniformBufferSize = 0; - blocks[i]._Packing = - gl_uniform_block_packing(block_type->interface_packing); - - parcel.process(block_type, - b->has_instance_name ? block_type->name : ""); - - 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 > ctx->Const.MaxShaderStorageBlockSize) { - linker_error(prog, "shader storage block `%s' has size %d, " - "which is larger than than the maximum allowed (%d)", - block_type->name, - parcel.buffer_size, - ctx->Const.MaxShaderStorageBlockSize); + 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; } - blocks[i].NumUniforms = - (unsigned)(ptrdiff_t)(&variables[parcel.index] - blocks[i].Uniforms); - - blocks[i].IsShaderStorage = b->is_shader_storage; - - i++; } + } - assert(parcel.index == num_variables); + create_buffer_blocks(mem_ctx, ctx, prog, ubo_blocks, *num_ubo_blocks, + block_hash, num_ubo_variables, true); + create_buffer_blocks(mem_ctx, ctx, prog, ssbo_blocks, *num_ssbo_blocks, + block_hash, num_ssbo_variables, false); _mesa_hash_table_destroy(block_hash, NULL); - - *blocks_ret = blocks; - return num_blocks; } bool diff --git a/src/compiler/glsl/link_uniform_initializers.cpp b/src/compiler/glsl/link_uniform_initializers.cpp index e5edf2e72e4..c6346d573ab 100644 --- a/src/compiler/glsl/link_uniform_initializers.cpp +++ b/src/compiler/glsl/link_uniform_initializers.cpp @@ -154,11 +154,17 @@ set_opaque_binding(void *mem_ctx, gl_shader_program *prog, } void -set_block_binding(gl_shader_program *prog, const char *block_name, int binding) +set_block_binding(gl_shader_program *prog, const char *block_name, + unsigned mode, int binding) { - for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) { - if (!strcmp(prog->BufferInterfaceBlocks[i].Name, block_name)) { - prog->BufferInterfaceBlocks[i].Binding = binding; + unsigned num_blocks = mode == ir_var_uniform ? prog->NumUniformBlocks : + prog->NumShaderStorageBlocks; + struct gl_uniform_block *blks = mode == ir_var_uniform ? + prog->UniformBlocks : prog->ShaderStorageBlocks; + + for (unsigned i = 0; i < num_blocks; i++) { + if (!strcmp(blks[i].Name, block_name)) { + blks[i].Binding = binding; return; } } @@ -308,11 +314,12 @@ link_set_uniform_initializers(struct gl_shader_program *prog, * each subsequent element takes the next consecutive * uniform block binding point." */ - linker::set_block_binding(prog, name, + linker::set_block_binding(prog, name, var->data.mode, var->data.binding + i); } } else { linker::set_block_binding(prog, iface_type->name, + var->data.mode, var->data.binding); } } else if (type->contains_atomic()) { diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp index 7d8a4b4fb79..8db60a36f16 100644 --- a/src/compiler/glsl/link_uniforms.cpp +++ b/src/compiler/glsl/link_uniforms.cpp @@ -462,7 +462,7 @@ public: buffer_block_index = -1; if (var->is_in_buffer_block()) { - struct gl_uniform_block **blks = var->is_in_shader_storage_block() ? + struct gl_uniform_block *blks = var->is_in_shader_storage_block() ? prog->ShaderStorageBlocks : prog->UniformBlocks; unsigned num_blks = var->is_in_shader_storage_block() ? prog->NumShaderStorageBlocks : prog->NumUniformBlocks; @@ -471,15 +471,15 @@ public: 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, l) - == 0 && blks[i]->Name[l] == '[') { + if (strncmp(var->get_interface_type()->name, blks[i].Name, l) + == 0 && blks[i].Name[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) == + if (strcmp(var->get_interface_type()->name, blks[i].Name) == 0) { buffer_block_index = i; break; @@ -500,7 +500,7 @@ public: var->get_interface_type()->name); } else { const struct gl_uniform_block *const block = - blks[buffer_block_index]; + &blks[buffer_block_index]; assert(var->data.location != -1); @@ -960,11 +960,16 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) sentinel = '['; } + unsigned num_blocks = var->data.mode == ir_var_uniform ? + shader->NumUniformBlocks : shader->NumShaderStorageBlocks; + struct gl_uniform_block **blks = var->data.mode == ir_var_uniform ? + shader->UniformBlocks : shader->ShaderStorageBlocks; + const unsigned l = strlen(var->name); - for (unsigned i = 0; i < shader->NumBufferInterfaceBlocks; i++) { - for (unsigned j = 0; j < shader->BufferInterfaceBlocks[i]->NumUniforms; j++) { + for (unsigned i = 0; i < num_blocks; i++) { + for (unsigned j = 0; j < blks[i]->NumUniforms; j++) { if (sentinel) { - const char *begin = shader->BufferInterfaceBlocks[i]->Uniforms[j].Name; + const char *begin = blks[i]->Uniforms[j].Name; const char *end = strchr(begin, sentinel); if (end == NULL) @@ -978,8 +983,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) var->data.location = j; break; } - } else if (!strcmp(var->name, - shader->BufferInterfaceBlocks[i]->Uniforms[j].Name)) { + } else if (!strcmp(var->name, blks[i]->Uniforms[j].Name)) { found = true; var->data.location = j; break; @@ -1104,11 +1108,9 @@ link_assign_uniform_locations(struct gl_shader_program *prog, 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->NumBufferInterfaceBlocks; i++) { - if (!sh->BufferInterfaceBlocks[i]->IsShaderStorage) { - sh->num_combined_uniform_components += - sh->BufferInterfaceBlocks[i]->UniformBufferSize / 4; - } + for (unsigned i = 0; i < sh->NumUniformBlocks; i++) { + sh->num_combined_uniform_components += + sh->UniformBlocks[i]->UniformBufferSize / 4; } } diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index d9a681ccca1..957efe5b55d 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -1165,39 +1165,58 @@ cross_validate_uniforms(struct gl_shader_program *prog) } /** - * Accumulates the array of prog->BufferInterfaceBlocks and checks that all - * definitons of blocks agree on their contents. + * Accumulates the array of buffer blocks and checks that all definitions of + * blocks agree on their contents. */ static bool -interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) +interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, + bool validate_ssbo) { int *InterfaceBlockStageIndex[MESA_SHADER_STAGES]; + struct gl_uniform_block *blks = NULL; + unsigned *num_blks = validate_ssbo ? &prog->NumShaderStorageBlocks : + &prog->NumUniformBlocks; - unsigned max_num_uniform_blocks = 0; + unsigned max_num_buffer_blocks = 0; for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - if (prog->_LinkedShaders[i]) - max_num_uniform_blocks += prog->_LinkedShaders[i]->NumBufferInterfaceBlocks; + if (prog->_LinkedShaders[i]) { + if (validate_ssbo) { + max_num_buffer_blocks += + prog->_LinkedShaders[i]->NumShaderStorageBlocks; + } else { + max_num_buffer_blocks += + prog->_LinkedShaders[i]->NumUniformBlocks; + } + } } for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { struct gl_shader *sh = prog->_LinkedShaders[i]; - InterfaceBlockStageIndex[i] = new int[max_num_uniform_blocks]; - for (unsigned int j = 0; j < max_num_uniform_blocks; j++) + InterfaceBlockStageIndex[i] = new int[max_num_buffer_blocks]; + for (unsigned int j = 0; j < max_num_buffer_blocks; j++) InterfaceBlockStageIndex[i][j] = -1; if (sh == NULL) continue; - for (unsigned int j = 0; j < sh->NumBufferInterfaceBlocks; j++) { - int index = link_cross_validate_uniform_block(prog, - &prog->BufferInterfaceBlocks, - &prog->NumBufferInterfaceBlocks, - sh->BufferInterfaceBlocks[j]); + unsigned sh_num_blocks; + struct gl_uniform_block **sh_blks; + if (validate_ssbo) { + sh_num_blocks = prog->_LinkedShaders[i]->NumShaderStorageBlocks; + sh_blks = sh->ShaderStorageBlocks; + } else { + sh_num_blocks = prog->_LinkedShaders[i]->NumUniformBlocks; + sh_blks = sh->UniformBlocks; + } + + for (unsigned int j = 0; j < sh_num_blocks; j++) { + int index = link_cross_validate_uniform_block(prog, &blks, num_blks, + sh_blks[j]); if (index == -1) { - linker_error(prog, "uniform block `%s' has mismatching definitions\n", - sh->BufferInterfaceBlocks[j]->Name); + linker_error(prog, "buffer block `%s' has mismatching " + "definitions\n", sh_blks[j]->Name); for (unsigned k = 0; k <= i; k++) { delete[] InterfaceBlockStageIndex[k]; @@ -1213,16 +1232,18 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) * FIXME: We should be able to free the per stage blocks here. */ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - for (unsigned j = 0; j < prog->NumBufferInterfaceBlocks; j++) { + for (unsigned j = 0; j < *num_blks; j++) { int stage_index = InterfaceBlockStageIndex[i][j]; if (stage_index != -1) { struct gl_shader *sh = prog->_LinkedShaders[i]; - prog->BufferInterfaceBlocks[j].stageref |= (1 << i); + blks[j].stageref |= (1 << i); + + struct gl_uniform_block **sh_blks = validate_ssbo ? + sh->ShaderStorageBlocks : sh->UniformBlocks; - sh->BufferInterfaceBlocks[stage_index] = - &prog->BufferInterfaceBlocks[j]; + sh_blks[stage_index] = &blks[j]; } } } @@ -1231,6 +1252,11 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) delete[] InterfaceBlockStageIndex[i]; } + if (validate_ssbo) + prog->ShaderStorageBlocks = blks; + else + prog->UniformBlocks = blks; + return true; } @@ -2074,7 +2100,10 @@ link_intrastage_shaders(void *mem_ctx, struct gl_shader **shader_list, unsigned num_shaders) { - struct gl_uniform_block *uniform_blocks = NULL; + struct gl_uniform_block *ubo_blocks = NULL; + struct gl_uniform_block *ssbo_blocks = NULL; + unsigned num_ubo_blocks = 0; + unsigned num_ssbo_blocks = 0; /* Check that global variables defined in multiple shaders are consistent. */ @@ -2090,9 +2119,10 @@ link_intrastage_shaders(void *mem_ctx, return NULL; /* Link up uniform blocks defined within this stage. */ - const unsigned num_uniform_blocks = - link_uniform_blocks(mem_ctx, ctx, prog, shader_list, num_shaders, - &uniform_blocks); + link_uniform_blocks(mem_ctx, ctx, prog, shader_list, num_shaders, + &ubo_blocks, &num_ubo_blocks, &ssbo_blocks, + &num_ssbo_blocks); + if (!prog->LinkStatus) return NULL; @@ -2159,15 +2189,23 @@ link_intrastage_shaders(void *mem_ctx, linked->ir = new(linked) exec_list; clone_ir_list(mem_ctx, linked->ir, main->ir); - linked->BufferInterfaceBlocks = - ralloc_array(linked, gl_uniform_block *, num_uniform_blocks); - - ralloc_steal(linked, uniform_blocks); - for (unsigned i = 0; i < num_uniform_blocks; i++) { - linked->BufferInterfaceBlocks[i] = &uniform_blocks[i]; + /* Copy ubo blocks to linked shader list */ + linked->UniformBlocks = + ralloc_array(linked, gl_uniform_block *, num_ubo_blocks); + ralloc_steal(linked, ubo_blocks); + for (unsigned i = 0; i < num_ubo_blocks; i++) { + linked->UniformBlocks[i] = &ubo_blocks[i]; } + linked->NumUniformBlocks = num_ubo_blocks; - linked->NumBufferInterfaceBlocks = num_uniform_blocks; + /* Copy ssbo blocks to linked shader list */ + linked->ShaderStorageBlocks = + ralloc_array(linked, gl_uniform_block *, num_ssbo_blocks); + ralloc_steal(linked, ssbo_blocks); + for (unsigned i = 0; i < num_ssbo_blocks; i++) { + linked->ShaderStorageBlocks[i] = &ssbo_blocks[i]; + } + linked->NumShaderStorageBlocks = num_ssbo_blocks; link_fs_input_layout_qualifiers(prog, linked, shader_list, num_shaders); link_tcs_out_layout_qualifiers(prog, linked, shader_list, num_shaders); @@ -2973,21 +3011,22 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) ctx->Const.MaxCombinedShaderStorageBlocks); } - for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) { - /* Don't check SSBOs for Uniform Block Size */ - if (!prog->BufferInterfaceBlocks[i].IsShaderStorage && - prog->BufferInterfaceBlocks[i].UniformBufferSize > ctx->Const.MaxUniformBlockSize) { + for (unsigned i = 0; i < prog->NumUniformBlocks; i++) { + if (prog->UniformBlocks[i].UniformBufferSize > + ctx->Const.MaxUniformBlockSize) { linker_error(prog, "Uniform block %s too big (%d/%d)\n", - prog->BufferInterfaceBlocks[i].Name, - prog->BufferInterfaceBlocks[i].UniformBufferSize, + prog->UniformBlocks[i].Name, + prog->UniformBlocks[i].UniformBufferSize, ctx->Const.MaxUniformBlockSize); } + } - if (prog->BufferInterfaceBlocks[i].IsShaderStorage && - prog->BufferInterfaceBlocks[i].UniformBufferSize > ctx->Const.MaxShaderStorageBlockSize) { + for (unsigned i = 0; i < prog->NumShaderStorageBlocks; i++) { + if (prog->ShaderStorageBlocks[i].UniformBufferSize > + ctx->Const.MaxShaderStorageBlockSize) { linker_error(prog, "Shader storage block %s too big (%d/%d)\n", - prog->BufferInterfaceBlocks[i].Name, - prog->BufferInterfaceBlocks[i].UniformBufferSize, + prog->ShaderStorageBlocks[i].Name, + prog->ShaderStorageBlocks[i].UniformBufferSize, ctx->Const.MaxShaderStorageBlockSize); } } @@ -3295,8 +3334,8 @@ should_add_buffer_variable(struct gl_shader_program *shProg, if (type != GL_BUFFER_VARIABLE) return true; - for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) { - const char *block_name = shProg->BufferInterfaceBlocks[i].Name; + for (unsigned i = 0; i < shProg->NumShaderStorageBlocks; i++) { + const char *block_name = shProg->ShaderStorageBlocks[i].Name; block_name_len = strlen(block_name); const char *block_square_bracket = strchr(block_name, '['); @@ -3805,8 +3844,8 @@ calculate_array_size_and_stride(struct gl_shader_program *shProg, char *var_name = get_top_level_name(uni->name); char *interface_name = get_top_level_name(uni->is_shader_storage ? - shProg->ShaderStorageBlocks[block_index]->Name : - shProg->UniformBlocks[block_index]->Name); + shProg->ShaderStorageBlocks[block_index].Name : + shProg->UniformBlocks[block_index].Name); if (strcmp(var_name, interface_name) == 0) { /* Deal with instanced array of SSBOs */ @@ -3947,8 +3986,8 @@ build_program_resource_list(struct gl_context *ctx, int block_index = shProg->UniformStorage[i].block_index; if (block_index != -1) { stageref |= is_shader_storage ? - shProg->ShaderStorageBlocks[block_index]->stageref : - shProg->UniformBlocks[block_index]->stageref; + shProg->ShaderStorageBlocks[block_index].stageref : + shProg->UniformBlocks[block_index].stageref; } GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM; @@ -3965,12 +4004,17 @@ build_program_resource_list(struct gl_context *ctx, return; } - /* Add program uniform blocks and shader storage blocks. */ - for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) { - bool is_shader_storage = shProg->BufferInterfaceBlocks[i].IsShaderStorage; - GLenum type = is_shader_storage ? GL_SHADER_STORAGE_BLOCK : GL_UNIFORM_BLOCK; - if (!add_program_resource(shProg, type, - &shProg->BufferInterfaceBlocks[i], 0)) + /* Add program uniform blocks. */ + for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) { + if (!add_program_resource(shProg, GL_UNIFORM_BLOCK, + &shProg->UniformBlocks[i], 0)) + return; + } + + /* Add program shader storage blocks. */ + for (unsigned i = 0; i < shProg->NumShaderStorageBlocks; i++) { + if (!add_program_resource(shProg, GL_SHADER_STORAGE_BLOCK, + &shProg->ShaderStorageBlocks[i], 0)) return; } @@ -4115,49 +4159,6 @@ link_assign_subroutine_types(struct gl_shader_program *prog) } } -static void -split_ubos_and_ssbos(void *mem_ctx, - struct gl_uniform_block **s_blks, - struct gl_uniform_block *p_blks, - unsigned num_blocks, - struct gl_uniform_block ***ubos, - unsigned *num_ubos, - struct gl_uniform_block ***ssbos, - unsigned *num_ssbos) -{ - unsigned num_ubo_blocks = 0; - unsigned num_ssbo_blocks = 0; - - /* Are we spliting the list of blocks for the shader or the program */ - bool is_shader = p_blks == NULL; - - for (unsigned i = 0; i < num_blocks; i++) { - if (is_shader ? s_blks[i]->IsShaderStorage : p_blks[i].IsShaderStorage) - num_ssbo_blocks++; - else - num_ubo_blocks++; - } - - *ubos = ralloc_array(mem_ctx, gl_uniform_block *, num_ubo_blocks); - *num_ubos = 0; - - *ssbos = ralloc_array(mem_ctx, gl_uniform_block *, num_ssbo_blocks); - *num_ssbos = 0; - - for (unsigned i = 0; i < num_blocks; i++) { - struct gl_uniform_block *blk = is_shader ? s_blks[i] : &p_blks[i]; - if (blk->IsShaderStorage) { - (*ssbos)[*num_ssbos] = blk; - (*num_ssbos)++; - } else { - (*ubos)[*num_ubos] = blk; - (*num_ubos)++; - } - } - - assert(*num_ubos + *num_ssbos == num_blocks); -} - static void set_always_active_io(exec_list *ir, ir_variable_mode io_mode) { @@ -4498,7 +4499,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (prog->SeparateShader) disable_varying_optimizations_for_sso(prog); - if (!interstage_cross_validate_uniform_blocks(prog)) + /* Process UBOs */ + if (!interstage_cross_validate_uniform_blocks(prog, false)) + goto done; + + /* Process SSBOs */ + if (!interstage_cross_validate_uniform_blocks(prog, true)) goto done; /* Do common optimization before assigning storage for attributes, @@ -4695,33 +4701,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) has_xfb_qualifiers)) goto done; - /* Split BufferInterfaceBlocks into UniformBlocks and ShaderStorageBlocks - * for gl_shader_program and gl_shader, so that drivers that need separate - * index spaces for each set can have that. - */ - for (unsigned i = MESA_SHADER_VERTEX; i < MESA_SHADER_STAGES; i++) { - if (prog->_LinkedShaders[i] != NULL) { - gl_shader *sh = prog->_LinkedShaders[i]; - split_ubos_and_ssbos(sh, - sh->BufferInterfaceBlocks, - NULL, - sh->NumBufferInterfaceBlocks, - &sh->UniformBlocks, - &sh->NumUniformBlocks, - &sh->ShaderStorageBlocks, - &sh->NumShaderStorageBlocks); - } - } - - split_ubos_and_ssbos(prog, - NULL, - prog->BufferInterfaceBlocks, - prog->NumBufferInterfaceBlocks, - &prog->UniformBlocks, - &prog->NumUniformBlocks, - &prog->ShaderStorageBlocks, - &prog->NumShaderStorageBlocks); - update_array_sizes(prog); link_assign_uniform_locations(prog, ctx->Const.UniformBooleanTrue, num_explicit_uniform_locs, diff --git a/src/compiler/glsl/linker.h b/src/compiler/glsl/linker.h index 97144df8ff7..3a0ec8b35d3 100644 --- a/src/compiler/glsl/linker.h +++ b/src/compiler/glsl/linker.h @@ -53,13 +53,16 @@ extern bool link_uniform_blocks_are_compatible(const gl_uniform_block *a, const gl_uniform_block *b); -extern unsigned +extern void link_uniform_blocks(void *mem_ctx, struct gl_context *ctx, struct gl_shader_program *prog, struct gl_shader **shader_list, unsigned num_shaders, - struct gl_uniform_block **blocks_ret); + 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, diff --git a/src/compiler/glsl/standalone_scaffolding.cpp b/src/compiler/glsl/standalone_scaffolding.cpp index 49b4a26dc12..09d7d6e8c26 100644 --- a/src/compiler/glsl/standalone_scaffolding.cpp +++ b/src/compiler/glsl/standalone_scaffolding.cpp @@ -105,10 +105,6 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg) ralloc_free(shProg->InfoLog); shProg->InfoLog = ralloc_strdup(shProg, ""); - ralloc_free(shProg->BufferInterfaceBlocks); - shProg->BufferInterfaceBlocks = NULL; - shProg->NumBufferInterfaceBlocks = 0; - ralloc_free(shProg->UniformBlocks); shProg->UniformBlocks = NULL; shProg->NumUniformBlocks = 0; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index b2060c282f4..dc73278424b 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2295,30 +2295,6 @@ struct gl_shader */ unsigned num_combined_uniform_components; - /** - * This shader's uniform/ssbo block information. - * - * These fields are only set post-linking. - * - * BufferInterfaceBlocks is a list containing both UBOs and SSBOs. This is - * useful during the linking process so that we don't have to handle SSBOs - * specifically. - * - * UniformBlocks is a list of UBOs. This is useful for backends that need - * or prefer to see separate index spaces for UBOS and SSBOs like the GL - * API specifies. - * - * ShaderStorageBlocks is a list of SSBOs. This is useful for backends that - * need or prefer to see separate index spaces for UBOS and SSBOs like the - * GL API specifies. - * - * UniformBlocks and ShaderStorageBlocks only have pointers into - * BufferInterfaceBlocks so the actual resource information is not - * duplicated. - */ - unsigned NumBufferInterfaceBlocks; - struct gl_uniform_block **BufferInterfaceBlocks; - unsigned NumUniformBlocks; struct gl_uniform_block **UniformBlocks; @@ -2804,33 +2780,11 @@ struct gl_shader_program */ unsigned LastClipDistanceArraySize; - /** - * This shader's uniform/ssbo block information. - * - * BufferInterfaceBlocks is a list containing both UBOs and SSBOs. This is - * useful during the linking process so that we don't have to handle SSBOs - * specifically. - * - * UniformBlocks is a list of UBOs. This is useful for backends that need - * or prefer to see separate index spaces for UBOS and SSBOs like the GL - * API specifies. - * - * ShaderStorageBlocks is a list of SSBOs. This is useful for backends that - * need or prefer to see separate index spaces for UBOS and SSBOs like the - * GL API specifies. - * - * UniformBlocks and ShaderStorageBlocks only have pointers into - * BufferInterfaceBlocks so the actual resource information is not - * duplicated and are only set after linking. - */ - unsigned NumBufferInterfaceBlocks; - struct gl_uniform_block *BufferInterfaceBlocks; - unsigned NumUniformBlocks; - struct gl_uniform_block **UniformBlocks; + struct gl_uniform_block *UniformBlocks; unsigned NumShaderStorageBlocks; - struct gl_uniform_block **ShaderStorageBlocks; + struct gl_uniform_block *ShaderStorageBlocks; /** * Map of active uniform names to locations diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index 4ef6a81204e..2c1a6ee3505 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -925,8 +925,11 @@ is_resource_referenced(struct gl_shader_program *shProg, if (res->Type == GL_ATOMIC_COUNTER_BUFFER) return RESOURCE_ATC(res)->StageReferences[stage]; - if (res->Type == GL_UNIFORM_BLOCK || res->Type == GL_SHADER_STORAGE_BLOCK) - return shProg->BufferInterfaceBlocks[index].stageref & (1 << stage); + if (res->Type == GL_UNIFORM_BLOCK) + return shProg->UniformBlocks[index].stageref & (1 << stage); + + if (res->Type == GL_SHADER_STORAGE_BLOCK) + return shProg->ShaderStorageBlocks[index].stageref & (1 << stage); return res->StageReferences & (1 << stage); } diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index ba2607221d9..b28b5ce5457 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -727,7 +727,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, for (i = 0; i < shProg->NumUniformBlocks; i++) { /* Add one for the terminating NUL character. */ - const GLint len = strlen(shProg->UniformBlocks[i]->Name) + 1; + const GLint len = strlen(shProg->UniformBlocks[i].Name) + 1; if (len > max_len) max_len = len; diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index 8b9166ceecb..274cb129b07 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -292,9 +292,13 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg) ralloc_free(shProg->InfoLog); shProg->InfoLog = ralloc_strdup(shProg, ""); - ralloc_free(shProg->BufferInterfaceBlocks); - shProg->BufferInterfaceBlocks = NULL; - shProg->NumBufferInterfaceBlocks = 0; + ralloc_free(shProg->UniformBlocks); + shProg->UniformBlocks = NULL; + shProg->NumUniformBlocks = 0; + + ralloc_free(shProg->ShaderStorageBlocks); + shProg->ShaderStorageBlocks = NULL; + shProg->NumShaderStorageBlocks = 0; ralloc_free(shProg->AtomicBuffers); shProg->AtomicBuffers = NULL; diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index 7dcbdccf442..a9308d09f69 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -1016,13 +1016,13 @@ _mesa_UniformBlockBinding(GLuint program, return; } - if (shProg->UniformBlocks[uniformBlockIndex]->Binding != + if (shProg->UniformBlocks[uniformBlockIndex].Binding != uniformBlockBinding) { FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer; - shProg->UniformBlocks[uniformBlockIndex]->Binding = uniformBlockBinding; + shProg->UniformBlocks[uniformBlockIndex].Binding = uniformBlockBinding; } } @@ -1059,13 +1059,13 @@ _mesa_ShaderStorageBlockBinding(GLuint program, return; } - if (shProg->ShaderStorageBlocks[shaderStorageBlockIndex]->Binding != + if (shProg->ShaderStorageBlocks[shaderStorageBlockIndex].Binding != shaderStorageBlockBinding) { FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer; - shProg->ShaderStorageBlocks[shaderStorageBlockIndex]->Binding = + shProg->ShaderStorageBlocks[shaderStorageBlockIndex].Binding = shaderStorageBlockBinding; } } -- 2.30.2