UBO data can be packed using 3 different strategies : packed, shader and std140. The spec defines in a non ambigous way the std140 strategy, this patch implements it. --- src/glsl/linker.cpp | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 121 insertions(+), 0 deletions(-)
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 0c8a2c2..34bc537 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1216,6 +1216,127 @@ static void expand_gl_ubo(struct gl_shader_program *sh, const struct gl_uniform_ dest->ReferencedByFS = dest->ReferencedByGS = dest->ReferencedByVS = 0; } + +static +unsigned align_offset(unsigned& base_offset,unsigned base_alignement) +{ + unsigned result = base_offset + base_alignement - 1; + result /= base_alignement; + result *= base_alignement; + base_offset = result; + return result; +} + +/** + * This function sets offset of UBO elements according to + * standard packing rule from GL_ARB_Uniform_Buffer_Object spec. + */ +static void set_standard_uniform_block_layout_recursive(union gl_variable_storage *storage_tree, const struct glsl_type *type, + unsigned& next_position) +{ + /** Rule 1 */ + if (type->is_scalar()) { + storage_tree->AsLeaf.Offset = align_offset(next_position,4); + next_position += 4; + return; + } + + /** Rule 2 and 3 */ + if (type->is_vector()) { + switch(type->vector_elements) { + case 4: + case 3: + storage_tree->AsLeaf.Offset = align_offset(next_position,16); + break; + case 2: + storage_tree->AsLeaf.Offset = align_offset(next_position,8); + break; + default: + break; + } + + next_position += 4 * type->vector_elements; + return; + } + + /** Rule 9 */ + if (type->is_record()) { + align_offset(next_position,16); + for (unsigned i = 0; i < type->length; i++) { + set_standard_uniform_block_layout_recursive(storage_tree->AsRecord.Fields[i], + type->fields.structure[i].type, + next_position); + } + return; + } + + /** Rule 5 */ + if (type->is_matrix()) { + storage_tree->AsMatrix.Offset = align_offset(next_position,16); + for (unsigned i = 0; i < type->matrix_columns; i++) { + align_offset(next_position,16); + next_position += 4 * type->vector_elements; + } + return; + } + + if (type->is_array()) { + const glsl_type* base_type = type->fields.array; + /** Rule 4 */ + if (base_type->is_scalar() || base_type->is_vector()) { + storage_tree->AsArray.FirstElement->AsLeaf.Offset = align_offset(next_position,16); + storage_tree->AsArray.Stride = 16; + next_position += type->length * storage_tree->AsArray.Stride; + align_offset(next_position,16); + return; + } + /** Rule 6 and 7 */ + if (base_type->is_matrix()) { + storage_tree->AsArray.FirstElement->AsMatrix.Offset = align_offset(next_position,16); + next_position += 4 * base_type->vector_elements; + storage_tree->AsArray.Stride = next_position - storage_tree->AsArray.FirstElement->AsMatrix.Offset; + + for (unsigned i = 1; i < base_type->matrix_columns * type->array_size(); i++) { + align_offset(next_position,16); + next_position += 4 * base_type->vector_elements; + } + return; + } + /** Rule 10 */ + else if (base_type->is_record()){ + unsigned offset = align_offset(next_position,16); + set_standard_uniform_block_layout_recursive(storage_tree->AsArray.FirstElement, + base_type, + next_position); + align_offset(next_position,16); + + storage_tree->AsArray.Stride = next_position - offset; + next_position = offset + type->length * storage_tree->AsArray.Stride; + align_offset(next_position,16); + return; + } + return; + } + + +} + +static void set_standard_uniform_block_layout(struct gl_uniform_buffer_object& prog_ubo) +{ + unsigned next_position = 0; + + for(unsigned i=0;i<prog_ubo.NumberOfVariables;i++) { + struct gl_shader_ubo_variable& var = prog_ubo.Variables[i]; + union gl_variable_storage *var_storage = create_storage_type(var.Type); + set_standard_uniform_block_layout_recursive( var_storage, var.Type, next_position); + var.Storage = var_storage; + } + + prog_ubo.Size = align_offset(next_position,16); + + return; +} + /** * At interstage this function extract UBOs from shaders to populate programs UBOs * It also performs checks coherency between UBOs with same name. -- 1.7.7 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev