[Mesa-dev] [PATCH 11/17] glsl: Linker generates std140 layout
Vincent Lejeune
vljn at ovi.com
Sun Dec 25 10:20:06 PST 2011
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
More information about the mesa-dev
mailing list