2 * Copyright (c) 2017 Lima Project
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:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
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.
25 #include "util/ralloc.h"
26 #include "compiler/nir/nir.h"
29 #include "lima_context.h"
32 static inline void *gpir_node_create_ssa(gpir_block
*block
, gpir_op op
, nir_ssa_def
*ssa
)
34 int index
= ssa
->index
;
35 gpir_node
*node
= gpir_node_create(block
, op
);
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
);
43 static inline void *gpir_node_create_reg(gpir_block
*block
, gpir_op op
, nir_reg_dest
*reg
)
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
);
49 snprintf(node
->name
, sizeof(node
->name
), "reg%d", index
);
52 gpir_node_add_dep(&store
->node
, node
, GPIR_DEP_INPUT
);
54 list_for_each_entry(gpir_reg
, reg
, &block
->comp
->reg_list
, list
) {
55 if (reg
->index
== index
) {
57 list_addtail(&store
->reg_link
, ®
->defs_list
);
62 list_addtail(&node
->list
, &block
->node_list
);
63 list_addtail(&store
->node
.list
, &block
->node_list
);
67 static void *gpir_node_create_dest(gpir_block
*block
, gpir_op op
, nir_dest
*dest
)
70 return gpir_node_create_ssa(block
, op
, &dest
->ssa
);
72 return gpir_node_create_reg(block
, op
, &dest
->reg
);
75 static gpir_node
*gpir_node_find(gpir_block
*block
, gpir_node
*succ
, nir_src
*src
)
80 pred
= block
->comp
->var_nodes
[src
->ssa
->index
];
84 pred
= gpir_node_create(block
, gpir_op_load_reg
);
85 list_addtail(&pred
->list
, &succ
->list
);
87 gpir_load_node
*load
= gpir_node_to_load(pred
);
88 list_for_each_entry(gpir_reg
, reg
, &block
->comp
->reg_list
, list
) {
89 if (reg
->index
== src
->reg
.reg
->index
) {
91 list_addtail(&load
->reg_link
, ®
->uses_list
);
100 static int nir_to_gpir_opcodes
[nir_num_opcodes
] = {
102 [0 ... nir_last_opcode
] = -1,
104 [nir_op_fmul
] = gpir_op_mul
,
105 [nir_op_fadd
] = gpir_op_add
,
106 [nir_op_fneg
] = gpir_op_neg
,
107 [nir_op_fnot
] = gpir_op_not
,
108 [nir_op_fmin
] = gpir_op_min
,
109 [nir_op_fmax
] = gpir_op_max
,
110 [nir_op_frcp
] = gpir_op_rcp
,
111 [nir_op_frsq
] = gpir_op_rsqrt
,
112 [nir_op_slt
] = gpir_op_lt
,
113 [nir_op_sge
] = gpir_op_ge
,
114 [nir_op_fcsel
] = gpir_op_select
,
115 [nir_op_ffloor
] = gpir_op_floor
,
116 [nir_op_fsign
] = gpir_op_sign
,
117 [nir_op_seq
] = gpir_op_eq
,
118 [nir_op_sne
] = gpir_op_ne
,
119 [nir_op_fand
] = gpir_op_min
,
120 [nir_op_for
] = gpir_op_max
,
121 [nir_op_fabs
] = gpir_op_abs
,
122 [nir_op_fmov
] = gpir_op_mov
,
125 static bool gpir_emit_alu(gpir_block
*block
, nir_instr
*ni
)
127 nir_alu_instr
*instr
= nir_instr_as_alu(ni
);
128 int op
= nir_to_gpir_opcodes
[instr
->op
];
131 gpir_error("unsupported nir_op: %s\n", nir_op_infos
[instr
->op
].name
);
135 gpir_alu_node
*node
= gpir_node_create_dest(block
, op
, &instr
->dest
.dest
);
139 unsigned num_child
= nir_op_infos
[instr
->op
].num_inputs
;
140 assert(num_child
<= ARRAY_SIZE(node
->children
));
141 node
->num_child
= num_child
;
143 for (int i
= 0; i
< num_child
; i
++) {
144 nir_alu_src
*src
= instr
->src
+ i
;
145 node
->children_negate
[i
] = src
->negate
;
147 gpir_node
*child
= gpir_node_find(block
, &node
->node
, &src
->src
);
148 node
->children
[i
] = child
;
150 gpir_node_add_dep(&node
->node
, child
, GPIR_DEP_INPUT
);
156 static bool gpir_emit_intrinsic(gpir_block
*block
, nir_instr
*ni
)
158 nir_intrinsic_instr
*instr
= nir_instr_as_intrinsic(ni
);
160 switch (instr
->intrinsic
) {
161 case nir_intrinsic_load_input
:
163 gpir_load_node
*load
=
164 gpir_node_create_dest(block
, gpir_op_load_attribute
, &instr
->dest
);
168 load
->index
= nir_intrinsic_base(instr
);
169 load
->component
= nir_intrinsic_component(instr
);
173 case nir_intrinsic_load_uniform
:
175 gpir_load_node
*load
=
176 gpir_node_create_dest(block
, gpir_op_load_uniform
, &instr
->dest
);
180 int offset
= nir_intrinsic_base(instr
);
181 offset
+= (int)nir_src_as_float(instr
->src
[0]);
183 load
->index
= offset
/ 4;
184 load
->component
= offset
% 4;
188 case nir_intrinsic_store_output
:
190 gpir_store_node
*store
= gpir_node_create(block
, gpir_op_store_varying
);
191 if (unlikely(!store
))
193 list_addtail(&store
->node
.list
, &block
->node_list
);
195 store
->index
= nir_intrinsic_base(instr
);
196 store
->component
= nir_intrinsic_component(instr
);
198 gpir_node
*child
= gpir_node_find(block
, &store
->node
, instr
->src
);
199 store
->child
= child
;
200 gpir_node_add_dep(&store
->node
, child
, GPIR_DEP_INPUT
);
205 gpir_error("unsupported nir_intrinsic_instr %s\n",
206 nir_intrinsic_infos
[instr
->intrinsic
].name
);
211 static bool gpir_emit_load_const(gpir_block
*block
, nir_instr
*ni
)
213 nir_load_const_instr
*instr
= nir_instr_as_load_const(ni
);
214 gpir_const_node
*node
=
215 gpir_node_create_ssa(block
, gpir_op_const
, &instr
->def
);
219 assert(instr
->def
.bit_size
== 32);
220 assert(instr
->def
.num_components
== 1);
222 node
->value
.i
= instr
->value
[0].i32
;
227 static bool gpir_emit_ssa_undef(gpir_block
*block
, nir_instr
*ni
)
229 gpir_error("nir_ssa_undef_instr not support\n");
233 static bool gpir_emit_tex(gpir_block
*block
, nir_instr
*ni
)
235 gpir_error("nir_jump_instr not support\n");
239 static bool gpir_emit_jump(gpir_block
*block
, nir_instr
*ni
)
241 gpir_error("nir_jump_instr not support\n");
245 static bool (*gpir_emit_instr
[nir_instr_type_phi
])(gpir_block
*, nir_instr
*) = {
246 [nir_instr_type_alu
] = gpir_emit_alu
,
247 [nir_instr_type_intrinsic
] = gpir_emit_intrinsic
,
248 [nir_instr_type_load_const
] = gpir_emit_load_const
,
249 [nir_instr_type_ssa_undef
] = gpir_emit_ssa_undef
,
250 [nir_instr_type_tex
] = gpir_emit_tex
,
251 [nir_instr_type_jump
] = gpir_emit_jump
,
254 static gpir_block
*gpir_block_create(gpir_compiler
*comp
)
256 gpir_block
*block
= ralloc(comp
, gpir_block
);
260 list_inithead(&block
->node_list
);
261 list_inithead(&block
->instr_list
);
266 static bool gpir_emit_block(gpir_compiler
*comp
, nir_block
*nblock
)
268 gpir_block
*block
= gpir_block_create(comp
);
272 list_addtail(&block
->list
, &comp
->block_list
);
275 nir_foreach_instr(instr
, nblock
) {
276 assert(instr
->type
< nir_instr_type_phi
);
277 if (!gpir_emit_instr
[instr
->type
](block
, instr
))
284 static bool gpir_emit_if(gpir_compiler
*comp
, nir_if
*nif
)
286 gpir_error("if nir_cf_node not support\n");
290 static bool gpir_emit_loop(gpir_compiler
*comp
, nir_loop
*nloop
)
292 gpir_error("loop nir_cf_node not support\n");
296 static bool gpir_emit_function(gpir_compiler
*comp
, nir_function_impl
*nfunc
)
298 gpir_error("function nir_cf_node not support\n");
302 static bool gpir_emit_cf_list(gpir_compiler
*comp
, struct exec_list
*list
)
304 foreach_list_typed(nir_cf_node
, node
, node
, list
) {
307 switch (node
->type
) {
308 case nir_cf_node_block
:
309 ret
= gpir_emit_block(comp
, nir_cf_node_as_block(node
));
312 ret
= gpir_emit_if(comp
, nir_cf_node_as_if(node
));
314 case nir_cf_node_loop
:
315 ret
= gpir_emit_loop(comp
, nir_cf_node_as_loop(node
));
317 case nir_cf_node_function
:
318 ret
= gpir_emit_function(comp
, nir_cf_node_as_function(node
));
321 gpir_error("unknown NIR node type %d\n", node
->type
);
332 gpir_reg
*gpir_create_reg(gpir_compiler
*comp
)
334 gpir_reg
*reg
= ralloc(comp
, gpir_reg
);
335 reg
->index
= comp
->cur_reg
++;
336 list_addtail(®
->list
, &comp
->reg_list
);
337 list_inithead(®
->defs_list
);
338 list_inithead(®
->uses_list
);
342 static gpir_compiler
*gpir_compiler_create(void *prog
, unsigned num_reg
, unsigned num_ssa
)
344 gpir_compiler
*comp
= rzalloc(prog
, gpir_compiler
);
346 list_inithead(&comp
->block_list
);
347 list_inithead(&comp
->reg_list
);
349 for (int i
= 0; i
< num_reg
; i
++)
350 gpir_create_reg(comp
);
352 comp
->var_nodes
= rzalloc_array(comp
, gpir_node
*, num_ssa
);
357 static int gpir_glsl_type_size(enum glsl_base_type type
)
359 /* only support GLSL_TYPE_FLOAT */
360 assert(type
== GLSL_TYPE_FLOAT
);
364 bool gpir_compile_nir(struct lima_vs_shader_state
*prog
, struct nir_shader
*nir
)
366 nir_function_impl
*func
= nir_shader_get_entrypoint(nir
);
367 gpir_compiler
*comp
= gpir_compiler_create(prog
, func
->reg_alloc
, func
->ssa_alloc
);
371 comp
->constant_base
= nir
->num_uniforms
;
372 prog
->uniform_pending_offset
= nir
->num_uniforms
* 16;
374 if (!gpir_emit_cf_list(comp
, &func
->body
))
377 gpir_node_print_prog_seq(comp
);
378 gpir_node_print_prog_dep(comp
);
380 if (!gpir_pre_rsched_lower_prog(comp
))
383 if (!gpir_reduce_reg_pressure_schedule_prog(comp
))
386 if (!gpir_post_rsched_lower_prog(comp
))
389 if (!gpir_value_regalloc_prog(comp
))
392 if (!gpir_physical_regalloc_prog(comp
))
395 if (!gpir_schedule_prog(comp
))
398 if (!gpir_codegen_prog(comp
))
401 nir_foreach_variable(var
, &nir
->outputs
) {
402 if (var
->data
.location
== VARYING_SLOT_POS
)
403 assert(var
->data
.driver_location
== 0);
405 struct lima_varying_info
*v
= prog
->varying
+ var
->data
.driver_location
;
406 if (!v
->components
) {
407 v
->component_size
= gpir_glsl_type_size(glsl_get_base_type(var
->type
));
411 v
->components
+= glsl_get_components(var
->type
);