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