• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2020 Valve Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 #include "helpers.h"
7 
8 #include "common/amd_family.h"
9 #include "common/nir/ac_nir.h"
10 #include "vk_format.h"
11 
12 #include <llvm-c/Target.h>
13 
14 #include <mutex>
15 #include <sstream>
16 #include <stdio.h>
17 
18 using namespace aco;
19 
20 extern "C" {
21 PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName);
22 }
23 
24 ac_shader_config config;
25 aco_shader_info info;
26 std::unique_ptr<Program> program;
27 Builder bld(NULL);
28 Temp inputs[16];
29 
30 static radeon_info rad_info;
31 static nir_shader_compiler_options nir_options;
32 static nir_builder _nb;
33 nir_builder *nb;
34 
35 static VkInstance instance_cache[CHIP_LAST] = {VK_NULL_HANDLE};
36 static VkDevice device_cache[CHIP_LAST] = {VK_NULL_HANDLE};
37 static std::mutex create_device_mutex;
38 
39 #define FUNCTION_LIST                                                                              \
40    ITEM(CreateInstance)                                                                            \
41    ITEM(DestroyInstance)                                                                           \
42    ITEM(EnumeratePhysicalDevices)                                                                  \
43    ITEM(GetPhysicalDeviceProperties2)                                                              \
44    ITEM(CreateDevice)                                                                              \
45    ITEM(DestroyDevice)                                                                             \
46    ITEM(CreateShaderModule)                                                                        \
47    ITEM(DestroyShaderModule)                                                                       \
48    ITEM(CreateGraphicsPipelines)                                                                   \
49    ITEM(CreateComputePipelines)                                                                    \
50    ITEM(DestroyPipeline)                                                                           \
51    ITEM(CreateDescriptorSetLayout)                                                                 \
52    ITEM(DestroyDescriptorSetLayout)                                                                \
53    ITEM(CreatePipelineLayout)                                                                      \
54    ITEM(DestroyPipelineLayout)                                                                     \
55    ITEM(CreateRenderPass)                                                                          \
56    ITEM(DestroyRenderPass)                                                                         \
57    ITEM(GetPipelineExecutablePropertiesKHR)                                                        \
58    ITEM(GetPipelineExecutableInternalRepresentationsKHR)
59 
60 #define ITEM(n) PFN_vk##n n;
61 FUNCTION_LIST
62 #undef ITEM
63 
64 void
create_program(enum amd_gfx_level gfx_level,Stage stage,unsigned wave_size,enum radeon_family family)65 create_program(enum amd_gfx_level gfx_level, Stage stage, unsigned wave_size,
66                enum radeon_family family)
67 {
68    memset(&config, 0, sizeof(config));
69    info.wave_size = wave_size;
70 
71    program.reset(new Program);
72    aco::init_program(program.get(), stage, &info, gfx_level, family, false, &config);
73    program->workgroup_size = UINT_MAX;
74    calc_min_waves(program.get());
75 
76    program->debug.func = nullptr;
77    program->debug.private_data = nullptr;
78 
79    program->debug.output = output;
80    program->debug.shorten_messages = true;
81    program->debug.func = nullptr;
82    program->debug.private_data = nullptr;
83 
84    Block* block = program->create_and_insert_block();
85    block->kind = block_kind_top_level;
86 
87    bld = Builder(program.get(), &program->blocks[0]);
88 
89    config.float_mode = program->blocks[0].fp_mode.val;
90 }
91 
92 bool
setup_cs(const char * input_spec,enum amd_gfx_level gfx_level,enum radeon_family family,const char * subvariant,unsigned wave_size)93 setup_cs(const char* input_spec, enum amd_gfx_level gfx_level, enum radeon_family family,
94          const char* subvariant, unsigned wave_size)
95 {
96    if (!set_variant(gfx_level, subvariant))
97       return false;
98 
99    memset(&info, 0, sizeof(info));
100    create_program(gfx_level, compute_cs, wave_size, family);
101 
102    if (input_spec) {
103       std::vector<RegClass> input_classes;
104       while (input_spec[0]) {
105          RegType type = input_spec[0] == 'v' ? RegType::vgpr : RegType::sgpr;
106          unsigned size = input_spec[1] - '0';
107          bool in_bytes = input_spec[2] == 'b';
108          input_classes.push_back(RegClass::get(type, size * (in_bytes ? 1 : 4)));
109 
110          input_spec += 2 + in_bytes;
111          while (input_spec[0] == ' ')
112             input_spec++;
113       }
114 
115       aco_ptr<Instruction> startpgm{
116          create_instruction(aco_opcode::p_startpgm, Format::PSEUDO, 0, input_classes.size())};
117       for (unsigned i = 0; i < input_classes.size(); i++) {
118          inputs[i] = bld.tmp(input_classes[i]);
119          startpgm->definitions[i] = Definition(inputs[i]);
120       }
121       bld.insert(std::move(startpgm));
122    }
123 
124    return true;
125 }
126 
127 bool
setup_nir_cs(enum amd_gfx_level gfx_level,gl_shader_stage stage,enum radeon_family family,const char * subvariant)128 setup_nir_cs(enum amd_gfx_level gfx_level, gl_shader_stage stage, enum radeon_family family, const char* subvariant)
129 {
130    if (!set_variant(gfx_level, subvariant))
131       return false;
132 
133    if (family == CHIP_UNKNOWN) {
134       switch (gfx_level) {
135       case GFX6: family = CHIP_TAHITI; break;
136       case GFX7: family = CHIP_BONAIRE; break;
137       case GFX8: family = CHIP_POLARIS10; break;
138       case GFX9: family = CHIP_VEGA10; break;
139       case GFX10: family = CHIP_NAVI10; break;
140       case GFX10_3: family = CHIP_NAVI21; break;
141       case GFX11: family = CHIP_NAVI31; break;
142       default: family = CHIP_UNKNOWN; break;
143       }
144    }
145 
146    memset(&rad_info, 0, sizeof(rad_info));
147    rad_info.gfx_level = gfx_level;
148    rad_info.family = family;
149 
150    memset(&nir_options, 0, sizeof(nir_options));
151    ac_nir_set_options(&rad_info, false, &nir_options);
152 
153    glsl_type_singleton_init_or_ref();
154 
155    _nb = nir_builder_init_simple_shader(stage, &nir_options, "aco_test");
156    nb = &_nb;
157 
158    return true;
159 }
160 
161 void
finish_program(Program * prog,bool endpgm,bool dominance)162 finish_program(Program* prog, bool endpgm, bool dominance)
163 {
164    for (Block& BB : prog->blocks) {
165       for (unsigned idx : BB.linear_preds)
166          prog->blocks[idx].linear_succs.emplace_back(BB.index);
167       for (unsigned idx : BB.logical_preds)
168          prog->blocks[idx].logical_succs.emplace_back(BB.index);
169    }
170 
171    for (Block& block : prog->blocks) {
172       if (block.linear_succs.size() == 0) {
173          block.kind |= block_kind_uniform;
174          if (endpgm)
175             Builder(prog, &block).sopp(aco_opcode::s_endpgm);
176       }
177    }
178 
179    if (dominance)
180       dominator_tree(program.get());
181 }
182 
183 void
finish_validator_test()184 finish_validator_test()
185 {
186    finish_program(program.get(), true, true);
187    aco_print_program(program.get(), output);
188    fprintf(output, "Validation results:\n");
189    if (aco::validate_ir(program.get()))
190       fprintf(output, "Validation passed\n");
191    else
192       fprintf(output, "Validation failed\n");
193 }
194 
195 void
finish_opt_test()196 finish_opt_test()
197 {
198    finish_program(program.get(), true, true);
199    if (!aco::validate_ir(program.get())) {
200       fail_test("Validation before optimization failed");
201       return;
202    }
203    aco::optimize(program.get());
204    if (!aco::validate_ir(program.get())) {
205       fail_test("Validation after optimization failed");
206       return;
207    }
208    aco_print_program(program.get(), output);
209 }
210 
211 void
finish_setup_reduce_temp_test()212 finish_setup_reduce_temp_test()
213 {
214    finish_program(program.get(), true, true);
215    if (!aco::validate_ir(program.get())) {
216       fail_test("Validation before setup_reduce_temp failed");
217       return;
218    }
219    aco::setup_reduce_temp(program.get());
220    if (!aco::validate_ir(program.get())) {
221       fail_test("Validation after setup_reduce_temp failed");
222       return;
223    }
224    aco_print_program(program.get(), output);
225 }
226 
227 void
finish_lower_subdword_test()228 finish_lower_subdword_test()
229 {
230    finish_program(program.get(), true, true);
231    if (!aco::validate_ir(program.get())) {
232       fail_test("Validation before lower_subdword failed");
233       return;
234    }
235    aco::lower_subdword(program.get());
236    if (!aco::validate_ir(program.get())) {
237       fail_test("Validation after lower_subdword failed");
238       return;
239    }
240    aco_print_program(program.get(), output);
241 }
242 
243 void
finish_ra_test(ra_test_policy policy)244 finish_ra_test(ra_test_policy policy)
245 {
246    finish_program(program.get(), true, true);
247    if (!aco::validate_ir(program.get())) {
248       fail_test("Validation before register allocation failed");
249       return;
250    }
251 
252    program->workgroup_size = program->wave_size;
253    aco::live_var_analysis(program.get());
254    aco::register_allocation(program.get(), policy);
255 
256    if (aco::validate_ra(program.get())) {
257       fail_test("Validation after register allocation failed");
258       return;
259    }
260 
261    aco_print_program(program.get(), output);
262 }
263 
264 void
finish_optimizer_postRA_test()265 finish_optimizer_postRA_test()
266 {
267    finish_program(program.get(), true, true);
268 
269    if (!aco::validate_ir(program.get())) {
270       fail_test("Validation before optimize_postRA failed");
271       return;
272    }
273 
274    aco::optimize_postRA(program.get());
275 
276    if (!aco::validate_ir(program.get())) {
277       fail_test("Validation after optimize_postRA failed");
278       return;
279    }
280 
281    aco_print_program(program.get(), output);
282 }
283 
284 void
finish_to_hw_instr_test()285 finish_to_hw_instr_test()
286 {
287    finish_program(program.get(), true, true);
288 
289    if (!aco::validate_ir(program.get())) {
290       fail_test("Validation before lower_to_hw_instr failed");
291       return;
292    }
293 
294    aco::lower_to_hw_instr(program.get());
295 
296    if (!aco::validate_ir(program.get())) {
297       fail_test("Validation after lower_to_hw_instr failed");
298       return;
299    }
300 
301    aco_print_program(program.get(), output);
302 }
303 
304 void
finish_schedule_vopd_test()305 finish_schedule_vopd_test()
306 {
307    finish_program(program.get());
308    aco::schedule_vopd(program.get());
309    aco_print_program(program.get(), output);
310 }
311 
312 void
finish_waitcnt_test()313 finish_waitcnt_test()
314 {
315    finish_program(program.get());
316    aco::insert_waitcnt(program.get());
317    aco_print_program(program.get(), output);
318 }
319 
320 void
finish_insert_nops_test(bool endpgm)321 finish_insert_nops_test(bool endpgm)
322 {
323    finish_program(program.get(), endpgm);
324    aco::insert_NOPs(program.get());
325    aco_print_program(program.get(), output);
326 }
327 
328 void
finish_form_hard_clause_test()329 finish_form_hard_clause_test()
330 {
331    finish_program(program.get());
332    aco::form_hard_clauses(program.get());
333    aco_print_program(program.get(), output);
334 }
335 
336 void
finish_assembler_test()337 finish_assembler_test()
338 {
339    finish_program(program.get());
340    std::vector<uint32_t> binary;
341    unsigned exec_size = emit_program(program.get(), binary);
342 
343    /* we could use CLRX for disassembly but that would require it to be
344     * installed */
345    if (program->gfx_level >= GFX8) {
346       print_asm(program.get(), binary, exec_size / 4u, output);
347    } else {
348       // TODO: maybe we should use CLRX and skip this test if it's not available?
349       for (uint32_t dword : binary)
350          fprintf(output, "%.8x\n", dword);
351    }
352 }
353 
354 void
live_var_analysis_debug_func(void * private_data,enum aco_compiler_debug_level level,const char * message)355 live_var_analysis_debug_func(void* private_data, enum aco_compiler_debug_level level, const char* message)
356 {
357    if (level == ACO_COMPILER_DEBUG_LEVEL_ERROR)
358       *(bool *)private_data = true;
359 }
360 
361 void
finish_isel_test(enum ac_hw_stage hw_stage,unsigned wave_size)362 finish_isel_test(enum ac_hw_stage hw_stage, unsigned wave_size)
363 {
364    nir_validate_shader(nb->shader, "in finish_isel_test");
365 
366    program.reset(new Program);
367    program->debug.func = nullptr;
368    program->debug.private_data = nullptr;
369 
370    ac_shader_args args = {};
371 
372    aco_compiler_options options = {};
373    options.family = rad_info.family;
374    options.gfx_level = rad_info.gfx_level;
375 
376    memset(&info, 0, sizeof(info));
377    info.hw_stage = hw_stage;
378    info.wave_size = wave_size;
379    info.workgroup_size = nb->shader->info.workgroup_size[0] * nb->shader->info.workgroup_size[1] * nb->shader->info.workgroup_size[2];
380 
381    memset(&config, 0, sizeof(config));
382 
383    select_program(program.get(), 1, &nb->shader, &config, &options, &info, &args);
384    dominator_tree(program.get());
385    if (program->should_repair_ssa)
386       repair_ssa(program.get());
387    lower_phis(program.get());
388 
389    ralloc_free(nb->shader);
390    glsl_type_singleton_decref();
391 
392    aco_print_program(program.get(), output);
393 
394    if (!aco::validate_ir(program.get())) {
395       fail_test("Validation after instruction selection failed");
396       return;
397    }
398    if (!aco::validate_cfg(program.get())) {
399       fail_test("Invalidate CFG");
400       return;
401    }
402 
403    bool live_var_fail = false;
404    program->debug.func = &live_var_analysis_debug_func;
405    program->debug.private_data = &live_var_fail;
406    aco::live_var_analysis(program.get());
407    if (live_var_fail) {
408       fail_test("Live var analysis failed");
409       return;
410    }
411 }
412 
413 void
writeout(unsigned i,Temp tmp)414 writeout(unsigned i, Temp tmp)
415 {
416    if (tmp.id())
417       bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), tmp);
418    else
419       bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i));
420 }
421 
422 void
writeout(unsigned i,aco::Builder::Result res)423 writeout(unsigned i, aco::Builder::Result res)
424 {
425    bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), res);
426 }
427 
428 void
writeout(unsigned i,Operand op)429 writeout(unsigned i, Operand op)
430 {
431    bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), op);
432 }
433 
434 void
writeout(unsigned i,Operand op0,Operand op1)435 writeout(unsigned i, Operand op0, Operand op1)
436 {
437    bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), op0, op1);
438 }
439 
440 Temp
fneg(Temp src,Builder b)441 fneg(Temp src, Builder b)
442 {
443    if (src.bytes() == 2)
444       return b.vop2(aco_opcode::v_mul_f16, b.def(v2b), Operand::c16(0xbc00u), src);
445    else
446       return b.vop2(aco_opcode::v_mul_f32, b.def(v1), Operand::c32(0xbf800000u), src);
447 }
448 
449 Temp
fabs(Temp src,Builder b)450 fabs(Temp src, Builder b)
451 {
452    if (src.bytes() == 2) {
453       Builder::Result res =
454          b.vop2_e64(aco_opcode::v_mul_f16, b.def(v2b), Operand::c16(0x3c00), src);
455       res->valu().abs[1] = true;
456       return res;
457    } else {
458       Builder::Result res =
459          b.vop2_e64(aco_opcode::v_mul_f32, b.def(v1), Operand::c32(0x3f800000u), src);
460       res->valu().abs[1] = true;
461       return res;
462    }
463 }
464 
465 Temp
f2f32(Temp src,Builder b)466 f2f32(Temp src, Builder b)
467 {
468    return b.vop1(aco_opcode::v_cvt_f32_f16, b.def(v1), src);
469 }
470 
471 Temp
f2f16(Temp src,Builder b)472 f2f16(Temp src, Builder b)
473 {
474    return b.vop1(aco_opcode::v_cvt_f16_f32, b.def(v2b), src);
475 }
476 
477 Temp
u2u16(Temp src,Builder b)478 u2u16(Temp src, Builder b)
479 {
480    return b.pseudo(aco_opcode::p_extract_vector, b.def(v2b), src, Operand::zero());
481 }
482 
483 Temp
fadd(Temp src0,Temp src1,Builder b)484 fadd(Temp src0, Temp src1, Builder b)
485 {
486    if (src0.bytes() == 2)
487       return b.vop2(aco_opcode::v_add_f16, b.def(v2b), src0, src1);
488    else
489       return b.vop2(aco_opcode::v_add_f32, b.def(v1), src0, src1);
490 }
491 
492 Temp
fmul(Temp src0,Temp src1,Builder b)493 fmul(Temp src0, Temp src1, Builder b)
494 {
495    if (src0.bytes() == 2)
496       return b.vop2(aco_opcode::v_mul_f16, b.def(v2b), src0, src1);
497    else
498       return b.vop2(aco_opcode::v_mul_f32, b.def(v1), src0, src1);
499 }
500 
501 Temp
fma(Temp src0,Temp src1,Temp src2,Builder b)502 fma(Temp src0, Temp src1, Temp src2, Builder b)
503 {
504    if (src0.bytes() == 2)
505       return b.vop3(aco_opcode::v_fma_f16, b.def(v2b), src0, src1, src2);
506    else
507       return b.vop3(aco_opcode::v_fma_f32, b.def(v1), src0, src1, src2);
508 }
509 
510 Temp
fsat(Temp src,Builder b)511 fsat(Temp src, Builder b)
512 {
513    if (src.bytes() == 2)
514       return b.vop3(aco_opcode::v_med3_f16, b.def(v2b), Operand::c16(0u), Operand::c16(0x3c00u),
515                     src);
516    else
517       return b.vop3(aco_opcode::v_med3_f32, b.def(v1), Operand::zero(), Operand::c32(0x3f800000u),
518                     src);
519 }
520 
521 Temp
fmin(Temp src0,Temp src1,Builder b)522 fmin(Temp src0, Temp src1, Builder b)
523 {
524    return b.vop2(aco_opcode::v_min_f32, b.def(v1), src0, src1);
525 }
526 
527 Temp
fmax(Temp src0,Temp src1,Builder b)528 fmax(Temp src0, Temp src1, Builder b)
529 {
530    return b.vop2(aco_opcode::v_max_f32, b.def(v1), src0, src1);
531 }
532 
533 static Temp
extract(Temp src,unsigned idx,unsigned size,bool sign_extend,Builder b)534 extract(Temp src, unsigned idx, unsigned size, bool sign_extend, Builder b)
535 {
536    if (src.type() == RegType::sgpr)
537       return b.pseudo(aco_opcode::p_extract, b.def(src.regClass()), bld.def(s1, scc), src,
538                       Operand::c32(idx), Operand::c32(size), Operand::c32(sign_extend));
539    else
540       return b.pseudo(aco_opcode::p_extract, b.def(src.regClass()), src, Operand::c32(idx),
541                       Operand::c32(size), Operand::c32(sign_extend));
542 }
543 
544 Temp
ext_ushort(Temp src,unsigned idx,Builder b)545 ext_ushort(Temp src, unsigned idx, Builder b)
546 {
547    return extract(src, idx, 16, false, b);
548 }
549 
550 Temp
ext_sshort(Temp src,unsigned idx,Builder b)551 ext_sshort(Temp src, unsigned idx, Builder b)
552 {
553    return extract(src, idx, 16, true, b);
554 }
555 
556 Temp
ext_ubyte(Temp src,unsigned idx,Builder b)557 ext_ubyte(Temp src, unsigned idx, Builder b)
558 {
559    return extract(src, idx, 8, false, b);
560 }
561 
562 Temp
ext_sbyte(Temp src,unsigned idx,Builder b)563 ext_sbyte(Temp src, unsigned idx, Builder b)
564 {
565    return extract(src, idx, 8, true, b);
566 }
567 
568 void
emit_divergent_if_else(Program * prog,aco::Builder & b,Operand cond,std::function<void ()> then,std::function<void ()> els)569 emit_divergent_if_else(Program* prog, aco::Builder& b, Operand cond, std::function<void()> then,
570                        std::function<void()> els)
571 {
572    prog->blocks.reserve(prog->blocks.size() + 6);
573 
574    Block* if_block = &prog->blocks.back();
575    Block* then_logical = prog->create_and_insert_block();
576    Block* then_linear = prog->create_and_insert_block();
577    Block* invert = prog->create_and_insert_block();
578    Block* else_logical = prog->create_and_insert_block();
579    Block* else_linear = prog->create_and_insert_block();
580    Block* endif_block = prog->create_and_insert_block();
581 
582    if_block->kind |= block_kind_branch;
583    invert->kind |= block_kind_invert;
584    endif_block->kind |= block_kind_merge | (if_block->kind & block_kind_top_level);
585 
586    /* Set up logical CF */
587    then_logical->logical_preds.push_back(if_block->index);
588    else_logical->logical_preds.push_back(if_block->index);
589    endif_block->logical_preds.push_back(then_logical->index);
590    endif_block->logical_preds.push_back(else_logical->index);
591 
592    /* Set up linear CF */
593    then_logical->linear_preds.push_back(if_block->index);
594    then_linear->linear_preds.push_back(if_block->index);
595    invert->linear_preds.push_back(then_logical->index);
596    invert->linear_preds.push_back(then_linear->index);
597    else_logical->linear_preds.push_back(invert->index);
598    else_linear->linear_preds.push_back(invert->index);
599    endif_block->linear_preds.push_back(else_logical->index);
600    endif_block->linear_preds.push_back(else_linear->index);
601 
602    PhysReg saved_exec_reg(84);
603 
604    b.reset(if_block);
605    Temp saved_exec = b.sop1(Builder::s_and_saveexec, b.def(b.lm, saved_exec_reg),
606                             Definition(scc, s1), Definition(exec, b.lm), cond, Operand(exec, b.lm));
607    b.branch(aco_opcode::p_cbranch_nz, then_logical->index, then_linear->index);
608 
609    b.reset(then_logical);
610    b.pseudo(aco_opcode::p_logical_start);
611    then();
612    b.pseudo(aco_opcode::p_logical_end);
613    b.branch(aco_opcode::p_branch, invert->index);
614 
615    b.reset(then_linear);
616    b.branch(aco_opcode::p_branch, invert->index);
617 
618    b.reset(invert);
619    b.sop2(Builder::s_andn2, Definition(exec, bld.lm), Definition(scc, s1),
620           Operand(saved_exec, saved_exec_reg), Operand(exec, bld.lm));
621    b.branch(aco_opcode::p_cbranch_nz, else_logical->index, else_linear->index);
622 
623    b.reset(else_logical);
624    b.pseudo(aco_opcode::p_logical_start);
625    els();
626    b.pseudo(aco_opcode::p_logical_end);
627    b.branch(aco_opcode::p_branch, endif_block->index);
628 
629    b.reset(else_linear);
630    b.branch(aco_opcode::p_branch, endif_block->index);
631 
632    b.reset(endif_block);
633    b.pseudo(aco_opcode::p_parallelcopy, Definition(exec, bld.lm),
634             Operand(saved_exec, saved_exec_reg));
635 }
636 
637 VkDevice
get_vk_device(enum amd_gfx_level gfx_level)638 get_vk_device(enum amd_gfx_level gfx_level)
639 {
640    enum radeon_family family;
641    switch (gfx_level) {
642    case GFX6: family = CHIP_TAHITI; break;
643    case GFX7: family = CHIP_BONAIRE; break;
644    case GFX8: family = CHIP_POLARIS10; break;
645    case GFX9: family = CHIP_VEGA10; break;
646    case GFX10: family = CHIP_NAVI10; break;
647    case GFX10_3: family = CHIP_NAVI21; break;
648    case GFX11: family = CHIP_NAVI31; break;
649    case GFX12: family = CHIP_GFX1200; break;
650    default: family = CHIP_UNKNOWN; break;
651    }
652    return get_vk_device(family);
653 }
654 
655 VkDevice
get_vk_device(enum radeon_family family)656 get_vk_device(enum radeon_family family)
657 {
658    assert(family != CHIP_UNKNOWN);
659 
660    std::lock_guard<std::mutex> guard(create_device_mutex);
661 
662    if (device_cache[family])
663       return device_cache[family];
664 
665    setenv("RADV_FORCE_FAMILY", ac_get_family_name(family), 1);
666 
667    VkApplicationInfo app_info = {};
668    app_info.pApplicationName = "aco_tests";
669    app_info.apiVersion = VK_API_VERSION_1_2;
670    VkInstanceCreateInfo instance_create_info = {};
671    instance_create_info.pApplicationInfo = &app_info;
672    instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
673    ASSERTED VkResult result = ((PFN_vkCreateInstance)vk_icdGetInstanceProcAddr(
674       NULL, "vkCreateInstance"))(&instance_create_info, NULL, &instance_cache[family]);
675    assert(result == VK_SUCCESS);
676 
677 #define ITEM(n) n = (PFN_vk##n)vk_icdGetInstanceProcAddr(instance_cache[family], "vk" #n);
678    FUNCTION_LIST
679 #undef ITEM
680 
681    uint32_t device_count = 1;
682    VkPhysicalDevice device = VK_NULL_HANDLE;
683    result = EnumeratePhysicalDevices(instance_cache[family], &device_count, &device);
684    assert(result == VK_SUCCESS);
685    assert(device != VK_NULL_HANDLE);
686 
687    VkDeviceCreateInfo device_create_info = {};
688    device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
689    static const char* extensions[] = {"VK_KHR_pipeline_executable_properties"};
690    device_create_info.enabledExtensionCount = sizeof(extensions) / sizeof(extensions[0]);
691    device_create_info.ppEnabledExtensionNames = extensions;
692    result = CreateDevice(device, &device_create_info, NULL, &device_cache[family]);
693 
694    return device_cache[family];
695 }
696 
697 static struct DestroyDevices {
~DestroyDevicesDestroyDevices698    ~DestroyDevices()
699    {
700       for (unsigned i = 0; i < CHIP_LAST; i++) {
701          if (!device_cache[i])
702             continue;
703          DestroyDevice(device_cache[i], NULL);
704          DestroyInstance(instance_cache[i], NULL);
705       }
706    }
707 } destroy_devices;
708 
709 void
print_pipeline_ir(VkDevice device,VkPipeline pipeline,VkShaderStageFlagBits stages,const char * name,bool remove_encoding)710 print_pipeline_ir(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits stages,
711                   const char* name, bool remove_encoding)
712 {
713    uint32_t executable_count = 16;
714    VkPipelineExecutablePropertiesKHR executables[16];
715    VkPipelineInfoKHR pipeline_info;
716    pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR;
717    pipeline_info.pNext = NULL;
718    pipeline_info.pipeline = pipeline;
719    ASSERTED VkResult result =
720       GetPipelineExecutablePropertiesKHR(device, &pipeline_info, &executable_count, executables);
721    assert(result == VK_SUCCESS);
722 
723    uint32_t executable = 0;
724    for (; executable < executable_count; executable++) {
725       if (executables[executable].stages == stages)
726          break;
727    }
728    assert(executable != executable_count);
729 
730    VkPipelineExecutableInfoKHR exec_info;
731    exec_info.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR;
732    exec_info.pNext = NULL;
733    exec_info.pipeline = pipeline;
734    exec_info.executableIndex = executable;
735 
736    uint32_t ir_count = 16;
737    VkPipelineExecutableInternalRepresentationKHR ir[16];
738    memset(ir, 0, sizeof(ir));
739    result = GetPipelineExecutableInternalRepresentationsKHR(device, &exec_info, &ir_count, ir);
740    assert(result == VK_SUCCESS);
741 
742    VkPipelineExecutableInternalRepresentationKHR* requested_ir = nullptr;
743    for (unsigned i = 0; i < ir_count; ++i) {
744       if (strcmp(ir[i].name, name) == 0) {
745          requested_ir = &ir[i];
746          break;
747       }
748    }
749    assert(requested_ir && "Could not find requested IR");
750 
751    char* data = (char*)malloc(requested_ir->dataSize);
752    requested_ir->pData = data;
753    result = GetPipelineExecutableInternalRepresentationsKHR(device, &exec_info, &ir_count, ir);
754    assert(result == VK_SUCCESS);
755 
756    if (remove_encoding) {
757       for (char* c = data; *c; c++) {
758          if (*c == ';') {
759             for (; *c && *c != '\n'; c++)
760                *c = ' ';
761          }
762       }
763    }
764 
765    fprintf(output, "%s", data);
766    free(data);
767 }
768 
769 VkShaderModule
__qoCreateShaderModule(VkDevice dev,const QoShaderModuleCreateInfo * module_info)770 __qoCreateShaderModule(VkDevice dev, const QoShaderModuleCreateInfo* module_info)
771 {
772    VkShaderModuleCreateInfo vk_module_info;
773    vk_module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
774    vk_module_info.pNext = NULL;
775    vk_module_info.flags = 0;
776    vk_module_info.codeSize = module_info->spirvSize;
777    vk_module_info.pCode = (const uint32_t*)module_info->pSpirv;
778 
779    VkShaderModule module;
780    ASSERTED VkResult result = CreateShaderModule(dev, &vk_module_info, NULL, &module);
781    assert(result == VK_SUCCESS);
782 
783    return module;
784 }
785 
PipelineBuilder(VkDevice dev)786 PipelineBuilder::PipelineBuilder(VkDevice dev)
787 {
788    memset(this, 0, sizeof(*this));
789    topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
790    device = dev;
791 }
792 
~PipelineBuilder()793 PipelineBuilder::~PipelineBuilder()
794 {
795    DestroyPipeline(device, pipeline, NULL);
796 
797    for (unsigned i = 0; i < (is_compute() ? 1 : gfx_pipeline_info.stageCount); i++) {
798       VkPipelineShaderStageCreateInfo* stage_info = &stages[i];
799       if (owned_stages & stage_info->stage)
800          DestroyShaderModule(device, stage_info->module, NULL);
801    }
802 
803    DestroyPipelineLayout(device, pipeline_layout, NULL);
804 
805    for (unsigned i = 0; i < util_bitcount64(desc_layouts_used); i++)
806       DestroyDescriptorSetLayout(device, desc_layouts[i], NULL);
807 
808    DestroyRenderPass(device, render_pass, NULL);
809 }
810 
811 void
add_desc_binding(VkShaderStageFlags stage_flags,uint32_t layout,uint32_t binding,VkDescriptorType type,uint32_t count)812 PipelineBuilder::add_desc_binding(VkShaderStageFlags stage_flags, uint32_t layout, uint32_t binding,
813                                   VkDescriptorType type, uint32_t count)
814 {
815    desc_layouts_used |= 1ull << layout;
816    desc_bindings[layout][num_desc_bindings[layout]++] = {binding, type, count, stage_flags, NULL};
817 }
818 
819 void
add_vertex_binding(uint32_t binding,uint32_t stride,VkVertexInputRate rate)820 PipelineBuilder::add_vertex_binding(uint32_t binding, uint32_t stride, VkVertexInputRate rate)
821 {
822    vs_bindings[vs_input.vertexBindingDescriptionCount++] = {binding, stride, rate};
823 }
824 
825 void
add_vertex_attribute(uint32_t location,uint32_t binding,VkFormat format,uint32_t offset)826 PipelineBuilder::add_vertex_attribute(uint32_t location, uint32_t binding, VkFormat format,
827                                       uint32_t offset)
828 {
829    vs_attributes[vs_input.vertexAttributeDescriptionCount++] = {location, binding, format, offset};
830 }
831 
832 void
add_resource_decls(QoShaderModuleCreateInfo * module)833 PipelineBuilder::add_resource_decls(QoShaderModuleCreateInfo* module)
834 {
835    for (unsigned i = 0; i < module->declarationCount; i++) {
836       const QoShaderDecl* decl = &module->pDeclarations[i];
837       switch (decl->decl_type) {
838       case QoShaderDeclType_ubo:
839          add_desc_binding(module->stage, decl->set, decl->binding,
840                           VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
841          break;
842       case QoShaderDeclType_ssbo:
843          add_desc_binding(module->stage, decl->set, decl->binding,
844                           VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
845          break;
846       case QoShaderDeclType_img_buf:
847          add_desc_binding(module->stage, decl->set, decl->binding,
848                           VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
849          break;
850       case QoShaderDeclType_img:
851          add_desc_binding(module->stage, decl->set, decl->binding,
852                           VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
853          break;
854       case QoShaderDeclType_tex_buf:
855          add_desc_binding(module->stage, decl->set, decl->binding,
856                           VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);
857          break;
858       case QoShaderDeclType_combined:
859          add_desc_binding(module->stage, decl->set, decl->binding,
860                           VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
861          break;
862       case QoShaderDeclType_tex:
863          add_desc_binding(module->stage, decl->set, decl->binding,
864                           VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
865          break;
866       case QoShaderDeclType_samp:
867          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_SAMPLER);
868          break;
869       default: break;
870       }
871    }
872 }
873 
874 void
add_io_decls(QoShaderModuleCreateInfo * module)875 PipelineBuilder::add_io_decls(QoShaderModuleCreateInfo* module)
876 {
877    unsigned next_vtx_offset = 0;
878    for (unsigned i = 0; i < module->declarationCount; i++) {
879       const QoShaderDecl* decl = &module->pDeclarations[i];
880       switch (decl->decl_type) {
881       case QoShaderDeclType_in:
882          if (module->stage == VK_SHADER_STAGE_VERTEX_BIT) {
883             if (!strcmp(decl->type, "float") || decl->type[0] == 'v')
884                add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_SFLOAT,
885                                     next_vtx_offset);
886             else if (decl->type[0] == 'u')
887                add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_UINT,
888                                     next_vtx_offset);
889             else if (decl->type[0] == 'i')
890                add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_SINT,
891                                     next_vtx_offset);
892             next_vtx_offset += 16;
893          }
894          break;
895       case QoShaderDeclType_out:
896          if (module->stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
897             if (!strcmp(decl->type, "float") || decl->type[0] == 'v')
898                color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_SFLOAT;
899             else if (decl->type[0] == 'u')
900                color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_UINT;
901             else if (decl->type[0] == 'i')
902                color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_SINT;
903          }
904          break;
905       default: break;
906       }
907    }
908    if (next_vtx_offset)
909       add_vertex_binding(0, next_vtx_offset);
910 }
911 
912 void
add_stage(VkShaderStageFlagBits stage,VkShaderModule module,const char * name)913 PipelineBuilder::add_stage(VkShaderStageFlagBits stage, VkShaderModule module, const char* name)
914 {
915    VkPipelineShaderStageCreateInfo* stage_info;
916    if (stage == VK_SHADER_STAGE_COMPUTE_BIT)
917       stage_info = &stages[0];
918    else
919       stage_info = &stages[gfx_pipeline_info.stageCount++];
920    stage_info->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
921    stage_info->pNext = NULL;
922    stage_info->flags = 0;
923    stage_info->stage = stage;
924    stage_info->module = module;
925    stage_info->pName = name;
926    stage_info->pSpecializationInfo = NULL;
927    owned_stages |= stage;
928 }
929 
930 void
add_stage(VkShaderStageFlagBits stage,QoShaderModuleCreateInfo module,const char * name)931 PipelineBuilder::add_stage(VkShaderStageFlagBits stage, QoShaderModuleCreateInfo module,
932                            const char* name)
933 {
934    add_stage(stage, __qoCreateShaderModule(device, &module), name);
935    add_resource_decls(&module);
936    add_io_decls(&module);
937 }
938 
939 void
add_vsfs(VkShaderModule vs,VkShaderModule fs)940 PipelineBuilder::add_vsfs(VkShaderModule vs, VkShaderModule fs)
941 {
942    add_stage(VK_SHADER_STAGE_VERTEX_BIT, vs);
943    add_stage(VK_SHADER_STAGE_FRAGMENT_BIT, fs);
944 }
945 
946 void
add_vsfs(QoShaderModuleCreateInfo vs,QoShaderModuleCreateInfo fs)947 PipelineBuilder::add_vsfs(QoShaderModuleCreateInfo vs, QoShaderModuleCreateInfo fs)
948 {
949    add_stage(VK_SHADER_STAGE_VERTEX_BIT, vs);
950    add_stage(VK_SHADER_STAGE_FRAGMENT_BIT, fs);
951 }
952 
953 void
add_cs(VkShaderModule cs)954 PipelineBuilder::add_cs(VkShaderModule cs)
955 {
956    add_stage(VK_SHADER_STAGE_COMPUTE_BIT, cs);
957 }
958 
959 void
add_cs(QoShaderModuleCreateInfo cs)960 PipelineBuilder::add_cs(QoShaderModuleCreateInfo cs)
961 {
962    add_stage(VK_SHADER_STAGE_COMPUTE_BIT, cs);
963 }
964 
965 bool
is_compute()966 PipelineBuilder::is_compute()
967 {
968    return gfx_pipeline_info.stageCount == 0;
969 }
970 
971 void
create_compute_pipeline()972 PipelineBuilder::create_compute_pipeline()
973 {
974    VkComputePipelineCreateInfo create_info;
975    create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
976    create_info.pNext = NULL;
977    create_info.flags = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
978    create_info.stage = stages[0];
979    create_info.layout = pipeline_layout;
980    create_info.basePipelineHandle = VK_NULL_HANDLE;
981    create_info.basePipelineIndex = 0;
982 
983    ASSERTED VkResult result =
984       CreateComputePipelines(device, VK_NULL_HANDLE, 1, &create_info, NULL, &pipeline);
985    assert(result == VK_SUCCESS);
986 }
987 
988 void
create_graphics_pipeline()989 PipelineBuilder::create_graphics_pipeline()
990 {
991    /* create the create infos */
992    if (!samples)
993       samples = VK_SAMPLE_COUNT_1_BIT;
994 
995    unsigned num_color_attachments = 0;
996    VkPipelineColorBlendAttachmentState blend_attachment_states[16];
997    VkAttachmentReference color_attachments[16];
998    VkAttachmentDescription attachment_descs[17];
999    for (unsigned i = 0; i < 16; i++) {
1000       if (color_outputs[i] == VK_FORMAT_UNDEFINED)
1001          continue;
1002 
1003       VkAttachmentDescription* desc = &attachment_descs[num_color_attachments];
1004       desc->flags = 0;
1005       desc->format = color_outputs[i];
1006       desc->samples = samples;
1007       desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1008       desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1009       desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1010       desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1011       desc->initialLayout = VK_IMAGE_LAYOUT_GENERAL;
1012       desc->finalLayout = VK_IMAGE_LAYOUT_GENERAL;
1013 
1014       VkAttachmentReference* ref = &color_attachments[num_color_attachments];
1015       ref->attachment = num_color_attachments;
1016       ref->layout = VK_IMAGE_LAYOUT_GENERAL;
1017 
1018       VkPipelineColorBlendAttachmentState* blend = &blend_attachment_states[num_color_attachments];
1019       blend->blendEnable = false;
1020       blend->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
1021                               VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
1022 
1023       num_color_attachments++;
1024    }
1025 
1026    unsigned num_attachments = num_color_attachments;
1027    VkAttachmentReference ds_attachment;
1028    if (ds_output != VK_FORMAT_UNDEFINED) {
1029       VkAttachmentDescription* desc = &attachment_descs[num_attachments];
1030       desc->flags = 0;
1031       desc->format = ds_output;
1032       desc->samples = samples;
1033       desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1034       desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1035       desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1036       desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1037       desc->initialLayout = VK_IMAGE_LAYOUT_GENERAL;
1038       desc->finalLayout = VK_IMAGE_LAYOUT_GENERAL;
1039 
1040       ds_attachment.attachment = num_color_attachments;
1041       ds_attachment.layout = VK_IMAGE_LAYOUT_GENERAL;
1042 
1043       num_attachments++;
1044    }
1045 
1046    vs_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1047    vs_input.pNext = NULL;
1048    vs_input.flags = 0;
1049    vs_input.pVertexBindingDescriptions = vs_bindings;
1050    vs_input.pVertexAttributeDescriptions = vs_attributes;
1051 
1052    VkPipelineInputAssemblyStateCreateInfo assembly_state;
1053    assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1054    assembly_state.pNext = NULL;
1055    assembly_state.flags = 0;
1056    assembly_state.topology = topology;
1057    assembly_state.primitiveRestartEnable = false;
1058 
1059    VkPipelineTessellationStateCreateInfo tess_state;
1060    tess_state.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
1061    tess_state.pNext = NULL;
1062    tess_state.flags = 0;
1063    tess_state.patchControlPoints = patch_size;
1064 
1065    VkPipelineViewportStateCreateInfo viewport_state;
1066    viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1067    viewport_state.pNext = NULL;
1068    viewport_state.flags = 0;
1069    viewport_state.viewportCount = 1;
1070    viewport_state.pViewports = NULL;
1071    viewport_state.scissorCount = 1;
1072    viewport_state.pScissors = NULL;
1073 
1074    VkPipelineRasterizationStateCreateInfo rasterization_state;
1075    rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1076    rasterization_state.pNext = NULL;
1077    rasterization_state.flags = 0;
1078    rasterization_state.depthClampEnable = false;
1079    rasterization_state.rasterizerDiscardEnable = false;
1080    rasterization_state.polygonMode = VK_POLYGON_MODE_FILL;
1081    rasterization_state.cullMode = VK_CULL_MODE_NONE;
1082    rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
1083    rasterization_state.depthBiasEnable = false;
1084    rasterization_state.lineWidth = 1.0;
1085 
1086    VkPipelineMultisampleStateCreateInfo ms_state;
1087    ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1088    ms_state.pNext = NULL;
1089    ms_state.flags = 0;
1090    ms_state.rasterizationSamples = samples;
1091    ms_state.sampleShadingEnable = sample_shading_enable;
1092    ms_state.minSampleShading = min_sample_shading;
1093    VkSampleMask sample_mask = 0xffffffff;
1094    ms_state.pSampleMask = &sample_mask;
1095    ms_state.alphaToCoverageEnable = false;
1096    ms_state.alphaToOneEnable = false;
1097 
1098    VkPipelineDepthStencilStateCreateInfo ds_state;
1099    ds_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1100    ds_state.pNext = NULL;
1101    ds_state.flags = 0;
1102    ds_state.depthTestEnable = ds_output != VK_FORMAT_UNDEFINED;
1103    ds_state.depthWriteEnable = true;
1104    ds_state.depthCompareOp = VK_COMPARE_OP_ALWAYS;
1105    ds_state.depthBoundsTestEnable = false;
1106    ds_state.stencilTestEnable = true;
1107    ds_state.front.failOp = VK_STENCIL_OP_KEEP;
1108    ds_state.front.passOp = VK_STENCIL_OP_REPLACE;
1109    ds_state.front.depthFailOp = VK_STENCIL_OP_REPLACE;
1110    ds_state.front.compareOp = VK_COMPARE_OP_ALWAYS;
1111    ds_state.front.compareMask = 0xffffffff, ds_state.front.writeMask = 0;
1112    ds_state.front.reference = 0;
1113    ds_state.back = ds_state.front;
1114 
1115    VkPipelineColorBlendStateCreateInfo color_blend_state;
1116    color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1117    color_blend_state.pNext = NULL;
1118    color_blend_state.flags = 0;
1119    color_blend_state.logicOpEnable = false;
1120    color_blend_state.attachmentCount = num_color_attachments;
1121    color_blend_state.pAttachments = blend_attachment_states;
1122 
1123    VkDynamicState dynamic_states[9] = {VK_DYNAMIC_STATE_VIEWPORT,
1124                                        VK_DYNAMIC_STATE_SCISSOR,
1125                                        VK_DYNAMIC_STATE_LINE_WIDTH,
1126                                        VK_DYNAMIC_STATE_DEPTH_BIAS,
1127                                        VK_DYNAMIC_STATE_BLEND_CONSTANTS,
1128                                        VK_DYNAMIC_STATE_DEPTH_BOUNDS,
1129                                        VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
1130                                        VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
1131                                        VK_DYNAMIC_STATE_STENCIL_REFERENCE};
1132 
1133    VkPipelineDynamicStateCreateInfo dynamic_state;
1134    dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1135    dynamic_state.pNext = NULL;
1136    dynamic_state.flags = 0;
1137    dynamic_state.dynamicStateCount = sizeof(dynamic_states) / sizeof(VkDynamicState);
1138    dynamic_state.pDynamicStates = dynamic_states;
1139 
1140    gfx_pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1141    gfx_pipeline_info.pNext = NULL;
1142    gfx_pipeline_info.flags = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
1143    gfx_pipeline_info.pVertexInputState = &vs_input;
1144    gfx_pipeline_info.pInputAssemblyState = &assembly_state;
1145    gfx_pipeline_info.pTessellationState = &tess_state;
1146    gfx_pipeline_info.pViewportState = &viewport_state;
1147    gfx_pipeline_info.pRasterizationState = &rasterization_state;
1148    gfx_pipeline_info.pMultisampleState = &ms_state;
1149    gfx_pipeline_info.pDepthStencilState = &ds_state;
1150    gfx_pipeline_info.pColorBlendState = &color_blend_state;
1151    gfx_pipeline_info.pDynamicState = &dynamic_state;
1152    gfx_pipeline_info.subpass = 0;
1153 
1154    /* create the objects used to create the pipeline */
1155    VkSubpassDescription subpass;
1156    subpass.flags = 0;
1157    subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1158    subpass.inputAttachmentCount = 0;
1159    subpass.pInputAttachments = NULL;
1160    subpass.colorAttachmentCount = num_color_attachments;
1161    subpass.pColorAttachments = color_attachments;
1162    subpass.pResolveAttachments = NULL;
1163    subpass.pDepthStencilAttachment = ds_output == VK_FORMAT_UNDEFINED ? NULL : &ds_attachment;
1164    subpass.preserveAttachmentCount = 0;
1165    subpass.pPreserveAttachments = NULL;
1166 
1167    VkRenderPassCreateInfo renderpass_info;
1168    renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1169    renderpass_info.pNext = NULL;
1170    renderpass_info.flags = 0;
1171    renderpass_info.attachmentCount = num_attachments;
1172    renderpass_info.pAttachments = attachment_descs;
1173    renderpass_info.subpassCount = 1;
1174    renderpass_info.pSubpasses = &subpass;
1175    renderpass_info.dependencyCount = 0;
1176    renderpass_info.pDependencies = NULL;
1177 
1178    ASSERTED VkResult result = CreateRenderPass(device, &renderpass_info, NULL, &render_pass);
1179    assert(result == VK_SUCCESS);
1180 
1181    gfx_pipeline_info.layout = pipeline_layout;
1182    gfx_pipeline_info.renderPass = render_pass;
1183 
1184    /* create the pipeline */
1185    gfx_pipeline_info.pStages = stages;
1186 
1187    result = CreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &gfx_pipeline_info, NULL, &pipeline);
1188    assert(result == VK_SUCCESS);
1189 }
1190 
1191 void
create_pipeline()1192 PipelineBuilder::create_pipeline()
1193 {
1194    unsigned num_desc_layouts = 0;
1195    for (unsigned i = 0; i < 64; i++) {
1196       if (!(desc_layouts_used & (1ull << i)))
1197          continue;
1198 
1199       VkDescriptorSetLayoutCreateInfo desc_layout_info;
1200       desc_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
1201       desc_layout_info.pNext = NULL;
1202       desc_layout_info.flags = 0;
1203       desc_layout_info.bindingCount = num_desc_bindings[i];
1204       desc_layout_info.pBindings = desc_bindings[i];
1205 
1206       ASSERTED VkResult result = CreateDescriptorSetLayout(device, &desc_layout_info, NULL,
1207                                                            &desc_layouts[num_desc_layouts]);
1208       assert(result == VK_SUCCESS);
1209       num_desc_layouts++;
1210    }
1211 
1212    VkPipelineLayoutCreateInfo pipeline_layout_info;
1213    pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1214    pipeline_layout_info.pNext = NULL;
1215    pipeline_layout_info.flags = 0;
1216    pipeline_layout_info.pushConstantRangeCount = 1;
1217    pipeline_layout_info.pPushConstantRanges = &push_constant_range;
1218    pipeline_layout_info.setLayoutCount = num_desc_layouts;
1219    pipeline_layout_info.pSetLayouts = desc_layouts;
1220 
1221    ASSERTED VkResult result =
1222       CreatePipelineLayout(device, &pipeline_layout_info, NULL, &pipeline_layout);
1223    assert(result == VK_SUCCESS);
1224 
1225    if (is_compute())
1226       create_compute_pipeline();
1227    else
1228       create_graphics_pipeline();
1229 }
1230 
1231 void
print_ir(VkShaderStageFlagBits stage_flags,const char * name,bool remove_encoding)1232 PipelineBuilder::print_ir(VkShaderStageFlagBits stage_flags, const char* name, bool remove_encoding)
1233 {
1234    if (!pipeline)
1235       create_pipeline();
1236    print_pipeline_ir(device, pipeline, stage_flags, name, remove_encoding);
1237 }
1238