On 15/09/15 21:03, Jordan Justen wrote: > On 2015-09-10 22:48:55, Samuel Iglesias Gonsálvez wrote: >> On 10/09/15 20:13, Jordan Justen wrote: >>> On 2015-09-10 06:35:41, Iago Toral Quiroga wrote: >>>> From: Samuel Iglesias Gonsalvez <sigles...@igalia.com> >>>> >>>> They are used to calculate size, base alignment and array stride values >>>> for a glsl_type following std430 rules. >>>> >>>> Signed-off-by: Samuel Iglesias Gonsalvez <sigles...@igalia.com> >>>> --- >>>> src/glsl/glsl_types.cpp | 209 >>>> ++++++++++++++++++++++++++++++++++++++++++++++++ >>>> src/glsl/glsl_types.h | 19 +++++ >>>> 2 files changed, 228 insertions(+) >>>> >>>> diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp >>>> index 755618a..d97991a 100644 >>>> --- a/src/glsl/glsl_types.cpp >>>> +++ b/src/glsl/glsl_types.cpp >>>> @@ -1357,6 +1357,215 @@ glsl_type::std140_size(bool row_major) const >>>> return -1; >>>> } >>>> >>>> +unsigned >>>> +glsl_type::std430_base_alignment(bool row_major) const >>>> +{ >>>> + >>>> + unsigned N = is_double() ? 8 : 4; >>>> + >>>> + /* (1) If the member is a scalar consuming <N> basic machine units, the >>>> + * base alignment is <N>. >>>> + * >>>> + * (2) If the member is a two- or four-component vector with components >>>> + * consuming <N> basic machine units, the base alignment is 2<N> or >>>> + * 4<N>, respectively. >>>> + * >>>> + * (3) If the member is a three-component vector with components >>>> consuming >>>> + * <N> basic machine units, the base alignment is 4<N>. >>>> + */ >>>> + if (this->is_scalar() || this->is_vector()) { >>>> + switch (this->vector_elements) { >>>> + case 1: >>>> + return N; >>>> + case 2: >>>> + return 2 * N; >>>> + case 3: >>>> + case 4: >>>> + return 4 * N; >>>> + } >>>> + } >>>> + >>>> + /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout": >>>> + * >>>> + * "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 of arrays of scalars and vectors in rule (4) and of >>>> structures >>> >>> Looking at the 4.3 spec (and 4.5), it actually adds "and stride" >>> following "base alignment". The extension spec *does not* have the >>> "and stride" text. >>> >> >> OK. If you agree, I will keep OpenGL 4.3 (and later) spec wording in all >> the places where this snippet is pasted. >> >>> This seems to be an inconsistency between the extension spec and the >>> actual spec, but the OpenGL spec form would produce more tightly >>> packed arrays. >>> >>> Maybe we want to confirm what another implementation does? >> >> Both NVIDIA and ATI proprietary drivers don't round up the stride of >> arrays of vectors to a multiple of a vec4 size, i.e., they are following >> the OpenGL spec. For example: for an array of vec2, they are returning >> an stride value of 8, not 16 as in std140. > > Well, my concern was that the 'and stride' part might mean that vec3 > array stride should be 12 rather than 16. But, I tested NVidia, and > they seem to use a stride of 16 for a vec3 array. So, I think your > interpretation is correct. > > I still say we could still use an update to idr's ubo-lolz branch to > handle ssbo and std430, but this would also involve extending shader > runner to better support ssbo. >
I have already done that work. I have a ubo-lolz modified branch [0] with an initial support of SSBOs and std430. About ssbo support for shader_runner, I have sent a couple of patches to piglit [1] and I plan to send a new version of them today with a generic approach (so it is not only for SSBOs but for other interface types defined in ARB_program_interface_query extension). FWIW, I executed [0] with no errors during 15 minutes. [0] https://github.com/Igalia/piglit.git Branch: ssbo-random-tests-std430-v2 [1] http://lists.freedesktop.org/archives/piglit/2015-September/017080.html > I guess I've looked at this enough at this point to say > > Reviewed-by: Jordan Justen <jordan.l.jus...@intel.com> > Thanks! Sam >>> >>>> + * in rule (9) are not rounded up a multiple of the base alignment of a >>>> + * vec4." >>>> + */ >>>> + >>>> + /* (1) If the member is a scalar consuming <N> basic machine units, the >>>> + * base alignment is <N>. >>>> + * >>>> + * (2) If the member is a two- or four-component vector with components >>>> + * consuming <N> basic machine units, the base alignment is 2<N> or >>>> + * 4<N>, respectively. >>>> + * >>>> + * (3) If the member is a three-component vector with components >>>> consuming >>>> + * <N> basic machine units, the base alignment is 4<N>. >>>> + */ >>>> + if (this->is_array()) >>>> + return this->fields.array->std430_base_alignment(row_major); >>>> + >>>> + /* (5) If the member is a column-major matrix with <C> columns and >>>> + * <R> rows, the matrix is stored identically to an array of >>>> + * <C> column vectors with <R> components each, according to >>>> + * rule (4). >>>> + * >>>> + * (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). >>>> + */ >>>> + if (this->is_matrix()) { >>>> + const struct glsl_type *vec_type, *array_type; >>>> + int c = this->matrix_columns; >>>> + int r = this->vector_elements; >>>> + >>>> + if (row_major) { >>>> + vec_type = get_instance(base_type, c, 1); >>>> + array_type = glsl_type::get_array_instance(vec_type, r); >>>> + } else { >>>> + vec_type = get_instance(base_type, r, 1); >>>> + array_type = glsl_type::get_array_instance(vec_type, c); >>>> + } >>>> + >>>> + return array_type->std430_base_alignment(false); >>>> + } >>>> + >>>> + /* (9) If the member is a structure, the base alignment of the >>>> + * structure is <N>, where <N> is the largest base alignment >>>> + * value of any of its members, and rounded up to the base >>>> + * alignment of a vec4. The individual members of this >>>> + * sub-structure are then assigned offsets by applying this set >>>> + * of rules recursively, where the base offset of the first >>>> + * member of the sub-structure is equal to the aligned offset >>>> + * of the structure. 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. >>>> + */ >>>> + if (this->is_record()) { >>>> + unsigned base_alignment = 0; >>>> + for (unsigned i = 0; i < this->length; i++) { >>>> + bool field_row_major = row_major; >>>> + const enum glsl_matrix_layout matrix_layout = >>>> + glsl_matrix_layout(this->fields.structure[i].matrix_layout); >>>> + if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { >>>> + field_row_major = true; >>>> + } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { >>>> + field_row_major = false; >>>> + } >>>> + >>>> + const struct glsl_type *field_type = >>>> this->fields.structure[i].type; >>>> + base_alignment = MAX2(base_alignment, >>>> + >>>> field_type->std430_base_alignment(field_row_major)); >>>> + } >>>> + return base_alignment; >>>> + } >>>> + assert(!"not reached"); >>>> + return -1; >>>> +} >>>> + >>>> +unsigned >>>> +glsl_type::std430_array_stride(bool row_major) const >>>> +{ >>>> + unsigned N = is_double() ? 8 : 4; >>>> + >>>> + /* Notice that the array stride of a vec3 is not 3 * N but 4 * N. >>>> + * See OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block >>>> Layout" >>>> + * >>>> + * (3) If the member is a three-component vector with components >>>> consuming >>>> + * <N> basic machine units, the base alignment is 4<N>. >>>> + */ >>>> + if (this->is_vector() && this->vector_elements == 3) >>>> + return 4 * N; >>>> + >>>> + /* By default use std430_size(row_major) */ >>>> + return this->std430_size(row_major); >>>> +} >>>> + >>>> +unsigned >>>> +glsl_type::std430_size(bool row_major) const >>>> +{ >>>> + unsigned N = is_double() ? 8 : 4; >>>> + >>>> + /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout": >>>> + * >>>> + * "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 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." >>>> + */ >>>> + if (this->is_scalar() || this->is_vector()) >>>> + return this->vector_elements * N; >>>> + >>>> + if (this->without_array()->is_matrix()) { >>>> + const struct glsl_type *element_type; >>>> + const struct glsl_type *vec_type; >>>> + unsigned int array_len; >>>> + >>>> + if (this->is_array()) { >>>> + element_type = this->fields.array; >>>> + array_len = this->length; >>>> + } else { >>>> + element_type = this; >>>> + array_len = 1; >>>> + } >>>> + >>>> + if (row_major) { >>>> + vec_type = get_instance(element_type->base_type, >>>> + element_type->matrix_columns, 1); >>>> + >>>> + array_len *= element_type->vector_elements; >>>> + } else { >>>> + vec_type = get_instance(element_type->base_type, >>>> + element_type->vector_elements, 1); >>>> + array_len *= element_type->matrix_columns; >>>> + } >>>> + const glsl_type *array_type = >>>> glsl_type::get_array_instance(vec_type, >>>> + >>>> array_len); >>>> + >>>> + return array_type->std430_size(false); >>>> + } >>>> + >>>> + if (this->is_array()) { >>>> + if (this->fields.array->is_record()) >>>> + return this->length * this->fields.array->std430_size(row_major); >>>> + else >>>> + return this->length * >>>> this->fields.array->std430_base_alignment(row_major); >>>> + } >>>> + >>>> + if (this->is_record() || this->is_interface()) { >>>> + unsigned size = 0; >>>> + unsigned max_align = 0; >>>> + >>>> + for (unsigned i = 0; i < this->length; i++) { >>>> + bool field_row_major = row_major; >>>> + const enum glsl_matrix_layout matrix_layout = >>>> + glsl_matrix_layout(this->fields.structure[i].matrix_layout); >>>> + if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { >>>> + field_row_major = true; >>>> + } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { >>>> + field_row_major = false; >>>> + } >>>> + >>>> + const struct glsl_type *field_type = >>>> this->fields.structure[i].type; >>>> + unsigned align = >>>> field_type->std430_base_alignment(field_row_major); >>>> + size = glsl_align(size, align); >>>> + size += field_type->std430_size(field_row_major); >>>> + >>>> + max_align = MAX2(align, max_align); >>>> + } >>>> + size = glsl_align(size, max_align); >>>> + return size; >>>> + } >>>> + >>>> + assert(!"not reached"); >>>> + return -1; >>>> +} >>>> >>>> unsigned >>>> glsl_type::count_attribute_slots() const >>>> diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h >>>> index 02a398f..5a6548d 100644 >>>> --- a/src/glsl/glsl_types.h >>>> +++ b/src/glsl/glsl_types.h >>>> @@ -326,6 +326,25 @@ struct glsl_type { >>>> unsigned std140_size(bool row_major) const; >>>> >>>> /** >>>> + * Alignment in bytes of the start of this type in a std430 shader >>>> + * storage block. >>>> + */ >>>> + unsigned std430_base_alignment(bool row_major) const; >>>> + >>>> + /** >>>> + * Calculate array stride in bytes of this type in a std430 shader >>>> storage >>>> + * block. >>>> + */ >>>> + unsigned std430_array_stride(bool row_major) const; >>>> + >>>> + /** >>>> + * Size in bytes of this type in a std430 shader storage block. >>>> + * >>>> + * Note that this is not GL_BUFFER_SIZE >>>> + */ >>>> + unsigned std430_size(bool row_major) const; >>>> + >>>> + /** >>>> * \brief Can this type be implicitly converted to another? >>>> * >>>> * \return True if the types are identical or if this type can be >>>> converted >>>> -- >>>> 1.9.1 >>>> >>> > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev