1/* 2 * Copyright © 2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#include "ir.h" 25#include "linker.h" 26#include "ir_uniform.h" 27#include "glsl_symbol_table.h" 28#include "program.h" 29#include "string_to_uint_map.h" 30#include "ir_array_refcount.h" 31 32#include "main/shader_types.h" 33#include "main/consts_exts.h" 34#include "util/strndup.h" 35 36/** 37 * \file link_uniforms.cpp 38 * Assign locations for GLSL uniforms. 39 * 40 * \author Ian Romanick <ian.d.romanick@intel.com> 41 */ 42 43void 44program_resource_visitor::process(const glsl_type *type, const char *name, 45 bool use_std430_as_default) 46{ 47 assert(type->without_array()->is_struct() 48 || type->without_array()->is_interface()); 49 50 unsigned record_array_count = 1; 51 char *name_copy = ralloc_strdup(NULL, name); 52 53 enum glsl_interface_packing packing = 54 type->get_internal_ifc_packing(use_std430_as_default); 55 56 recursion(type, &name_copy, strlen(name), false, NULL, packing, false, 57 record_array_count, NULL); 58 ralloc_free(name_copy); 59} 60 61void 62program_resource_visitor::process(ir_variable *var, bool use_std430_as_default) 63{ 64 const glsl_type *t = 65 var->data.from_named_ifc_block ? var->get_interface_type() : var->type; 66 process(var, t, use_std430_as_default); 67} 68 69void 70program_resource_visitor::process(ir_variable *var, const glsl_type *var_type, 71 bool use_std430_as_default) 72{ 73 unsigned record_array_count = 1; 74 const bool row_major = 75 var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR; 76 77 enum glsl_interface_packing packing = var->get_interface_type() ? 78 var->get_interface_type()-> 79 get_internal_ifc_packing(use_std430_as_default) : 80 var->type->get_internal_ifc_packing(use_std430_as_default); 81 82 const glsl_type *t = var_type; 83 const glsl_type *t_without_array = t->without_array(); 84 85 /* false is always passed for the row_major parameter to the other 86 * processing functions because no information is available to do 87 * otherwise. See the warning in linker.h. 88 */ 89 if (t_without_array->is_struct() || 90 (t->is_array() && t->fields.array->is_array())) { 91 char *name = ralloc_strdup(NULL, var->name); 92 recursion(var->type, &name, strlen(name), row_major, NULL, packing, 93 false, record_array_count, NULL); 94 ralloc_free(name); 95 } else if (t_without_array->is_interface()) { 96 char *name = ralloc_strdup(NULL, t_without_array->name); 97 const glsl_struct_field *ifc_member = var->data.from_named_ifc_block ? 98 &t_without_array-> 99 fields.structure[t_without_array->field_index(var->name)] : NULL; 100 101 recursion(t, &name, strlen(name), row_major, NULL, packing, 102 false, record_array_count, ifc_member); 103 ralloc_free(name); 104 } else { 105 this->set_record_array_count(record_array_count); 106 this->visit_field(t, var->name, row_major, NULL, packing, false); 107 } 108} 109 110void 111program_resource_visitor::recursion(const glsl_type *t, char **name, 112 size_t name_length, bool row_major, 113 const glsl_type *record_type, 114 const enum glsl_interface_packing packing, 115 bool last_field, 116 unsigned record_array_count, 117 const glsl_struct_field *named_ifc_member) 118{ 119 /* Records need to have each field processed individually. 120 * 121 * Arrays of records need to have each array element processed 122 * individually, then each field of the resulting array elements processed 123 * individually. 124 */ 125 if (t->is_interface() && named_ifc_member) { 126 ralloc_asprintf_rewrite_tail(name, &name_length, ".%s", 127 named_ifc_member->name); 128 recursion(named_ifc_member->type, name, name_length, row_major, NULL, 129 packing, false, record_array_count, NULL); 130 } else if (t->is_struct() || t->is_interface()) { 131 if (record_type == NULL && t->is_struct()) 132 record_type = t; 133 134 if (t->is_struct()) 135 this->enter_record(t, *name, row_major, packing); 136 137 for (unsigned i = 0; i < t->length; i++) { 138 const char *field = t->fields.structure[i].name; 139 size_t new_length = name_length; 140 141 if (t->is_interface() && t->fields.structure[i].offset != -1) 142 this->set_buffer_offset(t->fields.structure[i].offset); 143 144 /* Append '.field' to the current variable name. */ 145 if (name_length == 0) { 146 ralloc_asprintf_rewrite_tail(name, &new_length, "%s", field); 147 } else { 148 ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", field); 149 } 150 151 /* The layout of structures at the top level of the block is set 152 * during parsing. For matrices contained in multiple levels of 153 * structures in the block, the inner structures have no layout. 154 * These cases must potentially inherit the layout from the outer 155 * levels. 156 */ 157 bool field_row_major = row_major; 158 const enum glsl_matrix_layout matrix_layout = 159 glsl_matrix_layout(t->fields.structure[i].matrix_layout); 160 if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { 161 field_row_major = true; 162 } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { 163 field_row_major = false; 164 } 165 166 recursion(t->fields.structure[i].type, name, new_length, 167 field_row_major, 168 record_type, 169 packing, 170 (i + 1) == t->length, record_array_count, NULL); 171 172 /* Only the first leaf-field of the record gets called with the 173 * record type pointer. 174 */ 175 record_type = NULL; 176 } 177 178 if (t->is_struct()) { 179 (*name)[name_length] = '\0'; 180 this->leave_record(t, *name, row_major, packing); 181 } 182 } else if (t->without_array()->is_struct() || 183 t->without_array()->is_interface() || 184 (t->is_array() && t->fields.array->is_array())) { 185 if (record_type == NULL && t->fields.array->is_struct()) 186 record_type = t->fields.array; 187 188 unsigned length = t->length; 189 190 /* Shader storage block unsized arrays: add subscript [0] to variable 191 * names. 192 */ 193 if (t->is_unsized_array()) 194 length = 1; 195 196 record_array_count *= length; 197 198 for (unsigned i = 0; i < length; i++) { 199 size_t new_length = name_length; 200 201 /* Append the subscript to the current variable name */ 202 ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i); 203 204 recursion(t->fields.array, name, new_length, row_major, 205 record_type, 206 packing, 207 (i + 1) == t->length, record_array_count, 208 named_ifc_member); 209 210 /* Only the first leaf-field of the record gets called with the 211 * record type pointer. 212 */ 213 record_type = NULL; 214 } 215 } else { 216 this->set_record_array_count(record_array_count); 217 this->visit_field(t, *name, row_major, record_type, packing, last_field); 218 } 219} 220 221void 222program_resource_visitor::enter_record(const glsl_type *, const char *, bool, 223 const enum glsl_interface_packing) 224{ 225} 226 227void 228program_resource_visitor::leave_record(const glsl_type *, const char *, bool, 229 const enum glsl_interface_packing) 230{ 231} 232 233void 234program_resource_visitor::set_buffer_offset(unsigned) 235{ 236} 237 238void 239program_resource_visitor::set_record_array_count(unsigned) 240{ 241} 242 243unsigned 244link_calculate_matrix_stride(const glsl_type *matrix, bool row_major, 245 enum glsl_interface_packing packing) 246{ 247 const unsigned N = matrix->is_double() ? 8 : 4; 248 const unsigned items = 249 row_major ? matrix->matrix_columns : matrix->vector_elements; 250 251 assert(items <= 4); 252 253 /* Matrix stride for std430 mat2xY matrices are not rounded up to 254 * vec4 size. 255 * 256 * Section 7.6.2.2 "Standard Uniform Block Layout" of the OpenGL 4.3 spec 257 * says: 258 * 259 * 2. If the member is a two- or four-component vector with components 260 * consuming N basic machine units, the base alignment is 2N or 4N, 261 * respectively. 262 * ... 263 * 4. If the member is an array of scalars or vectors, the base 264 * alignment and array stride are set to match the base alignment of 265 * a single array element, according to rules (1), (2), and (3), and 266 * rounded up to the base alignment of a vec4. 267 * ... 268 * 7. If the member is a row-major matrix with C columns and R rows, the 269 * matrix is stored identically to an array of R row vectors with C 270 * components each, according to rule (4). 271 * ... 272 * 273 * When using the std430 storage layout, shader storage blocks will be 274 * laid out in buffer storage identically to uniform and shader storage 275 * blocks using the std140 layout, except that the base alignment and 276 * stride of arrays of scalars and vectors in rule 4 and of structures 277 * in rule 9 are not rounded up a multiple of the base alignment of a 278 * vec4. 279 */ 280 return packing == GLSL_INTERFACE_PACKING_STD430 281 ? (items < 3 ? items * N : glsl_align(items * N, 16)) 282 : glsl_align(items * N, 16); 283} 284