2 * Copyright © 2014 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_const_arrays_to_uniforms.cpp
27 * Lower constant arrays to uniform arrays.
29 * Some driver backends (such as i965 and nouveau) don't handle constant arrays
30 * gracefully, instead treating them as ordinary writable temporary arrays.
31 * Since arrays can be large, this often means spilling them to scratch memory,
32 * which usually involves a large number of instructions.
34 * This must be called prior to link_set_uniform_initializers(); we need the
35 * linker to process our new uniform's constant initializer.
37 * This should be called after optimizations, since those can result in
38 * splitting and removing arrays that are indexed by constant expressions.
41 #include "ir_visitor.h"
42 #include "ir_rvalue_visitor.h"
43 #include "compiler/glsl_types.h"
46 class lower_const_array_visitor
: public ir_rvalue_visitor
{
48 lower_const_array_visitor(exec_list
*insts
, unsigned s
,
49 unsigned available_uni_components
)
54 free_uni_components
= available_uni_components
;
60 visit_list_elements(this, instructions
);
64 ir_visitor_status
visit_enter(ir_texture
*);
65 void handle_rvalue(ir_rvalue
**rvalue
);
68 exec_list
*instructions
;
71 unsigned free_uni_components
;
76 lower_const_array_visitor::visit_enter(ir_texture
*)
78 return visit_continue_with_parent
;
82 lower_const_array_visitor::handle_rvalue(ir_rvalue
**rvalue
)
87 ir_constant
*con
= (*rvalue
)->as_constant();
88 if (!con
|| !con
->type
->is_array())
91 /* How many uniform component slots are required? */
92 unsigned component_slots
= con
->type
->component_slots();
94 /* We would utilize more than is available, bail out. */
95 if (component_slots
> free_uni_components
)
98 free_uni_components
-= component_slots
;
100 void *mem_ctx
= ralloc_parent(con
);
102 /* In the very unlikely event of 4294967295 constant arrays in a single
103 * shader, don't promote this to a uniform.
106 if (const_count
== limit
)
109 char *uniform_name
= ralloc_asprintf(mem_ctx
, "constarray_%x_%u",
114 new(mem_ctx
) ir_variable(con
->type
, uniform_name
, ir_var_uniform
);
115 uni
->constant_initializer
= con
;
116 uni
->constant_value
= con
;
117 uni
->data
.has_initializer
= true;
118 uni
->data
.how_declared
= ir_var_hidden
;
119 uni
->data
.read_only
= true;
120 /* Assume the whole thing is accessed. */
121 uni
->data
.max_array_access
= uni
->type
->length
- 1;
122 instructions
->push_head(uni
);
124 *rvalue
= new(mem_ctx
) ir_dereference_variable(uni
);
129 } /* anonymous namespace */
133 count_uniforms(exec_list
*instructions
)
137 foreach_in_list(ir_instruction
, node
, instructions
) {
138 ir_variable
*const var
= node
->as_variable();
140 if (!var
|| var
->data
.mode
!= ir_var_uniform
)
143 total
+= var
->type
->component_slots();
149 lower_const_arrays_to_uniforms(exec_list
*instructions
, unsigned stage
,
150 unsigned max_uniform_components
)
152 unsigned uniform_components
= count_uniforms(instructions
);
153 unsigned free_uniform_slots
= max_uniform_components
- uniform_components
;
155 lower_const_array_visitor
v(instructions
, stage
, free_uniform_slots
);