xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/panfrost/pan_nir_lower_res_indices.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2024 Collabora Ltd.
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 "compiler/nir/nir_builder.h"
25 #include "genxml/gen_macros.h"
26 #include "pan_context.h"
27 #include "pan_shader.h"
28 
29 static bool
lower_tex(nir_builder * b,nir_tex_instr * tex)30 lower_tex(nir_builder *b, nir_tex_instr *tex)
31 {
32    b->cursor = nir_before_instr(&tex->instr);
33 
34    nir_def *tex_offset = nir_steal_tex_src(tex, nir_tex_src_texture_offset);
35    nir_def *sampler_offset = nir_steal_tex_src(tex, nir_tex_src_sampler_offset);
36 
37    if (tex_offset != NULL) {
38       tex_offset =
39          nir_ior_imm(b, tex_offset, pan_res_handle(PAN_TABLE_TEXTURE, 0));
40       nir_tex_instr_add_src(tex, nir_tex_src_texture_offset, tex_offset);
41    } else {
42       tex->texture_index =
43          pan_res_handle(PAN_TABLE_TEXTURE, tex->texture_index);
44    }
45 
46    /* By ABI with the compiler, we assume there is a valid sampler bound at
47     * index 0 for txf.
48     */
49    if (!nir_tex_instr_need_sampler(tex)) {
50       tex->sampler_index = pan_res_handle(PAN_TABLE_SAMPLER, 0);
51    } else if (sampler_offset != NULL) {
52       sampler_offset =
53          nir_ior_imm(b, sampler_offset, pan_res_handle(PAN_TABLE_SAMPLER, 0));
54       nir_tex_instr_add_src(tex, nir_tex_src_sampler_offset, sampler_offset);
55    } else {
56       tex->sampler_index =
57          pan_res_handle(PAN_TABLE_SAMPLER, tex->sampler_index);
58    }
59 
60    return true;
61 }
62 
63 static bool
lower_image_intrin(nir_builder * b,nir_intrinsic_instr * intrin)64 lower_image_intrin(nir_builder *b, nir_intrinsic_instr *intrin)
65 {
66    b->cursor = nir_before_instr(&intrin->instr);
67 
68    nir_src *tex_handle = &intrin->src[0];
69    nir_def *new_handle =
70       nir_ior_imm(b, tex_handle->ssa, pan_res_handle(PAN_TABLE_IMAGE, 0));
71    nir_src_rewrite(tex_handle, new_handle);
72 
73    return true;
74 }
75 
76 static bool
lower_input_intrin(nir_builder * b,nir_intrinsic_instr * intrin,const struct panfrost_compile_inputs * inputs)77 lower_input_intrin(nir_builder *b, nir_intrinsic_instr *intrin,
78                    const struct panfrost_compile_inputs *inputs)
79 {
80    /* We always use heap-based varying allocation when IDVS is used on Valhall. */
81    bool malloc_idvs = !inputs->no_idvs;
82 
83    /* All vertex attributes come from the attribute table.
84     * Fragment inputs come from the attribute table too, unless they've
85     * been allocated on the heap.
86     */
87    if (b->shader->info.stage == MESA_SHADER_VERTEX ||
88        (b->shader->info.stage == MESA_SHADER_FRAGMENT && !malloc_idvs)) {
89       nir_intrinsic_set_base(
90          intrin,
91          pan_res_handle(PAN_TABLE_ATTRIBUTE, nir_intrinsic_base(intrin)));
92       return true;
93    }
94 
95    return false;
96 }
97 
98 static bool
lower_load_ubo_intrin(nir_builder * b,nir_intrinsic_instr * intrin)99 lower_load_ubo_intrin(nir_builder *b, nir_intrinsic_instr *intrin)
100 {
101    b->cursor = nir_before_instr(&intrin->instr);
102 
103    nir_def *new_offset =
104       nir_ior_imm(b, intrin->src[0].ssa, pan_res_handle(PAN_TABLE_UBO, 0));
105 
106    nir_src_rewrite(&intrin->src[0], new_offset);
107 
108    return true;
109 }
110 
111 static bool
lower_ssbo_intrin(nir_builder * b,nir_intrinsic_instr * intrin)112 lower_ssbo_intrin(nir_builder *b, nir_intrinsic_instr *intrin)
113 {
114    b->cursor = nir_before_instr(&intrin->instr);
115 
116    nir_def *new_offset = nir_ior_imm(b, intrin->src[0].ssa,
117                                      pan_res_handle(PAN_TABLE_SSBO, 0));
118 
119    nir_src_rewrite(&intrin->src[0], new_offset);
120 
121    return true;
122 }
123 
124 static bool
lower_intrinsic(nir_builder * b,nir_intrinsic_instr * intrin,const struct panfrost_compile_inputs * inputs)125 lower_intrinsic(nir_builder *b, nir_intrinsic_instr *intrin,
126                 const struct panfrost_compile_inputs *inputs)
127 {
128    switch (intrin->intrinsic) {
129    case nir_intrinsic_image_load:
130    case nir_intrinsic_image_store:
131    case nir_intrinsic_image_texel_address:
132       return lower_image_intrin(b, intrin);
133    case nir_intrinsic_load_input:
134       return lower_input_intrin(b, intrin, inputs);
135    case nir_intrinsic_load_ubo:
136       return lower_load_ubo_intrin(b, intrin);
137    case nir_intrinsic_load_ssbo:
138    case nir_intrinsic_load_ssbo_address:
139       return lower_ssbo_intrin(b, intrin);
140    default:
141       return false;
142    }
143 }
144 
145 static bool
lower_instr(nir_builder * b,nir_instr * instr,void * data)146 lower_instr(nir_builder *b, nir_instr *instr, void *data)
147 {
148    const struct panfrost_compile_inputs *inputs = data;
149 
150    switch (instr->type) {
151    case nir_instr_type_tex:
152       return lower_tex(b, nir_instr_as_tex(instr));
153    case nir_instr_type_intrinsic:
154       return lower_intrinsic(b, nir_instr_as_intrinsic(instr), inputs);
155    default:
156       return false;
157    }
158 }
159 
160 bool
panfrost_nir_lower_res_indices(nir_shader * shader,struct panfrost_compile_inputs * inputs)161 panfrost_nir_lower_res_indices(nir_shader *shader,
162                                struct panfrost_compile_inputs *inputs)
163 {
164    /**
165     * Starting with Valhall, we are required to encode table indices by the
166     * compiler ABI.
167     */
168    if (pan_arch(inputs->gpu_id) < 9)
169       return false;
170 
171    return nir_shader_instructions_pass(
172       shader, lower_instr, nir_metadata_control_flow,
173       inputs);
174 }
175