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