diff options
author | Timothy Arceri <[email protected]> | 2016-04-03 12:44:33 +1000 |
---|---|---|
committer | Timothy Arceri <[email protected]> | 2016-04-06 09:56:24 +1000 |
commit | f1293b2f9bc3a45c71941931edb5148d7b5f5a27 (patch) | |
tree | ba998230fc2b04bf8d130b6d7704650dbba09e83 /src/compiler/glsl/linker.cpp | |
parent | 506b561ba7e3df2a7759dded684fae84bf459f65 (diff) |
glsl: fully split apart buffer block arrays
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 <[email protected]>
Diffstat (limited to 'src/compiler/glsl/linker.cpp')
-rw-r--r-- | src/compiler/glsl/linker.cpp | 225 |
1 files changed, 102 insertions, 123 deletions
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; } @@ -4116,49 +4160,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) { assert(io_mode == ir_var_shader_in || io_mode == ir_var_shader_out); @@ -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, |