xref: /aosp_15_r20/external/mesa3d/src/intel/blorp/blorp_elk.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2012 Intel Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "blorp_priv.h"
7 #include "blorp_nir_builder.h"
8 #include "compiler/elk/elk_compiler.h"
9 #include "compiler/elk/elk_nir.h"
10 #include "compiler/intel_nir.h"
11 #include "dev/intel_debug.h"
12 
13 static const nir_shader_compiler_options *
blorp_nir_options_elk(struct blorp_context * blorp,gl_shader_stage stage)14 blorp_nir_options_elk(struct blorp_context *blorp,
15                       gl_shader_stage stage)
16 {
17    const struct elk_compiler *compiler = blorp->compiler->elk;
18    return compiler->nir_options[stage];
19 }
20 
21 static struct blorp_program
blorp_compile_fs_elk(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir,bool multisample_fbo,bool use_repclear)22 blorp_compile_fs_elk(struct blorp_context *blorp, void *mem_ctx,
23                      struct nir_shader *nir,
24                      bool multisample_fbo,
25                      bool use_repclear)
26 {
27    const struct elk_compiler *compiler = blorp->compiler->elk;
28 
29    struct elk_wm_prog_data *wm_prog_data = rzalloc(mem_ctx, struct elk_wm_prog_data);
30    wm_prog_data->base.nr_params = 0;
31    wm_prog_data->base.param = NULL;
32 
33    struct elk_nir_compiler_opts opts = {};
34    elk_preprocess_nir(compiler, nir, &opts);
35    nir_remove_dead_variables(nir, nir_var_shader_in, NULL);
36    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
37 
38    struct elk_wm_prog_key wm_key;
39    memset(&wm_key, 0, sizeof(wm_key));
40    wm_key.multisample_fbo = multisample_fbo ? ELK_ALWAYS : ELK_NEVER;
41    wm_key.nr_color_regions = 1;
42 
43    if (compiler->devinfo->ver < 6) {
44       if (nir->info.fs.uses_discard)
45          wm_key.iz_lookup |= ELK_WM_IZ_PS_KILL_ALPHATEST_BIT;
46 
47       wm_key.input_slots_valid = nir->info.inputs_read | VARYING_BIT_POS;
48    }
49 
50    struct elk_compile_fs_params params = {
51       .base = {
52          .mem_ctx = mem_ctx,
53          .nir = nir,
54          .log_data = blorp->driver_ctx,
55          .debug_flag = DEBUG_BLORP,
56       },
57       .key = &wm_key,
58       .prog_data = wm_prog_data,
59 
60       .use_rep_send = use_repclear,
61       .max_polygons = 1,
62    };
63 
64    const unsigned *kernel = elk_compile_fs(compiler, &params);
65    return (struct blorp_program){
66       .kernel         = kernel,
67       .kernel_size    = wm_prog_data->base.program_size,
68       .prog_data      = wm_prog_data,
69       .prog_data_size = sizeof(*wm_prog_data),
70    };
71 }
72 
73 static struct blorp_program
blorp_compile_vs_elk(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir)74 blorp_compile_vs_elk(struct blorp_context *blorp, void *mem_ctx,
75                      struct nir_shader *nir)
76 {
77    const struct elk_compiler *compiler = blorp->compiler->elk;
78 
79    struct elk_nir_compiler_opts opts = {};
80    elk_preprocess_nir(compiler, nir, &opts);
81    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
82 
83    struct elk_vs_prog_data *vs_prog_data = rzalloc(mem_ctx, struct elk_vs_prog_data);
84    vs_prog_data->inputs_read = nir->info.inputs_read;
85 
86    elk_compute_vue_map(compiler->devinfo,
87                        &vs_prog_data->base.vue_map,
88                        nir->info.outputs_written,
89                        nir->info.separate_shader,
90                        1);
91 
92    struct elk_vs_prog_key vs_key = { 0, };
93 
94    struct elk_compile_vs_params params = {
95       .base = {
96          .mem_ctx = mem_ctx,
97          .nir = nir,
98          .log_data = blorp->driver_ctx,
99          .debug_flag = DEBUG_BLORP,
100       },
101       .key = &vs_key,
102       .prog_data = vs_prog_data,
103    };
104 
105    const unsigned *kernel = elk_compile_vs(compiler, &params);
106    return (struct blorp_program) {
107       .kernel         = kernel,
108       .kernel_size    = vs_prog_data->base.base.program_size,
109       .prog_data      = vs_prog_data,
110       .prog_data_size = sizeof(*vs_prog_data),
111    };
112 }
113 
114 static bool
lower_base_workgroup_id(nir_builder * b,nir_intrinsic_instr * intrin,UNUSED void * data)115 lower_base_workgroup_id(nir_builder *b, nir_intrinsic_instr *intrin,
116                         UNUSED void *data)
117 {
118    if (intrin->intrinsic != nir_intrinsic_load_base_workgroup_id)
119       return false;
120 
121    b->cursor = nir_instr_remove(&intrin->instr);
122    nir_def_rewrite_uses(&intrin->def, nir_imm_zero(b, 3, 32));
123    return true;
124 }
125 
126 static struct blorp_program
blorp_compile_cs_elk(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir)127 blorp_compile_cs_elk(struct blorp_context *blorp, void *mem_ctx,
128                      struct nir_shader *nir)
129 {
130    const struct elk_compiler *compiler = blorp->compiler->elk;
131 
132    struct elk_nir_compiler_opts opts = {};
133    elk_preprocess_nir(compiler, nir, &opts);
134    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
135 
136    NIR_PASS_V(nir, nir_lower_io, nir_var_uniform, elk_type_size_scalar_bytes,
137               (nir_lower_io_options)0);
138 
139    STATIC_ASSERT(offsetof(struct blorp_wm_inputs, subgroup_id) + 4 ==
140                  sizeof(struct blorp_wm_inputs));
141    nir->num_uniforms = offsetof(struct blorp_wm_inputs, subgroup_id);
142    unsigned nr_params = nir->num_uniforms / 4;
143 
144    struct elk_cs_prog_data *cs_prog_data = rzalloc(mem_ctx, struct elk_cs_prog_data);
145    cs_prog_data->base.nr_params = nr_params;
146    cs_prog_data->base.param = rzalloc_array(NULL, uint32_t, nr_params);
147 
148    NIR_PASS_V(nir, elk_nir_lower_cs_intrinsics, compiler->devinfo,
149               cs_prog_data);
150    NIR_PASS_V(nir, nir_shader_intrinsics_pass, lower_base_workgroup_id,
151               nir_metadata_control_flow, NULL);
152 
153    struct elk_cs_prog_key cs_key;
154    memset(&cs_key, 0, sizeof(cs_key));
155 
156    struct elk_compile_cs_params params = {
157       .base = {
158          .mem_ctx = mem_ctx,
159          .nir = nir,
160          .log_data = blorp->driver_ctx,
161          .debug_flag = DEBUG_BLORP,
162       },
163       .key = &cs_key,
164       .prog_data = cs_prog_data,
165    };
166 
167    const unsigned *kernel = elk_compile_cs(compiler, &params);
168 
169    ralloc_free(cs_prog_data->base.param);
170    cs_prog_data->base.param = NULL;
171 
172    return (struct blorp_program) {
173       .kernel         = kernel,
174       .kernel_size    = cs_prog_data->base.program_size,
175       .prog_data      = cs_prog_data,
176       .prog_data_size = sizeof(*cs_prog_data),
177    };
178 }
179 
180 struct blorp_sf_key {
181    struct blorp_base_key base;
182    struct elk_sf_prog_key key;
183 };
184 
185 static bool
blorp_ensure_sf_program_elk(struct blorp_batch * batch,struct blorp_params * params)186 blorp_ensure_sf_program_elk(struct blorp_batch *batch,
187                             struct blorp_params *params)
188 {
189    struct blorp_context *blorp = batch->blorp;
190    const struct elk_compiler *compiler = blorp->compiler->elk;
191    const struct elk_wm_prog_data *wm_prog_data = params->wm_prog_data;
192    assert(params->wm_prog_data);
193 
194    /* Gfx6+ doesn't need a strips and fans program */
195    if (compiler->devinfo->ver >= 6)
196       return true;
197 
198    struct blorp_sf_key key = {
199       .base = BLORP_BASE_KEY_INIT(BLORP_SHADER_TYPE_GFX4_SF),
200    };
201 
202    /* Everything gets compacted in vertex setup, so we just need a
203     * pass-through for the correct number of input varyings.
204     */
205    const uint64_t slots_valid = VARYING_BIT_POS |
206       ((1ull << wm_prog_data->num_varying_inputs) - 1) << VARYING_SLOT_VAR0;
207 
208    key.key.attrs = slots_valid;
209    key.key.primitive = ELK_SF_PRIM_TRIANGLES;
210    key.key.contains_flat_varying = wm_prog_data->contains_flat_varying;
211 
212    STATIC_ASSERT(sizeof(key.key.interp_mode) ==
213                  sizeof(wm_prog_data->interp_mode));
214    memcpy(key.key.interp_mode, wm_prog_data->interp_mode,
215           sizeof(key.key.interp_mode));
216 
217    if (blorp->lookup_shader(batch, &key, sizeof(key),
218                             &params->sf_prog_kernel, &params->sf_prog_data))
219       return true;
220 
221    void *mem_ctx = ralloc_context(NULL);
222 
223    const unsigned *program;
224    unsigned program_size;
225 
226    struct intel_vue_map vue_map;
227    elk_compute_vue_map(compiler->devinfo, &vue_map, slots_valid, false, 1);
228 
229    struct elk_sf_prog_data prog_data_tmp;
230    program = elk_compile_sf(compiler, mem_ctx, &key.key,
231                             &prog_data_tmp, &vue_map, &program_size);
232 
233    bool result =
234       blorp->upload_shader(batch, MESA_SHADER_NONE,
235                            &key, sizeof(key), program, program_size,
236                            (void *)&prog_data_tmp, sizeof(prog_data_tmp),
237                            &params->sf_prog_kernel, &params->sf_prog_data);
238 
239    ralloc_free(mem_ctx);
240 
241    return result;
242 }
243 
244 #pragma pack(push, 1)
245 struct layer_offset_vs_key {
246    struct blorp_base_key base;
247    unsigned num_inputs;
248 };
249 #pragma pack(pop)
250 
251 /* In the case of doing attachment clears, we are using a surface state that
252  * is handed to us so we can't set (and don't even know) the base array layer.
253  * In order to do a layered clear in this scenario, we need some way of adding
254  * the base array layer to the instance id.  Unfortunately, our hardware has
255  * no real concept of "base instance", so we have to do it manually in a
256  * vertex shader.
257  */
258 static bool
blorp_params_get_layer_offset_vs_elk(struct blorp_batch * batch,struct blorp_params * params)259 blorp_params_get_layer_offset_vs_elk(struct blorp_batch *batch,
260                                      struct blorp_params *params)
261 {
262    struct blorp_context *blorp = batch->blorp;
263    struct layer_offset_vs_key blorp_key = {
264       .base = BLORP_BASE_KEY_INIT(BLORP_SHADER_TYPE_LAYER_OFFSET_VS),
265    };
266 
267    struct elk_wm_prog_data *wm_prog_data = params->wm_prog_data;
268    if (wm_prog_data)
269       blorp_key.num_inputs = wm_prog_data->num_varying_inputs;
270 
271    if (blorp->lookup_shader(batch, &blorp_key, sizeof(blorp_key),
272                             &params->vs_prog_kernel, &params->vs_prog_data))
273       return true;
274 
275    void *mem_ctx = ralloc_context(NULL);
276 
277    nir_builder b;
278    blorp_nir_init_shader(&b, blorp, mem_ctx, MESA_SHADER_VERTEX,
279                          blorp_shader_type_to_name(blorp_key.base.shader_type));
280 
281    const struct glsl_type *uvec4_type = glsl_vector_type(GLSL_TYPE_UINT, 4);
282 
283    /* First we deal with the header which has instance and base instance */
284    nir_variable *a_header = nir_variable_create(b.shader, nir_var_shader_in,
285                                                 uvec4_type, "header");
286    a_header->data.location = VERT_ATTRIB_GENERIC0;
287 
288    nir_variable *v_layer = nir_variable_create(b.shader, nir_var_shader_out,
289                                                glsl_int_type(), "layer_id");
290    v_layer->data.location = VARYING_SLOT_LAYER;
291 
292    /* Compute the layer id */
293    nir_def *header = nir_load_var(&b, a_header);
294    nir_def *base_layer = nir_channel(&b, header, 0);
295    nir_def *instance = nir_channel(&b, header, 1);
296    nir_store_var(&b, v_layer, nir_iadd(&b, instance, base_layer), 0x1);
297 
298    /* Then we copy the vertex from the next slot to VARYING_SLOT_POS */
299    nir_variable *a_vertex = nir_variable_create(b.shader, nir_var_shader_in,
300                                                 glsl_vec4_type(), "a_vertex");
301    a_vertex->data.location = VERT_ATTRIB_GENERIC1;
302 
303    nir_variable *v_pos = nir_variable_create(b.shader, nir_var_shader_out,
304                                              glsl_vec4_type(), "v_pos");
305    v_pos->data.location = VARYING_SLOT_POS;
306 
307    nir_copy_var(&b, v_pos, a_vertex);
308 
309    /* Then we copy everything else */
310    for (unsigned i = 0; i < blorp_key.num_inputs; i++) {
311       nir_variable *a_in = nir_variable_create(b.shader, nir_var_shader_in,
312                                                uvec4_type, "input");
313       a_in->data.location = VERT_ATTRIB_GENERIC2 + i;
314 
315       nir_variable *v_out = nir_variable_create(b.shader, nir_var_shader_out,
316                                                 uvec4_type, "output");
317       v_out->data.location = VARYING_SLOT_VAR0 + i;
318 
319       nir_copy_var(&b, v_out, a_in);
320    }
321 
322    const struct blorp_program p =
323       blorp_compile_vs(blorp, mem_ctx, b.shader);
324 
325    bool result =
326       blorp->upload_shader(batch, MESA_SHADER_VERTEX,
327                            &blorp_key, sizeof(blorp_key),
328                            p.kernel, p.kernel_size,
329                            p.prog_data, p.prog_data_size,
330                            &params->vs_prog_kernel, &params->vs_prog_data);
331 
332    ralloc_free(mem_ctx);
333    return result;
334 }
335 
336 void
blorp_init_elk(struct blorp_context * blorp,void * driver_ctx,struct isl_device * isl_dev,const struct elk_compiler * elk,const struct blorp_config * config)337 blorp_init_elk(struct blorp_context *blorp, void *driver_ctx,
338                struct isl_device *isl_dev, const struct elk_compiler *elk,
339                const struct blorp_config *config)
340 {
341    blorp_init(blorp, driver_ctx, isl_dev, config);
342    assert(elk);
343 
344    blorp->compiler->elk = elk;
345    blorp->compiler->nir_options = blorp_nir_options_elk;
346    blorp->compiler->compile_fs = blorp_compile_fs_elk;
347    blorp->compiler->compile_vs = blorp_compile_vs_elk;
348    blorp->compiler->compile_cs = blorp_compile_cs_elk;
349    blorp->compiler->ensure_sf_program = blorp_ensure_sf_program_elk;
350    blorp->compiler->params_get_layer_offset_vs =
351       blorp_params_get_layer_offset_vs_elk;
352 }
353