lima/gp: Support exp2 and log2
[mesa.git] / src / gallium / drivers / lima / ir / gp / nir.c
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
28 #include "gpir.h"
29 #include "lima_context.h"
30
31
32 static inline void *gpir_node_create_ssa(gpir_block *block, gpir_op op, nir_ssa_def *ssa)
33 {
34 int index = ssa->index;
35 gpir_node *node = gpir_node_create(block, op);
36
37 block->comp->var_nodes[index] = node;
38 snprintf(node->name, sizeof(node->name), "ssa%d", index);
39 list_addtail(&node->list, &block->node_list);
40 return node;
41 }
42
43 static inline void *gpir_node_create_reg(gpir_block *block, gpir_op op, nir_reg_dest *reg)
44 {
45 int index = reg->reg->index;
46 gpir_node *node = gpir_node_create(block, op);
47 gpir_store_node *store = gpir_node_create(block, gpir_op_store_reg);
48
49 snprintf(node->name, sizeof(node->name), "reg%d", index);
50
51 store->child = node;
52 gpir_node_add_dep(&store->node, node, GPIR_DEP_INPUT);
53
54 list_for_each_entry(gpir_reg, reg, &block->comp->reg_list, list) {
55 if (reg->index == index) {
56 store->reg = reg;
57 list_addtail(&store->reg_link, &reg->defs_list);
58 break;
59 }
60 }
61
62 list_addtail(&node->list, &block->node_list);
63 list_addtail(&store->node.list, &block->node_list);
64 return node;
65 }
66
67 static void *gpir_node_create_dest(gpir_block *block, gpir_op op, nir_dest *dest)
68 {
69 if (dest->is_ssa)
70 return gpir_node_create_ssa(block, op, &dest->ssa);
71 else
72 return gpir_node_create_reg(block, op, &dest->reg);
73 }
74
75 static gpir_node *gpir_node_find(gpir_block *block, gpir_node *succ, nir_src *src,
76 int channel)
77 {
78 gpir_node *pred = NULL;
79
80 if (src->is_ssa) {
81 if (src->ssa->num_components > 1) {
82 for (int i = 0; i < GPIR_VECTOR_SSA_NUM; i++) {
83 if (block->comp->vector_ssa[i].ssa == src->ssa->index) {
84 pred = block->comp->vector_ssa[i].nodes[channel];
85 break;
86 }
87 }
88 } else
89 pred = block->comp->var_nodes[src->ssa->index];
90
91 assert(pred);
92 }
93 else {
94 pred = gpir_node_create(block, gpir_op_load_reg);
95 list_addtail(&pred->list, &succ->list);
96
97 gpir_load_node *load = gpir_node_to_load(pred);
98 list_for_each_entry(gpir_reg, reg, &block->comp->reg_list, list) {
99 if (reg->index == src->reg.reg->index) {
100 load->reg = reg;
101 list_addtail(&load->reg_link, &reg->uses_list);
102 break;
103 }
104 }
105 }
106
107 return pred;
108 }
109
110 static int nir_to_gpir_opcodes[nir_num_opcodes] = {
111 /* not supported */
112 [0 ... nir_last_opcode] = -1,
113
114 [nir_op_fmul] = gpir_op_mul,
115 [nir_op_fadd] = gpir_op_add,
116 [nir_op_fneg] = gpir_op_neg,
117 [nir_op_fmin] = gpir_op_min,
118 [nir_op_fmax] = gpir_op_max,
119 [nir_op_frcp] = gpir_op_rcp,
120 [nir_op_frsq] = gpir_op_rsqrt,
121 [nir_op_fexp2] = gpir_op_exp2,
122 [nir_op_flog2] = gpir_op_log2,
123 [nir_op_slt] = gpir_op_lt,
124 [nir_op_sge] = gpir_op_ge,
125 [nir_op_fcsel] = gpir_op_select,
126 [nir_op_ffloor] = gpir_op_floor,
127 [nir_op_fsign] = gpir_op_sign,
128 [nir_op_seq] = gpir_op_eq,
129 [nir_op_sne] = gpir_op_ne,
130 [nir_op_fabs] = gpir_op_abs,
131 [nir_op_mov] = gpir_op_mov,
132 };
133
134 static bool gpir_emit_alu(gpir_block *block, nir_instr *ni)
135 {
136 nir_alu_instr *instr = nir_instr_as_alu(ni);
137 int op = nir_to_gpir_opcodes[instr->op];
138
139 if (op < 0) {
140 gpir_error("unsupported nir_op: %s\n", nir_op_infos[instr->op].name);
141 return false;
142 }
143
144 gpir_alu_node *node = gpir_node_create_dest(block, op, &instr->dest.dest);
145 if (unlikely(!node))
146 return false;
147
148 unsigned num_child = nir_op_infos[instr->op].num_inputs;
149 assert(num_child <= ARRAY_SIZE(node->children));
150 node->num_child = num_child;
151
152 for (int i = 0; i < num_child; i++) {
153 nir_alu_src *src = instr->src + i;
154 node->children_negate[i] = src->negate;
155
156 gpir_node *child = gpir_node_find(block, &node->node, &src->src, src->swizzle[0]);
157 node->children[i] = child;
158
159 gpir_node_add_dep(&node->node, child, GPIR_DEP_INPUT);
160 }
161
162 return true;
163 }
164
165 static gpir_node *gpir_create_load(gpir_block *block, nir_dest *dest,
166 int op, int index, int component)
167 {
168 gpir_load_node *load = gpir_node_create_dest(block, op, dest);
169 if (unlikely(!load))
170 return NULL;
171
172 load->index = index;
173 load->component = component;
174 return &load->node;
175 }
176
177 static bool gpir_create_vector_load(gpir_block *block, nir_dest *dest, int index)
178 {
179 assert(dest->is_ssa);
180 assert(index < GPIR_VECTOR_SSA_NUM);
181
182 block->comp->vector_ssa[index].ssa = dest->ssa.index;
183
184 for (int i = 0; i < dest->ssa.num_components; i++) {
185 gpir_node *node = gpir_create_load(block, dest, gpir_op_load_uniform,
186 block->comp->constant_base + index, i);
187 if (!node)
188 return false;
189
190 block->comp->vector_ssa[index].nodes[i] = node;
191 snprintf(node->name, sizeof(node->name), "ssa%d.%c", dest->ssa.index, "xyzw"[i]);
192 }
193
194 return true;
195 }
196
197 static bool gpir_emit_intrinsic(gpir_block *block, nir_instr *ni)
198 {
199 nir_intrinsic_instr *instr = nir_instr_as_intrinsic(ni);
200
201 switch (instr->intrinsic) {
202 case nir_intrinsic_load_input:
203 return gpir_create_load(block, &instr->dest,
204 gpir_op_load_attribute,
205 nir_intrinsic_base(instr),
206 nir_intrinsic_component(instr)) != NULL;
207 case nir_intrinsic_load_uniform:
208 {
209 int offset = nir_intrinsic_base(instr);
210 offset += (int)nir_src_as_float(instr->src[0]);
211
212 return gpir_create_load(block, &instr->dest,
213 gpir_op_load_uniform,
214 offset / 4, offset % 4) != NULL;
215 }
216 case nir_intrinsic_load_viewport_scale:
217 return gpir_create_vector_load(block, &instr->dest, GPIR_VECTOR_SSA_VIEWPORT_SCALE);
218 case nir_intrinsic_load_viewport_offset:
219 return gpir_create_vector_load(block, &instr->dest, GPIR_VECTOR_SSA_VIEWPORT_OFFSET);
220 case nir_intrinsic_store_output:
221 {
222 gpir_store_node *store = gpir_node_create(block, gpir_op_store_varying);
223 if (unlikely(!store))
224 return false;
225 list_addtail(&store->node.list, &block->node_list);
226
227 store->index = nir_intrinsic_base(instr);
228 store->component = nir_intrinsic_component(instr);
229
230 gpir_node *child = gpir_node_find(block, &store->node, instr->src, 0);
231 store->child = child;
232 gpir_node_add_dep(&store->node, child, GPIR_DEP_INPUT);
233
234 return true;
235 }
236 default:
237 gpir_error("unsupported nir_intrinsic_instr %s\n",
238 nir_intrinsic_infos[instr->intrinsic].name);
239 return false;
240 }
241 }
242
243 static bool gpir_emit_load_const(gpir_block *block, nir_instr *ni)
244 {
245 nir_load_const_instr *instr = nir_instr_as_load_const(ni);
246 gpir_const_node *node =
247 gpir_node_create_ssa(block, gpir_op_const, &instr->def);
248 if (unlikely(!node))
249 return false;
250
251 assert(instr->def.bit_size == 32);
252 assert(instr->def.num_components == 1);
253
254 node->value.i = instr->value[0].i32;
255
256 return true;
257 }
258
259 static bool gpir_emit_ssa_undef(gpir_block *block, nir_instr *ni)
260 {
261 gpir_error("nir_ssa_undef_instr not support\n");
262 return false;
263 }
264
265 static bool gpir_emit_tex(gpir_block *block, nir_instr *ni)
266 {
267 gpir_error("nir_jump_instr not support\n");
268 return false;
269 }
270
271 static bool gpir_emit_jump(gpir_block *block, nir_instr *ni)
272 {
273 gpir_error("nir_jump_instr not support\n");
274 return false;
275 }
276
277 static bool (*gpir_emit_instr[nir_instr_type_phi])(gpir_block *, nir_instr *) = {
278 [nir_instr_type_alu] = gpir_emit_alu,
279 [nir_instr_type_intrinsic] = gpir_emit_intrinsic,
280 [nir_instr_type_load_const] = gpir_emit_load_const,
281 [nir_instr_type_ssa_undef] = gpir_emit_ssa_undef,
282 [nir_instr_type_tex] = gpir_emit_tex,
283 [nir_instr_type_jump] = gpir_emit_jump,
284 };
285
286 static gpir_block *gpir_block_create(gpir_compiler *comp)
287 {
288 gpir_block *block = ralloc(comp, gpir_block);
289 if (!block)
290 return NULL;
291
292 list_inithead(&block->node_list);
293 list_inithead(&block->instr_list);
294
295 return block;
296 }
297
298 static bool gpir_emit_block(gpir_compiler *comp, nir_block *nblock)
299 {
300 gpir_block *block = gpir_block_create(comp);
301 if (!block)
302 return false;
303
304 list_addtail(&block->list, &comp->block_list);
305 block->comp = comp;
306
307 nir_foreach_instr(instr, nblock) {
308 assert(instr->type < nir_instr_type_phi);
309 if (!gpir_emit_instr[instr->type](block, instr))
310 return false;
311 }
312
313 return true;
314 }
315
316 static bool gpir_emit_if(gpir_compiler *comp, nir_if *nif)
317 {
318 gpir_error("if nir_cf_node not support\n");
319 return false;
320 }
321
322 static bool gpir_emit_loop(gpir_compiler *comp, nir_loop *nloop)
323 {
324 gpir_error("loop nir_cf_node not support\n");
325 return false;
326 }
327
328 static bool gpir_emit_function(gpir_compiler *comp, nir_function_impl *nfunc)
329 {
330 gpir_error("function nir_cf_node not support\n");
331 return false;
332 }
333
334 static bool gpir_emit_cf_list(gpir_compiler *comp, struct exec_list *list)
335 {
336 foreach_list_typed(nir_cf_node, node, node, list) {
337 bool ret;
338
339 switch (node->type) {
340 case nir_cf_node_block:
341 ret = gpir_emit_block(comp, nir_cf_node_as_block(node));
342 break;
343 case nir_cf_node_if:
344 ret = gpir_emit_if(comp, nir_cf_node_as_if(node));
345 break;
346 case nir_cf_node_loop:
347 ret = gpir_emit_loop(comp, nir_cf_node_as_loop(node));
348 break;
349 case nir_cf_node_function:
350 ret = gpir_emit_function(comp, nir_cf_node_as_function(node));
351 break;
352 default:
353 gpir_error("unknown NIR node type %d\n", node->type);
354 return false;
355 }
356
357 if (!ret)
358 return false;
359 }
360
361 return true;
362 }
363
364 gpir_reg *gpir_create_reg(gpir_compiler *comp)
365 {
366 gpir_reg *reg = ralloc(comp, gpir_reg);
367 reg->index = comp->cur_reg++;
368 list_addtail(&reg->list, &comp->reg_list);
369 list_inithead(&reg->defs_list);
370 list_inithead(&reg->uses_list);
371 return reg;
372 }
373
374 static gpir_compiler *gpir_compiler_create(void *prog, unsigned num_reg, unsigned num_ssa)
375 {
376 gpir_compiler *comp = rzalloc(prog, gpir_compiler);
377
378 list_inithead(&comp->block_list);
379 list_inithead(&comp->reg_list);
380
381 for (int i = 0; i < num_reg; i++)
382 gpir_create_reg(comp);
383
384 for (int i = 0; i < GPIR_VECTOR_SSA_NUM; i++)
385 comp->vector_ssa[i].ssa = -1;
386
387 comp->var_nodes = rzalloc_array(comp, gpir_node *, num_ssa);
388 comp->prog = prog;
389 return comp;
390 }
391
392 static int gpir_glsl_type_size(enum glsl_base_type type)
393 {
394 /* only support GLSL_TYPE_FLOAT */
395 assert(type == GLSL_TYPE_FLOAT);
396 return 4;
397 }
398
399 bool gpir_compile_nir(struct lima_vs_shader_state *prog, struct nir_shader *nir)
400 {
401 nir_function_impl *func = nir_shader_get_entrypoint(nir);
402 gpir_compiler *comp = gpir_compiler_create(prog, func->reg_alloc, func->ssa_alloc);
403 if (!comp)
404 return false;
405
406 comp->constant_base = nir->num_uniforms;
407 prog->uniform_pending_offset = nir->num_uniforms * 16;
408
409 if (!gpir_emit_cf_list(comp, &func->body))
410 goto err_out0;
411
412 gpir_node_print_prog_seq(comp);
413 gpir_node_print_prog_dep(comp);
414
415 /* increase for viewport uniforms */
416 comp->constant_base += GPIR_VECTOR_SSA_NUM;
417
418 if (!gpir_pre_rsched_lower_prog(comp))
419 goto err_out0;
420
421 if (!gpir_reduce_reg_pressure_schedule_prog(comp))
422 goto err_out0;
423
424 if (!gpir_post_rsched_lower_prog(comp))
425 goto err_out0;
426
427 if (!gpir_regalloc_prog(comp))
428 goto err_out0;
429
430 if (!gpir_schedule_prog(comp))
431 goto err_out0;
432
433 if (!gpir_codegen_prog(comp))
434 goto err_out0;
435
436 nir_foreach_variable(var, &nir->outputs) {
437 if (var->data.location == VARYING_SLOT_POS)
438 assert(var->data.driver_location == 0);
439
440 struct lima_varying_info *v = prog->varying + var->data.driver_location;
441 if (!v->components) {
442 v->component_size = gpir_glsl_type_size(glsl_get_base_type(var->type));
443 prog->num_varying++;
444 }
445
446 v->components += glsl_get_components(var->type);
447 }
448
449 ralloc_free(comp);
450 return true;
451
452 err_out0:
453 ralloc_free(comp);
454 return false;
455 }
456