diff options
author | Ilia Mirkin <[email protected]> | 2015-02-10 03:02:09 -0500 |
---|---|---|
committer | Ilia Mirkin <[email protected]> | 2015-02-19 00:28:34 -0500 |
commit | 53bf7c8fd2e11a6c64d6ff3a98b56d64d2242505 (patch) | |
tree | 7214d2697606da847ffbaa0ba6878c125efdd1dd /src/glsl/link_uniforms.cpp | |
parent | 1ec715ce8b126da3cfe3b383054f9a176960c218 (diff) |
glsl: fix uniform linking logic in the presence of structs
Add a enter/leave record callback so that the offset may be aligned to
the proper value. Otherwise only leaf fields are called, and the first
field needs to be aligned to the outer struct's base alignment while the
last field needs to be aligned to the inner struct's base alignment.
This removes most usage of the last field/record type values passed into
visit_field.
Signed-off-by: Ilia Mirkin <[email protected]>
Reviewed-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/glsl/link_uniforms.cpp')
-rw-r--r-- | src/glsl/link_uniforms.cpp | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index 3aa6e0a9c74..347f079fa42 100644 --- a/src/glsl/link_uniforms.cpp +++ b/src/glsl/link_uniforms.cpp @@ -169,6 +169,9 @@ program_resource_visitor::recursion(const glsl_type *t, char **name, if (record_type == NULL && t->is_record()) record_type = t; + if (t->is_record()) + this->enter_record(t, *name, row_major); + for (unsigned i = 0; i < t->length; i++) { const char *field = t->fields.structure[i].name; size_t new_length = name_length; @@ -208,6 +211,11 @@ program_resource_visitor::recursion(const glsl_type *t, char **name, */ record_type = NULL; } + + if (t->is_record()) { + (*name)[name_length] = '\0'; + this->leave_record(t, *name, row_major); + } } else if (t->is_array() && (t->fields.array->is_record() || t->fields.array->is_interface())) { if (record_type == NULL && t->fields.array->is_record()) @@ -249,6 +257,16 @@ program_resource_visitor::visit_field(const glsl_struct_field *field) /* empty */ } +void +program_resource_visitor::enter_record(const glsl_type *, const char *, bool) +{ +} + +void +program_resource_visitor::leave_record(const glsl_type *, const char *, bool) +{ +} + namespace { /** @@ -526,6 +544,18 @@ private: assert(!"Should not get here."); } + virtual void enter_record(const glsl_type *type, const char *name, + bool row_major) { + this->ubo_byte_offset = glsl_align( + this->ubo_byte_offset, type->std140_base_alignment(row_major)); + } + + virtual void leave_record(const glsl_type *type, const char *name, + bool row_major) { + this->ubo_byte_offset = glsl_align( + this->ubo_byte_offset, type->std140_base_alignment(row_major)); + } + virtual void visit_field(const glsl_type *type, const char *name, bool row_major, const glsl_type *record_type, bool last_field) @@ -590,16 +620,11 @@ private: if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; - const unsigned alignment = record_type - ? record_type->std140_base_alignment(row_major) - : type->std140_base_alignment(row_major); + const unsigned alignment = type->std140_base_alignment(row_major); this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment); this->uniforms[id].offset = this->ubo_byte_offset; this->ubo_byte_offset += type->std140_size(row_major); - if (last_field) - this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, 16); - if (type->is_array()) { this->uniforms[id].array_stride = glsl_align(type->fields.array->std140_size(row_major), 16); |