freedreno/ir3: Enable PIPE_CAP_PACKED_UNIFORMS
[mesa.git] / src / freedreno / ir3 / ir3_nir_analyze_ubo_ranges.c
1 /*
2 * Copyright © 2019 Google, Inc.
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include "ir3_nir.h"
25 #include "compiler/nir/nir.h"
26 #include "compiler/nir/nir_builder.h"
27 #include "util/u_dynarray.h"
28 #include "mesa/main/macros.h"
29
30 struct ir3_ubo_analysis_state {
31 unsigned lower_count;
32 };
33
34 static void
35 lower_ubo_load_to_uniform(nir_intrinsic_instr *instr, nir_builder *b,
36 struct ir3_ubo_analysis_state *state)
37 {
38 /* We don't lower dynamic block index UBO loads to load_uniform, but we
39 * could probably with some effort determine a block stride in number of
40 * registers.
41 */
42 if (!nir_src_is_const(instr->src[0]))
43 return;
44
45 const uint32_t block = nir_src_as_uint(instr->src[0]);
46 if (block > 0)
47 return;
48
49 b->cursor = nir_before_instr(&instr->instr);
50
51 nir_ssa_def *ubo_offset = nir_ssa_for_src(b, instr->src[1], 1);
52 nir_ssa_def *uniform_offset = ir3_nir_try_propagate_bit_shift(b, ubo_offset, -2);
53 if (uniform_offset == NULL)
54 uniform_offset = nir_ushr(b, ubo_offset, nir_imm_int(b, 2));
55
56 nir_intrinsic_instr *uniform =
57 nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_uniform);
58 uniform->num_components = instr->num_components;
59 uniform->src[0] = nir_src_for_ssa(uniform_offset);
60 nir_ssa_dest_init(&uniform->instr, &uniform->dest,
61 uniform->num_components, instr->dest.ssa.bit_size,
62 instr->dest.ssa.name);
63 nir_builder_instr_insert(b, &uniform->instr);
64 nir_ssa_def_rewrite_uses(&instr->dest.ssa,
65 nir_src_for_ssa(&uniform->dest.ssa));
66
67 nir_instr_remove(&instr->instr);
68
69 state->lower_count++;
70 }
71
72 bool
73 ir3_nir_analyze_ubo_ranges(nir_shader *nir, struct ir3_shader *shader)
74 {
75 struct ir3_ubo_analysis_state state = { 0 };
76
77 nir_foreach_function(function, nir) {
78 if (function->impl) {
79 nir_builder builder;
80 nir_builder_init(&builder, function->impl);
81 nir_foreach_block(block, function->impl) {
82 nir_foreach_instr_safe(instr, block) {
83 if (instr->type == nir_instr_type_intrinsic &&
84 nir_instr_as_intrinsic(instr)->intrinsic == nir_intrinsic_load_ubo)
85 lower_ubo_load_to_uniform(nir_instr_as_intrinsic(instr), &builder, &state);
86 }
87 }
88
89 nir_metadata_preserve(function->impl, nir_metadata_block_index |
90 nir_metadata_dominance);
91 }
92 }
93
94 return state.lower_count > 0;
95 }