2 * Copyright © 2018 Intel Corporation
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:
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
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 DEALINGS
25 #include "gl_nir_linker.h"
26 #include "compiler/glsl/ir_uniform.h" /* for gl_uniform_storage */
27 #include "linker_util.h"
28 #include "main/context.h"
29 #include "main/mtypes.h"
31 /* This file do the common link for GLSL uniforms, using NIR, instead of IR as
32 * the counter-part glsl/link_uniforms.cpp
34 * Also note that this is tailored for ARB_gl_spirv needs and particularities
35 * (like need to work/link without name available, explicit location for
36 * normal uniforms as mandatory, and so on).
39 #define UNMAPPED_UNIFORM_LOC ~0u
42 nir_setup_uniform_remap_tables(struct gl_context
*ctx
,
43 struct gl_shader_program
*prog
)
45 prog
->UniformRemapTable
= rzalloc_array(prog
,
46 struct gl_uniform_storage
*,
47 prog
->NumUniformRemapTable
);
48 union gl_constant_value
*data
=
49 rzalloc_array(prog
->data
,
50 union gl_constant_value
, prog
->data
->NumUniformDataSlots
);
51 if (!prog
->UniformRemapTable
|| !data
) {
52 linker_error(prog
, "Out of memory during linking.\n");
55 prog
->data
->UniformDataSlots
= data
;
57 unsigned data_pos
= 0;
59 /* Reserve all the explicit locations of the active uniforms. */
60 for (unsigned i
= 0; i
< prog
->data
->NumUniformStorage
; i
++) {
61 struct gl_uniform_storage
*uniform
= &prog
->data
->UniformStorage
[i
];
63 if (prog
->data
->UniformStorage
[i
].remap_location
== UNMAPPED_UNIFORM_LOC
)
66 /* How many new entries for this uniform? */
67 const unsigned entries
= MAX2(1, uniform
->array_elements
);
68 unsigned num_slots
= glsl_get_component_slots(uniform
->type
);
70 uniform
->storage
= &data
[data_pos
];
72 /* Set remap table entries point to correct gl_uniform_storage. */
73 for (unsigned j
= 0; j
< entries
; j
++) {
74 unsigned element_loc
= uniform
->remap_location
+ j
;
75 prog
->UniformRemapTable
[element_loc
] = uniform
;
77 data_pos
+= num_slots
;
81 /* Reserve locations for rest of the uniforms. */
82 link_util_update_empty_uniform_locations(prog
);
84 for (unsigned i
= 0; i
< prog
->data
->NumUniformStorage
; i
++) {
85 struct gl_uniform_storage
*uniform
= &prog
->data
->UniformStorage
[i
];
87 if (uniform
->is_shader_storage
)
90 /* Built-in uniforms should not get any location. */
94 /* Explicit ones have been set already. */
95 if (uniform
->remap_location
!= UNMAPPED_UNIFORM_LOC
)
98 /* How many entries for this uniform? */
99 const unsigned entries
= MAX2(1, uniform
->array_elements
);
102 link_util_find_empty_block(prog
, &prog
->data
->UniformStorage
[i
]);
104 if (location
== -1) {
105 location
= prog
->NumUniformRemapTable
;
107 /* resize remap table to fit new entries */
108 prog
->UniformRemapTable
=
110 prog
->UniformRemapTable
,
111 struct gl_uniform_storage
*,
112 prog
->NumUniformRemapTable
+ entries
);
113 prog
->NumUniformRemapTable
+= entries
;
116 /* set the base location in remap table for the uniform */
117 uniform
->remap_location
= location
;
119 unsigned num_slots
= glsl_get_component_slots(uniform
->type
);
121 uniform
->storage
= &data
[data_pos
];
123 /* Set remap table entries point to correct gl_uniform_storage. */
124 for (unsigned j
= 0; j
< entries
; j
++) {
125 unsigned element_loc
= uniform
->remap_location
+ j
;
126 prog
->UniformRemapTable
[element_loc
] = uniform
;
128 data_pos
+= num_slots
;
133 static struct gl_uniform_storage
*
134 find_previous_uniform_storage(struct gl_shader_program
*prog
,
137 /* This would only work for uniform with explicit location, as all the
138 * uniforms without location (ie: atomic counters) would have a initial
139 * location equal to -1. We early return in that case.
144 for (unsigned i
= 0; i
< prog
->data
->NumUniformStorage
; i
++)
145 if (prog
->data
->UniformStorage
[i
].remap_location
== location
)
146 return &prog
->data
->UniformStorage
[i
];
151 /* Used to build a tree representing the glsl_type so that we can have a place
152 * to store the next index for opaque types. Array types are expanded so that
153 * they have a single child which is used for all elements of the array.
154 * Struct types have a child for each member. The tree is walked while
155 * processing a uniform so that we can recognise when an opaque type is
156 * encountered a second time in order to reuse the same range of indices that
157 * was reserved the first time. That way the sampler indices can be arranged
158 * so that members of an array are placed sequentially even if the array is an
159 * array of structs containing other opaque members.
161 struct type_tree_entry
{
162 /* For opaque types, this will be the next index to use. If we haven’t
163 * encountered this member yet, it will be UINT_MAX.
167 struct type_tree_entry
*parent
;
168 struct type_tree_entry
*next_sibling
;
169 struct type_tree_entry
*children
;
172 struct nir_link_uniforms_state
{
173 /* per-whole program */
174 unsigned num_hidden_uniforms
;
176 unsigned max_uniform_location
;
177 unsigned next_sampler_index
;
178 unsigned next_image_index
;
180 /* per-shader stage */
181 unsigned num_shader_samplers
;
182 unsigned num_shader_images
;
183 unsigned num_shader_uniform_components
;
184 unsigned shader_samplers_used
;
185 unsigned shader_shadow_samplers
;
187 nir_variable
*current_var
;
189 struct type_tree_entry
*current_type
;
192 static struct type_tree_entry
*
193 build_type_tree_for_type(const struct glsl_type
*type
)
195 struct type_tree_entry
*entry
= malloc(sizeof *entry
);
197 entry
->array_size
= 1;
198 entry
->next_index
= UINT_MAX
;
199 entry
->children
= NULL
;
200 entry
->next_sibling
= NULL
;
201 entry
->parent
= NULL
;
203 if (glsl_type_is_array(type
)) {
204 entry
->array_size
= glsl_get_length(type
);
205 entry
->children
= build_type_tree_for_type(glsl_get_array_element(type
));
206 entry
->children
->parent
= entry
;
207 } else if (glsl_type_is_struct_or_ifc(type
)) {
208 struct type_tree_entry
*last
= NULL
;
210 for (unsigned i
= 0; i
< glsl_get_length(type
); i
++) {
211 const struct glsl_type
*field_type
= glsl_get_struct_field(type
, i
);
212 struct type_tree_entry
*field_entry
=
213 build_type_tree_for_type(field_type
);
216 entry
->children
= field_entry
;
218 last
->next_sibling
= field_entry
;
220 field_entry
->parent
= entry
;
230 free_type_tree(struct type_tree_entry
*entry
)
232 struct type_tree_entry
*p
, *next
;
234 for (p
= entry
->children
; p
; p
= next
) {
235 next
= p
->next_sibling
;
243 get_next_index(struct nir_link_uniforms_state
*state
,
244 const struct gl_uniform_storage
*uniform
,
245 unsigned *next_index
)
247 /* If we’ve already calculated an index for this member then we can just
250 if (state
->current_type
->next_index
== UINT_MAX
) {
251 /* Otherwise we need to reserve enough indices for all of the arrays
252 * enclosing this member.
255 unsigned array_size
= 1;
257 for (const struct type_tree_entry
*p
= state
->current_type
;
260 array_size
*= p
->array_size
;
263 state
->current_type
->next_index
= *next_index
;
264 *next_index
+= array_size
;
267 unsigned index
= state
->current_type
->next_index
;
269 state
->current_type
->next_index
+= MAX2(1, uniform
->array_elements
);
276 * Creates the neccessary entries in UniformStorage for the uniform. Returns
277 * the number of locations used or -1 on failure.
280 nir_link_uniform(struct gl_context
*ctx
,
281 struct gl_shader_program
*prog
,
282 struct gl_program
*stage_program
,
283 gl_shader_stage stage
,
284 const struct glsl_type
*type
,
286 struct nir_link_uniforms_state
*state
)
288 struct gl_uniform_storage
*uniform
= NULL
;
290 /* gl_uniform_storage can cope with one level of array, so if the type is a
291 * composite type or an array where each element occupies more than one
292 * location than we need to recursively process it.
294 if (glsl_type_is_struct_or_ifc(type
) ||
295 (glsl_type_is_array(type
) &&
296 (glsl_type_is_array(glsl_get_array_element(type
)) ||
297 glsl_type_is_struct_or_ifc(glsl_get_array_element(type
))))) {
298 int location_count
= 0;
299 struct type_tree_entry
*old_type
= state
->current_type
;
301 state
->current_type
= old_type
->children
;
303 for (unsigned i
= 0; i
< glsl_get_length(type
); i
++) {
304 const struct glsl_type
*field_type
;
306 if (glsl_type_is_struct_or_ifc(type
))
307 field_type
= glsl_get_struct_field(type
, i
);
309 field_type
= glsl_get_array_element(type
);
311 int entries
= nir_link_uniform(ctx
, prog
, stage_program
, stage
,
312 field_type
, location
,
319 location_count
+= entries
;
321 if (glsl_type_is_struct_or_ifc(type
))
322 state
->current_type
= state
->current_type
->next_sibling
;
325 state
->current_type
= old_type
;
327 return location_count
;
329 /* Create a new uniform storage entry */
330 prog
->data
->UniformStorage
=
332 prog
->data
->UniformStorage
,
333 struct gl_uniform_storage
,
334 prog
->data
->NumUniformStorage
+ 1);
335 if (!prog
->data
->UniformStorage
) {
336 linker_error(prog
, "Out of memory during linking.\n");
340 uniform
= &prog
->data
->UniformStorage
[prog
->data
->NumUniformStorage
];
341 prog
->data
->NumUniformStorage
++;
343 /* Initialize its members */
344 memset(uniform
, 0x00, sizeof(struct gl_uniform_storage
));
345 /* ARB_gl_spirv: names are considered optional debug info, so the linker
346 * needs to work without them, and returning them is optional. For
347 * simplicity we ignore names.
349 uniform
->name
= NULL
;
351 const struct glsl_type
*type_no_array
= glsl_without_array(type
);
352 if (glsl_type_is_array(type
)) {
353 uniform
->type
= type_no_array
;
354 uniform
->array_elements
= glsl_get_length(type
);
356 uniform
->type
= type
;
357 uniform
->array_elements
= 0;
359 uniform
->active_shader_mask
|= 1 << stage
;
362 /* Uniform has an explicit location */
363 uniform
->remap_location
= location
;
365 uniform
->remap_location
= UNMAPPED_UNIFORM_LOC
;
368 uniform
->hidden
= state
->current_var
->data
.how_declared
== nir_var_hidden
;
370 state
->num_hidden_uniforms
++;
372 uniform
->is_shader_storage
= nir_variable_is_in_ssbo(state
->current_var
);
374 /* @FIXME: the initialization of the following will be done as we
375 * implement support for their specific features, like SSBO, atomics,
378 uniform
->block_index
= -1;
379 uniform
->offset
= -1;
380 uniform
->matrix_stride
= -1;
381 uniform
->array_stride
= -1;
382 uniform
->row_major
= false;
383 uniform
->builtin
= false;
384 uniform
->atomic_buffer_index
= -1;
385 uniform
->top_level_array_size
= 0;
386 uniform
->top_level_array_stride
= 0;
387 uniform
->is_bindless
= false;
389 /* The following are not for features not supported by ARB_gl_spirv */
390 uniform
->num_compatible_subroutines
= 0;
392 unsigned entries
= MAX2(1, uniform
->array_elements
);
394 if (glsl_type_is_sampler(type_no_array
)) {
396 get_next_index(state
, uniform
, &state
->next_sampler_index
);
398 state
->num_shader_samplers
++;
400 uniform
->opaque
[stage
].active
= true;
401 uniform
->opaque
[stage
].index
= sampler_index
;
403 const unsigned shadow
= glsl_sampler_type_is_shadow(type_no_array
);
405 for (unsigned i
= sampler_index
;
406 i
< MIN2(state
->next_sampler_index
, MAX_SAMPLERS
);
408 stage_program
->sh
.SamplerTargets
[i
] =
409 glsl_get_sampler_target(type_no_array
);
410 state
->shader_samplers_used
|= 1U << i
;
411 state
->shader_shadow_samplers
|= shadow
<< i
;
413 } else if (glsl_type_is_image(type_no_array
)) {
414 /* @FIXME: image_index should match that of the same image
415 * uniform in other shaders. This means we need to match image
416 * uniforms by location (GLSL does it by variable name, but we
417 * want to avoid that).
419 int image_index
= state
->next_image_index
;
420 state
->next_image_index
+= entries
;
422 state
->num_shader_images
++;
424 uniform
->opaque
[stage
].active
= true;
425 uniform
->opaque
[stage
].index
= image_index
;
427 /* Set image access qualifiers */
428 enum gl_access_qualifier image_access
=
429 state
->current_var
->data
.image
.access
;
430 const GLenum access
=
431 (image_access
& ACCESS_NON_WRITEABLE
) ?
432 ((image_access
& ACCESS_NON_READABLE
) ? GL_NONE
:
434 ((image_access
& ACCESS_NON_READABLE
) ? GL_WRITE_ONLY
:
436 for (unsigned i
= image_index
;
437 i
< MIN2(state
->next_image_index
, MAX_IMAGE_UNIFORMS
);
439 stage_program
->sh
.ImageAccess
[i
] = access
;
443 unsigned values
= glsl_get_component_slots(type
);
444 state
->num_shader_uniform_components
+= values
;
445 state
->num_values
+= values
;
447 if (state
->max_uniform_location
< uniform
->remap_location
+ entries
)
448 state
->max_uniform_location
= uniform
->remap_location
+ entries
;
450 return MAX2(uniform
->array_elements
, 1);
455 gl_nir_link_uniforms(struct gl_context
*ctx
,
456 struct gl_shader_program
*prog
)
458 /* First free up any previous UniformStorage items */
459 ralloc_free(prog
->data
->UniformStorage
);
460 prog
->data
->UniformStorage
= NULL
;
461 prog
->data
->NumUniformStorage
= 0;
463 /* Iterate through all linked shaders */
464 struct nir_link_uniforms_state state
= {0,};
466 for (unsigned shader_type
= 0; shader_type
< MESA_SHADER_STAGES
; shader_type
++) {
467 struct gl_linked_shader
*sh
= prog
->_LinkedShaders
[shader_type
];
471 nir_shader
*nir
= sh
->Program
->nir
;
474 state
.num_shader_samplers
= 0;
475 state
.num_shader_images
= 0;
476 state
.num_shader_uniform_components
= 0;
477 state
.shader_samplers_used
= 0;
478 state
.shader_shadow_samplers
= 0;
480 nir_foreach_variable(var
, &nir
->uniforms
) {
481 struct gl_uniform_storage
*uniform
= NULL
;
483 /* Check if the uniform has been processed already for
484 * other stage. If so, validate they are compatible and update
485 * the active stage mask.
487 uniform
= find_previous_uniform_storage(prog
, var
->data
.location
);
489 uniform
->active_shader_mask
|= 1 << shader_type
;
490 var
->data
.location
= uniform
- prog
->data
->UniformStorage
;
495 int location
= var
->data
.location
;
496 /* From now on the variable’s location will be its uniform index */
497 var
->data
.location
= prog
->data
->NumUniformStorage
;
499 state
.current_var
= var
;
501 struct type_tree_entry
*type_tree
=
502 build_type_tree_for_type(var
->type
);
503 state
.current_type
= type_tree
;
505 int res
= nir_link_uniform(ctx
, prog
, sh
->Program
, shader_type
, var
->type
,
508 free_type_tree(type_tree
);
514 sh
->Program
->SamplersUsed
= state
.shader_samplers_used
;
515 sh
->shadow_samplers
= state
.shader_shadow_samplers
;
516 sh
->Program
->info
.num_textures
= state
.num_shader_samplers
;
517 sh
->Program
->info
.num_images
= state
.num_shader_images
;
518 sh
->num_uniform_components
= state
.num_shader_uniform_components
;
519 sh
->num_combined_uniform_components
= sh
->num_uniform_components
;
522 prog
->data
->NumHiddenUniforms
= state
.num_hidden_uniforms
;
523 prog
->NumUniformRemapTable
= state
.max_uniform_location
;
524 prog
->data
->NumUniformDataSlots
= state
.num_values
;
526 nir_setup_uniform_remap_tables(ctx
, prog
);
527 gl_nir_set_uniform_initializers(ctx
, prog
);