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(®->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