• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2020 Valve Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
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
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24 #include "helpers.h"
25 #include "vulkan/vk_format.h"
26 #include "llvm/ac_llvm_util.h"
27 #include <stdio.h>
28 #include <sstream>
29 #include <llvm-c/Target.h>
30 #include <mutex>
31 
32 using namespace aco;
33 
34 extern "C" {
35 PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
36 	VkInstance                                  instance,
37 	const char*                                 pName);
38 }
39 
40 ac_shader_config config;
41 radv_shader_info info;
42 std::unique_ptr<Program> program;
43 Builder bld(NULL);
44 Temp inputs[16];
45 Temp exec_input;
46 const char *subvariant = "";
47 
48 static VkInstance instance_cache[CHIP_LAST] = {VK_NULL_HANDLE};
49 static VkDevice device_cache[CHIP_LAST] = {VK_NULL_HANDLE};
50 static std::mutex create_device_mutex;
51 
52 #define FUNCTION_LIST\
53    ITEM(CreateInstance)\
54    ITEM(DestroyInstance)\
55    ITEM(EnumeratePhysicalDevices)\
56    ITEM(GetPhysicalDeviceProperties2)\
57    ITEM(CreateDevice)\
58    ITEM(DestroyDevice)\
59    ITEM(CreateShaderModule)\
60    ITEM(DestroyShaderModule)\
61    ITEM(CreateGraphicsPipelines)\
62    ITEM(CreateComputePipelines)\
63    ITEM(DestroyPipeline)\
64    ITEM(CreateDescriptorSetLayout)\
65    ITEM(DestroyDescriptorSetLayout)\
66    ITEM(CreatePipelineLayout)\
67    ITEM(DestroyPipelineLayout)\
68    ITEM(CreateRenderPass)\
69    ITEM(DestroyRenderPass)\
70    ITEM(GetPipelineExecutablePropertiesKHR)\
71    ITEM(GetPipelineExecutableInternalRepresentationsKHR)
72 
73 #define ITEM(n) PFN_vk##n n;
74 FUNCTION_LIST
75 #undef ITEM
76 
create_program(enum chip_class chip_class,Stage stage,unsigned wave_size,enum radeon_family family)77 void create_program(enum chip_class chip_class, Stage stage, unsigned wave_size, enum radeon_family family)
78 {
79    memset(&config, 0, sizeof(config));
80    info.wave_size = wave_size;
81 
82    program.reset(new Program);
83    aco::init_program(program.get(), stage, &info, chip_class, family, &config);
84 
85    Block *block = program->create_and_insert_block();
86    block->kind = block_kind_top_level;
87 
88    bld = Builder(program.get(), &program->blocks[0]);
89 
90    config.float_mode = program->blocks[0].fp_mode.val;
91 }
92 
setup_cs(const char * input_spec,enum chip_class chip_class,enum radeon_family family,unsigned wave_size)93 bool setup_cs(const char *input_spec, enum chip_class chip_class,
94               enum radeon_family family, unsigned wave_size)
95 {
96    const char *old_subvariant = subvariant;
97    subvariant = "";
98    if (!set_variant(chip_class, old_subvariant))
99       return false;
100 
101    memset(&info, 0, sizeof(info));
102    info.cs.block_size[0] = 1;
103    info.cs.block_size[1] = 1;
104    info.cs.block_size[2] = 1;
105 
106    create_program(chip_class, compute_cs, wave_size, family);
107 
108    if (input_spec) {
109       unsigned num_inputs = DIV_ROUND_UP(strlen(input_spec), 3u);
110       aco_ptr<Instruction> startpgm{create_instruction<Pseudo_instruction>(aco_opcode::p_startpgm, Format::PSEUDO, 0, num_inputs + 1)};
111       for (unsigned i = 0; i < num_inputs; i++) {
112          RegClass cls(input_spec[i * 3] == 'v' ? RegType::vgpr : RegType::sgpr, input_spec[i * 3 + 1] - '0');
113          inputs[i] = bld.tmp(cls);
114          startpgm->definitions[i] = Definition(inputs[i]);
115       }
116       exec_input = bld.tmp(program->lane_mask);
117       startpgm->definitions[num_inputs] = bld.exec(Definition(exec_input));
118       bld.insert(std::move(startpgm));
119    }
120 
121    return true;
122 }
123 
finish_program(Program * program)124 void finish_program(Program *program)
125 {
126    for (Block& BB : program->blocks) {
127       for (unsigned idx : BB.linear_preds)
128          program->blocks[idx].linear_succs.emplace_back(BB.index);
129       for (unsigned idx : BB.logical_preds)
130          program->blocks[idx].logical_succs.emplace_back(BB.index);
131    }
132 
133    for (Block& block : program->blocks) {
134       if (block.linear_succs.size() == 0) {
135          block.kind |= block_kind_uniform;
136          Builder bld(program, &block);
137          if (program->wb_smem_l1_on_end)
138             bld.smem(aco_opcode::s_dcache_wb, false);
139          bld.sopp(aco_opcode::s_endpgm);
140       }
141    }
142 }
143 
finish_validator_test()144 void finish_validator_test()
145 {
146    finish_program(program.get());
147    aco_print_program(program.get(), output);
148    fprintf(output, "Validation results:\n");
149    if (aco::validate_ir(program.get()))
150       fprintf(output, "Validation passed\n");
151    else
152       fprintf(output, "Validation failed\n");
153 }
154 
finish_opt_test()155 void finish_opt_test()
156 {
157    finish_program(program.get());
158    if (!aco::validate_ir(program.get())) {
159       fail_test("Validation before optimization failed");
160       return;
161    }
162    aco::optimize(program.get());
163    if (!aco::validate_ir(program.get())) {
164       fail_test("Validation after optimization failed");
165       return;
166    }
167    aco_print_program(program.get(), output);
168 }
169 
finish_to_hw_instr_test()170 void finish_to_hw_instr_test()
171 {
172    finish_program(program.get());
173    aco::lower_to_hw_instr(program.get());
174    aco_print_program(program.get(), output);
175 }
176 
finish_assembler_test()177 void finish_assembler_test()
178 {
179    finish_program(program.get());
180    std::vector<uint32_t> binary;
181    unsigned exec_size = emit_program(program.get(), binary);
182 
183    /* we could use CLRX for disassembly but that would require it to be
184     * installed */
185    if (program->chip_class == GFX10_3 && LLVM_VERSION_MAJOR < 9) {
186       skip_test("LLVM 11 needed for GFX10_3 disassembly");
187    } else if (program->chip_class == GFX10 && LLVM_VERSION_MAJOR < 9) {
188       skip_test("LLVM 9 needed for GFX10 disassembly");
189    } else if (program->chip_class >= GFX8) {
190       print_asm(program.get(), binary, exec_size / 4u, output);
191    } else {
192       //TODO: maybe we should use CLRX and skip this test if it's not available?
193       for (uint32_t dword : binary)
194          fprintf(output, "%.8x\n", dword);
195    }
196 }
197 
writeout(unsigned i,Temp tmp)198 void writeout(unsigned i, Temp tmp)
199 {
200    if (tmp.id())
201       bld.pseudo(aco_opcode::p_unit_test, Operand(i), tmp);
202    else
203       bld.pseudo(aco_opcode::p_unit_test, Operand(i));
204 }
205 
get_vk_device(enum chip_class chip_class)206 VkDevice get_vk_device(enum chip_class chip_class)
207 {
208    enum radeon_family family;
209    switch (chip_class) {
210    case GFX6:
211       family = CHIP_TAHITI;
212       break;
213    case GFX7:
214       family = CHIP_BONAIRE;
215       break;
216    case GFX8:
217       family = CHIP_POLARIS10;
218       break;
219    case GFX9:
220       family = CHIP_VEGA10;
221       break;
222    case GFX10:
223       family = CHIP_NAVI10;
224       break;
225    default:
226       family = CHIP_UNKNOWN;
227       break;
228    }
229    return get_vk_device(family);
230 }
231 
get_vk_device(enum radeon_family family)232 VkDevice get_vk_device(enum radeon_family family)
233 {
234    assert(family != CHIP_UNKNOWN);
235 
236    std::lock_guard<std::mutex> guard(create_device_mutex);
237 
238    if (device_cache[family])
239       return device_cache[family];
240 
241    setenv("RADV_FORCE_FAMILY", ac_get_llvm_processor_name(family), 1);
242 
243    VkApplicationInfo app_info = {};
244    app_info.pApplicationName = "aco_tests";
245    app_info.apiVersion = VK_API_VERSION_1_2;
246    VkInstanceCreateInfo instance_create_info = {};
247    instance_create_info.pApplicationInfo = &app_info;
248    instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
249    VkResult result = ((PFN_vkCreateInstance)vk_icdGetInstanceProcAddr(NULL, "vkCreateInstance"))(&instance_create_info, NULL, &instance_cache[family]);
250    assert(result == VK_SUCCESS);
251 
252    #define ITEM(n) n = (PFN_vk##n)vk_icdGetInstanceProcAddr(instance_cache[family], "vk" #n);
253    FUNCTION_LIST
254    #undef ITEM
255 
256    uint32_t device_count = 1;
257    VkPhysicalDevice device = VK_NULL_HANDLE;
258    result = EnumeratePhysicalDevices(instance_cache[family], &device_count, &device);
259    assert(result == VK_SUCCESS);
260    assert(device != VK_NULL_HANDLE);
261 
262    VkDeviceCreateInfo device_create_info = {};
263    device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
264    static const char *extensions[] = {"VK_KHR_pipeline_executable_properties"};
265    device_create_info.enabledExtensionCount = sizeof(extensions) / sizeof(extensions[0]);
266    device_create_info.ppEnabledExtensionNames = extensions;
267    result = CreateDevice(device, &device_create_info, NULL, &device_cache[family]);
268 
269    return device_cache[family];
270 }
271 
272 static struct DestroyDevices {
~DestroyDevicesDestroyDevices273    ~DestroyDevices() {
274       for (unsigned i = 0; i < CHIP_LAST; i++) {
275          if (!device_cache[i])
276             continue;
277          DestroyDevice(device_cache[i], NULL);
278          DestroyInstance(instance_cache[i], NULL);
279       }
280    }
281 } destroy_devices;
282 
print_pipeline_ir(VkDevice device,VkPipeline pipeline,VkShaderStageFlagBits stages,const char * name,bool remove_encoding)283 void print_pipeline_ir(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits stages,
284                        const char *name, bool remove_encoding)
285 {
286    uint32_t executable_count = 16;
287    VkPipelineExecutablePropertiesKHR executables[16];
288    VkPipelineInfoKHR pipeline_info;
289    pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR;
290    pipeline_info.pNext = NULL;
291    pipeline_info.pipeline = pipeline;
292    VkResult result = GetPipelineExecutablePropertiesKHR(device, &pipeline_info, &executable_count, executables);
293    assert(result == VK_SUCCESS);
294 
295    uint32_t executable = 0;
296    for (; executable < executable_count; executable++) {
297       if (executables[executable].stages == stages)
298          break;
299    }
300    assert(executable != executable_count);
301 
302    VkPipelineExecutableInfoKHR exec_info;
303    exec_info.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR;
304    exec_info.pNext = NULL;
305    exec_info.pipeline = pipeline;
306    exec_info.executableIndex = executable;
307 
308    uint32_t ir_count = 16;
309    VkPipelineExecutableInternalRepresentationKHR ir[16];
310    memset(ir, 0, sizeof(ir));
311    result = GetPipelineExecutableInternalRepresentationsKHR(device, &exec_info, &ir_count, ir);
312    assert(result == VK_SUCCESS);
313 
314    for (unsigned i = 0; i < ir_count; i++) {
315       if (strcmp(ir[i].name, name))
316          continue;
317 
318       char *data = (char*)malloc(ir[i].dataSize);
319       ir[i].pData = data;
320       result = GetPipelineExecutableInternalRepresentationsKHR(device, &exec_info, &ir_count, ir);
321       assert(result == VK_SUCCESS);
322 
323       if (remove_encoding) {
324          for (char *c = data; *c; c++) {
325             if (*c == ';') {
326                for (; *c && *c != '\n'; c++)
327                   *c = ' ';
328             }
329          }
330       }
331 
332       fprintf(output, "%s", data);
333       free(data);
334       return;
335    }
336 }
337 
__qoCreateShaderModule(VkDevice dev,const QoShaderModuleCreateInfo * info)338 VkShaderModule __qoCreateShaderModule(VkDevice dev, const QoShaderModuleCreateInfo *info)
339 {
340     VkShaderModuleCreateInfo module_info;
341     module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
342     module_info.pNext = NULL;
343     module_info.flags = 0;
344     module_info.codeSize = info->spirvSize;
345     module_info.pCode = (const uint32_t*)info->pSpirv;
346 
347     VkShaderModule module;
348     VkResult result = CreateShaderModule(dev, &module_info, NULL, &module);
349     assert(result == VK_SUCCESS);
350 
351     return module;
352 }
353 
PipelineBuilder(VkDevice dev)354 PipelineBuilder::PipelineBuilder(VkDevice dev) {
355    memset(this, 0, sizeof(*this));
356    topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
357    device = dev;
358 }
359 
~PipelineBuilder()360 PipelineBuilder::~PipelineBuilder()
361 {
362    DestroyPipeline(device, pipeline, NULL);
363 
364    for (unsigned i = 0; i < (is_compute() ? 1 : gfx_pipeline_info.stageCount); i++) {
365       VkPipelineShaderStageCreateInfo *stage_info = &stages[i];
366       if (owned_stages & stage_info->stage)
367          DestroyShaderModule(device, stage_info->module, NULL);
368    }
369 
370    DestroyPipelineLayout(device, pipeline_layout, NULL);
371 
372    for (unsigned i = 0; i < util_bitcount64(desc_layouts_used); i++)
373       DestroyDescriptorSetLayout(device, desc_layouts[i], NULL);
374 
375    DestroyRenderPass(device, render_pass, NULL);
376 }
377 
add_desc_binding(VkShaderStageFlags stage_flags,uint32_t layout,uint32_t binding,VkDescriptorType type,uint32_t count)378 void PipelineBuilder::add_desc_binding(VkShaderStageFlags stage_flags, uint32_t layout,
379                                        uint32_t binding, VkDescriptorType type, uint32_t count)
380 {
381    desc_layouts_used |= 1ull << layout;
382    desc_bindings[layout][num_desc_bindings[layout]++] = {binding, type, count, stage_flags, NULL};
383 }
384 
add_vertex_binding(uint32_t binding,uint32_t stride,VkVertexInputRate rate)385 void PipelineBuilder::add_vertex_binding(uint32_t binding, uint32_t stride, VkVertexInputRate rate)
386 {
387    vs_bindings[vs_input.vertexBindingDescriptionCount++] = {binding, stride, rate};
388 }
389 
add_vertex_attribute(uint32_t location,uint32_t binding,VkFormat format,uint32_t offset)390 void PipelineBuilder::add_vertex_attribute(uint32_t location, uint32_t binding, VkFormat format, uint32_t offset)
391 {
392    vs_attributes[vs_input.vertexAttributeDescriptionCount++] = {location, binding, format, offset};
393 }
394 
add_resource_decls(QoShaderModuleCreateInfo * module)395 void PipelineBuilder::add_resource_decls(QoShaderModuleCreateInfo *module)
396 {
397    for (unsigned i = 0; i < module->declarationCount; i++) {
398       const QoShaderDecl *decl = &module->pDeclarations[i];
399       switch (decl->decl_type) {
400       case QoShaderDeclType_ubo:
401          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
402          break;
403       case QoShaderDeclType_ssbo:
404          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
405          break;
406       case QoShaderDeclType_img_buf:
407          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
408          break;
409       case QoShaderDeclType_img:
410          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
411          break;
412       case QoShaderDeclType_tex_buf:
413          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);
414          break;
415       case QoShaderDeclType_combined:
416          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
417          break;
418       case QoShaderDeclType_tex:
419          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
420          break;
421       case QoShaderDeclType_samp:
422          add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_SAMPLER);
423          break;
424       default:
425          break;
426       }
427    }
428 }
429 
add_io_decls(QoShaderModuleCreateInfo * module)430 void PipelineBuilder::add_io_decls(QoShaderModuleCreateInfo *module)
431 {
432    unsigned next_vtx_offset = 0;
433    for (unsigned i = 0; i < module->declarationCount; i++) {
434       const QoShaderDecl *decl = &module->pDeclarations[i];
435       switch (decl->decl_type) {
436       case QoShaderDeclType_in:
437          if (module->stage == VK_SHADER_STAGE_VERTEX_BIT) {
438             if (!strcmp(decl->type, "float") || decl->type[0] == 'v')
439                add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_SFLOAT, next_vtx_offset);
440             else if (decl->type[0] == 'u')
441                add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_UINT, next_vtx_offset);
442             else if (decl->type[0] == 'i')
443                add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_SINT, next_vtx_offset);
444             next_vtx_offset += 16;
445          }
446          break;
447       case QoShaderDeclType_out:
448          if (module->stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
449             if (!strcmp(decl->type, "float") || decl->type[0] == 'v')
450                color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_SFLOAT;
451             else if (decl->type[0] == 'u')
452                color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_UINT;
453             else if (decl->type[0] == 'i')
454                color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_SINT;
455          }
456          break;
457       default:
458          break;
459       }
460    }
461    if (next_vtx_offset)
462       add_vertex_binding(0, next_vtx_offset);
463 }
464 
add_stage(VkShaderStageFlagBits stage,VkShaderModule module,const char * name)465 void PipelineBuilder::add_stage(VkShaderStageFlagBits stage, VkShaderModule module, const char *name)
466 {
467    VkPipelineShaderStageCreateInfo *stage_info;
468    if (stage == VK_SHADER_STAGE_COMPUTE_BIT)
469       stage_info = &stages[0];
470    else
471       stage_info = &stages[gfx_pipeline_info.stageCount++];
472    stage_info->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
473    stage_info->pNext = NULL;
474    stage_info->flags = 0;
475    stage_info->stage = stage;
476    stage_info->module = module;
477    stage_info->pName = name;
478    stage_info->pSpecializationInfo = NULL;
479    owned_stages |= stage;
480 }
481 
add_vsfs(VkShaderModule vs,VkShaderModule fs)482 void PipelineBuilder::add_vsfs(VkShaderModule vs, VkShaderModule fs)
483 {
484    add_stage(VK_SHADER_STAGE_VERTEX_BIT, vs);
485    add_stage(VK_SHADER_STAGE_FRAGMENT_BIT, fs);
486 }
487 
add_vsfs(QoShaderModuleCreateInfo vs,QoShaderModuleCreateInfo fs)488 void PipelineBuilder::add_vsfs(QoShaderModuleCreateInfo vs, QoShaderModuleCreateInfo fs)
489 {
490    add_vsfs(__qoCreateShaderModule(device, &vs), __qoCreateShaderModule(device, &fs));
491    add_resource_decls(&vs);
492    add_io_decls(&vs);
493    add_resource_decls(&fs);
494    add_io_decls(&fs);
495 }
496 
add_cs(VkShaderModule cs)497 void PipelineBuilder::add_cs(VkShaderModule cs)
498 {
499    add_stage(VK_SHADER_STAGE_COMPUTE_BIT, cs);
500 }
501 
add_cs(QoShaderModuleCreateInfo cs)502 void PipelineBuilder::add_cs(QoShaderModuleCreateInfo cs)
503 {
504    add_cs(__qoCreateShaderModule(device, &cs));
505    add_resource_decls(&cs);
506 }
507 
is_compute()508 bool PipelineBuilder::is_compute() {
509    return gfx_pipeline_info.stageCount == 0;
510 }
511 
create_compute_pipeline()512 void PipelineBuilder::create_compute_pipeline() {
513    VkComputePipelineCreateInfo create_info;
514    create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
515    create_info.pNext = NULL;
516    create_info.flags = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
517    create_info.stage = stages[0];
518    create_info.layout = pipeline_layout;
519    create_info.basePipelineHandle = VK_NULL_HANDLE;
520    create_info.basePipelineIndex = 0;
521 
522    VkResult result = CreateComputePipelines(device, VK_NULL_HANDLE, 1, &create_info, NULL, &pipeline);
523    assert(result == VK_SUCCESS);
524 }
525 
create_graphics_pipeline()526 void PipelineBuilder::create_graphics_pipeline() {
527    /* create the create infos */
528    if (!samples)
529       samples = VK_SAMPLE_COUNT_1_BIT;
530 
531    unsigned num_color_attachments = 0;
532    VkPipelineColorBlendAttachmentState blend_attachment_states[16];
533    VkAttachmentReference color_attachments[16];
534    VkAttachmentDescription attachment_descs[17];
535    for (unsigned i = 0; i < 16; i++) {
536       if (color_outputs[i] == VK_FORMAT_UNDEFINED)
537          continue;
538 
539       VkAttachmentDescription *desc = &attachment_descs[num_color_attachments];
540       desc->flags = 0;
541       desc->format = color_outputs[i];
542       desc->samples = samples;
543       desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
544       desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
545       desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
546       desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
547       desc->initialLayout = VK_IMAGE_LAYOUT_GENERAL;
548       desc->finalLayout = VK_IMAGE_LAYOUT_GENERAL;
549 
550       VkAttachmentReference *ref = &color_attachments[num_color_attachments];
551       ref->attachment = num_color_attachments;
552       ref->layout = VK_IMAGE_LAYOUT_GENERAL;
553 
554       VkPipelineColorBlendAttachmentState *blend = &blend_attachment_states[num_color_attachments];
555       blend->blendEnable = false;
556       blend->colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
557                               VK_COLOR_COMPONENT_G_BIT |
558                               VK_COLOR_COMPONENT_B_BIT |
559                               VK_COLOR_COMPONENT_A_BIT;
560 
561       num_color_attachments++;
562    }
563 
564    unsigned num_attachments = num_color_attachments;
565    VkAttachmentReference ds_attachment;
566    if (ds_output != VK_FORMAT_UNDEFINED) {
567       VkAttachmentDescription *desc = &attachment_descs[num_attachments];
568       desc->flags = 0;
569       desc->format = ds_output;
570       desc->samples = samples;
571       desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
572       desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
573       desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
574       desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
575       desc->initialLayout = VK_IMAGE_LAYOUT_GENERAL;
576       desc->finalLayout = VK_IMAGE_LAYOUT_GENERAL;
577 
578       ds_attachment.attachment = num_color_attachments;
579       ds_attachment.layout = VK_IMAGE_LAYOUT_GENERAL;
580 
581       num_attachments++;
582    }
583 
584    vs_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
585    vs_input.pNext = NULL;
586    vs_input.flags = 0;
587    vs_input.pVertexBindingDescriptions = vs_bindings;
588    vs_input.pVertexAttributeDescriptions = vs_attributes;
589 
590    VkPipelineInputAssemblyStateCreateInfo assembly_state;
591    assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
592    assembly_state.pNext = NULL;
593    assembly_state.flags = 0;
594    assembly_state.topology = topology;
595    assembly_state.primitiveRestartEnable = false;
596 
597    VkPipelineTessellationStateCreateInfo tess_state;
598    tess_state.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
599    tess_state.pNext = NULL;
600    tess_state.flags = 0;
601    tess_state.patchControlPoints = patch_size;
602 
603    VkPipelineViewportStateCreateInfo viewport_state;
604    viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
605    viewport_state.pNext = NULL;
606    viewport_state.flags = 0;
607    viewport_state.viewportCount = 1;
608    viewport_state.pViewports = NULL;
609    viewport_state.scissorCount = 1;
610    viewport_state.pScissors = NULL;
611 
612    VkPipelineRasterizationStateCreateInfo rasterization_state;
613    rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
614    rasterization_state.pNext = NULL;
615    rasterization_state.flags = 0;
616    rasterization_state.depthClampEnable = false;
617    rasterization_state.rasterizerDiscardEnable = false;
618    rasterization_state.polygonMode = VK_POLYGON_MODE_FILL;
619    rasterization_state.cullMode = VK_CULL_MODE_NONE;
620    rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
621    rasterization_state.depthBiasEnable = false;
622    rasterization_state.lineWidth = 1.0;
623 
624    VkPipelineMultisampleStateCreateInfo ms_state;
625    ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
626    ms_state.pNext = NULL;
627    ms_state.flags = 0;
628    ms_state.rasterizationSamples = samples;
629    ms_state.sampleShadingEnable = sample_shading_enable;
630    ms_state.minSampleShading = min_sample_shading;
631    VkSampleMask sample_mask = 0xffffffff;
632    ms_state.pSampleMask = &sample_mask;
633    ms_state.alphaToCoverageEnable = false;
634    ms_state.alphaToOneEnable = false;
635 
636    VkPipelineDepthStencilStateCreateInfo ds_state;
637    ds_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
638    ds_state.pNext = NULL;
639    ds_state.flags = 0;
640    ds_state.depthTestEnable = ds_output != VK_FORMAT_UNDEFINED;
641    ds_state.depthWriteEnable = true;
642    ds_state.depthCompareOp = VK_COMPARE_OP_ALWAYS;
643    ds_state.depthBoundsTestEnable = false;
644    ds_state.stencilTestEnable = true;
645    ds_state.front.failOp = VK_STENCIL_OP_KEEP;
646    ds_state.front.passOp = VK_STENCIL_OP_REPLACE;
647    ds_state.front.depthFailOp = VK_STENCIL_OP_REPLACE;
648    ds_state.front.compareOp = VK_COMPARE_OP_ALWAYS;
649    ds_state.front.compareMask = 0xffffffff,
650    ds_state.front.reference = 0;
651    ds_state.back = ds_state.front;
652 
653    VkPipelineColorBlendStateCreateInfo color_blend_state;
654    color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
655    color_blend_state.pNext = NULL;
656    color_blend_state.flags = 0;
657    color_blend_state.logicOpEnable = false;
658    color_blend_state.attachmentCount = num_color_attachments;
659    color_blend_state.pAttachments = blend_attachment_states;
660 
661    VkDynamicState dynamic_states[9] = {
662       VK_DYNAMIC_STATE_VIEWPORT,
663       VK_DYNAMIC_STATE_SCISSOR,
664       VK_DYNAMIC_STATE_LINE_WIDTH,
665       VK_DYNAMIC_STATE_DEPTH_BIAS,
666       VK_DYNAMIC_STATE_BLEND_CONSTANTS,
667       VK_DYNAMIC_STATE_DEPTH_BOUNDS,
668       VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
669       VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
670       VK_DYNAMIC_STATE_STENCIL_REFERENCE
671    };
672 
673    VkPipelineDynamicStateCreateInfo dynamic_state;
674    dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
675    dynamic_state.pNext = NULL;
676    dynamic_state.flags = 0;
677    dynamic_state.dynamicStateCount = sizeof(dynamic_states) / sizeof(VkDynamicState);
678    dynamic_state.pDynamicStates = dynamic_states;
679 
680    gfx_pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
681    gfx_pipeline_info.pNext = NULL;
682    gfx_pipeline_info.flags = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
683    gfx_pipeline_info.pVertexInputState = &vs_input;
684    gfx_pipeline_info.pInputAssemblyState = &assembly_state;
685    gfx_pipeline_info.pTessellationState = &tess_state;
686    gfx_pipeline_info.pViewportState = &viewport_state;
687    gfx_pipeline_info.pRasterizationState = &rasterization_state;
688    gfx_pipeline_info.pMultisampleState = &ms_state;
689    gfx_pipeline_info.pDepthStencilState = &ds_state;
690    gfx_pipeline_info.pColorBlendState = &color_blend_state;
691    gfx_pipeline_info.pDynamicState = &dynamic_state;
692    gfx_pipeline_info.subpass = 0;
693 
694    /* create the objects used to create the pipeline */
695    VkSubpassDescription subpass;
696    subpass.flags = 0;
697    subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
698    subpass.inputAttachmentCount = 0;
699    subpass.pInputAttachments = NULL;
700    subpass.colorAttachmentCount = num_color_attachments;
701    subpass.pColorAttachments = color_attachments;
702    subpass.pResolveAttachments = NULL;
703    subpass.pDepthStencilAttachment = ds_output == VK_FORMAT_UNDEFINED ? NULL : &ds_attachment;
704    subpass.preserveAttachmentCount = 0;
705    subpass.pPreserveAttachments = NULL;
706 
707    VkRenderPassCreateInfo renderpass_info;
708    renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
709    renderpass_info.pNext = NULL;
710    renderpass_info.flags = 0;
711    renderpass_info.attachmentCount = num_attachments;
712    renderpass_info.pAttachments = attachment_descs;
713    renderpass_info.subpassCount = 1;
714    renderpass_info.pSubpasses = &subpass;
715    renderpass_info.dependencyCount = 0;
716    renderpass_info.pDependencies = NULL;
717 
718    VkResult result = CreateRenderPass(device, &renderpass_info, NULL, &render_pass);
719    assert(result == VK_SUCCESS);
720 
721    gfx_pipeline_info.layout = pipeline_layout;
722    gfx_pipeline_info.renderPass = render_pass;
723 
724    /* create the pipeline */
725    gfx_pipeline_info.pStages = stages;
726 
727    result = CreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &gfx_pipeline_info, NULL, &pipeline);
728    assert(result == VK_SUCCESS);
729 }
730 
create_pipeline()731 void PipelineBuilder::create_pipeline() {
732    unsigned num_desc_layouts = 0;
733    for (unsigned i = 0; i < 64; i++) {
734       if (!(desc_layouts_used & (1ull << i)))
735          continue;
736 
737       VkDescriptorSetLayoutCreateInfo desc_layout_info;
738       desc_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
739       desc_layout_info.pNext = NULL;
740       desc_layout_info.flags = 0;
741       desc_layout_info.bindingCount = num_desc_bindings[i];
742       desc_layout_info.pBindings = desc_bindings[i];
743 
744       VkResult result = CreateDescriptorSetLayout(device, &desc_layout_info, NULL, &desc_layouts[num_desc_layouts]);
745       assert(result == VK_SUCCESS);
746       num_desc_layouts++;
747    }
748 
749    VkPipelineLayoutCreateInfo pipeline_layout_info;
750    pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
751    pipeline_layout_info.pNext = NULL;
752    pipeline_layout_info.flags = 0;
753    pipeline_layout_info.pushConstantRangeCount = 1;
754    pipeline_layout_info.pPushConstantRanges = &push_constant_range;
755    pipeline_layout_info.setLayoutCount = num_desc_layouts;
756    pipeline_layout_info.pSetLayouts = desc_layouts;
757 
758    VkResult result = CreatePipelineLayout(device, &pipeline_layout_info, NULL, &pipeline_layout);
759    assert(result == VK_SUCCESS);
760 
761    if (is_compute())
762       create_compute_pipeline();
763    else
764       create_graphics_pipeline();
765 }
766 
print_ir(VkShaderStageFlagBits stages,const char * name,bool remove_encoding)767 void PipelineBuilder::print_ir(VkShaderStageFlagBits stages, const char *name, bool remove_encoding)
768 {
769    if (!pipeline)
770       create_pipeline();
771    print_pipeline_ir(device, pipeline, stages, name, remove_encoding);
772 }
773