mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 05:08:08 +02:00
glsl: Assign locations for uniforms in UBOs using the std140 rules.
Fixes piglit layout-std140. Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
parent
9feb403b0e
commit
8ab5842a6d
5 changed files with 270 additions and 2 deletions
|
|
@ -628,3 +628,223 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired) const
|
|||
&& this->is_integer()
|
||||
&& this->vector_elements == desired->vector_elements;
|
||||
}
|
||||
|
||||
unsigned
|
||||
glsl_type::std140_base_alignment(bool row_major) const
|
||||
{
|
||||
/* (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 4;
|
||||
case 2:
|
||||
return 8;
|
||||
case 3:
|
||||
case 4:
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
/* (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. The array may have padding at the
|
||||
* end; the base offset of the member following the array is rounded up
|
||||
* to the next multiple of the base alignment.
|
||||
*
|
||||
* (6) If the member is an array of <S> column-major matrices with <C>
|
||||
* columns and <R> rows, the matrix is stored identically to a row of
|
||||
* <S>*<C> column vectors with <R> components each, according to rule
|
||||
* (4).
|
||||
*
|
||||
* (8) If the member is an array of <S> row-major matrices with <C> columns
|
||||
* and <R> rows, the matrix is stored identically to a row of <S>*<R>
|
||||
* row vectors with <C> components each, according to rule (4).
|
||||
*
|
||||
* (10) If the member is an array of <S> structures, the <S> elements of
|
||||
* the array are laid out in order, according to rule (9).
|
||||
*/
|
||||
if (this->is_array()) {
|
||||
if (this->fields.array->is_scalar() ||
|
||||
this->fields.array->is_vector() ||
|
||||
this->fields.array->is_matrix()) {
|
||||
return MAX2(this->fields.array->std140_base_alignment(row_major), 16);
|
||||
} else {
|
||||
assert(this->fields.array->is_record());
|
||||
return this->fields.array->std140_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;
|
||||
if (row_major) {
|
||||
vec_type = get_instance(GLSL_TYPE_FLOAT, this->vector_elements, 1);
|
||||
} else {
|
||||
vec_type = get_instance(GLSL_TYPE_FLOAT, this->matrix_columns, 1);
|
||||
}
|
||||
|
||||
return vec_type->std140_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 = 16;
|
||||
for (unsigned i = 0; i < this->length; i++) {
|
||||
const struct glsl_type *field_type = this->fields.structure[i].type;
|
||||
base_alignment = MAX2(base_alignment,
|
||||
field_type->std140_base_alignment(row_major));
|
||||
}
|
||||
return base_alignment;
|
||||
}
|
||||
|
||||
assert(!"not reached");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
align(unsigned val, unsigned align)
|
||||
{
|
||||
return (val + align - 1) / align * align;
|
||||
}
|
||||
|
||||
unsigned
|
||||
glsl_type::std140_size(bool row_major) const
|
||||
{
|
||||
/* (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()) {
|
||||
return this->vector_elements * 4;
|
||||
}
|
||||
|
||||
/* (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).
|
||||
*
|
||||
* (6) If the member is an array of <S> column-major matrices with <C>
|
||||
* columns and <R> rows, the matrix is stored identically to a row of
|
||||
* <S>*<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).
|
||||
*
|
||||
* (8) If the member is an array of <S> row-major matrices with <C> columns
|
||||
* and <R> rows, the matrix is stored identically to a row of <S>*<R>
|
||||
* row vectors with <C> components each, according to rule (4).
|
||||
*/
|
||||
if (this->is_matrix() || (this->is_array() &&
|
||||
this->fields.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(GLSL_TYPE_FLOAT,
|
||||
element_type->matrix_columns, 1);
|
||||
array_len *= element_type->vector_elements;
|
||||
} else {
|
||||
vec_type = get_instance(GLSL_TYPE_FLOAT,
|
||||
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->std140_size(false);
|
||||
}
|
||||
|
||||
/* (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. The array may have padding at the
|
||||
* end; the base offset of the member following the array is rounded up
|
||||
* to the next multiple of the base alignment.
|
||||
*
|
||||
* (10) If the member is an array of <S> structures, the <S> elements of
|
||||
* the array are laid out in order, according to rule (9).
|
||||
*/
|
||||
if (this->is_array()) {
|
||||
if (this->fields.array->is_record()) {
|
||||
return this->length * this->fields.array->std140_size(row_major);
|
||||
} else {
|
||||
unsigned element_base_align =
|
||||
this->fields.array->std140_base_alignment(row_major);
|
||||
return this->length * MAX2(element_base_align, 16);
|
||||
}
|
||||
}
|
||||
|
||||
/* (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 size = 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 = (size + align - 1) / align * align;
|
||||
size += field_type->std140_size(row_major);
|
||||
}
|
||||
size = align(size,
|
||||
this->fields.structure[0].type->std140_base_alignment(row_major));
|
||||
return size;
|
||||
}
|
||||
|
||||
assert(!"not reached");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,6 +242,19 @@ struct glsl_type {
|
|||
*/
|
||||
unsigned component_slots() const;
|
||||
|
||||
/**
|
||||
* Alignment in bytes of the start of this type in a std140 uniform
|
||||
* block.
|
||||
*/
|
||||
unsigned std140_base_alignment(bool row_major) const;
|
||||
|
||||
/** Size in bytes of this type in a std140 uniform block.
|
||||
*
|
||||
* Note that this is not GL_UNIFORM_SIZE (which is the number of
|
||||
* elements in the array)
|
||||
*/
|
||||
unsigned std140_size(bool row_major) const;
|
||||
|
||||
/**
|
||||
* \brief Can this type be implicitly converted to another?
|
||||
*
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@
|
|||
#include "program/hash_table.h"
|
||||
#include "program.h"
|
||||
|
||||
static inline unsigned int
|
||||
align(unsigned int a, unsigned int align)
|
||||
{
|
||||
return (a + align - 1) / align * align;
|
||||
}
|
||||
|
||||
/**
|
||||
* \file link_uniforms.cpp
|
||||
* Assign locations for GLSL uniforms.
|
||||
|
|
@ -317,9 +323,11 @@ private:
|
|||
if (this->ubo_var) {
|
||||
this->uniforms[id].block_index = this->ubo_block_index;
|
||||
|
||||
/* FINISHME: Actual std140 offset assignment. */
|
||||
unsigned alignment = type->std140_base_alignment(ubo_var->RowMajor);
|
||||
this->ubo_byte_offset = align(this->ubo_byte_offset, alignment);
|
||||
this->uniforms[id].offset = this->ubo_byte_offset;
|
||||
this->ubo_byte_offset += 4 * type->components();
|
||||
this->ubo_byte_offset += type->std140_size(ubo_var->RowMajor);
|
||||
|
||||
this->uniforms[id].array_stride = 0;
|
||||
this->uniforms[id].matrix_stride = 0;
|
||||
this->uniforms[id].row_major = base_type->is_matrix() &&
|
||||
|
|
@ -453,6 +461,28 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
link_assign_uniform_block_offsets(struct gl_shader *shader)
|
||||
{
|
||||
for (unsigned b = 0; b < shader->NumUniformBlocks; b++) {
|
||||
struct gl_uniform_block *block = &shader->UniformBlocks[b];
|
||||
|
||||
unsigned offset = 0;
|
||||
for (unsigned int i = 0; i < block->NumUniforms; i++) {
|
||||
struct gl_uniform_buffer_variable *ubo_var = &block->Uniforms[i];
|
||||
const struct glsl_type *type = ubo_var->Type;
|
||||
|
||||
unsigned alignment = type->std140_base_alignment(ubo_var->RowMajor);
|
||||
unsigned size = type->std140_size(ubo_var->RowMajor);
|
||||
|
||||
offset = align(offset, alignment);
|
||||
ubo_var->Offset = offset;
|
||||
offset += size;
|
||||
}
|
||||
block->UniformBufferSize = offset;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
link_assign_uniform_locations(struct gl_shader_program *prog)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -979,6 +979,8 @@ link_intrastage_shaders(void *mem_ctx,
|
|||
struct gl_shader *sh = shader_list[i];
|
||||
|
||||
for (unsigned j = 0; j < shader_list[i]->NumUniformBlocks; j++) {
|
||||
link_assign_uniform_block_offsets(shader_list[i]);
|
||||
|
||||
int index = link_cross_validate_uniform_block(mem_ctx,
|
||||
&uniform_blocks,
|
||||
&num_uniform_blocks,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ link_cross_validate_uniform_block(void *mem_ctx,
|
|||
unsigned int *num_linked_blocks,
|
||||
struct gl_uniform_block *new_block);
|
||||
|
||||
void
|
||||
link_assign_uniform_block_offsets(struct gl_shader *shader);
|
||||
|
||||
/**
|
||||
* Class for processing all of the leaf fields of an uniform
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue