xref: /aosp_15_r20/external/mesa3d/src/imagination/rogue/rogue_compile.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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