diff options
-rw-r--r-- | src/compiler/glsl/link_uniforms.cpp | 57 | ||||
-rw-r--r-- | src/compiler/glsl/linker.h | 4 |
2 files changed, 50 insertions, 11 deletions
diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp index 4aa29f45b27..46c746bc701 100644 --- a/src/compiler/glsl/link_uniforms.cpp +++ b/src/compiler/glsl/link_uniforms.cpp @@ -398,6 +398,48 @@ private: } /* anonymous namespace */ +unsigned +link_calculate_matrix_stride(const glsl_type *matrix, bool row_major, + enum glsl_interface_packing packing) +{ + const unsigned N = matrix->is_double() ? 8 : 4; + const unsigned items = + row_major ? matrix->matrix_columns : matrix->vector_elements; + + assert(items <= 4); + + /* Matrix stride for std430 mat2xY matrices are not rounded up to + * vec4 size. + * + * Section 7.6.2.2 "Standard Uniform Block Layout" of the OpenGL 4.3 spec + * says: + * + * 2. If the member is a two- or four-component vector with components + * consuming N basic machine units, the base alignment is 2N or 4N, + * respectively. + * ... + * 4. If the member is an array of scalars or vectors, the base + * alignment and array stride are set to match the base alignment of + * a single array element, according to rules (1), (2), and (3), and + * rounded up to the base alignment of a vec4. + * ... + * 7. If the member is a row-major matrix with C columns and R rows, the + * matrix is stored identically to an array of R row vectors with C + * components each, according to rule (4). + * ... + * + * When using the std430 storage layout, shader storage blocks will be + * laid out in buffer storage identically to uniform and shader storage + * blocks using the std140 layout, except that the base alignment and + * stride of arrays of scalars and vectors in rule 4 and of structures + * in rule 9 are not rounded up a multiple of the base alignment of a + * vec4. + */ + return packing == GLSL_INTERFACE_PACKING_STD430 + ? (items < 3 ? items * N : glsl_align(items * N, 16)) + : glsl_align(items * N, 16); +} + /** * Class to help parcel out pieces of backing storage to uniforms * @@ -856,17 +898,10 @@ private: } if (type->without_array()->is_matrix()) { - const glsl_type *matrix = type->without_array(); - const unsigned N = matrix->is_double() ? 8 : 4; - const unsigned items = - row_major ? matrix->matrix_columns : matrix->vector_elements; - - assert(items <= 4); - if (packing == GLSL_INTERFACE_PACKING_STD430) - this->uniforms[id].matrix_stride = items < 3 ? items * N : - glsl_align(items * N, 16); - else - this->uniforms[id].matrix_stride = glsl_align(items * N, 16); + this->uniforms[id].matrix_stride = + link_calculate_matrix_stride(type->without_array(), + row_major, + packing); this->uniforms[id].row_major = row_major; } else { this->uniforms[id].matrix_stride = 0; diff --git a/src/compiler/glsl/linker.h b/src/compiler/glsl/linker.h index 03ed9d5f84c..12a48e0dcd8 100644 --- a/src/compiler/glsl/linker.h +++ b/src/compiler/glsl/linker.h @@ -92,6 +92,10 @@ link_intrastage_shaders(void *mem_ctx, unsigned num_shaders, bool allow_missing_main); +extern unsigned +link_calculate_matrix_stride(const glsl_type *matrix, bool row_major, + enum glsl_interface_packing packing); + /** * Class for processing all of the leaf fields of a variable that corresponds * to a program resource. |