xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/lima/ir/gp/nir.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (c) 2017 Lima Project
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, sub license,
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
12  * next paragraph) shall be included in all copies or substantial portions
13  * of the 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 NON-INFRINGEMENT. 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 
25 #include "util/ralloc.h"
26 #include "compiler/nir/nir.h"
27 #include "pipe/p_state.h"
28 
29 
30 #include "gpir.h"
31 #include "lima_context.h"
32 
gpir_create_reg(gpir_compiler * comp)33 gpir_reg *gpir_create_reg(gpir_compiler *comp)
34 {
35    gpir_reg *reg = ralloc(comp, gpir_reg);
36    reg->index = comp->cur_reg++;
37    list_addtail(&reg->list, &comp->reg_list);
38    return reg;
39 }
40 
41 /* Register the given gpir_node as providing the given NIR destination, so
42  * that gpir_node_find() will return it. Also insert any stores necessary if
43  * the destination will be used after the end of this basic block. The node
44  * must already be inserted.
45  */
register_node_ssa(gpir_block * block,gpir_node * node,nir_def * ssa)46 static void register_node_ssa(gpir_block *block, gpir_node *node, nir_def *ssa)
47 {
48    block->comp->node_for_ssa[ssa->index] = node;
49    snprintf(node->name, sizeof(node->name), "ssa%d", ssa->index);
50 
51    /* If any uses are outside the current block, we'll need to create a
52     * register and store to it.
53     */
54    bool needs_register = false;
55    nir_foreach_use(use, ssa) {
56       if (nir_src_parent_instr(use)->block != ssa->parent_instr->block) {
57          needs_register = true;
58          break;
59       }
60    }
61 
62    if (!needs_register) {
63       nir_foreach_if_use(use, ssa) {
64          if (nir_cf_node_prev(&nir_src_parent_if(use)->cf_node) !=
65              &ssa->parent_instr->block->cf_node) {
66             needs_register = true;
67             break;
68          }
69       }
70    }
71 
72    if (needs_register) {
73       gpir_store_node *store = gpir_node_create(block, gpir_op_store_reg);
74       store->child = node;
75       store->reg = gpir_create_reg(block->comp);
76       gpir_node_add_dep(&store->node, node, GPIR_DEP_INPUT);
77       list_addtail(&store->node.list, &block->node_list);
78       block->comp->reg_for_ssa[ssa->index] = store->reg;
79    }
80 }
81 
register_node_reg(gpir_block * block,gpir_node * node,int index)82 static void register_node_reg(gpir_block *block, gpir_node *node, int index)
83 {
84    block->comp->node_for_ssa[index] = node;
85    gpir_store_node *store = gpir_node_create(block, gpir_op_store_reg);
86 
87    snprintf(store->node.name, sizeof(node->name), "reg%d", index);
88 
89    store->child = node;
90    store->reg = block->comp->reg_for_ssa[index];
91    gpir_node_add_dep(&store->node, node, GPIR_DEP_INPUT);
92 
93    list_addtail(&store->node.list, &block->node_list);
94 }
95 
gpir_node_find(gpir_block * block,nir_src * src,int channel)96 static gpir_node *gpir_node_find(gpir_block *block, nir_src *src,
97                                  int channel)
98 {
99    gpir_reg *reg = NULL;
100    gpir_node *pred = NULL;
101    if (src->ssa->num_components > 1) {
102       for (int i = 0; i < GPIR_VECTOR_SSA_NUM; i++) {
103          if (block->comp->vector_ssa[i].ssa == src->ssa->index) {
104             return block->comp->vector_ssa[i].nodes[channel];
105          }
106       }
107    } else {
108       gpir_node *pred = block->comp->node_for_ssa[src->ssa->index];
109       if (pred && pred->block == block)
110          return pred;
111       reg = block->comp->reg_for_ssa[src->ssa->index];
112    }
113 
114    assert(reg);
115    pred = gpir_node_create(block, gpir_op_load_reg);
116    gpir_load_node *load = gpir_node_to_load(pred);
117    load->reg = reg;
118    list_addtail(&pred->list, &block->node_list);
119 
120    return pred;
121 }
122 
123 static int nir_to_gpir_opcodes[nir_num_opcodes] = {
124    [nir_op_fmul] = gpir_op_mul,
125    [nir_op_fadd] = gpir_op_add,
126    [nir_op_fneg] = gpir_op_neg,
127    [nir_op_fmin] = gpir_op_min,
128    [nir_op_fmax] = gpir_op_max,
129    [nir_op_frcp] = gpir_op_rcp,
130    [nir_op_frsq] = gpir_op_rsqrt,
131    [nir_op_fexp2] = gpir_op_exp2,
132    [nir_op_flog2] = gpir_op_log2,
133    [nir_op_slt] = gpir_op_lt,
134    [nir_op_sge] = gpir_op_ge,
135    [nir_op_fcsel] = gpir_op_select,
136    [nir_op_ffloor] = gpir_op_floor,
137    [nir_op_fsign] = gpir_op_sign,
138    [nir_op_seq] = gpir_op_eq,
139    [nir_op_sne] = gpir_op_ne,
140    [nir_op_fabs] = gpir_op_abs,
141 };
142 
gpir_emit_alu(gpir_block * block,nir_instr * ni)143 static bool gpir_emit_alu(gpir_block *block, nir_instr *ni)
144 {
145    nir_alu_instr *instr = nir_instr_as_alu(ni);
146 
147    /* gpir_op_mov is useless before the final scheduler, and the scheduler
148     * currently doesn't expect us to emit it. Just register the destination of
149     * this instruction with its source. This will also emit any necessary
150     * register loads/stores for things like "r0 = mov ssa_0" or
151     * "ssa_0 = mov r0".
152     */
153    if (instr->op == nir_op_mov) {
154       gpir_node *child = gpir_node_find(block, &instr->src[0].src,
155                                         instr->src[0].swizzle[0]);
156       register_node_ssa(block, child, &instr->def);
157       return true;
158    }
159 
160    int op = nir_to_gpir_opcodes[instr->op];
161 
162    if (op == gpir_op_unsupported) {
163       gpir_error("unsupported nir_op: %s\n", nir_op_infos[instr->op].name);
164       return false;
165    }
166 
167    gpir_alu_node *node = gpir_node_create(block, op);
168    if (unlikely(!node))
169       return false;
170 
171    unsigned num_child = nir_op_infos[instr->op].num_inputs;
172    assert(num_child <= ARRAY_SIZE(node->children));
173    node->num_child = num_child;
174 
175    for (int i = 0; i < num_child; i++) {
176       nir_alu_src *src = instr->src + i;
177 
178       gpir_node *child = gpir_node_find(block, &src->src, src->swizzle[0]);
179       node->children[i] = child;
180 
181       gpir_node_add_dep(&node->node, child, GPIR_DEP_INPUT);
182    }
183 
184    list_addtail(&node->node.list, &block->node_list);
185    register_node_ssa(block, &node->node, &instr->def);
186 
187    return true;
188 }
189 
gpir_create_load(gpir_block * block,nir_def * def,int op,int index,int component)190 static gpir_node *gpir_create_load(gpir_block *block, nir_def *def,
191                                    int op, int index, int component)
192 {
193    gpir_load_node *load = gpir_node_create(block, op);
194    if (unlikely(!load))
195       return NULL;
196 
197    load->index = index;
198    load->component = component;
199    list_addtail(&load->node.list, &block->node_list);
200    register_node_ssa(block, &load->node, def);
201    return &load->node;
202 }
203 
gpir_create_vector_load(gpir_block * block,nir_def * def,int index)204 static bool gpir_create_vector_load(gpir_block *block, nir_def *def, int index)
205 {
206    assert(index < GPIR_VECTOR_SSA_NUM);
207 
208    block->comp->vector_ssa[index].ssa = def->index;
209 
210    for (int i = 0; i < def->num_components; i++) {
211       gpir_node *node = gpir_create_load(block, def, gpir_op_load_uniform,
212                                          block->comp->constant_base + index, i);
213       if (!node)
214          return false;
215 
216       block->comp->vector_ssa[index].nodes[i] = node;
217       snprintf(node->name, sizeof(node->name), "ssa%d.%c", def->index, "xyzw"[i]);
218    }
219 
220    return true;
221 }
222 
gpir_emit_intrinsic(gpir_block * block,nir_instr * ni)223 static bool gpir_emit_intrinsic(gpir_block *block, nir_instr *ni)
224 {
225    nir_intrinsic_instr *instr = nir_instr_as_intrinsic(ni);
226 
227    switch (instr->intrinsic) {
228    case nir_intrinsic_decl_reg:
229    {
230       gpir_reg *reg = gpir_create_reg(block->comp);
231       block->comp->reg_for_ssa[instr->def.index] = reg;
232       return true;
233    }
234    case nir_intrinsic_load_reg:
235    {
236       gpir_node *node = gpir_node_find(block, &instr->src[0], 0);
237       assert(node);
238       block->comp->node_for_ssa[instr->def.index] = node;
239       return true;
240    }
241    case nir_intrinsic_store_reg:
242    {
243       gpir_node *child = gpir_node_find(block, &instr->src[0], 0);
244       assert(child);
245       register_node_reg(block, child, instr->src[1].ssa->index);
246       return true;
247    }
248    case nir_intrinsic_load_input:
249       return gpir_create_load(block, &instr->def,
250                               gpir_op_load_attribute,
251                               nir_intrinsic_base(instr),
252                               nir_intrinsic_component(instr)) != NULL;
253    case nir_intrinsic_load_uniform:
254    {
255       int offset = nir_intrinsic_base(instr);
256 
257       if (!nir_src_is_const(instr->src[0])) {
258          gpir_error("indirect indexing for uniforms is not implemented\n");
259          return false;
260       }
261       offset += (int)nir_src_as_float(instr->src[0]);
262 
263       return gpir_create_load(block, &instr->def,
264                               gpir_op_load_uniform,
265                               offset / 4, offset % 4) != NULL;
266    }
267    case nir_intrinsic_load_viewport_scale:
268       return gpir_create_vector_load(block, &instr->def, GPIR_VECTOR_SSA_VIEWPORT_SCALE);
269    case nir_intrinsic_load_viewport_offset:
270       return gpir_create_vector_load(block, &instr->def, GPIR_VECTOR_SSA_VIEWPORT_OFFSET);
271    case nir_intrinsic_store_output:
272    {
273       gpir_store_node *store = gpir_node_create(block, gpir_op_store_varying);
274       if (unlikely(!store))
275          return false;
276       gpir_node *child = gpir_node_find(block, instr->src, 0);
277       store->child = child;
278       store->index = nir_intrinsic_base(instr);
279       store->component = nir_intrinsic_component(instr);
280 
281       gpir_node_add_dep(&store->node, child, GPIR_DEP_INPUT);
282       list_addtail(&store->node.list, &block->node_list);
283 
284       return true;
285    }
286    default:
287       gpir_error("unsupported nir_intrinsic_instr %s\n",
288                  nir_intrinsic_infos[instr->intrinsic].name);
289       return false;
290    }
291 }
292 
gpir_emit_load_const(gpir_block * block,nir_instr * ni)293 static bool gpir_emit_load_const(gpir_block *block, nir_instr *ni)
294 {
295    nir_load_const_instr *instr = nir_instr_as_load_const(ni);
296    gpir_const_node *node = gpir_node_create(block, gpir_op_const);
297    if (unlikely(!node))
298       return false;
299 
300    assert(instr->def.bit_size == 32);
301    assert(instr->def.num_components == 1);
302 
303    node->value.i = instr->value[0].i32;
304 
305    list_addtail(&node->node.list, &block->node_list);
306    register_node_ssa(block, &node->node, &instr->def);
307    return true;
308 }
309 
gpir_emit_ssa_undef(gpir_block * block,nir_instr * ni)310 static bool gpir_emit_ssa_undef(gpir_block *block, nir_instr *ni)
311 {
312    gpir_error("nir_undef_instr is not supported\n");
313    return false;
314 }
315 
gpir_emit_tex(gpir_block * block,nir_instr * ni)316 static bool gpir_emit_tex(gpir_block *block, nir_instr *ni)
317 {
318    gpir_error("texture operations are not supported\n");
319    return false;
320 }
321 
gpir_emit_jump(gpir_block * block,nir_instr * ni)322 static bool gpir_emit_jump(gpir_block *block, nir_instr *ni)
323 {
324    /* Jumps are emitted at the end of the basic block, so do nothing. */
325    return true;
326 }
327 
328 static bool (*gpir_emit_instr[nir_instr_type_phi])(gpir_block *, nir_instr *) = {
329    [nir_instr_type_alu]        = gpir_emit_alu,
330    [nir_instr_type_intrinsic]  = gpir_emit_intrinsic,
331    [nir_instr_type_load_const] = gpir_emit_load_const,
332    [nir_instr_type_undef]      = gpir_emit_ssa_undef,
333    [nir_instr_type_tex]        = gpir_emit_tex,
334    [nir_instr_type_jump]       = gpir_emit_jump,
335 };
336 
gpir_emit_function(gpir_compiler * comp,nir_function_impl * impl)337 static bool gpir_emit_function(gpir_compiler *comp, nir_function_impl *impl)
338 {
339    nir_index_blocks(impl);
340    comp->blocks = ralloc_array(comp, gpir_block *, impl->num_blocks);
341 
342    nir_foreach_block(block_nir, impl) {
343       gpir_block *block = ralloc(comp, gpir_block);
344       if (!block)
345          return false;
346 
347       list_inithead(&block->node_list);
348       list_inithead(&block->instr_list);
349 
350       list_addtail(&block->list, &comp->block_list);
351       block->comp = comp;
352       comp->blocks[block_nir->index] = block;
353    }
354 
355    nir_foreach_block(block_nir, impl) {
356       gpir_block *block = comp->blocks[block_nir->index];
357       nir_foreach_instr(instr, block_nir) {
358          assert(instr->type < nir_instr_type_phi);
359          if (!gpir_emit_instr[instr->type](block, instr))
360             return false;
361       }
362 
363       if (block_nir->successors[0] == impl->end_block)
364          block->successors[0] = NULL;
365       else
366          block->successors[0] = comp->blocks[block_nir->successors[0]->index];
367       block->successors[1] = NULL;
368 
369       if (block_nir->successors[1] != NULL) {
370          nir_if *nif = nir_cf_node_as_if(nir_cf_node_next(&block_nir->cf_node));
371          gpir_alu_node *cond = gpir_node_create(block, gpir_op_not);
372          cond->children[0] = gpir_node_find(block, &nif->condition, 0);
373 
374          gpir_node_add_dep(&cond->node, cond->children[0], GPIR_DEP_INPUT);
375          list_addtail(&cond->node.list, &block->node_list);
376 
377          gpir_branch_node *branch = gpir_node_create(block, gpir_op_branch_cond);
378          list_addtail(&branch->node.list, &block->node_list);
379 
380          branch->dest = comp->blocks[block_nir->successors[1]->index];
381          block->successors[1] = branch->dest;
382 
383          branch->cond = &cond->node;
384          gpir_node_add_dep(&branch->node, &cond->node, GPIR_DEP_INPUT);
385 
386          assert(block_nir->successors[0]->index == block_nir->index + 1);
387       } else if (block_nir->successors[0]->index != block_nir->index + 1) {
388          gpir_branch_node *branch = gpir_node_create(block, gpir_op_branch_uncond);
389          list_addtail(&branch->node.list, &block->node_list);
390 
391          branch->dest = comp->blocks[block_nir->successors[0]->index];
392       }
393    }
394 
395    return true;
396 }
397 
gpir_compiler_create(void * prog,unsigned num_ssa)398 static gpir_compiler *gpir_compiler_create(void *prog, unsigned num_ssa)
399 {
400    gpir_compiler *comp = rzalloc(prog, gpir_compiler);
401 
402    list_inithead(&comp->block_list);
403    list_inithead(&comp->reg_list);
404 
405    for (int i = 0; i < GPIR_VECTOR_SSA_NUM; i++)
406       comp->vector_ssa[i].ssa = -1;
407 
408    comp->node_for_ssa = rzalloc_array(comp, gpir_node *, num_ssa);
409    comp->reg_for_ssa = rzalloc_array(comp, gpir_reg *, num_ssa);
410    comp->prog = prog;
411    return comp;
412 }
413 
gpir_glsl_type_size(enum glsl_base_type type)414 static int gpir_glsl_type_size(enum glsl_base_type type)
415 {
416    /* only support GLSL_TYPE_FLOAT */
417    assert(type == GLSL_TYPE_FLOAT);
418    return 4;
419 }
420 
gpir_print_shader_db(struct nir_shader * nir,gpir_compiler * comp,struct util_debug_callback * debug)421 static void gpir_print_shader_db(struct nir_shader *nir, gpir_compiler *comp,
422                                  struct util_debug_callback *debug)
423 {
424    const struct shader_info *info = &nir->info;
425    char *shaderdb;
426    ASSERTED int ret = asprintf(&shaderdb,
427                                "%s shader: %d inst, %d loops, %d:%d spills:fills\n",
428                                gl_shader_stage_name(info->stage),
429                                comp->num_instr,
430                                comp->num_loops,
431                                comp->num_spills,
432                                comp->num_fills);
433    assert(ret >= 0);
434 
435    if (lima_debug & LIMA_DEBUG_SHADERDB)
436       fprintf(stderr, "SHADER-DB: %s\n", shaderdb);
437 
438    util_debug_message(debug, SHADER_INFO, "%s", shaderdb);
439    free(shaderdb);
440 }
441 
gpir_compile_nir(struct lima_vs_compiled_shader * prog,struct nir_shader * nir,struct util_debug_callback * debug)442 bool gpir_compile_nir(struct lima_vs_compiled_shader *prog, struct nir_shader *nir,
443                       struct util_debug_callback *debug)
444 {
445    nir_function_impl *func = nir_shader_get_entrypoint(nir);
446    gpir_compiler *comp = gpir_compiler_create(prog, func->ssa_alloc);
447    if (!comp)
448       return false;
449 
450    comp->constant_base = nir->num_uniforms;
451    prog->state.uniform_size = nir->num_uniforms * 16;
452    prog->state.gl_pos_idx = 0;
453    prog->state.point_size_idx = -1;
454 
455    if (!gpir_emit_function(comp, func))
456       goto err_out0;
457 
458    gpir_node_print_prog_seq(comp);
459    gpir_node_print_prog_dep(comp);
460 
461    /* increase for viewport uniforms */
462    comp->constant_base += GPIR_VECTOR_SSA_NUM;
463 
464    if (!gpir_optimize(comp))
465       goto err_out0;
466 
467    if (!gpir_pre_rsched_lower_prog(comp))
468       goto err_out0;
469 
470    if (!gpir_reduce_reg_pressure_schedule_prog(comp))
471       goto err_out0;
472 
473    if (!gpir_regalloc_prog(comp))
474       goto err_out0;
475 
476    if (!gpir_schedule_prog(comp))
477       goto err_out0;
478 
479    if (!gpir_codegen_prog(comp))
480       goto err_out0;
481 
482    /* initialize to support accumulating below */
483    nir_foreach_shader_out_variable(var, nir) {
484       struct lima_varying_info *v = prog->state.varying + var->data.driver_location;
485       v->components = 0;
486    }
487 
488    nir_foreach_shader_out_variable(var, nir) {
489       bool varying = true;
490       switch (var->data.location) {
491       case VARYING_SLOT_POS:
492          prog->state.gl_pos_idx = var->data.driver_location;
493          varying = false;
494          break;
495       case VARYING_SLOT_PSIZ:
496          prog->state.point_size_idx = var->data.driver_location;
497          varying = false;
498          break;
499       }
500 
501       struct lima_varying_info *v = prog->state.varying + var->data.driver_location;
502       if (!v->components) {
503          v->component_size = gpir_glsl_type_size(glsl_get_base_type(var->type));
504          prog->state.num_outputs++;
505          if (varying)
506             prog->state.num_varyings++;
507       }
508 
509       v->components += glsl_get_components(var->type);
510    }
511 
512    gpir_print_shader_db(nir, comp, debug);
513 
514    ralloc_free(comp);
515    return true;
516 
517 err_out0:
518    ralloc_free(comp);
519    return false;
520 }
521 
522