summaryrefslogtreecommitdiffstats
path: root/src/glsl/link_uniform_blocks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl/link_uniform_blocks.cpp')
-rw-r--r--src/glsl/link_uniform_blocks.cpp22
1 files changed, 19 insertions, 3 deletions
diff --git a/src/glsl/link_uniform_blocks.cpp b/src/glsl/link_uniform_blocks.cpp
index 5285d8d01e4..d5d30bb0a0d 100644
--- a/src/glsl/link_uniform_blocks.cpp
+++ b/src/glsl/link_uniform_blocks.cpp
@@ -100,7 +100,7 @@ private:
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major, const glsl_type *,
const unsigned packing,
- bool /* last_field */)
+ bool last_field)
{
assert(this->index < this->num_variables);
@@ -131,12 +131,28 @@ private:
unsigned alignment = 0;
unsigned size = 0;
+ /* From ARB_program_interface_query:
+ *
+ * "If the final member of an active shader storage block is array
+ * with no declared size, the minimum buffer size is computed
+ * assuming the array was declared as an array with one element."
+ *
+ * For that reason, we use the base type of the unsized array to calculate
+ * its size. We don't need to check if the unsized array is the last member
+ * of a shader storage block (that check was already done by the parser).
+ */
+ const glsl_type *type_for_size = type;
+ if (type->is_unsized_array()) {
+ assert(last_field);
+ type_for_size = type->without_array();
+ }
+
if (packing == GLSL_INTERFACE_PACKING_STD430) {
alignment = type->std430_base_alignment(v->RowMajor);
- size = type->std430_size(v->RowMajor);
+ size = type_for_size->std430_size(v->RowMajor);
} else {
alignment = type->std140_base_alignment(v->RowMajor);
- size = type->std140_size(v->RowMajor);
+ size = type_for_size->std140_size(v->RowMajor);
}
this->offset = glsl_align(this->offset, alignment);