2 * Copyright © 2012 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
21 * DEALINGS IN THE SOFTWARE.
25 * \file lower_ubo_reference.cpp
27 * IR lower pass to replace dereferences of variables in a uniform
28 * buffer object with usage of ir_binop_ubo_load expressions, each of
29 * which can read data up to the size of a vec4.
31 * This relieves drivers of the responsibility to deal with tricky UBO
32 * layout issues like std140 structures and row_major matrices on
37 #include "ir_builder.h"
38 #include "ir_rvalue_visitor.h"
39 #include "main/macros.h"
40 #include "glsl_parser_extras.h"
42 using namespace ir_builder
;
45 * Determine if a thing being dereferenced is row-major
47 * There is some trickery here.
49 * If the thing being dereferenced is a member of uniform block \b without an
50 * instance name, then the name of the \c ir_variable is the field name of an
51 * interface type. If this field is row-major, then the thing referenced is
54 * If the thing being dereferenced is a member of uniform block \b with an
55 * instance name, then the last dereference in the tree will be an
56 * \c ir_dereference_record. If that record field is row-major, then the
57 * thing referenced is row-major.
60 is_dereferenced_thing_row_major(const ir_dereference
*deref
)
63 const ir_rvalue
*ir
= deref
;
66 matrix
= matrix
|| ir
->type
->without_array()->is_matrix();
68 switch (ir
->ir_type
) {
69 case ir_type_dereference_array
: {
70 const ir_dereference_array
*const array_deref
=
71 (const ir_dereference_array
*) ir
;
73 ir
= array_deref
->array
;
77 case ir_type_dereference_record
: {
78 const ir_dereference_record
*const record_deref
=
79 (const ir_dereference_record
*) ir
;
81 ir
= record_deref
->record
;
83 const int idx
= ir
->type
->field_index(record_deref
->field
);
86 const enum glsl_matrix_layout matrix_layout
=
87 glsl_matrix_layout(ir
->type
->fields
.structure
[idx
].matrix_layout
);
89 switch (matrix_layout
) {
90 case GLSL_MATRIX_LAYOUT_INHERITED
:
92 case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR
:
94 case GLSL_MATRIX_LAYOUT_ROW_MAJOR
:
95 return matrix
|| deref
->type
->without_array()->is_record();
101 case ir_type_dereference_variable
: {
102 const ir_dereference_variable
*const var_deref
=
103 (const ir_dereference_variable
*) ir
;
105 const enum glsl_matrix_layout matrix_layout
=
106 glsl_matrix_layout(var_deref
->var
->data
.matrix_layout
);
108 switch (matrix_layout
) {
109 case GLSL_MATRIX_LAYOUT_INHERITED
:
112 case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR
:
114 case GLSL_MATRIX_LAYOUT_ROW_MAJOR
:
115 return matrix
|| deref
->type
->without_array()->is_record();
118 unreachable("invalid matrix layout");
127 /* The tree must have ended with a dereference that wasn't an
128 * ir_dereference_variable. That is invalid, and it should be impossible.
130 unreachable("invalid dereference tree");
135 class lower_ubo_reference_visitor
: public ir_rvalue_enter_visitor
{
137 lower_ubo_reference_visitor(struct gl_shader
*shader
)
142 void handle_rvalue(ir_rvalue
**rvalue
);
143 ir_visitor_status
visit_enter(ir_assignment
*ir
);
145 void setup_for_load_or_store(ir_variable
*var
,
146 ir_dereference
*deref
,
148 unsigned *const_offset
,
150 int *matrix_columns
);
151 ir_expression
*ubo_load(const struct glsl_type
*type
,
153 ir_call
*ssbo_load(const struct glsl_type
*type
,
156 void check_for_ssbo_store(ir_assignment
*ir
);
157 void write_to_memory(ir_dereference
*deref
,
159 ir_variable
*write_var
,
160 unsigned write_mask
);
161 ir_call
*ssbo_store(ir_rvalue
*deref
, ir_rvalue
*offset
,
162 unsigned write_mask
);
164 void emit_access(bool is_write
, ir_dereference
*deref
,
165 ir_variable
*base_offset
, unsigned int deref_offset
,
166 bool row_major
, int matrix_columns
,
167 unsigned write_mask
);
170 struct gl_shader
*shader
;
171 struct gl_uniform_buffer_variable
*ubo_var
;
172 ir_rvalue
*uniform_block
;
174 bool is_shader_storage
;
178 * Determine the name of the interface block field
180 * This is the name of the specific member as it would appear in the
181 * \c gl_uniform_buffer_variable::Name field in the shader's
182 * \c UniformBlocks array.
185 interface_field_name(void *mem_ctx
, char *base_name
, ir_dereference
*d
,
186 ir_rvalue
**nonconst_block_index
)
188 ir_rvalue
*previous_index
= NULL
;
189 *nonconst_block_index
= NULL
;
192 switch (d
->ir_type
) {
193 case ir_type_dereference_variable
: {
194 ir_dereference_variable
*v
= (ir_dereference_variable
*) d
;
196 && v
->var
->is_interface_instance()
197 && v
->var
->type
->is_array()) {
199 ir_constant
*const_index
= previous_index
->as_constant();
201 *nonconst_block_index
= previous_index
;
202 return ralloc_asprintf(mem_ctx
, "%s[0]", base_name
);
204 return ralloc_asprintf(mem_ctx
,
207 const_index
->get_uint_component(0));
216 case ir_type_dereference_record
: {
217 ir_dereference_record
*r
= (ir_dereference_record
*) d
;
219 d
= r
->record
->as_dereference();
223 case ir_type_dereference_array
: {
224 ir_dereference_array
*a
= (ir_dereference_array
*) d
;
226 d
= a
->array
->as_dereference();
227 previous_index
= a
->array_index
;
233 assert(!"Should not get here.");
238 assert(!"Should not get here.");
243 lower_ubo_reference_visitor::setup_for_load_or_store(ir_variable
*var
,
244 ir_dereference
*deref
,
246 unsigned *const_offset
,
250 /* Determine the name of the interface block */
251 ir_rvalue
*nonconst_block_index
;
252 const char *const field_name
=
253 interface_field_name(mem_ctx
, (char *) var
->get_interface_type()->name
,
254 deref
, &nonconst_block_index
);
256 /* Locate the ubo block by interface name */
257 this->uniform_block
= NULL
;
258 for (unsigned i
= 0; i
< shader
->NumUniformBlocks
; i
++) {
259 if (strcmp(field_name
, shader
->UniformBlocks
[i
].Name
) == 0) {
261 ir_constant
*index
= new(mem_ctx
) ir_constant(i
);
263 if (nonconst_block_index
) {
264 if (nonconst_block_index
->type
!= glsl_type::uint_type
)
265 nonconst_block_index
= i2u(nonconst_block_index
);
266 this->uniform_block
= add(nonconst_block_index
, index
);
268 this->uniform_block
= index
;
271 this->is_shader_storage
= shader
->UniformBlocks
[i
].IsShaderStorage
;
273 struct gl_uniform_block
*block
= &shader
->UniformBlocks
[i
];
275 this->ubo_var
= var
->is_interface_instance()
276 ? &block
->Uniforms
[0] : &block
->Uniforms
[var
->data
.location
];
282 assert(this->uniform_block
);
284 *offset
= new(mem_ctx
) ir_constant(0u);
286 *row_major
= is_dereferenced_thing_row_major(deref
);
289 /* Calculate the offset to the start of the region of the UBO
290 * dereferenced by *rvalue. This may be a variable offset if an
291 * array dereference has a variable index.
294 switch (deref
->ir_type
) {
295 case ir_type_dereference_variable
: {
296 *const_offset
+= ubo_var
->Offset
;
301 case ir_type_dereference_array
: {
302 ir_dereference_array
*deref_array
= (ir_dereference_array
*) deref
;
303 unsigned array_stride
;
304 if (deref_array
->array
->type
->is_matrix() && *row_major
) {
305 /* When loading a vector out of a row major matrix, the
306 * step between the columns (vectors) is the size of a
307 * float, while the step between the rows (elements of a
308 * vector) is handled below in emit_ubo_loads.
311 if (deref_array
->array
->type
->is_double())
313 *matrix_columns
= deref_array
->array
->type
->matrix_columns
;
314 } else if (deref_array
->type
->is_interface()) {
315 /* We're processing an array dereference of an interface instance
316 * array. The thing being dereferenced *must* be a variable
317 * dereference because interfaces cannot be embedded in other
318 * types. In terms of calculating the offsets for the lowering
319 * pass, we don't care about the array index. All elements of an
320 * interface instance array will have the same offsets relative to
321 * the base of the block that backs them.
323 assert(deref_array
->array
->as_dereference_variable());
324 deref
= deref_array
->array
->as_dereference();
327 /* Whether or not the field is row-major (because it might be a
328 * bvec2 or something) does not affect the array itself. We need
329 * to know whether an array element in its entirety is row-major.
331 const bool array_row_major
=
332 is_dereferenced_thing_row_major(deref_array
);
334 array_stride
= deref_array
->type
->std140_size(array_row_major
);
335 array_stride
= glsl_align(array_stride
, 16);
338 ir_rvalue
*array_index
= deref_array
->array_index
;
339 if (array_index
->type
->base_type
== GLSL_TYPE_INT
)
340 array_index
= i2u(array_index
);
342 ir_constant
*const_index
=
343 array_index
->constant_expression_value(NULL
);
345 *const_offset
+= array_stride
* const_index
->value
.u
[0];
347 *offset
= add(*offset
,
349 new(mem_ctx
) ir_constant(array_stride
)));
351 deref
= deref_array
->array
->as_dereference();
355 case ir_type_dereference_record
: {
356 ir_dereference_record
*deref_record
= (ir_dereference_record
*) deref
;
357 const glsl_type
*struct_type
= deref_record
->record
->type
;
358 unsigned intra_struct_offset
= 0;
360 for (unsigned int i
= 0; i
< struct_type
->length
; i
++) {
361 const glsl_type
*type
= struct_type
->fields
.structure
[i
].type
;
363 ir_dereference_record
*field_deref
= new(mem_ctx
)
364 ir_dereference_record(deref_record
->record
,
365 struct_type
->fields
.structure
[i
].name
);
366 const bool field_row_major
=
367 is_dereferenced_thing_row_major(field_deref
);
369 ralloc_free(field_deref
);
371 unsigned field_align
= type
->std140_base_alignment(field_row_major
);
373 intra_struct_offset
= glsl_align(intra_struct_offset
, field_align
);
375 if (strcmp(struct_type
->fields
.structure
[i
].name
,
376 deref_record
->field
) == 0)
379 intra_struct_offset
+= type
->std140_size(field_row_major
);
381 /* If the field just examined was itself a structure, apply rule
384 * "The structure may have padding at the end; the base offset
385 * of the member following the sub-structure is rounded up to
386 * the next multiple of the base alignment of the structure."
388 if (type
->without_array()->is_record()) {
389 intra_struct_offset
= glsl_align(intra_struct_offset
,
395 *const_offset
+= intra_struct_offset
;
396 deref
= deref_record
->record
->as_dereference();
401 assert(!"not reached");
409 lower_ubo_reference_visitor::handle_rvalue(ir_rvalue
**rvalue
)
414 ir_dereference
*deref
= (*rvalue
)->as_dereference();
418 ir_variable
*var
= deref
->variable_referenced();
419 if (!var
|| !var
->is_in_buffer_block())
422 mem_ctx
= ralloc_parent(shader
->ir
);
424 ir_rvalue
*offset
= NULL
;
425 unsigned const_offset
;
429 /* Compute the offset to the start if the dereference as well as other
430 * information we need to configure the write
432 setup_for_load_or_store(var
, deref
,
433 &offset
, &const_offset
,
434 &row_major
, &matrix_columns
);
437 /* Now that we've calculated the offset to the start of the
438 * dereference, walk over the type and emit loads into a temporary.
440 const glsl_type
*type
= (*rvalue
)->type
;
441 ir_variable
*load_var
= new(mem_ctx
) ir_variable(type
,
444 base_ir
->insert_before(load_var
);
446 ir_variable
*load_offset
= new(mem_ctx
) ir_variable(glsl_type::uint_type
,
447 "ubo_load_temp_offset",
449 base_ir
->insert_before(load_offset
);
450 base_ir
->insert_before(assign(load_offset
, offset
));
452 deref
= new(mem_ctx
) ir_dereference_variable(load_var
);
453 emit_access(false, deref
, load_offset
, const_offset
,
454 row_major
, matrix_columns
, 0);
461 lower_ubo_reference_visitor::ubo_load(const glsl_type
*type
,
464 ir_rvalue
*block_ref
= this->uniform_block
->clone(mem_ctx
, NULL
);
466 ir_expression(ir_binop_ubo_load
,
474 shader_storage_buffer_object(const _mesa_glsl_parse_state
*state
)
476 return state
->ARB_shader_storage_buffer_object_enable
;
480 lower_ubo_reference_visitor::ssbo_store(ir_rvalue
*deref
,
484 exec_list sig_params
;
486 ir_variable
*block_ref
= new(mem_ctx
)
487 ir_variable(glsl_type::uint_type
, "block_ref" , ir_var_function_in
);
488 sig_params
.push_tail(block_ref
);
490 ir_variable
*offset_ref
= new(mem_ctx
)
491 ir_variable(glsl_type::uint_type
, "offset" , ir_var_function_in
);
492 sig_params
.push_tail(offset_ref
);
494 ir_variable
*val_ref
= new(mem_ctx
)
495 ir_variable(deref
->type
, "value" , ir_var_function_in
);
496 sig_params
.push_tail(val_ref
);
498 ir_variable
*writemask_ref
= new(mem_ctx
)
499 ir_variable(glsl_type::uint_type
, "write_mask" , ir_var_function_in
);
500 sig_params
.push_tail(writemask_ref
);
502 ir_function_signature
*sig
= new(mem_ctx
)
503 ir_function_signature(glsl_type::void_type
, shader_storage_buffer_object
);
505 sig
->replace_parameters(&sig_params
);
506 sig
->is_intrinsic
= true;
508 ir_function
*f
= new(mem_ctx
) ir_function("__intrinsic_store_ssbo");
509 f
->add_signature(sig
);
511 exec_list call_params
;
512 call_params
.push_tail(this->uniform_block
->clone(mem_ctx
, NULL
));
513 call_params
.push_tail(offset
->clone(mem_ctx
, NULL
));
514 call_params
.push_tail(deref
->clone(mem_ctx
, NULL
));
515 call_params
.push_tail(new(mem_ctx
) ir_constant(write_mask
));
516 return new(mem_ctx
) ir_call(sig
, NULL
, &call_params
);
520 lower_ubo_reference_visitor::ssbo_load(const struct glsl_type
*type
,
523 exec_list sig_params
;
525 ir_variable
*block_ref
= new(mem_ctx
)
526 ir_variable(glsl_type::uint_type
, "block_ref" , ir_var_function_in
);
527 sig_params
.push_tail(block_ref
);
529 ir_variable
*offset_ref
= new(mem_ctx
)
530 ir_variable(glsl_type::uint_type
, "offset_ref" , ir_var_function_in
);
531 sig_params
.push_tail(offset_ref
);
533 ir_function_signature
*sig
=
534 new(mem_ctx
) ir_function_signature(type
, shader_storage_buffer_object
);
536 sig
->replace_parameters(&sig_params
);
537 sig
->is_intrinsic
= true;
539 ir_function
*f
= new(mem_ctx
) ir_function("__intrinsic_load_ssbo");
540 f
->add_signature(sig
);
542 ir_variable
*result
= new(mem_ctx
)
543 ir_variable(type
, "ssbo_load_result", ir_var_temporary
);
544 base_ir
->insert_before(result
);
545 ir_dereference_variable
*deref_result
= new(mem_ctx
)
546 ir_dereference_variable(result
);
548 exec_list call_params
;
549 call_params
.push_tail(this->uniform_block
->clone(mem_ctx
, NULL
));
550 call_params
.push_tail(offset
->clone(mem_ctx
, NULL
));
552 return new(mem_ctx
) ir_call(sig
, deref_result
, &call_params
);
556 writemask_for_size(unsigned n
)
558 return ((1 << n
) - 1);
562 * Takes a deref and recursively calls itself to break the deref down to the
563 * point that the reads or writes generated are contiguous scalars or vectors.
566 lower_ubo_reference_visitor::emit_access(bool is_write
,
567 ir_dereference
*deref
,
568 ir_variable
*base_offset
,
569 unsigned int deref_offset
,
574 if (deref
->type
->is_record()) {
575 unsigned int field_offset
= 0;
577 for (unsigned i
= 0; i
< deref
->type
->length
; i
++) {
578 const struct glsl_struct_field
*field
=
579 &deref
->type
->fields
.structure
[i
];
580 ir_dereference
*field_deref
=
581 new(mem_ctx
) ir_dereference_record(deref
->clone(mem_ctx
, NULL
),
585 glsl_align(field_offset
,
586 field
->type
->std140_base_alignment(row_major
));
588 emit_access(is_write
, field_deref
, base_offset
,
589 deref_offset
+ field_offset
,
591 writemask_for_size(field_deref
->type
->vector_elements
));
593 field_offset
+= field
->type
->std140_size(row_major
);
598 if (deref
->type
->is_array()) {
599 unsigned array_stride
=
600 glsl_align(deref
->type
->fields
.array
->std140_size(row_major
), 16);
602 for (unsigned i
= 0; i
< deref
->type
->length
; i
++) {
603 ir_constant
*element
= new(mem_ctx
) ir_constant(i
);
604 ir_dereference
*element_deref
=
605 new(mem_ctx
) ir_dereference_array(deref
->clone(mem_ctx
, NULL
),
607 emit_access(is_write
, element_deref
, base_offset
,
608 deref_offset
+ i
* array_stride
,
610 writemask_for_size(element_deref
->type
->vector_elements
));
615 if (deref
->type
->is_matrix()) {
616 for (unsigned i
= 0; i
< deref
->type
->matrix_columns
; i
++) {
617 ir_constant
*col
= new(mem_ctx
) ir_constant(i
);
618 ir_dereference
*col_deref
=
619 new(mem_ctx
) ir_dereference_array(deref
->clone(mem_ctx
, NULL
), col
);
622 /* For a row-major matrix, the next column starts at the next
625 int size_mul
= deref
->type
->is_double() ? 8 : 4;
626 emit_access(is_write
, col_deref
, base_offset
,
627 deref_offset
+ i
* size_mul
,
628 row_major
, deref
->type
->matrix_columns
,
629 writemask_for_size(col_deref
->type
->vector_elements
));
631 /* std140 always rounds the stride of arrays (and matrices) to a
632 * vec4, so matrices are always 16 between columns/rows. With
633 * doubles, they will be 32 apart when there are more than 2 rows.
635 int size_mul
= (deref
->type
->is_double() &&
636 deref
->type
->vector_elements
> 2) ? 32 : 16;
637 emit_access(is_write
, col_deref
, base_offset
,
638 deref_offset
+ i
* size_mul
,
639 row_major
, deref
->type
->matrix_columns
,
640 writemask_for_size(col_deref
->type
->vector_elements
));
646 assert(deref
->type
->is_scalar() || deref
->type
->is_vector());
650 add(base_offset
, new(mem_ctx
) ir_constant(deref_offset
));
652 base_ir
->insert_after(ssbo_store(deref
, offset
, write_mask
));
654 if (!this->is_shader_storage
) {
655 base_ir
->insert_before(assign(deref
->clone(mem_ctx
, NULL
),
656 ubo_load(deref
->type
, offset
)));
658 ir_call
*load_ssbo
= ssbo_load(deref
->type
, offset
);
659 base_ir
->insert_before(load_ssbo
);
660 ir_rvalue
*value
= load_ssbo
->return_deref
->as_rvalue()->clone(mem_ctx
, NULL
);
661 base_ir
->insert_before(assign(deref
->clone(mem_ctx
, NULL
), value
));
665 unsigned N
= deref
->type
->is_double() ? 8 : 4;
667 /* We're dereffing a column out of a row-major matrix, so we
668 * gather the vector from each stored row.
670 assert(deref
->type
->base_type
== GLSL_TYPE_FLOAT
||
671 deref
->type
->base_type
== GLSL_TYPE_DOUBLE
);
672 /* Matrices, row_major or not, are stored as if they were
673 * arrays of vectors of the appropriate size in std140.
674 * Arrays have their strides rounded up to a vec4, so the
675 * matrix stride is always 16. However a double matrix may either be 16
676 * or 32 depending on the number of columns.
678 assert(matrix_columns
<= 4);
679 unsigned matrix_stride
= glsl_align(matrix_columns
* N
, 16);
681 const glsl_type
*deref_type
= deref
->type
->base_type
== GLSL_TYPE_FLOAT
?
682 glsl_type::float_type
: glsl_type::double_type
;
684 for (unsigned i
= 0; i
< deref
->type
->vector_elements
; i
++) {
685 ir_rvalue
*chan_offset
=
687 new(mem_ctx
) ir_constant(deref_offset
+ i
* matrix_stride
));
689 base_ir
->insert_after(ssbo_store(swizzle(deref
, i
, 1), chan_offset
, 1));
691 if (!this->is_shader_storage
) {
692 base_ir
->insert_before(assign(deref
->clone(mem_ctx
, NULL
),
693 ubo_load(deref_type
, chan_offset
),
696 ir_call
*load_ssbo
= ssbo_load(deref_type
, chan_offset
);
697 base_ir
->insert_before(load_ssbo
);
698 ir_rvalue
*value
= load_ssbo
->return_deref
->as_rvalue()->clone(mem_ctx
, NULL
);
699 base_ir
->insert_before(assign(deref
->clone(mem_ctx
, NULL
),
709 lower_ubo_reference_visitor::write_to_memory(ir_dereference
*deref
,
711 ir_variable
*write_var
,
714 ir_rvalue
*offset
= NULL
;
715 unsigned const_offset
;
719 /* Compute the offset to the start if the dereference as well as other
720 * information we need to configure the write
722 setup_for_load_or_store(var
, deref
,
723 &offset
, &const_offset
,
724 &row_major
, &matrix_columns
);
727 /* Now emit writes from the temporary to memory */
728 ir_variable
*write_offset
=
729 new(mem_ctx
) ir_variable(glsl_type::uint_type
,
730 "ssbo_store_temp_offset",
733 base_ir
->insert_before(write_offset
);
734 base_ir
->insert_before(assign(write_offset
, offset
));
736 deref
= new(mem_ctx
) ir_dereference_variable(write_var
);
737 emit_access(true, deref
, write_offset
, const_offset
,
738 row_major
, matrix_columns
, write_mask
);
742 lower_ubo_reference_visitor::check_for_ssbo_store(ir_assignment
*ir
)
747 ir_rvalue
*rvalue
= ir
->lhs
->as_rvalue();
751 ir_dereference
*deref
= ir
->lhs
->as_dereference();
755 ir_variable
*var
= ir
->lhs
->variable_referenced();
756 if (!var
|| !var
->is_in_buffer_block())
759 /* We have a write to a buffer variable, so declare a temporary and rewrite
760 * the assignment so that the temporary is the LHS.
762 mem_ctx
= ralloc_parent(shader
->ir
);
764 const glsl_type
*type
= rvalue
->type
;
765 ir_variable
*write_var
= new(mem_ctx
) ir_variable(type
,
768 base_ir
->insert_before(write_var
);
769 ir
->lhs
= new(mem_ctx
) ir_dereference_variable(write_var
);
771 /* Now we have to write the value assigned to the temporary back to memory */
772 write_to_memory(deref
, var
, write_var
, ir
->write_mask
);
778 lower_ubo_reference_visitor::visit_enter(ir_assignment
*ir
)
780 check_for_ssbo_store(ir
);
781 return rvalue_visit(ir
);
784 } /* unnamed namespace */
787 lower_ubo_reference(struct gl_shader
*shader
, exec_list
*instructions
)
789 lower_ubo_reference_visitor
v(shader
);
791 /* Loop over the instructions lowering references, because we take
792 * a deref of a UBO array using a UBO dereference as the index will
793 * produce a collection of instructions all of which have cloned
794 * UBO dereferences for that array index.
798 visit_list_elements(&v
, instructions
);
799 } while (v
.progress
);