[Mesa-dev] [PATCH 09/16] linker: Add padding after the last field of a structure
Ian Romanick
idr at freedesktop.org
Mon Jul 21 14:04:25 PDT 2014
From: Ian Romanick <ian.d.romanick at intel.com>
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 <ian.d.romanick at intel.com>
---
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(-)
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index 932c72b..01a84b1 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 d1c7da4..8db5296 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 6dd8de4..c88ecbd 100644
--- a/src/glsl/link_uniforms.cpp
+++ b/src/glsl/link_uniforms.cpp
@@ -512,7 +512,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->is_record_or_array_of());
assert(!type->is_interface_or_array_of());
@@ -581,6 +581,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);
--
1.8.1.4
More information about the mesa-dev
mailing list