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