From 7f731340d25b0c4a86ec3cc7b9a33f66c4818c2b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 16 Jul 2014 15:40:32 -0700 Subject: linker: Add padding after the last field of a structure This causes the thing following the structure to be vec4-aligned. Fixes gles3conform failures in: ES3-CTS.shaders.uniform_block.random.nested_structs.2 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.5 Signed-off-by: Ian Romanick Reviewed-by: Matt Turner --- src/glsl/glsl_types.cpp | 10 ++++++++-- src/glsl/link_uniform_blocks.cpp | 13 +++++++++++++ src/glsl/link_uniforms.cpp | 5 ++++- 3 files changed, 25 insertions(+), 3 deletions(-) (limited to 'src/glsl') diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index 737e6dd0422..50e4fe558bc 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -934,14 +934,20 @@ glsl_type::std140_size(bool row_major) const */ if (this->is_record()) { unsigned size = 0; + unsigned max_align = 0; + for (unsigned i = 0; i < this->length; i++) { const struct glsl_type *field_type = this->fields.structure[i].type; unsigned align = field_type->std140_base_alignment(row_major); size = glsl_align(size, align); size += field_type->std140_size(row_major); + + max_align = MAX2(align, max_align); + + if (field_type->is_record() && (i + 1 < this->length)) + size = glsl_align(size, 16); } - size = glsl_align(size, - this->fields.structure[0].type->std140_base_alignment(row_major)); + size = glsl_align(size, max_align); return size; } diff --git a/src/glsl/link_uniform_blocks.cpp b/src/glsl/link_uniform_blocks.cpp index ddd134a348a..3768205ee1f 100644 --- a/src/glsl/link_uniform_blocks.cpp +++ b/src/glsl/link_uniform_blocks.cpp @@ -104,7 +104,20 @@ private: this->offset = glsl_align(this->offset, alignment); v->Offset = this->offset; + + /* If this is the last field of a structure, apply rule #9. The + * GL_ARB_uniform_buffer_object spec says: + * + * "The structure may have padding at the end; the base offset of + * the member following the sub-structure is rounded up to the next + * multiple of the base alignment of the structure." + * + * last_field won't be set if this is the last field of a UBO that is + * not a named instance. + */ this->offset += size; + if (last_field) + this->offset = glsl_align(this->offset, 16); /* From the GL_ARB_uniform_buffer_object spec: * diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index 8014a3d9a99..cfb23effcf7 100644 --- a/src/glsl/link_uniforms.cpp +++ b/src/glsl/link_uniforms.cpp @@ -513,7 +513,7 @@ private: virtual void visit_field(const glsl_type *type, const char *name, bool row_major, const glsl_type *record_type, - bool /* last_field */) + bool last_field) { assert(!type->without_array()->is_record()); assert(!type->without_array()->is_interface()); @@ -582,6 +582,9 @@ private: this->uniforms[id].offset = this->ubo_byte_offset; this->ubo_byte_offset += type->std140_size(ubo_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(ubo_row_major), 16); -- cgit v1.2.3