/** * * \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, struct gl_context *ctx, 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; /* Append the subscript to the current variable name */ ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", ub_array->array_elements[j]); if (ub_array->array) { process_block_array(ub_array->array, name, new_length, blocks, parcel, variables, b, block_index, binding_offset, ctx, prog, first_index); } else { process_block_array_leaf(*name, blocks, parcel, variables, b, block_index, binding_offset, *block_index - first_index, ctx, prog); } } }
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, struct gl_context *ctx, struct gl_shader_program *prog) { if (ub_array) { for (unsigned j = 0; j < ub_array->num_array_elements; j++) { size_t new_length = name_length; /* Append the subscript to the current variable name */ ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", ub_array->array_elements[j]); process_block_array(ub_array->array, name, new_length, blocks, parcel, variables, b, block_index, binding_offset, ctx, prog); } } else { unsigned i = *block_index; const glsl_type *type = b->type->without_array(); blocks[i].Name = ralloc_strdup(blocks, *name); blocks[i].Uniforms = &variables[(*parcel).index]; /* The GL_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 = gl_uniform_block_packing(type->interface_packing); parcel->process(type, blocks[i].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)", b->type->name, parcel->buffer_size, ctx->Const.MaxShaderStorageBlockSize); } blocks[i].NumUniforms = (unsigned)(ptrdiff_t)(&variables[parcel->index] - blocks[i].Uniforms); *block_index = *block_index + 1; *binding_offset = *binding_offset + 1; } }
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 = 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); 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); blocks[i]._RowMajor = block_type->get_interface_row_major(); 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); }
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 = 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, ctx->Const.UseSTD430AsDefaultPacking); 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)) { unsigned binding_offset = 0; if (b->array != NULL) { 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, i); ralloc_free(name); } else { process_block_array_leaf(block_type->name, blocks, &parcel, variables, b, &i, &binding_offset, 0, ctx, prog); } } } *out_blks = blocks; assert(parcel.index == num_variables); }