• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       offset += (int)nir_src_as_float(instr->src[0]);
257 
258       return gpir_create_load(block, &instr->def,
259                               gpir_op_load_uniform,
260                               offset / 4, offset % 4) != NULL;
261    }
262    case nir_intrinsic_load_viewport_scale:
263       return gpir_create_vector_load(block, &instr->def, GPIR_VECTOR_SSA_VIEWPORT_SCALE);
264    case nir_intrinsic_load_viewport_offset:
265       return gpir_create_vector_load(block, &instr->def, GPIR_VECTOR_SSA_VIEWPORT_OFFSET);
266    case nir_intrinsic_store_output:
267    {
268       gpir_store_node *store = gpir_node_create(block, gpir_op_store_varying);
269       if (unlikely(!store))
270          return false;
271       gpir_node *child = gpir_node_find(block, instr->src, 0);
272       store->child = child;
273       store->index = nir_intrinsic_base(instr);
274       store->component = nir_intrinsic_component(instr);
275 
276       gpir_node_add_dep(&store->node, child, GPIR_DEP_INPUT);
277       list_addtail(&store->node.list, &block->node_list);
278 
279       return true;
280    }
281    default:
282       gpir_error("unsupported nir_intrinsic_instr %s\n",
283                  nir_intrinsic_infos[instr->intrinsic].name);
284       return false;
285    }
286 }
287 
gpir_emit_load_const(gpir_block * block,nir_instr * ni)288 static bool gpir_emit_load_const(gpir_block *block, nir_instr *ni)
289 {
290    nir_load_const_instr *instr = nir_instr_as_load_const(ni);
291    gpir_const_node *node = gpir_node_create(block, gpir_op_const);
292    if (unlikely(!node))
293       return false;
294 
295    assert(instr->def.bit_size == 32);
296    assert(instr->def.num_components == 1);
297 
298    node->value.i = instr->value[0].i32;
299 
300    list_addtail(&node->node.list, &block->node_list);
301    register_node_ssa(block, &node->node, &instr->def);
302    return true;
303 }
304 
gpir_emit_ssa_undef(gpir_block * block,nir_instr * ni)305 static bool gpir_emit_ssa_undef(gpir_block *block, nir_instr *ni)
306 {
307    gpir_error("nir_undef_instr is not supported\n");
308    return false;
309 }
310 
gpir_emit_tex(gpir_block * block,nir_instr * ni)311 static bool gpir_emit_tex(gpir_block *block, nir_instr *ni)
312 {
313    gpir_error("texture operations are not supported\n");
314    return false;
315 }
316 
gpir_emit_jump(gpir_block * block,nir_instr * ni)317 static bool gpir_emit_jump(gpir_block *block, nir_instr *ni)
318 {
319    /* Jumps are emitted at the end of the basic block, so do nothing. */
320    return true;
321 }
322 
323 static bool (*gpir_emit_instr[nir_instr_type_phi])(gpir_block *, nir_instr *) = {
324    [nir_instr_type_alu]        = gpir_emit_alu,
325    [nir_instr_type_intrinsic]  = gpir_emit_intrinsic,
326    [nir_instr_type_load_const] = gpir_emit_load_const,
327    [nir_instr_type_undef]      = gpir_emit_ssa_undef,
328    [nir_instr_type_tex]        = gpir_emit_tex,
329    [nir_instr_type_jump]       = gpir_emit_jump,
330 };
331 
gpir_emit_function(gpir_compiler * comp,nir_function_impl * impl)332 static bool gpir_emit_function(gpir_compiler *comp, nir_function_impl *impl)
333 {
334    nir_index_blocks(impl);
335    comp->blocks = ralloc_array(comp, gpir_block *, impl->num_blocks);
336 
337    nir_foreach_block(block_nir, impl) {
338       gpir_block *block = ralloc(comp, gpir_block);
339       if (!block)
340          return false;
341 
342       list_inithead(&block->node_list);
343       list_inithead(&block->instr_list);
344 
345       list_addtail(&block->list, &comp->block_list);
346       block->comp = comp;
347       comp->blocks[block_nir->index] = block;
348    }
349 
350    nir_foreach_block(block_nir, impl) {
351       gpir_block *block = comp->blocks[block_nir->index];
352       nir_foreach_instr(instr, block_nir) {
353          assert(instr->type < nir_instr_type_phi);
354          if (!gpir_emit_instr[instr->type](block, instr))
355             return false;
356       }
357 
358       if (block_nir->successors[0] == impl->end_block)
359          block->successors[0] = NULL;
360       else
361          block->successors[0] = comp->blocks[block_nir->successors[0]->index];
362       block->successors[1] = NULL;
363 
364       if (block_nir->successors[1] != NULL) {
365          nir_if *nif = nir_cf_node_as_if(nir_cf_node_next(&block_nir->cf_node));
366          gpir_alu_node *cond = gpir_node_create(block, gpir_op_not);
367          cond->children[0] = gpir_node_find(block, &nif->condition, 0);
368 
369          gpir_node_add_dep(&cond->node, cond->children[0], GPIR_DEP_INPUT);
370          list_addtail(&cond->node.list, &block->node_list);
371 
372          gpir_branch_node *branch = gpir_node_create(block, gpir_op_branch_cond);
373          list_addtail(&branch->node.list, &block->node_list);
374 
375          branch->dest = comp->blocks[block_nir->successors[1]->index];
376          block->successors[1] = branch->dest;
377 
378          branch->cond = &cond->node;
379          gpir_node_add_dep(&branch->node, &cond->node, GPIR_DEP_INPUT);
380 
381          assert(block_nir->successors[0]->index == block_nir->index + 1);
382       } else if (block_nir->successors[0]->index != block_nir->index + 1) {
383          gpir_branch_node *branch = gpir_node_create(block, gpir_op_branch_uncond);
384          list_addtail(&branch->node.list, &block->node_list);
385 
386          branch->dest = comp->blocks[block_nir->successors[0]->index];
387       }
388    }
389 
390    return true;
391 }
392 
gpir_compiler_create(void * prog,unsigned num_ssa)393 static gpir_compiler *gpir_compiler_create(void *prog, unsigned num_ssa)
394 {
395    gpir_compiler *comp = rzalloc(prog, gpir_compiler);
396 
397    list_inithead(&comp->block_list);
398    list_inithead(&comp->reg_list);
399 
400    for (int i = 0; i < GPIR_VECTOR_SSA_NUM; i++)
401       comp->vector_ssa[i].ssa = -1;
402 
403    comp->node_for_ssa = rzalloc_array(comp, gpir_node *, num_ssa);
404    comp->reg_for_ssa = rzalloc_array(comp, gpir_reg *, num_ssa);
405    comp->prog = prog;
406    return comp;
407 }
408 
gpir_glsl_type_size(enum glsl_base_type type)409 static int gpir_glsl_type_size(enum glsl_base_type type)
410 {
411    /* only support GLSL_TYPE_FLOAT */
412    assert(type == GLSL_TYPE_FLOAT);
413    return 4;
414 }
415 
gpir_print_shader_db(struct nir_shader * nir,gpir_compiler * comp,struct util_debug_callback * debug)416 static void gpir_print_shader_db(struct nir_shader *nir, gpir_compiler *comp,
417                                  struct util_debug_callback *debug)
418 {
419    const struct shader_info *info = &nir->info;
420    char *shaderdb;
421    ASSERTED int ret = asprintf(&shaderdb,
422                                "%s shader: %d inst, %d loops, %d:%d spills:fills\n",
423                                gl_shader_stage_name(info->stage),
424                                comp->num_instr,
425                                comp->num_loops,
426                                comp->num_spills,
427                                comp->num_fills);
428    assert(ret >= 0);
429 
430    if (lima_debug & LIMA_DEBUG_SHADERDB)
431       fprintf(stderr, "SHADER-DB: %s\n", shaderdb);
432 
433    util_debug_message(debug, SHADER_INFO, "%s", shaderdb);
434    free(shaderdb);
435 }
436 
gpir_compile_nir(struct lima_vs_compiled_shader * prog,struct nir_shader * nir,struct util_debug_callback * debug)437 bool gpir_compile_nir(struct lima_vs_compiled_shader *prog, struct nir_shader *nir,
438                       struct util_debug_callback *debug)
439 {
440    nir_function_impl *func = nir_shader_get_entrypoint(nir);
441    gpir_compiler *comp = gpir_compiler_create(prog, func->ssa_alloc);
442    if (!comp)
443       return false;
444 
445    comp->constant_base = nir->num_uniforms;
446    prog->state.uniform_size = nir->num_uniforms * 16;
447    prog->state.gl_pos_idx = 0;
448    prog->state.point_size_idx = -1;
449 
450    if (!gpir_emit_function(comp, func))
451       goto err_out0;
452 
453    gpir_node_print_prog_seq(comp);
454    gpir_node_print_prog_dep(comp);
455 
456    /* increase for viewport uniforms */
457    comp->constant_base += GPIR_VECTOR_SSA_NUM;
458 
459    if (!gpir_optimize(comp))
460       goto err_out0;
461 
462    if (!gpir_pre_rsched_lower_prog(comp))
463       goto err_out0;
464 
465    if (!gpir_reduce_reg_pressure_schedule_prog(comp))
466       goto err_out0;
467 
468    if (!gpir_regalloc_prog(comp))
469       goto err_out0;
470 
471    if (!gpir_schedule_prog(comp))
472       goto err_out0;
473 
474    if (!gpir_codegen_prog(comp))
475       goto err_out0;
476 
477    /* initialize to support accumulating below */
478    nir_foreach_shader_out_variable(var, nir) {
479       struct lima_varying_info *v = prog->state.varying + var->data.driver_location;
480       v->components = 0;
481    }
482 
483    nir_foreach_shader_out_variable(var, nir) {
484       bool varying = true;
485       switch (var->data.location) {
486       case VARYING_SLOT_POS:
487          prog->state.gl_pos_idx = var->data.driver_location;
488          varying = false;
489          break;
490       case VARYING_SLOT_PSIZ:
491          prog->state.point_size_idx = var->data.driver_location;
492          varying = false;
493          break;
494       }
495 
496       struct lima_varying_info *v = prog->state.varying + var->data.driver_location;
497       if (!v->components) {
498          v->component_size = gpir_glsl_type_size(glsl_get_base_type(var->type));
499          prog->state.num_outputs++;
500          if (varying)
501             prog->state.num_varyings++;
502       }
503 
504       v->components += glsl_get_components(var->type);
505    }
506 
507    gpir_print_shader_db(nir, comp, debug);
508 
509    ralloc_free(comp);
510    return true;
511 
512 err_out0:
513    ralloc_free(comp);
514    return false;
515 }
516 
517