• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
43 void
process(const glsl_type * type,const char * name,bool use_std430_as_default)44 program_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 
61 void
process(ir_variable * var,bool use_std430_as_default)62 program_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 
69 void
process(ir_variable * var,const glsl_type * var_type,bool use_std430_as_default)70 program_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 
110 void
recursion(const glsl_type * t,char ** name,size_t name_length,bool row_major,const glsl_type * record_type,const enum glsl_interface_packing packing,bool last_field,unsigned record_array_count,const glsl_struct_field * named_ifc_member)111 program_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 
221 void
enter_record(const glsl_type *,const char *,bool,const enum glsl_interface_packing)222 program_resource_visitor::enter_record(const glsl_type *, const char *, bool,
223                                        const enum glsl_interface_packing)
224 {
225 }
226 
227 void
leave_record(const glsl_type *,const char *,bool,const enum glsl_interface_packing)228 program_resource_visitor::leave_record(const glsl_type *, const char *, bool,
229                                        const enum glsl_interface_packing)
230 {
231 }
232 
233 void
set_buffer_offset(unsigned)234 program_resource_visitor::set_buffer_offset(unsigned)
235 {
236 }
237 
238 void
set_record_array_count(unsigned)239 program_resource_visitor::set_record_array_count(unsigned)
240 {
241 }
242 
243 unsigned
link_calculate_matrix_stride(const glsl_type * matrix,bool row_major,enum glsl_interface_packing packing)244 link_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