class ubo_visitor : public program_resource_visitor {
public:
ubo_visitor(void *mem_ctx, gl_uniform_buffer_variable *variables,
- unsigned num_variables)
+ unsigned num_variables, struct gl_shader_program *prog)
: index(0), offset(0), buffer_size(0), variables(variables),
- num_variables(num_variables), mem_ctx(mem_ctx), is_array_instance(false)
+ num_variables(num_variables), mem_ctx(mem_ctx), is_array_instance(false),
+ prog(prog)
{
/* empty */
}
unsigned num_variables;
void *mem_ctx;
bool is_array_instance;
+ struct gl_shader_program *prog;
private:
virtual void visit_field(const glsl_type *type, const char *name,
}
virtual void enter_record(const glsl_type *type, const char *,
- bool row_major, const unsigned packing) {
+ bool row_major, const enum glsl_interface_packing packing) {
assert(type->is_record());
if (packing == GLSL_INTERFACE_PACKING_STD430)
this->offset = glsl_align(
}
virtual void leave_record(const glsl_type *type, const char *,
- bool row_major, const unsigned packing) {
+ bool row_major, const enum glsl_interface_packing packing) {
assert(type->is_record());
/* If this is the last field of a structure, apply rule #9. The
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major, const glsl_type *,
- const unsigned packing,
+ const enum glsl_interface_packing packing,
bool last_field)
{
assert(this->index < this->num_variables);
blocks[i].UniformBufferSize = 0;
blocks[i]._Packing = gl_uniform_block_packing(type->interface_packing);
+ blocks[i]._RowMajor = type->get_interface_row_major();
parcel->process(type, blocks[i].Name);
/* 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);
+ 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);
+ ubo_visitor parcel(blocks, variables, num_variables, prog);
STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD140)
== unsigned(ubo_packing_std140));
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 : "");
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_linked_shader *shader,
struct gl_uniform_block **ubo_blocks,
unsigned *num_ubo_blocks,
struct gl_uniform_block **ssbo_blocks,
/* Determine which uniform blocks are active.
*/
link_uniform_block_active_visitor v(mem_ctx, block_hash, prog);
- for (unsigned i = 0; i < num_shaders; i++) {
- visit_list_elements(&v, shader_list[i]->ir);
- }
+ visit_list_elements(&v, shader->ir);
/* Count the number of active uniform blocks. Count the total number of
* active slots in those uniform blocks.
_mesa_hash_table_destroy(block_hash, NULL);
}
-bool
+static bool
link_uniform_blocks_are_compatible(const gl_uniform_block *a,
const gl_uniform_block *b)
{
if (a->_Packing != b->_Packing)
return false;
+ if (a->_RowMajor != b->_RowMajor)
+ return false;
+
for (unsigned i = 0; i < a->NumUniforms; i++) {
if (strcmp(a->Uniforms[i].Name, b->Uniforms[i].Name) != 0)
return false;
return true;
}
+
+/**
+ * Merges a uniform block into an array of uniform blocks that may or
+ * may not already contain a copy of it.
+ *
+ * Returns the index of the new block in the array.
+ */
+int
+link_cross_validate_uniform_block(void *mem_ctx,
+ struct gl_uniform_block **linked_blocks,
+ unsigned int *num_linked_blocks,
+ struct gl_uniform_block *new_block)
+{
+ for (unsigned int i = 0; i < *num_linked_blocks; i++) {
+ struct gl_uniform_block *old_block = &(*linked_blocks)[i];
+
+ if (strcmp(old_block->Name, new_block->Name) == 0)
+ return link_uniform_blocks_are_compatible(old_block, new_block)
+ ? i : -1;
+ }
+
+ *linked_blocks = reralloc(mem_ctx, *linked_blocks,
+ struct gl_uniform_block,
+ *num_linked_blocks + 1);
+ int linked_block_index = (*num_linked_blocks)++;
+ struct gl_uniform_block *linked_block = &(*linked_blocks)[linked_block_index];
+
+ memcpy(linked_block, new_block, sizeof(*new_block));
+ linked_block->Uniforms = ralloc_array(*linked_blocks,
+ struct gl_uniform_buffer_variable,
+ linked_block->NumUniforms);
+
+ memcpy(linked_block->Uniforms,
+ new_block->Uniforms,
+ sizeof(*linked_block->Uniforms) * linked_block->NumUniforms);
+
+ linked_block->Name = ralloc_strdup(*linked_blocks, linked_block->Name);
+
+ for (unsigned int i = 0; i < linked_block->NumUniforms; i++) {
+ struct gl_uniform_buffer_variable *ubo_var =
+ &linked_block->Uniforms[i];
+
+ if (ubo_var->Name == ubo_var->IndexName) {
+ ubo_var->Name = ralloc_strdup(*linked_blocks, ubo_var->Name);
+ ubo_var->IndexName = ubo_var->Name;
+ } else {
+ ubo_var->Name = ralloc_strdup(*linked_blocks, ubo_var->Name);
+ ubo_var->IndexName = ralloc_strdup(*linked_blocks, ubo_var->IndexName);
+ }
+ }
+
+ return linked_block_index;
+}