[Mesa-dev] [PATCH v5 25/70] glsl: Add std430 related member functions to glsl_type class
Samuel Iglesias Gonsálvez
siglesias at igalia.com
Tue Sep 15 22:14:03 PDT 2015
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 <siglesias at 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 <siglesias at 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.justen at 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
>>>>
>>>
>
More information about the mesa-dev
mailing list