1 /*
2 * Copyright © 2022 Imagination Technologies Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include "compiler/shader_enums.h"
25 #include "compiler/spirv/nir_spirv.h"
26 #include "nir/nir.h"
27 #include "rogue.h"
28 #include "rogue_builder.h"
29 #include "util/macros.h"
30 /* FIXME: Remove once the compiler/driver interface is finalised. */
31 #include "vulkan/vulkan_core.h"
32
33 /**
34 * \file rogue_compile.c
35 *
36 * \brief Contains NIR to Rogue translation functions, and Rogue passes.
37 */
38
39 /* For ALU scalars */
40 /* TODO: expand and use these helpers. */
nir_ssa_reg(rogue_shader * shader,unsigned index,unsigned num_components,unsigned component)41 static rogue_ref nir_ssa_reg(rogue_shader *shader,
42 unsigned index,
43 unsigned num_components,
44 unsigned component)
45 {
46 if (num_components > 1) {
47 return rogue_ref_regarray(
48 rogue_ssa_vec_regarray(shader, 1, index, component));
49 }
50
51 return rogue_ref_reg(rogue_ssa_reg(shader, index));
52 }
53
nir_ssa_regarray(rogue_shader * shader,unsigned index,unsigned num_components,unsigned component)54 static rogue_ref nir_ssa_regarray(rogue_shader *shader,
55 unsigned index,
56 unsigned num_components,
57 unsigned component)
58 {
59 return rogue_ref_regarray(
60 rogue_ssa_vec_regarray(shader, num_components, index, component));
61 }
62
nir_ssa_reg_alu_src(rogue_shader * shader,const nir_alu_instr * alu,unsigned src_num,bool vec)63 static rogue_ref nir_ssa_reg_alu_src(rogue_shader *shader,
64 const nir_alu_instr *alu,
65 unsigned src_num,
66 bool vec)
67 {
68 unsigned index = alu->src[src_num].src.ssa->index;
69 unsigned num_components = alu->src[src_num].src.ssa->num_components;
70 unsigned component = alu->src[src_num].swizzle[0];
71
72 assert(num_components == 1);
73
74 return vec ? nir_ssa_regarray(shader, index, num_components, component)
75 : nir_ssa_reg(shader, index, num_components, component);
76 }
77
78 static rogue_ref
nir_ssa_reg_alu_dst(rogue_shader * shader,const nir_alu_instr * alu,bool vec)79 nir_ssa_reg_alu_dst(rogue_shader *shader, const nir_alu_instr *alu, bool vec)
80 {
81 unsigned num_components = alu->def.num_components;
82 unsigned index = alu->def.index;
83
84 assert(num_components == 1);
85
86 return vec ? nir_ssa_regarray(shader, index, num_components, 0)
87 : nir_ssa_reg(shader, index, num_components, 0);
88 }
89
trans_nir_jump_return(rogue_builder * b,nir_jump_instr * jump)90 static void trans_nir_jump_return(rogue_builder *b, nir_jump_instr *jump)
91 {
92 rogue_END(b);
93 }
94
trans_nir_jump(rogue_builder * b,nir_jump_instr * jump)95 static void trans_nir_jump(rogue_builder *b, nir_jump_instr *jump)
96 {
97 switch (jump->type) {
98 case nir_jump_return:
99 return trans_nir_jump_return(b, jump);
100
101 default:
102 break;
103 }
104
105 unreachable("Unimplemented NIR jump instruction type.");
106 }
107
trans_nir_load_const(rogue_builder * b,nir_load_const_instr * load_const)108 static void trans_nir_load_const(rogue_builder *b,
109 nir_load_const_instr *load_const)
110 {
111 unsigned dst_index = load_const->def.index;
112 unsigned bit_size = load_const->def.bit_size;
113 switch (bit_size) {
114 case 32: {
115 rogue_reg *dst = rogue_ssa_reg(b->shader, dst_index);
116 uint32_t imm = nir_const_value_as_uint(load_const->value[0], 32);
117 rogue_MOV(b, rogue_ref_reg(dst), rogue_ref_imm(imm));
118
119 break;
120 }
121
122 case 64: {
123 uint64_t imm = nir_const_value_as_uint(load_const->value[0], 64);
124 uint32_t imm_2x32[2] = { imm & 0xffffffff, (imm >> 32) & 0xffffffff };
125
126 rogue_regarray *dst[2] = {
127 rogue_ssa_vec_regarray(b->shader, 1, dst_index, 0),
128 rogue_ssa_vec_regarray(b->shader, 1, dst_index, 1),
129 };
130
131 rogue_MOV(b, rogue_ref_regarray(dst[0]), rogue_ref_imm(imm_2x32[0]));
132 rogue_MOV(b, rogue_ref_regarray(dst[1]), rogue_ref_imm(imm_2x32[1]));
133
134 break;
135 }
136
137 default:
138 unreachable("Unimplemented NIR load_const bit size.");
139 }
140 }
141
trans_nir_intrinsic_load_input_fs(rogue_builder * b,nir_intrinsic_instr * intr)142 static void trans_nir_intrinsic_load_input_fs(rogue_builder *b,
143 nir_intrinsic_instr *intr)
144 {
145 struct rogue_fs_build_data *fs_data = &b->shader->ctx->stage_data.fs;
146
147 unsigned load_size = intr->def.num_components;
148 assert(load_size == 1); /* TODO: We can support larger load sizes. */
149
150 rogue_reg *dst = rogue_ssa_reg(b->shader, intr->def.index);
151
152 struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
153 unsigned component = nir_intrinsic_component(intr);
154 unsigned coeff_index = rogue_coeff_index_fs(&fs_data->iterator_args,
155 io_semantics.location,
156 component);
157 unsigned wcoeff_index = rogue_coeff_index_fs(&fs_data->iterator_args, ~0, 0);
158
159 rogue_regarray *coeffs = rogue_coeff_regarray(b->shader,
160 ROGUE_COEFF_ALIGN * load_size,
161 coeff_index);
162 rogue_regarray *wcoeffs =
163 rogue_coeff_regarray(b->shader, ROGUE_COEFF_ALIGN, wcoeff_index);
164
165 rogue_instr *instr = &rogue_FITRP_PIXEL(b,
166 rogue_ref_reg(dst),
167 rogue_ref_drc(0),
168 rogue_ref_regarray(coeffs),
169 rogue_ref_regarray(wcoeffs),
170 rogue_ref_val(load_size))
171 ->instr;
172 rogue_add_instr_comment(instr, "load_input_fs");
173 }
174
trans_nir_intrinsic_load_input_vs(rogue_builder * b,nir_intrinsic_instr * intr)175 static void trans_nir_intrinsic_load_input_vs(rogue_builder *b,
176 nir_intrinsic_instr *intr)
177 {
178 struct pvr_pipeline_layout *pipeline_layout =
179 b->shader->ctx->pipeline_layout;
180
181 ASSERTED unsigned load_size = intr->def.num_components;
182 assert(load_size == 1); /* TODO: We can support larger load sizes. */
183
184 rogue_reg *dst = rogue_ssa_reg(b->shader, intr->def.index);
185
186 struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
187 unsigned input = io_semantics.location - VERT_ATTRIB_GENERIC0;
188 unsigned component = nir_intrinsic_component(intr);
189 unsigned vtxin_index = ~0U;
190
191 if (pipeline_layout) {
192 rogue_vertex_inputs *vs_inputs = &b->shader->ctx->stage_data.vs.inputs;
193 assert(input < vs_inputs->num_input_vars);
194 assert(component < vs_inputs->components[input]);
195
196 vtxin_index = vs_inputs->base[input] + component;
197 } else {
198 /* Dummy defaults for offline compiler. */
199 /* TODO: Load these from an offline description
200 * if using the offline compiler.
201 */
202
203 nir_shader *nir = b->shader->ctx->nir[MESA_SHADER_VERTEX];
204 vtxin_index = 0;
205
206 /* Process inputs. */
207 nir_foreach_shader_in_variable (var, nir) {
208 unsigned input_components = glsl_get_components(var->type);
209 unsigned bit_size =
210 glsl_base_type_bit_size(glsl_get_base_type(var->type));
211 assert(bit_size >= 32); /* TODO: Support smaller bit sizes. */
212 unsigned reg_count = bit_size / 32;
213
214 /* Check input location. */
215 assert(var->data.location >= VERT_ATTRIB_GENERIC0 &&
216 var->data.location <= VERT_ATTRIB_GENERIC15);
217
218 if (var->data.location == io_semantics.location) {
219 assert(component < input_components);
220 vtxin_index += reg_count * component;
221 break;
222 }
223
224 vtxin_index += reg_count * input_components;
225 }
226 }
227
228 assert(vtxin_index != ~0U);
229
230 rogue_reg *src = rogue_vtxin_reg(b->shader, vtxin_index);
231 rogue_instr *instr =
232 &rogue_MOV(b, rogue_ref_reg(dst), rogue_ref_reg(src))->instr;
233 rogue_add_instr_comment(instr, "load_input_vs");
234 }
235
trans_nir_intrinsic_load_input(rogue_builder * b,nir_intrinsic_instr * intr)236 static void trans_nir_intrinsic_load_input(rogue_builder *b,
237 nir_intrinsic_instr *intr)
238 {
239 switch (b->shader->stage) {
240 case MESA_SHADER_FRAGMENT:
241 return trans_nir_intrinsic_load_input_fs(b, intr);
242
243 case MESA_SHADER_VERTEX:
244 return trans_nir_intrinsic_load_input_vs(b, intr);
245
246 default:
247 break;
248 }
249
250 unreachable("Unimplemented NIR load_input variant.");
251 }
252
trans_nir_intrinsic_store_output_fs(rogue_builder * b,nir_intrinsic_instr * intr)253 static void trans_nir_intrinsic_store_output_fs(rogue_builder *b,
254 nir_intrinsic_instr *intr)
255 {
256 ASSERTED unsigned store_size = nir_src_num_components(intr->src[0]);
257 assert(store_size == 1);
258
259 /* TODO: When hoisting I/O allocation to the driver, check if this is
260 * correct.
261 */
262 unsigned pixout_index = nir_src_as_uint(intr->src[1]);
263
264 rogue_reg *dst = rogue_pixout_reg(b->shader, pixout_index);
265 rogue_reg *src = rogue_ssa_reg(b->shader, intr->src[0].ssa->index);
266
267 rogue_instr *instr =
268 &rogue_MOV(b, rogue_ref_reg(dst), rogue_ref_reg(src))->instr;
269 rogue_add_instr_comment(instr, "store_output_fs");
270 }
271
trans_nir_intrinsic_store_output_vs(rogue_builder * b,nir_intrinsic_instr * intr)272 static void trans_nir_intrinsic_store_output_vs(rogue_builder *b,
273 nir_intrinsic_instr *intr)
274 {
275 struct rogue_vs_build_data *vs_data = &b->shader->ctx->stage_data.vs;
276
277 ASSERTED unsigned store_size = nir_src_num_components(intr->src[0]);
278 assert(store_size == 1);
279
280 struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
281 unsigned component = nir_intrinsic_component(intr);
282 unsigned vtxout_index = rogue_output_index_vs(&vs_data->outputs,
283 io_semantics.location,
284 component);
285
286 rogue_reg *dst = rogue_vtxout_reg(b->shader, vtxout_index);
287 rogue_reg *src = rogue_ssa_reg(b->shader, intr->src[0].ssa->index);
288
289 rogue_instr *instr =
290 &rogue_MOV(b, rogue_ref_reg(dst), rogue_ref_reg(src))->instr;
291 rogue_add_instr_comment(instr, "store_output_vs");
292 }
293
trans_nir_intrinsic_store_output(rogue_builder * b,nir_intrinsic_instr * intr)294 static void trans_nir_intrinsic_store_output(rogue_builder *b,
295 nir_intrinsic_instr *intr)
296 {
297 switch (b->shader->stage) {
298 case MESA_SHADER_FRAGMENT:
299 return trans_nir_intrinsic_store_output_fs(b, intr);
300
301 case MESA_SHADER_VERTEX:
302 return trans_nir_intrinsic_store_output_vs(b, intr);
303
304 default:
305 break;
306 }
307
308 unreachable("Unimplemented NIR store_output variant.");
309 }
310
311 static inline gl_shader_stage
pvr_stage_to_mesa(enum pvr_stage_allocation pvr_stage)312 pvr_stage_to_mesa(enum pvr_stage_allocation pvr_stage)
313 {
314 switch (pvr_stage) {
315 case PVR_STAGE_ALLOCATION_VERTEX_GEOMETRY:
316 return MESA_SHADER_VERTEX;
317
318 case PVR_STAGE_ALLOCATION_FRAGMENT:
319 return MESA_SHADER_FRAGMENT;
320
321 case PVR_STAGE_ALLOCATION_COMPUTE:
322 return MESA_SHADER_COMPUTE;
323
324 default:
325 break;
326 }
327
328 unreachable("Unsupported pvr_stage_allocation.");
329 }
330
331 static inline enum pvr_stage_allocation
mesa_stage_to_pvr(gl_shader_stage mesa_stage)332 mesa_stage_to_pvr(gl_shader_stage mesa_stage)
333 {
334 switch (mesa_stage) {
335 case MESA_SHADER_VERTEX:
336 return PVR_STAGE_ALLOCATION_VERTEX_GEOMETRY;
337
338 case MESA_SHADER_FRAGMENT:
339 return PVR_STAGE_ALLOCATION_FRAGMENT;
340
341 case MESA_SHADER_COMPUTE:
342 return PVR_STAGE_ALLOCATION_COMPUTE;
343
344 default:
345 break;
346 }
347
348 unreachable("Unsupported gl_shader_stage.");
349 }
descriptor_is_dynamic(VkDescriptorType type)350 static bool descriptor_is_dynamic(VkDescriptorType type)
351 {
352 return (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
353 type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
354 }
355
356 static void
trans_nir_intrinsic_load_vulkan_descriptor(rogue_builder * b,nir_intrinsic_instr * intr)357 trans_nir_intrinsic_load_vulkan_descriptor(rogue_builder *b,
358 nir_intrinsic_instr *intr)
359 {
360 rogue_instr *instr;
361 unsigned desc_set = nir_src_comp_as_uint(intr->src[0], 0);
362 unsigned binding = nir_src_comp_as_uint(intr->src[0], 1);
363 ASSERTED VkDescriptorType desc_type = nir_src_comp_as_uint(intr->src[0], 2);
364 assert(desc_type == nir_intrinsic_desc_type(intr));
365
366 struct pvr_pipeline_layout *pipeline_layout =
367 b->shader->ctx->pipeline_layout;
368
369 unsigned desc_set_table_sh_reg;
370 unsigned desc_set_offset;
371 unsigned desc_offset;
372
373 if (pipeline_layout) {
374 /* Fetch shared registers containing descriptor set table address. */
375 enum pvr_stage_allocation pvr_stage = mesa_stage_to_pvr(b->shader->stage);
376 assert(pipeline_layout->sh_reg_layout_per_stage[pvr_stage]
377 .descriptor_set_addrs_table.present);
378 desc_set_table_sh_reg =
379 pipeline_layout->sh_reg_layout_per_stage[pvr_stage]
380 .descriptor_set_addrs_table.offset;
381
382 /* Calculate offset for the descriptor set. */
383 assert(desc_set < pipeline_layout->set_count);
384 desc_set_offset = desc_set * sizeof(pvr_dev_addr_t); /* Table is an array
385 of addresses. */
386
387 const struct pvr_descriptor_set_layout *set_layout =
388 pipeline_layout->set_layout[desc_set];
389 const struct pvr_descriptor_set_layout_mem_layout *mem_layout =
390 &set_layout->memory_layout_in_dwords_per_stage[pvr_stage];
391
392 /* Calculate offset for the descriptor/binding. */
393 assert(binding < set_layout->binding_count);
394
395 const struct pvr_descriptor_set_layout_binding *binding_layout =
396 pvr_get_descriptor_binding(set_layout, binding);
397 assert(binding_layout);
398
399 /* TODO: Handle secondaries. */
400 /* TODO: Handle bindings having multiple descriptors
401 * (VkDescriptorSetLayoutBinding->descriptorCount).
402 */
403
404 if (descriptor_is_dynamic(binding_layout->type))
405 desc_offset = set_layout->total_size_in_dwords;
406 else
407 desc_offset = mem_layout->primary_offset;
408
409 desc_offset +=
410 binding_layout->per_stage_offset_in_dwords[pvr_stage].primary;
411
412 desc_offset *= sizeof(uint32_t); /* DWORDs to bytes. */
413 } else {
414 /* Dummy defaults for offline compiler. */
415 /* TODO: Load these from an offline pipeline description
416 * if using the offline compiler.
417 */
418 desc_set_table_sh_reg = 0;
419 desc_set_offset = desc_set * sizeof(pvr_dev_addr_t);
420 desc_offset = binding * sizeof(pvr_dev_addr_t);
421 }
422
423 unsigned desc_set_table_addr_idx = b->shader->ctx->next_ssa_idx++;
424 rogue_ssa_vec_regarray(b->shader, 2, desc_set_table_addr_idx, 0);
425 rogue_regarray *desc_set_table_addr_2x32[2] = {
426 rogue_ssa_vec_regarray(b->shader, 1, desc_set_table_addr_idx, 0),
427 rogue_ssa_vec_regarray(b->shader, 1, desc_set_table_addr_idx, 1),
428 };
429
430 instr = &rogue_MOV(b,
431 rogue_ref_regarray(desc_set_table_addr_2x32[0]),
432 rogue_ref_reg(
433 rogue_shared_reg(b->shader, desc_set_table_sh_reg)))
434 ->instr;
435 rogue_add_instr_comment(instr, "desc_set_table_addr_lo");
436 instr =
437 &rogue_MOV(
438 b,
439 rogue_ref_regarray(desc_set_table_addr_2x32[1]),
440 rogue_ref_reg(rogue_shared_reg(b->shader, desc_set_table_sh_reg + 1)))
441 ->instr;
442 rogue_add_instr_comment(instr, "desc_set_table_addr_hi");
443
444 /* Offset the descriptor set table address to access the descriptor set. */
445 unsigned desc_set_table_addr_offset_idx = b->shader->ctx->next_ssa_idx++;
446 rogue_regarray *desc_set_table_addr_offset_64 =
447 rogue_ssa_vec_regarray(b->shader, 2, desc_set_table_addr_offset_idx, 0);
448 rogue_regarray *desc_set_table_addr_offset_2x32[2] = {
449 rogue_ssa_vec_regarray(b->shader, 1, desc_set_table_addr_offset_idx, 0),
450 rogue_ssa_vec_regarray(b->shader, 1, desc_set_table_addr_offset_idx, 1),
451 };
452
453 unsigned desc_set_table_addr_offset_lo_idx = b->shader->ctx->next_ssa_idx++;
454 unsigned desc_set_table_addr_offset_hi_idx = b->shader->ctx->next_ssa_idx++;
455
456 rogue_reg *desc_set_table_addr_offset_lo =
457 rogue_ssa_reg(b->shader, desc_set_table_addr_offset_lo_idx);
458 rogue_reg *desc_set_table_addr_offset_hi =
459 rogue_ssa_reg(b->shader, desc_set_table_addr_offset_hi_idx);
460
461 rogue_MOV(b,
462 rogue_ref_reg(desc_set_table_addr_offset_lo),
463 rogue_ref_imm(desc_set_offset));
464 rogue_MOV(b, rogue_ref_reg(desc_set_table_addr_offset_hi), rogue_ref_imm(0));
465
466 rogue_ADD64(b,
467 rogue_ref_regarray(desc_set_table_addr_offset_2x32[0]),
468 rogue_ref_regarray(desc_set_table_addr_offset_2x32[1]),
469 rogue_ref_io(ROGUE_IO_NONE),
470 rogue_ref_regarray(desc_set_table_addr_2x32[0]),
471 rogue_ref_regarray(desc_set_table_addr_2x32[1]),
472 rogue_ref_reg(desc_set_table_addr_offset_lo),
473 rogue_ref_reg(desc_set_table_addr_offset_hi),
474 rogue_ref_io(ROGUE_IO_NONE));
475
476 unsigned desc_set_addr_idx = b->shader->ctx->next_ssa_idx++;
477 rogue_regarray *desc_set_addr_64 =
478 rogue_ssa_vec_regarray(b->shader, 2, desc_set_addr_idx, 0);
479 rogue_regarray *desc_set_addr_2x32[2] = {
480 rogue_ssa_vec_regarray(b->shader, 1, desc_set_addr_idx, 0),
481 rogue_ssa_vec_regarray(b->shader, 1, desc_set_addr_idx, 1),
482 };
483 instr = &rogue_LD(b,
484 rogue_ref_regarray(desc_set_addr_64),
485 rogue_ref_drc(0),
486 rogue_ref_val(2),
487 rogue_ref_regarray(desc_set_table_addr_offset_64))
488 ->instr;
489 rogue_add_instr_comment(instr, "load descriptor set");
490
491 /* Offset the descriptor set address to access the descriptor. */
492 unsigned desc_addr_offset_idx = b->shader->ctx->next_ssa_idx++;
493 rogue_regarray *desc_addr_offset_64 =
494 rogue_ssa_vec_regarray(b->shader, 2, desc_addr_offset_idx, 0);
495 rogue_regarray *desc_addr_offset_2x32[2] = {
496 rogue_ssa_vec_regarray(b->shader, 1, desc_addr_offset_idx, 0),
497 rogue_ssa_vec_regarray(b->shader, 1, desc_addr_offset_idx, 1),
498 };
499
500 unsigned desc_addr_offset_lo_idx = b->shader->ctx->next_ssa_idx++;
501 unsigned desc_addr_offset_hi_idx = b->shader->ctx->next_ssa_idx++;
502
503 rogue_reg *desc_addr_offset_val_lo =
504 rogue_ssa_reg(b->shader, desc_addr_offset_lo_idx);
505 rogue_reg *desc_addr_offset_val_hi =
506 rogue_ssa_reg(b->shader, desc_addr_offset_hi_idx);
507
508 rogue_MOV(b,
509 rogue_ref_reg(desc_addr_offset_val_lo),
510 rogue_ref_imm(desc_offset));
511 rogue_MOV(b, rogue_ref_reg(desc_addr_offset_val_hi), rogue_ref_imm(0));
512
513 rogue_ADD64(b,
514 rogue_ref_regarray(desc_addr_offset_2x32[0]),
515 rogue_ref_regarray(desc_addr_offset_2x32[1]),
516 rogue_ref_io(ROGUE_IO_NONE),
517 rogue_ref_regarray(desc_set_addr_2x32[0]),
518 rogue_ref_regarray(desc_set_addr_2x32[1]),
519 rogue_ref_reg(desc_addr_offset_val_lo),
520 rogue_ref_reg(desc_addr_offset_val_hi),
521 rogue_ref_io(ROGUE_IO_NONE));
522
523 unsigned desc_addr_idx = intr->def.index;
524 rogue_regarray *desc_addr_64 =
525 rogue_ssa_vec_regarray(b->shader, 2, desc_addr_idx, 0);
526 instr = &rogue_LD(b,
527 rogue_ref_regarray(desc_addr_64),
528 rogue_ref_drc(0),
529 rogue_ref_val(2),
530 rogue_ref_regarray(desc_addr_offset_64))
531 ->instr;
532 rogue_add_instr_comment(instr, "load descriptor");
533 }
534
trans_nir_intrinsic_load_global_constant(rogue_builder * b,nir_intrinsic_instr * intr)535 static void trans_nir_intrinsic_load_global_constant(rogue_builder *b,
536 nir_intrinsic_instr *intr)
537 {
538 /* 64-bit source address. */
539 unsigned src_index = intr->src[0].ssa->index;
540 rogue_regarray *src = rogue_ssa_vec_regarray(b->shader, 2, src_index, 0);
541
542 /*** TODO NEXT: this could be either a reg or regarray. ***/
543 rogue_reg *dst = rogue_ssa_reg(b->shader, intr->def.index);
544
545 /* TODO NEXT: src[1] should be depending on ssa vec size for burst loads */
546 rogue_instr *instr = &rogue_LD(b,
547 rogue_ref_reg(dst),
548 rogue_ref_drc(0),
549 rogue_ref_val(1),
550 rogue_ref_regarray(src))
551 ->instr;
552 rogue_add_instr_comment(instr, "load_global_constant");
553 }
554
trans_nir_intrinsic(rogue_builder * b,nir_intrinsic_instr * intr)555 static void trans_nir_intrinsic(rogue_builder *b, nir_intrinsic_instr *intr)
556 {
557 switch (intr->intrinsic) {
558 case nir_intrinsic_load_input:
559 return trans_nir_intrinsic_load_input(b, intr);
560
561 case nir_intrinsic_store_output:
562 return trans_nir_intrinsic_store_output(b, intr);
563
564 case nir_intrinsic_load_vulkan_descriptor:
565 return trans_nir_intrinsic_load_vulkan_descriptor(b, intr);
566
567 case nir_intrinsic_load_global_constant:
568 return trans_nir_intrinsic_load_global_constant(b, intr);
569
570 default:
571 break;
572 }
573
574 unreachable("Unimplemented NIR intrinsic instruction.");
575 }
576
trans_nir_alu_pack_unorm_4x8(rogue_builder * b,nir_alu_instr * alu)577 static void trans_nir_alu_pack_unorm_4x8(rogue_builder *b, nir_alu_instr *alu)
578 {
579 rogue_ref dst = nir_ssa_reg_alu_dst(b->shader, alu, false);
580 rogue_ref src = nir_ssa_reg_alu_src(b->shader, alu, 0, true);
581
582 rogue_alu_instr *pck_u8888 = rogue_PCK_U8888(b, dst, src);
583 rogue_set_instr_repeat(&pck_u8888->instr, 4);
584 rogue_set_alu_op_mod(pck_u8888, ROGUE_ALU_OP_MOD_SCALE);
585 }
586
trans_nir_alu_fmul(rogue_builder * b,nir_alu_instr * alu)587 static void trans_nir_alu_fmul(rogue_builder *b, nir_alu_instr *alu)
588 {
589 rogue_ref dst = nir_ssa_reg_alu_dst(b->shader, alu, false);
590 rogue_ref src0 = nir_ssa_reg_alu_src(b->shader, alu, 0, false);
591 rogue_ref src1 = nir_ssa_reg_alu_src(b->shader, alu, 1, false);
592
593 rogue_FMUL(b, dst, src0, src1);
594 }
595
trans_nir_alu_ffma(rogue_builder * b,nir_alu_instr * alu)596 static void trans_nir_alu_ffma(rogue_builder *b, nir_alu_instr *alu)
597 {
598 rogue_ref dst = nir_ssa_reg_alu_dst(b->shader, alu, false);
599 rogue_ref src0 = nir_ssa_reg_alu_src(b->shader, alu, 0, false);
600 rogue_ref src1 = nir_ssa_reg_alu_src(b->shader, alu, 1, false);
601 rogue_ref src2 = nir_ssa_reg_alu_src(b->shader, alu, 2, false);
602
603 rogue_FMAD(b, dst, src0, src1, src2);
604 }
605
trans_nir_alu_vecN(rogue_builder * b,nir_alu_instr * alu,unsigned n)606 static void trans_nir_alu_vecN(rogue_builder *b, nir_alu_instr *alu, unsigned n)
607 {
608 unsigned dst_index = alu->def.index;
609 rogue_regarray *dst;
610 rogue_reg *src;
611
612 for (unsigned u = 0; u < n; ++u) {
613 dst = rogue_ssa_vec_regarray(b->shader, 1, dst_index, u);
614 src = rogue_ssa_reg(b->shader, alu->src[u].src.ssa->index);
615 rogue_MOV(b, rogue_ref_regarray(dst), rogue_ref_reg(src));
616 }
617 }
618
trans_nir_alu_iadd64(rogue_builder * b,nir_alu_instr * alu)619 static void trans_nir_alu_iadd64(rogue_builder *b, nir_alu_instr *alu)
620 {
621 unsigned dst_index = alu->def.index;
622 rogue_regarray *dst[2] = {
623 rogue_ssa_vec_regarray(b->shader, 1, dst_index, 0),
624 rogue_ssa_vec_regarray(b->shader, 1, dst_index, 1),
625 };
626
627 unsigned src_index[2] = { alu->src[0].src.ssa->index,
628 alu->src[1].src.ssa->index };
629 rogue_regarray *src[2][2] = {
630 [0] = {
631 rogue_ssa_vec_regarray(b->shader, 1, src_index[0], 0),
632 rogue_ssa_vec_regarray(b->shader, 1, src_index[0], 1),
633 },
634 [1] = {
635 rogue_ssa_vec_regarray(b->shader, 1, src_index[1], 0),
636 rogue_ssa_vec_regarray(b->shader, 1, src_index[1], 1),
637 },
638 };
639
640 rogue_ADD64(b,
641 rogue_ref_regarray(dst[0]),
642 rogue_ref_regarray(dst[1]),
643 rogue_ref_io(ROGUE_IO_NONE),
644 rogue_ref_regarray(src[0][0]),
645 rogue_ref_regarray(src[0][1]),
646 rogue_ref_regarray(src[1][0]),
647 rogue_ref_regarray(src[1][1]),
648 rogue_ref_io(ROGUE_IO_NONE));
649 }
650
trans_nir_alu_iadd(rogue_builder * b,nir_alu_instr * alu)651 static void trans_nir_alu_iadd(rogue_builder *b, nir_alu_instr *alu)
652 {
653 unsigned bit_size = alu->def.bit_size;
654
655 switch (bit_size) {
656 /* TODO: case 32: */
657
658 case 64:
659 return trans_nir_alu_iadd64(b, alu);
660
661 default:
662 break;
663 }
664
665 unreachable("Unsupported bit size.");
666 }
667
trans_nir_alu(rogue_builder * b,nir_alu_instr * alu)668 static void trans_nir_alu(rogue_builder *b, nir_alu_instr *alu)
669 {
670 switch (alu->op) {
671 case nir_op_pack_unorm_4x8:
672 return trans_nir_alu_pack_unorm_4x8(b, alu);
673 return;
674
675 case nir_op_fmul:
676 return trans_nir_alu_fmul(b, alu);
677
678 case nir_op_ffma:
679 return trans_nir_alu_ffma(b, alu);
680
681 case nir_op_vec4:
682 return trans_nir_alu_vecN(b, alu, 4);
683
684 case nir_op_iadd:
685 return trans_nir_alu_iadd(b, alu);
686
687 default:
688 break;
689 }
690
691 unreachable("Unimplemented NIR ALU instruction.");
692 }
693
694 PUBLIC
rogue_count_used_regs(const rogue_shader * shader,enum rogue_reg_class class)695 unsigned rogue_count_used_regs(const rogue_shader *shader,
696 enum rogue_reg_class class)
697 {
698 unsigned reg_count;
699 if (rogue_reg_infos[class].num) {
700 reg_count = __bitset_count(shader->regs_used[class],
701 BITSET_WORDS(rogue_reg_infos[class].num));
702 } else {
703 reg_count = list_length(&shader->regs[class]);
704 }
705
706 #ifndef NDEBUG
707 /* Check that registers are contiguous. */
708 rogue_foreach_reg (reg, shader, class) {
709 assert(reg->index < reg_count);
710 }
711 #endif /* NDEBUG */
712
713 return reg_count;
714 }
715
rogue_feedback_used_regs(rogue_build_ctx * ctx,const rogue_shader * shader)716 static inline void rogue_feedback_used_regs(rogue_build_ctx *ctx,
717 const rogue_shader *shader)
718 {
719 /* TODO NEXT: Use this counting method elsewhere as well. */
720 ctx->common_data[shader->stage].temps =
721 rogue_count_used_regs(shader, ROGUE_REG_CLASS_TEMP);
722 ctx->common_data[shader->stage].internals =
723 rogue_count_used_regs(shader, ROGUE_REG_CLASS_INTERNAL);
724 }
725
ssa_def_cb(nir_def * ssa,void * state)726 static bool ssa_def_cb(nir_def *ssa, void *state)
727 {
728 rogue_shader *shader = (rogue_shader *)state;
729
730 if (ssa->num_components == 1) {
731 if (ssa->bit_size == 32) {
732 rogue_ssa_reg(shader, ssa->index);
733 } else if (ssa->bit_size == 64) {
734 rogue_ssa_vec_regarray(shader, 2, ssa->index, 0);
735 }
736 } else {
737 rogue_ssa_vec_regarray(shader, ssa->num_components, ssa->index, 0);
738 }
739
740 /* Keep track of the last SSA index so we can use more. */
741 shader->ctx->next_ssa_idx = MAX2(shader->ctx->next_ssa_idx, ssa->index);
742
743 return true;
744 }
745
746 /**
747 * \brief Translates a NIR shader to Rogue.
748 *
749 * \param[in] ctx Shared multi-stage build context.
750 * \param[in] nir NIR shader.
751 * \return A rogue_shader* if successful, or NULL if unsuccessful.
752 */
753 PUBLIC
rogue_nir_to_rogue(rogue_build_ctx * ctx,const nir_shader * nir)754 rogue_shader *rogue_nir_to_rogue(rogue_build_ctx *ctx, const nir_shader *nir)
755 {
756 gl_shader_stage stage = nir->info.stage;
757 rogue_shader *shader = rogue_shader_create(ctx, stage);
758 if (!shader)
759 return NULL;
760
761 shader->ctx = ctx;
762
763 /* Make sure we only have a single function. */
764 assert(exec_list_length(&nir->functions) == 1);
765
766 rogue_builder b;
767 rogue_builder_init(&b, shader);
768
769 nir_function_impl *entry = nir_shader_get_entrypoint((nir_shader *)nir);
770
771 /* Go through SSA used by NIR and "reserve" them so that sub-arrays won't be
772 * declared before the parent arrays. */
773 nir_foreach_block_unstructured (block, entry) {
774 nir_foreach_instr (instr, block) {
775 if (instr->type == nir_instr_type_load_const) {
776 nir_load_const_instr *load_const = nir_instr_as_load_const(instr);
777 if (load_const->def.num_components > 1)
778 continue;
779 }
780 nir_foreach_def(instr, ssa_def_cb, shader);
781 }
782 }
783 ++shader->ctx->next_ssa_idx;
784
785 /* Translate shader entrypoint. */
786 nir_foreach_block (block, entry) {
787 rogue_push_block(&b);
788
789 nir_foreach_instr (instr, block) {
790 switch (instr->type) {
791 case nir_instr_type_alu:
792 trans_nir_alu(&b, nir_instr_as_alu(instr));
793 break;
794
795 case nir_instr_type_intrinsic:
796 trans_nir_intrinsic(&b, nir_instr_as_intrinsic(instr));
797 break;
798
799 case nir_instr_type_load_const:
800 trans_nir_load_const(&b, nir_instr_as_load_const(instr));
801 break;
802
803 case nir_instr_type_jump:
804 trans_nir_jump(&b, nir_instr_as_jump(instr));
805 break;
806
807 default:
808 unreachable("Unimplemented NIR instruction type.");
809 }
810 }
811 }
812
813 /* Apply passes. */
814 rogue_shader_passes(shader);
815
816 rogue_feedback_used_regs(ctx, shader);
817
818 return shader;
819 }
820
821 /**
822 * \brief Performs Rogue passes on a shader.
823 *
824 * \param[in] shader The shader.
825 */
826 PUBLIC
rogue_shader_passes(rogue_shader * shader)827 void rogue_shader_passes(rogue_shader *shader)
828 {
829 rogue_validate_shader(shader, "before passes");
830
831 if (ROGUE_DEBUG(IR_PASSES))
832 rogue_print_pass_debug(shader, "before passes", stdout);
833
834 /* Passes */
835 ROGUE_PASS_V(shader, rogue_constreg);
836 ROGUE_PASS_V(shader, rogue_copy_prop);
837 ROGUE_PASS_V(shader, rogue_dce);
838 ROGUE_PASS_V(shader, rogue_lower_pseudo_ops);
839 ROGUE_PASS_V(shader, rogue_schedule_wdf, false);
840 ROGUE_PASS_V(shader, rogue_schedule_uvsw, false);
841 ROGUE_PASS_V(shader, rogue_trim);
842 ROGUE_PASS_V(shader, rogue_regalloc);
843 ROGUE_PASS_V(shader, rogue_lower_late_ops);
844 ROGUE_PASS_V(shader, rogue_dce);
845 ROGUE_PASS_V(shader, rogue_schedule_instr_groups, false);
846
847 if (ROGUE_DEBUG(IR))
848 rogue_print_pass_debug(shader, "after passes", stdout);
849 }
850