17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2020 Valve Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg * 237ec681f3Smrg */ 247ec681f3Smrg#include "helpers.h" 257ec681f3Smrg#include "vulkan/vk_format.h" 267ec681f3Smrg#include "common/amd_family.h" 277ec681f3Smrg#include <stdio.h> 287ec681f3Smrg#include <sstream> 297ec681f3Smrg#include <llvm-c/Target.h> 307ec681f3Smrg#include <mutex> 317ec681f3Smrg 327ec681f3Smrgusing namespace aco; 337ec681f3Smrg 347ec681f3Smrgextern "C" { 357ec681f3SmrgPFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr( 367ec681f3Smrg VkInstance instance, 377ec681f3Smrg const char* pName); 387ec681f3Smrg} 397ec681f3Smrg 407ec681f3Smrgac_shader_config config; 417ec681f3Smrgradv_shader_info info; 427ec681f3Smrgstd::unique_ptr<Program> program; 437ec681f3SmrgBuilder bld(NULL); 447ec681f3SmrgTemp inputs[16]; 457ec681f3Smrg 467ec681f3Smrgstatic VkInstance instance_cache[CHIP_LAST] = {VK_NULL_HANDLE}; 477ec681f3Smrgstatic VkDevice device_cache[CHIP_LAST] = {VK_NULL_HANDLE}; 487ec681f3Smrgstatic std::mutex create_device_mutex; 497ec681f3Smrg 507ec681f3Smrg#define FUNCTION_LIST\ 517ec681f3Smrg ITEM(CreateInstance)\ 527ec681f3Smrg ITEM(DestroyInstance)\ 537ec681f3Smrg ITEM(EnumeratePhysicalDevices)\ 547ec681f3Smrg ITEM(GetPhysicalDeviceProperties2)\ 557ec681f3Smrg ITEM(CreateDevice)\ 567ec681f3Smrg ITEM(DestroyDevice)\ 577ec681f3Smrg ITEM(CreateShaderModule)\ 587ec681f3Smrg ITEM(DestroyShaderModule)\ 597ec681f3Smrg ITEM(CreateGraphicsPipelines)\ 607ec681f3Smrg ITEM(CreateComputePipelines)\ 617ec681f3Smrg ITEM(DestroyPipeline)\ 627ec681f3Smrg ITEM(CreateDescriptorSetLayout)\ 637ec681f3Smrg ITEM(DestroyDescriptorSetLayout)\ 647ec681f3Smrg ITEM(CreatePipelineLayout)\ 657ec681f3Smrg ITEM(DestroyPipelineLayout)\ 667ec681f3Smrg ITEM(CreateRenderPass)\ 677ec681f3Smrg ITEM(DestroyRenderPass)\ 687ec681f3Smrg ITEM(GetPipelineExecutablePropertiesKHR)\ 697ec681f3Smrg ITEM(GetPipelineExecutableInternalRepresentationsKHR) 707ec681f3Smrg 717ec681f3Smrg#define ITEM(n) PFN_vk##n n; 727ec681f3SmrgFUNCTION_LIST 737ec681f3Smrg#undef ITEM 747ec681f3Smrg 757ec681f3Smrgvoid create_program(enum chip_class chip_class, Stage stage, unsigned wave_size, enum radeon_family family) 767ec681f3Smrg{ 777ec681f3Smrg memset(&config, 0, sizeof(config)); 787ec681f3Smrg info.wave_size = wave_size; 797ec681f3Smrg 807ec681f3Smrg program.reset(new Program); 817ec681f3Smrg aco::init_program(program.get(), stage, &info, chip_class, family, false, &config); 827ec681f3Smrg program->workgroup_size = UINT_MAX; 837ec681f3Smrg calc_min_waves(program.get()); 847ec681f3Smrg 857ec681f3Smrg program->debug.func = nullptr; 867ec681f3Smrg program->debug.private_data = nullptr; 877ec681f3Smrg 887ec681f3Smrg program->debug.output = output; 897ec681f3Smrg program->debug.shorten_messages = true; 907ec681f3Smrg program->debug.func = nullptr; 917ec681f3Smrg program->debug.private_data = nullptr; 927ec681f3Smrg 937ec681f3Smrg Block *block = program->create_and_insert_block(); 947ec681f3Smrg block->kind = block_kind_top_level; 957ec681f3Smrg 967ec681f3Smrg bld = Builder(program.get(), &program->blocks[0]); 977ec681f3Smrg 987ec681f3Smrg config.float_mode = program->blocks[0].fp_mode.val; 997ec681f3Smrg} 1007ec681f3Smrg 1017ec681f3Smrgbool setup_cs(const char *input_spec, enum chip_class chip_class, 1027ec681f3Smrg enum radeon_family family, const char* subvariant, 1037ec681f3Smrg unsigned wave_size) 1047ec681f3Smrg{ 1057ec681f3Smrg if (!set_variant(chip_class, subvariant)) 1067ec681f3Smrg return false; 1077ec681f3Smrg 1087ec681f3Smrg memset(&info, 0, sizeof(info)); 1097ec681f3Smrg info.cs.block_size[0] = 1; 1107ec681f3Smrg info.cs.block_size[1] = 1; 1117ec681f3Smrg info.cs.block_size[2] = 1; 1127ec681f3Smrg 1137ec681f3Smrg create_program(chip_class, compute_cs, wave_size, family); 1147ec681f3Smrg 1157ec681f3Smrg if (input_spec) { 1167ec681f3Smrg unsigned num_inputs = DIV_ROUND_UP(strlen(input_spec), 3u); 1177ec681f3Smrg aco_ptr<Instruction> startpgm{create_instruction<Pseudo_instruction>(aco_opcode::p_startpgm, Format::PSEUDO, 0, num_inputs)}; 1187ec681f3Smrg for (unsigned i = 0; i < num_inputs; i++) { 1197ec681f3Smrg RegClass cls(input_spec[i * 3] == 'v' ? RegType::vgpr : RegType::sgpr, input_spec[i * 3 + 1] - '0'); 1207ec681f3Smrg inputs[i] = bld.tmp(cls); 1217ec681f3Smrg startpgm->definitions[i] = Definition(inputs[i]); 1227ec681f3Smrg } 1237ec681f3Smrg bld.insert(std::move(startpgm)); 1247ec681f3Smrg } 1257ec681f3Smrg 1267ec681f3Smrg return true; 1277ec681f3Smrg} 1287ec681f3Smrg 1297ec681f3Smrgvoid finish_program(Program *prog) 1307ec681f3Smrg{ 1317ec681f3Smrg for (Block& BB : prog->blocks) { 1327ec681f3Smrg for (unsigned idx : BB.linear_preds) 1337ec681f3Smrg prog->blocks[idx].linear_succs.emplace_back(BB.index); 1347ec681f3Smrg for (unsigned idx : BB.logical_preds) 1357ec681f3Smrg prog->blocks[idx].logical_succs.emplace_back(BB.index); 1367ec681f3Smrg } 1377ec681f3Smrg 1387ec681f3Smrg for (Block& block : prog->blocks) { 1397ec681f3Smrg if (block.linear_succs.size() == 0) { 1407ec681f3Smrg block.kind |= block_kind_uniform; 1417ec681f3Smrg Builder(prog, &block).sopp(aco_opcode::s_endpgm); 1427ec681f3Smrg } 1437ec681f3Smrg } 1447ec681f3Smrg} 1457ec681f3Smrg 1467ec681f3Smrgvoid finish_validator_test() 1477ec681f3Smrg{ 1487ec681f3Smrg finish_program(program.get()); 1497ec681f3Smrg aco_print_program(program.get(), output); 1507ec681f3Smrg fprintf(output, "Validation results:\n"); 1517ec681f3Smrg if (aco::validate_ir(program.get())) 1527ec681f3Smrg fprintf(output, "Validation passed\n"); 1537ec681f3Smrg else 1547ec681f3Smrg fprintf(output, "Validation failed\n"); 1557ec681f3Smrg} 1567ec681f3Smrg 1577ec681f3Smrgvoid finish_opt_test() 1587ec681f3Smrg{ 1597ec681f3Smrg finish_program(program.get()); 1607ec681f3Smrg if (!aco::validate_ir(program.get())) { 1617ec681f3Smrg fail_test("Validation before optimization failed"); 1627ec681f3Smrg return; 1637ec681f3Smrg } 1647ec681f3Smrg aco::optimize(program.get()); 1657ec681f3Smrg if (!aco::validate_ir(program.get())) { 1667ec681f3Smrg fail_test("Validation after optimization failed"); 1677ec681f3Smrg return; 1687ec681f3Smrg } 1697ec681f3Smrg aco_print_program(program.get(), output); 1707ec681f3Smrg} 1717ec681f3Smrg 1727ec681f3Smrgvoid finish_ra_test(ra_test_policy policy, bool lower) 1737ec681f3Smrg{ 1747ec681f3Smrg finish_program(program.get()); 1757ec681f3Smrg if (!aco::validate_ir(program.get())) { 1767ec681f3Smrg fail_test("Validation before register allocation failed"); 1777ec681f3Smrg return; 1787ec681f3Smrg } 1797ec681f3Smrg 1807ec681f3Smrg program->workgroup_size = program->wave_size; 1817ec681f3Smrg aco::live live_vars = aco::live_var_analysis(program.get()); 1827ec681f3Smrg aco::register_allocation(program.get(), live_vars.live_out, policy); 1837ec681f3Smrg 1847ec681f3Smrg if (aco::validate_ra(program.get())) { 1857ec681f3Smrg fail_test("Validation after register allocation failed"); 1867ec681f3Smrg return; 1877ec681f3Smrg } 1887ec681f3Smrg 1897ec681f3Smrg if (lower) { 1907ec681f3Smrg aco::ssa_elimination(program.get()); 1917ec681f3Smrg aco::lower_to_hw_instr(program.get()); 1927ec681f3Smrg } 1937ec681f3Smrg 1947ec681f3Smrg aco_print_program(program.get(), output); 1957ec681f3Smrg} 1967ec681f3Smrg 1977ec681f3Smrgvoid finish_optimizer_postRA_test() 1987ec681f3Smrg{ 1997ec681f3Smrg finish_program(program.get()); 2007ec681f3Smrg aco::optimize_postRA(program.get()); 2017ec681f3Smrg aco_print_program(program.get(), output); 2027ec681f3Smrg} 2037ec681f3Smrg 2047ec681f3Smrgvoid finish_to_hw_instr_test() 2057ec681f3Smrg{ 2067ec681f3Smrg finish_program(program.get()); 2077ec681f3Smrg aco::lower_to_hw_instr(program.get()); 2087ec681f3Smrg aco_print_program(program.get(), output); 2097ec681f3Smrg} 2107ec681f3Smrg 2117ec681f3Smrgvoid finish_insert_nops_test() 2127ec681f3Smrg{ 2137ec681f3Smrg finish_program(program.get()); 2147ec681f3Smrg aco::insert_NOPs(program.get()); 2157ec681f3Smrg aco_print_program(program.get(), output); 2167ec681f3Smrg} 2177ec681f3Smrg 2187ec681f3Smrgvoid finish_form_hard_clause_test() 2197ec681f3Smrg{ 2207ec681f3Smrg finish_program(program.get()); 2217ec681f3Smrg aco::form_hard_clauses(program.get()); 2227ec681f3Smrg aco_print_program(program.get(), output); 2237ec681f3Smrg} 2247ec681f3Smrg 2257ec681f3Smrgvoid finish_assembler_test() 2267ec681f3Smrg{ 2277ec681f3Smrg finish_program(program.get()); 2287ec681f3Smrg std::vector<uint32_t> binary; 2297ec681f3Smrg unsigned exec_size = emit_program(program.get(), binary); 2307ec681f3Smrg 2317ec681f3Smrg /* we could use CLRX for disassembly but that would require it to be 2327ec681f3Smrg * installed */ 2337ec681f3Smrg if (program->chip_class >= GFX8) { 2347ec681f3Smrg print_asm(program.get(), binary, exec_size / 4u, output); 2357ec681f3Smrg } else { 2367ec681f3Smrg //TODO: maybe we should use CLRX and skip this test if it's not available? 2377ec681f3Smrg for (uint32_t dword : binary) 2387ec681f3Smrg fprintf(output, "%.8x\n", dword); 2397ec681f3Smrg } 2407ec681f3Smrg} 2417ec681f3Smrg 2427ec681f3Smrgvoid writeout(unsigned i, Temp tmp) 2437ec681f3Smrg{ 2447ec681f3Smrg if (tmp.id()) 2457ec681f3Smrg bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), tmp); 2467ec681f3Smrg else 2477ec681f3Smrg bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i)); 2487ec681f3Smrg} 2497ec681f3Smrg 2507ec681f3Smrgvoid writeout(unsigned i, aco::Builder::Result res) 2517ec681f3Smrg{ 2527ec681f3Smrg bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), res); 2537ec681f3Smrg} 2547ec681f3Smrg 2557ec681f3Smrgvoid writeout(unsigned i, Operand op) 2567ec681f3Smrg{ 2577ec681f3Smrg bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), op); 2587ec681f3Smrg} 2597ec681f3Smrg 2607ec681f3Smrgvoid writeout(unsigned i, Operand op0, Operand op1) 2617ec681f3Smrg{ 2627ec681f3Smrg bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), op0, op1); 2637ec681f3Smrg} 2647ec681f3Smrg 2657ec681f3SmrgTemp fneg(Temp src) 2667ec681f3Smrg{ 2677ec681f3Smrg return bld.vop2(aco_opcode::v_mul_f32, bld.def(v1), Operand::c32(0xbf800000u), src); 2687ec681f3Smrg} 2697ec681f3Smrg 2707ec681f3SmrgTemp fabs(Temp src) 2717ec681f3Smrg{ 2727ec681f3Smrg Builder::Result res = 2737ec681f3Smrg bld.vop2_e64(aco_opcode::v_mul_f32, bld.def(v1), Operand::c32(0x3f800000u), src); 2747ec681f3Smrg res.instr->vop3().abs[1] = true; 2757ec681f3Smrg return res; 2767ec681f3Smrg} 2777ec681f3Smrg 2787ec681f3SmrgVkDevice get_vk_device(enum chip_class chip_class) 2797ec681f3Smrg{ 2807ec681f3Smrg enum radeon_family family; 2817ec681f3Smrg switch (chip_class) { 2827ec681f3Smrg case GFX6: 2837ec681f3Smrg family = CHIP_TAHITI; 2847ec681f3Smrg break; 2857ec681f3Smrg case GFX7: 2867ec681f3Smrg family = CHIP_BONAIRE; 2877ec681f3Smrg break; 2887ec681f3Smrg case GFX8: 2897ec681f3Smrg family = CHIP_POLARIS10; 2907ec681f3Smrg break; 2917ec681f3Smrg case GFX9: 2927ec681f3Smrg family = CHIP_VEGA10; 2937ec681f3Smrg break; 2947ec681f3Smrg case GFX10: 2957ec681f3Smrg family = CHIP_NAVI10; 2967ec681f3Smrg break; 2977ec681f3Smrg case GFX10_3: 2987ec681f3Smrg family = CHIP_SIENNA_CICHLID; 2997ec681f3Smrg break; 3007ec681f3Smrg default: 3017ec681f3Smrg family = CHIP_UNKNOWN; 3027ec681f3Smrg break; 3037ec681f3Smrg } 3047ec681f3Smrg return get_vk_device(family); 3057ec681f3Smrg} 3067ec681f3Smrg 3077ec681f3SmrgVkDevice get_vk_device(enum radeon_family family) 3087ec681f3Smrg{ 3097ec681f3Smrg assert(family != CHIP_UNKNOWN); 3107ec681f3Smrg 3117ec681f3Smrg std::lock_guard<std::mutex> guard(create_device_mutex); 3127ec681f3Smrg 3137ec681f3Smrg if (device_cache[family]) 3147ec681f3Smrg return device_cache[family]; 3157ec681f3Smrg 3167ec681f3Smrg setenv("RADV_FORCE_FAMILY", ac_get_family_name(family), 1); 3177ec681f3Smrg 3187ec681f3Smrg VkApplicationInfo app_info = {}; 3197ec681f3Smrg app_info.pApplicationName = "aco_tests"; 3207ec681f3Smrg app_info.apiVersion = VK_API_VERSION_1_2; 3217ec681f3Smrg VkInstanceCreateInfo instance_create_info = {}; 3227ec681f3Smrg instance_create_info.pApplicationInfo = &app_info; 3237ec681f3Smrg instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 3247ec681f3Smrg ASSERTED VkResult result = ((PFN_vkCreateInstance)vk_icdGetInstanceProcAddr(NULL, "vkCreateInstance"))(&instance_create_info, NULL, &instance_cache[family]); 3257ec681f3Smrg assert(result == VK_SUCCESS); 3267ec681f3Smrg 3277ec681f3Smrg #define ITEM(n) n = (PFN_vk##n)vk_icdGetInstanceProcAddr(instance_cache[family], "vk" #n); 3287ec681f3Smrg FUNCTION_LIST 3297ec681f3Smrg #undef ITEM 3307ec681f3Smrg 3317ec681f3Smrg uint32_t device_count = 1; 3327ec681f3Smrg VkPhysicalDevice device = VK_NULL_HANDLE; 3337ec681f3Smrg result = EnumeratePhysicalDevices(instance_cache[family], &device_count, &device); 3347ec681f3Smrg assert(result == VK_SUCCESS); 3357ec681f3Smrg assert(device != VK_NULL_HANDLE); 3367ec681f3Smrg 3377ec681f3Smrg VkDeviceCreateInfo device_create_info = {}; 3387ec681f3Smrg device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 3397ec681f3Smrg static const char *extensions[] = {"VK_KHR_pipeline_executable_properties"}; 3407ec681f3Smrg device_create_info.enabledExtensionCount = sizeof(extensions) / sizeof(extensions[0]); 3417ec681f3Smrg device_create_info.ppEnabledExtensionNames = extensions; 3427ec681f3Smrg result = CreateDevice(device, &device_create_info, NULL, &device_cache[family]); 3437ec681f3Smrg 3447ec681f3Smrg return device_cache[family]; 3457ec681f3Smrg} 3467ec681f3Smrg 3477ec681f3Smrgstatic struct DestroyDevices { 3487ec681f3Smrg ~DestroyDevices() { 3497ec681f3Smrg for (unsigned i = 0; i < CHIP_LAST; i++) { 3507ec681f3Smrg if (!device_cache[i]) 3517ec681f3Smrg continue; 3527ec681f3Smrg DestroyDevice(device_cache[i], NULL); 3537ec681f3Smrg DestroyInstance(instance_cache[i], NULL); 3547ec681f3Smrg } 3557ec681f3Smrg } 3567ec681f3Smrg} destroy_devices; 3577ec681f3Smrg 3587ec681f3Smrgvoid print_pipeline_ir(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits stages, 3597ec681f3Smrg const char *name, bool remove_encoding) 3607ec681f3Smrg{ 3617ec681f3Smrg uint32_t executable_count = 16; 3627ec681f3Smrg VkPipelineExecutablePropertiesKHR executables[16]; 3637ec681f3Smrg VkPipelineInfoKHR pipeline_info; 3647ec681f3Smrg pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR; 3657ec681f3Smrg pipeline_info.pNext = NULL; 3667ec681f3Smrg pipeline_info.pipeline = pipeline; 3677ec681f3Smrg ASSERTED VkResult result = GetPipelineExecutablePropertiesKHR(device, &pipeline_info, &executable_count, executables); 3687ec681f3Smrg assert(result == VK_SUCCESS); 3697ec681f3Smrg 3707ec681f3Smrg uint32_t executable = 0; 3717ec681f3Smrg for (; executable < executable_count; executable++) { 3727ec681f3Smrg if (executables[executable].stages == stages) 3737ec681f3Smrg break; 3747ec681f3Smrg } 3757ec681f3Smrg assert(executable != executable_count); 3767ec681f3Smrg 3777ec681f3Smrg VkPipelineExecutableInfoKHR exec_info; 3787ec681f3Smrg exec_info.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR; 3797ec681f3Smrg exec_info.pNext = NULL; 3807ec681f3Smrg exec_info.pipeline = pipeline; 3817ec681f3Smrg exec_info.executableIndex = executable; 3827ec681f3Smrg 3837ec681f3Smrg uint32_t ir_count = 16; 3847ec681f3Smrg VkPipelineExecutableInternalRepresentationKHR ir[16]; 3857ec681f3Smrg memset(ir, 0, sizeof(ir)); 3867ec681f3Smrg result = GetPipelineExecutableInternalRepresentationsKHR(device, &exec_info, &ir_count, ir); 3877ec681f3Smrg assert(result == VK_SUCCESS); 3887ec681f3Smrg 3897ec681f3Smrg VkPipelineExecutableInternalRepresentationKHR* requested_ir = nullptr; 3907ec681f3Smrg for (unsigned i = 0; i < ir_count; ++i) { 3917ec681f3Smrg if (strcmp(ir[i].name, name) == 0) { 3927ec681f3Smrg requested_ir = &ir[i]; 3937ec681f3Smrg break; 3947ec681f3Smrg } 3957ec681f3Smrg } 3967ec681f3Smrg assert(requested_ir && "Could not find requested IR"); 3977ec681f3Smrg 3987ec681f3Smrg char *data = (char*)malloc(requested_ir->dataSize); 3997ec681f3Smrg requested_ir->pData = data; 4007ec681f3Smrg result = GetPipelineExecutableInternalRepresentationsKHR(device, &exec_info, &ir_count, ir); 4017ec681f3Smrg assert(result == VK_SUCCESS); 4027ec681f3Smrg 4037ec681f3Smrg if (remove_encoding) { 4047ec681f3Smrg for (char *c = data; *c; c++) { 4057ec681f3Smrg if (*c == ';') { 4067ec681f3Smrg for (; *c && *c != '\n'; c++) 4077ec681f3Smrg *c = ' '; 4087ec681f3Smrg } 4097ec681f3Smrg } 4107ec681f3Smrg } 4117ec681f3Smrg 4127ec681f3Smrg fprintf(output, "%s", data); 4137ec681f3Smrg free(data); 4147ec681f3Smrg} 4157ec681f3Smrg 4167ec681f3SmrgVkShaderModule __qoCreateShaderModule(VkDevice dev, const QoShaderModuleCreateInfo *module_info) 4177ec681f3Smrg{ 4187ec681f3Smrg VkShaderModuleCreateInfo vk_module_info; 4197ec681f3Smrg vk_module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 4207ec681f3Smrg vk_module_info.pNext = NULL; 4217ec681f3Smrg vk_module_info.flags = 0; 4227ec681f3Smrg vk_module_info.codeSize = module_info->spirvSize; 4237ec681f3Smrg vk_module_info.pCode = (const uint32_t*)module_info->pSpirv; 4247ec681f3Smrg 4257ec681f3Smrg VkShaderModule module; 4267ec681f3Smrg ASSERTED VkResult result = CreateShaderModule(dev, &vk_module_info, NULL, &module); 4277ec681f3Smrg assert(result == VK_SUCCESS); 4287ec681f3Smrg 4297ec681f3Smrg return module; 4307ec681f3Smrg} 4317ec681f3Smrg 4327ec681f3SmrgPipelineBuilder::PipelineBuilder(VkDevice dev) { 4337ec681f3Smrg memset(this, 0, sizeof(*this)); 4347ec681f3Smrg topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 4357ec681f3Smrg device = dev; 4367ec681f3Smrg} 4377ec681f3Smrg 4387ec681f3SmrgPipelineBuilder::~PipelineBuilder() 4397ec681f3Smrg{ 4407ec681f3Smrg DestroyPipeline(device, pipeline, NULL); 4417ec681f3Smrg 4427ec681f3Smrg for (unsigned i = 0; i < (is_compute() ? 1 : gfx_pipeline_info.stageCount); i++) { 4437ec681f3Smrg VkPipelineShaderStageCreateInfo *stage_info = &stages[i]; 4447ec681f3Smrg if (owned_stages & stage_info->stage) 4457ec681f3Smrg DestroyShaderModule(device, stage_info->module, NULL); 4467ec681f3Smrg } 4477ec681f3Smrg 4487ec681f3Smrg DestroyPipelineLayout(device, pipeline_layout, NULL); 4497ec681f3Smrg 4507ec681f3Smrg for (unsigned i = 0; i < util_bitcount64(desc_layouts_used); i++) 4517ec681f3Smrg DestroyDescriptorSetLayout(device, desc_layouts[i], NULL); 4527ec681f3Smrg 4537ec681f3Smrg DestroyRenderPass(device, render_pass, NULL); 4547ec681f3Smrg} 4557ec681f3Smrg 4567ec681f3Smrgvoid PipelineBuilder::add_desc_binding(VkShaderStageFlags stage_flags, uint32_t layout, 4577ec681f3Smrg uint32_t binding, VkDescriptorType type, uint32_t count) 4587ec681f3Smrg{ 4597ec681f3Smrg desc_layouts_used |= 1ull << layout; 4607ec681f3Smrg desc_bindings[layout][num_desc_bindings[layout]++] = {binding, type, count, stage_flags, NULL}; 4617ec681f3Smrg} 4627ec681f3Smrg 4637ec681f3Smrgvoid PipelineBuilder::add_vertex_binding(uint32_t binding, uint32_t stride, VkVertexInputRate rate) 4647ec681f3Smrg{ 4657ec681f3Smrg vs_bindings[vs_input.vertexBindingDescriptionCount++] = {binding, stride, rate}; 4667ec681f3Smrg} 4677ec681f3Smrg 4687ec681f3Smrgvoid PipelineBuilder::add_vertex_attribute(uint32_t location, uint32_t binding, VkFormat format, uint32_t offset) 4697ec681f3Smrg{ 4707ec681f3Smrg vs_attributes[vs_input.vertexAttributeDescriptionCount++] = {location, binding, format, offset}; 4717ec681f3Smrg} 4727ec681f3Smrg 4737ec681f3Smrgvoid PipelineBuilder::add_resource_decls(QoShaderModuleCreateInfo *module) 4747ec681f3Smrg{ 4757ec681f3Smrg for (unsigned i = 0; i < module->declarationCount; i++) { 4767ec681f3Smrg const QoShaderDecl *decl = &module->pDeclarations[i]; 4777ec681f3Smrg switch (decl->decl_type) { 4787ec681f3Smrg case QoShaderDeclType_ubo: 4797ec681f3Smrg add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); 4807ec681f3Smrg break; 4817ec681f3Smrg case QoShaderDeclType_ssbo: 4827ec681f3Smrg add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 4837ec681f3Smrg break; 4847ec681f3Smrg case QoShaderDeclType_img_buf: 4857ec681f3Smrg add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); 4867ec681f3Smrg break; 4877ec681f3Smrg case QoShaderDeclType_img: 4887ec681f3Smrg add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); 4897ec681f3Smrg break; 4907ec681f3Smrg case QoShaderDeclType_tex_buf: 4917ec681f3Smrg add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); 4927ec681f3Smrg break; 4937ec681f3Smrg case QoShaderDeclType_combined: 4947ec681f3Smrg add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 4957ec681f3Smrg break; 4967ec681f3Smrg case QoShaderDeclType_tex: 4977ec681f3Smrg add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); 4987ec681f3Smrg break; 4997ec681f3Smrg case QoShaderDeclType_samp: 5007ec681f3Smrg add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_SAMPLER); 5017ec681f3Smrg break; 5027ec681f3Smrg default: 5037ec681f3Smrg break; 5047ec681f3Smrg } 5057ec681f3Smrg } 5067ec681f3Smrg} 5077ec681f3Smrg 5087ec681f3Smrgvoid PipelineBuilder::add_io_decls(QoShaderModuleCreateInfo *module) 5097ec681f3Smrg{ 5107ec681f3Smrg unsigned next_vtx_offset = 0; 5117ec681f3Smrg for (unsigned i = 0; i < module->declarationCount; i++) { 5127ec681f3Smrg const QoShaderDecl *decl = &module->pDeclarations[i]; 5137ec681f3Smrg switch (decl->decl_type) { 5147ec681f3Smrg case QoShaderDeclType_in: 5157ec681f3Smrg if (module->stage == VK_SHADER_STAGE_VERTEX_BIT) { 5167ec681f3Smrg if (!strcmp(decl->type, "float") || decl->type[0] == 'v') 5177ec681f3Smrg add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_SFLOAT, next_vtx_offset); 5187ec681f3Smrg else if (decl->type[0] == 'u') 5197ec681f3Smrg add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_UINT, next_vtx_offset); 5207ec681f3Smrg else if (decl->type[0] == 'i') 5217ec681f3Smrg add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_SINT, next_vtx_offset); 5227ec681f3Smrg next_vtx_offset += 16; 5237ec681f3Smrg } 5247ec681f3Smrg break; 5257ec681f3Smrg case QoShaderDeclType_out: 5267ec681f3Smrg if (module->stage == VK_SHADER_STAGE_FRAGMENT_BIT) { 5277ec681f3Smrg if (!strcmp(decl->type, "float") || decl->type[0] == 'v') 5287ec681f3Smrg color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_SFLOAT; 5297ec681f3Smrg else if (decl->type[0] == 'u') 5307ec681f3Smrg color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_UINT; 5317ec681f3Smrg else if (decl->type[0] == 'i') 5327ec681f3Smrg color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_SINT; 5337ec681f3Smrg } 5347ec681f3Smrg break; 5357ec681f3Smrg default: 5367ec681f3Smrg break; 5377ec681f3Smrg } 5387ec681f3Smrg } 5397ec681f3Smrg if (next_vtx_offset) 5407ec681f3Smrg add_vertex_binding(0, next_vtx_offset); 5417ec681f3Smrg} 5427ec681f3Smrg 5437ec681f3Smrgvoid PipelineBuilder::add_stage(VkShaderStageFlagBits stage, VkShaderModule module, const char *name) 5447ec681f3Smrg{ 5457ec681f3Smrg VkPipelineShaderStageCreateInfo *stage_info; 5467ec681f3Smrg if (stage == VK_SHADER_STAGE_COMPUTE_BIT) 5477ec681f3Smrg stage_info = &stages[0]; 5487ec681f3Smrg else 5497ec681f3Smrg stage_info = &stages[gfx_pipeline_info.stageCount++]; 5507ec681f3Smrg stage_info->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 5517ec681f3Smrg stage_info->pNext = NULL; 5527ec681f3Smrg stage_info->flags = 0; 5537ec681f3Smrg stage_info->stage = stage; 5547ec681f3Smrg stage_info->module = module; 5557ec681f3Smrg stage_info->pName = name; 5567ec681f3Smrg stage_info->pSpecializationInfo = NULL; 5577ec681f3Smrg owned_stages |= stage; 5587ec681f3Smrg} 5597ec681f3Smrg 5607ec681f3Smrgvoid PipelineBuilder::add_stage(VkShaderStageFlagBits stage, QoShaderModuleCreateInfo module, const char *name) 5617ec681f3Smrg{ 5627ec681f3Smrg add_stage(stage, __qoCreateShaderModule(device, &module), name); 5637ec681f3Smrg add_resource_decls(&module); 5647ec681f3Smrg add_io_decls(&module); 5657ec681f3Smrg} 5667ec681f3Smrg 5677ec681f3Smrgvoid PipelineBuilder::add_vsfs(VkShaderModule vs, VkShaderModule fs) 5687ec681f3Smrg{ 5697ec681f3Smrg add_stage(VK_SHADER_STAGE_VERTEX_BIT, vs); 5707ec681f3Smrg add_stage(VK_SHADER_STAGE_FRAGMENT_BIT, fs); 5717ec681f3Smrg} 5727ec681f3Smrg 5737ec681f3Smrgvoid PipelineBuilder::add_vsfs(QoShaderModuleCreateInfo vs, QoShaderModuleCreateInfo fs) 5747ec681f3Smrg{ 5757ec681f3Smrg add_stage(VK_SHADER_STAGE_VERTEX_BIT, vs); 5767ec681f3Smrg add_stage(VK_SHADER_STAGE_FRAGMENT_BIT, fs); 5777ec681f3Smrg} 5787ec681f3Smrg 5797ec681f3Smrgvoid PipelineBuilder::add_cs(VkShaderModule cs) 5807ec681f3Smrg{ 5817ec681f3Smrg add_stage(VK_SHADER_STAGE_COMPUTE_BIT, cs); 5827ec681f3Smrg} 5837ec681f3Smrg 5847ec681f3Smrgvoid PipelineBuilder::add_cs(QoShaderModuleCreateInfo cs) 5857ec681f3Smrg{ 5867ec681f3Smrg add_stage(VK_SHADER_STAGE_COMPUTE_BIT, cs); 5877ec681f3Smrg} 5887ec681f3Smrg 5897ec681f3Smrgbool PipelineBuilder::is_compute() { 5907ec681f3Smrg return gfx_pipeline_info.stageCount == 0; 5917ec681f3Smrg} 5927ec681f3Smrg 5937ec681f3Smrgvoid PipelineBuilder::create_compute_pipeline() { 5947ec681f3Smrg VkComputePipelineCreateInfo create_info; 5957ec681f3Smrg create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; 5967ec681f3Smrg create_info.pNext = NULL; 5977ec681f3Smrg create_info.flags = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR; 5987ec681f3Smrg create_info.stage = stages[0]; 5997ec681f3Smrg create_info.layout = pipeline_layout; 6007ec681f3Smrg create_info.basePipelineHandle = VK_NULL_HANDLE; 6017ec681f3Smrg create_info.basePipelineIndex = 0; 6027ec681f3Smrg 6037ec681f3Smrg ASSERTED VkResult result = CreateComputePipelines(device, VK_NULL_HANDLE, 1, &create_info, NULL, &pipeline); 6047ec681f3Smrg assert(result == VK_SUCCESS); 6057ec681f3Smrg} 6067ec681f3Smrg 6077ec681f3Smrgvoid PipelineBuilder::create_graphics_pipeline() { 6087ec681f3Smrg /* create the create infos */ 6097ec681f3Smrg if (!samples) 6107ec681f3Smrg samples = VK_SAMPLE_COUNT_1_BIT; 6117ec681f3Smrg 6127ec681f3Smrg unsigned num_color_attachments = 0; 6137ec681f3Smrg VkPipelineColorBlendAttachmentState blend_attachment_states[16]; 6147ec681f3Smrg VkAttachmentReference color_attachments[16]; 6157ec681f3Smrg VkAttachmentDescription attachment_descs[17]; 6167ec681f3Smrg for (unsigned i = 0; i < 16; i++) { 6177ec681f3Smrg if (color_outputs[i] == VK_FORMAT_UNDEFINED) 6187ec681f3Smrg continue; 6197ec681f3Smrg 6207ec681f3Smrg VkAttachmentDescription *desc = &attachment_descs[num_color_attachments]; 6217ec681f3Smrg desc->flags = 0; 6227ec681f3Smrg desc->format = color_outputs[i]; 6237ec681f3Smrg desc->samples = samples; 6247ec681f3Smrg desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 6257ec681f3Smrg desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE; 6267ec681f3Smrg desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 6277ec681f3Smrg desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; 6287ec681f3Smrg desc->initialLayout = VK_IMAGE_LAYOUT_GENERAL; 6297ec681f3Smrg desc->finalLayout = VK_IMAGE_LAYOUT_GENERAL; 6307ec681f3Smrg 6317ec681f3Smrg VkAttachmentReference *ref = &color_attachments[num_color_attachments]; 6327ec681f3Smrg ref->attachment = num_color_attachments; 6337ec681f3Smrg ref->layout = VK_IMAGE_LAYOUT_GENERAL; 6347ec681f3Smrg 6357ec681f3Smrg VkPipelineColorBlendAttachmentState *blend = &blend_attachment_states[num_color_attachments]; 6367ec681f3Smrg blend->blendEnable = false; 6377ec681f3Smrg blend->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | 6387ec681f3Smrg VK_COLOR_COMPONENT_G_BIT | 6397ec681f3Smrg VK_COLOR_COMPONENT_B_BIT | 6407ec681f3Smrg VK_COLOR_COMPONENT_A_BIT; 6417ec681f3Smrg 6427ec681f3Smrg num_color_attachments++; 6437ec681f3Smrg } 6447ec681f3Smrg 6457ec681f3Smrg unsigned num_attachments = num_color_attachments; 6467ec681f3Smrg VkAttachmentReference ds_attachment; 6477ec681f3Smrg if (ds_output != VK_FORMAT_UNDEFINED) { 6487ec681f3Smrg VkAttachmentDescription *desc = &attachment_descs[num_attachments]; 6497ec681f3Smrg desc->flags = 0; 6507ec681f3Smrg desc->format = ds_output; 6517ec681f3Smrg desc->samples = samples; 6527ec681f3Smrg desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 6537ec681f3Smrg desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE; 6547ec681f3Smrg desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 6557ec681f3Smrg desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; 6567ec681f3Smrg desc->initialLayout = VK_IMAGE_LAYOUT_GENERAL; 6577ec681f3Smrg desc->finalLayout = VK_IMAGE_LAYOUT_GENERAL; 6587ec681f3Smrg 6597ec681f3Smrg ds_attachment.attachment = num_color_attachments; 6607ec681f3Smrg ds_attachment.layout = VK_IMAGE_LAYOUT_GENERAL; 6617ec681f3Smrg 6627ec681f3Smrg num_attachments++; 6637ec681f3Smrg } 6647ec681f3Smrg 6657ec681f3Smrg vs_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 6667ec681f3Smrg vs_input.pNext = NULL; 6677ec681f3Smrg vs_input.flags = 0; 6687ec681f3Smrg vs_input.pVertexBindingDescriptions = vs_bindings; 6697ec681f3Smrg vs_input.pVertexAttributeDescriptions = vs_attributes; 6707ec681f3Smrg 6717ec681f3Smrg VkPipelineInputAssemblyStateCreateInfo assembly_state; 6727ec681f3Smrg assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 6737ec681f3Smrg assembly_state.pNext = NULL; 6747ec681f3Smrg assembly_state.flags = 0; 6757ec681f3Smrg assembly_state.topology = topology; 6767ec681f3Smrg assembly_state.primitiveRestartEnable = false; 6777ec681f3Smrg 6787ec681f3Smrg VkPipelineTessellationStateCreateInfo tess_state; 6797ec681f3Smrg tess_state.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; 6807ec681f3Smrg tess_state.pNext = NULL; 6817ec681f3Smrg tess_state.flags = 0; 6827ec681f3Smrg tess_state.patchControlPoints = patch_size; 6837ec681f3Smrg 6847ec681f3Smrg VkPipelineViewportStateCreateInfo viewport_state; 6857ec681f3Smrg viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 6867ec681f3Smrg viewport_state.pNext = NULL; 6877ec681f3Smrg viewport_state.flags = 0; 6887ec681f3Smrg viewport_state.viewportCount = 1; 6897ec681f3Smrg viewport_state.pViewports = NULL; 6907ec681f3Smrg viewport_state.scissorCount = 1; 6917ec681f3Smrg viewport_state.pScissors = NULL; 6927ec681f3Smrg 6937ec681f3Smrg VkPipelineRasterizationStateCreateInfo rasterization_state; 6947ec681f3Smrg rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 6957ec681f3Smrg rasterization_state.pNext = NULL; 6967ec681f3Smrg rasterization_state.flags = 0; 6977ec681f3Smrg rasterization_state.depthClampEnable = false; 6987ec681f3Smrg rasterization_state.rasterizerDiscardEnable = false; 6997ec681f3Smrg rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; 7007ec681f3Smrg rasterization_state.cullMode = VK_CULL_MODE_NONE; 7017ec681f3Smrg rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 7027ec681f3Smrg rasterization_state.depthBiasEnable = false; 7037ec681f3Smrg rasterization_state.lineWidth = 1.0; 7047ec681f3Smrg 7057ec681f3Smrg VkPipelineMultisampleStateCreateInfo ms_state; 7067ec681f3Smrg ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 7077ec681f3Smrg ms_state.pNext = NULL; 7087ec681f3Smrg ms_state.flags = 0; 7097ec681f3Smrg ms_state.rasterizationSamples = samples; 7107ec681f3Smrg ms_state.sampleShadingEnable = sample_shading_enable; 7117ec681f3Smrg ms_state.minSampleShading = min_sample_shading; 7127ec681f3Smrg VkSampleMask sample_mask = 0xffffffff; 7137ec681f3Smrg ms_state.pSampleMask = &sample_mask; 7147ec681f3Smrg ms_state.alphaToCoverageEnable = false; 7157ec681f3Smrg ms_state.alphaToOneEnable = false; 7167ec681f3Smrg 7177ec681f3Smrg VkPipelineDepthStencilStateCreateInfo ds_state; 7187ec681f3Smrg ds_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 7197ec681f3Smrg ds_state.pNext = NULL; 7207ec681f3Smrg ds_state.flags = 0; 7217ec681f3Smrg ds_state.depthTestEnable = ds_output != VK_FORMAT_UNDEFINED; 7227ec681f3Smrg ds_state.depthWriteEnable = true; 7237ec681f3Smrg ds_state.depthCompareOp = VK_COMPARE_OP_ALWAYS; 7247ec681f3Smrg ds_state.depthBoundsTestEnable = false; 7257ec681f3Smrg ds_state.stencilTestEnable = true; 7267ec681f3Smrg ds_state.front.failOp = VK_STENCIL_OP_KEEP; 7277ec681f3Smrg ds_state.front.passOp = VK_STENCIL_OP_REPLACE; 7287ec681f3Smrg ds_state.front.depthFailOp = VK_STENCIL_OP_REPLACE; 7297ec681f3Smrg ds_state.front.compareOp = VK_COMPARE_OP_ALWAYS; 7307ec681f3Smrg ds_state.front.compareMask = 0xffffffff, 7317ec681f3Smrg ds_state.front.writeMask = 0; 7327ec681f3Smrg ds_state.front.reference = 0; 7337ec681f3Smrg ds_state.back = ds_state.front; 7347ec681f3Smrg 7357ec681f3Smrg VkPipelineColorBlendStateCreateInfo color_blend_state; 7367ec681f3Smrg color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 7377ec681f3Smrg color_blend_state.pNext = NULL; 7387ec681f3Smrg color_blend_state.flags = 0; 7397ec681f3Smrg color_blend_state.logicOpEnable = false; 7407ec681f3Smrg color_blend_state.attachmentCount = num_color_attachments; 7417ec681f3Smrg color_blend_state.pAttachments = blend_attachment_states; 7427ec681f3Smrg 7437ec681f3Smrg VkDynamicState dynamic_states[9] = { 7447ec681f3Smrg VK_DYNAMIC_STATE_VIEWPORT, 7457ec681f3Smrg VK_DYNAMIC_STATE_SCISSOR, 7467ec681f3Smrg VK_DYNAMIC_STATE_LINE_WIDTH, 7477ec681f3Smrg VK_DYNAMIC_STATE_DEPTH_BIAS, 7487ec681f3Smrg VK_DYNAMIC_STATE_BLEND_CONSTANTS, 7497ec681f3Smrg VK_DYNAMIC_STATE_DEPTH_BOUNDS, 7507ec681f3Smrg VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, 7517ec681f3Smrg VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, 7527ec681f3Smrg VK_DYNAMIC_STATE_STENCIL_REFERENCE 7537ec681f3Smrg }; 7547ec681f3Smrg 7557ec681f3Smrg VkPipelineDynamicStateCreateInfo dynamic_state; 7567ec681f3Smrg dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 7577ec681f3Smrg dynamic_state.pNext = NULL; 7587ec681f3Smrg dynamic_state.flags = 0; 7597ec681f3Smrg dynamic_state.dynamicStateCount = sizeof(dynamic_states) / sizeof(VkDynamicState); 7607ec681f3Smrg dynamic_state.pDynamicStates = dynamic_states; 7617ec681f3Smrg 7627ec681f3Smrg gfx_pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 7637ec681f3Smrg gfx_pipeline_info.pNext = NULL; 7647ec681f3Smrg gfx_pipeline_info.flags = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR; 7657ec681f3Smrg gfx_pipeline_info.pVertexInputState = &vs_input; 7667ec681f3Smrg gfx_pipeline_info.pInputAssemblyState = &assembly_state; 7677ec681f3Smrg gfx_pipeline_info.pTessellationState = &tess_state; 7687ec681f3Smrg gfx_pipeline_info.pViewportState = &viewport_state; 7697ec681f3Smrg gfx_pipeline_info.pRasterizationState = &rasterization_state; 7707ec681f3Smrg gfx_pipeline_info.pMultisampleState = &ms_state; 7717ec681f3Smrg gfx_pipeline_info.pDepthStencilState = &ds_state; 7727ec681f3Smrg gfx_pipeline_info.pColorBlendState = &color_blend_state; 7737ec681f3Smrg gfx_pipeline_info.pDynamicState = &dynamic_state; 7747ec681f3Smrg gfx_pipeline_info.subpass = 0; 7757ec681f3Smrg 7767ec681f3Smrg /* create the objects used to create the pipeline */ 7777ec681f3Smrg VkSubpassDescription subpass; 7787ec681f3Smrg subpass.flags = 0; 7797ec681f3Smrg subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 7807ec681f3Smrg subpass.inputAttachmentCount = 0; 7817ec681f3Smrg subpass.pInputAttachments = NULL; 7827ec681f3Smrg subpass.colorAttachmentCount = num_color_attachments; 7837ec681f3Smrg subpass.pColorAttachments = color_attachments; 7847ec681f3Smrg subpass.pResolveAttachments = NULL; 7857ec681f3Smrg subpass.pDepthStencilAttachment = ds_output == VK_FORMAT_UNDEFINED ? NULL : &ds_attachment; 7867ec681f3Smrg subpass.preserveAttachmentCount = 0; 7877ec681f3Smrg subpass.pPreserveAttachments = NULL; 7887ec681f3Smrg 7897ec681f3Smrg VkRenderPassCreateInfo renderpass_info; 7907ec681f3Smrg renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 7917ec681f3Smrg renderpass_info.pNext = NULL; 7927ec681f3Smrg renderpass_info.flags = 0; 7937ec681f3Smrg renderpass_info.attachmentCount = num_attachments; 7947ec681f3Smrg renderpass_info.pAttachments = attachment_descs; 7957ec681f3Smrg renderpass_info.subpassCount = 1; 7967ec681f3Smrg renderpass_info.pSubpasses = &subpass; 7977ec681f3Smrg renderpass_info.dependencyCount = 0; 7987ec681f3Smrg renderpass_info.pDependencies = NULL; 7997ec681f3Smrg 8007ec681f3Smrg ASSERTED VkResult result = CreateRenderPass(device, &renderpass_info, NULL, &render_pass); 8017ec681f3Smrg assert(result == VK_SUCCESS); 8027ec681f3Smrg 8037ec681f3Smrg gfx_pipeline_info.layout = pipeline_layout; 8047ec681f3Smrg gfx_pipeline_info.renderPass = render_pass; 8057ec681f3Smrg 8067ec681f3Smrg /* create the pipeline */ 8077ec681f3Smrg gfx_pipeline_info.pStages = stages; 8087ec681f3Smrg 8097ec681f3Smrg result = CreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &gfx_pipeline_info, NULL, &pipeline); 8107ec681f3Smrg assert(result == VK_SUCCESS); 8117ec681f3Smrg} 8127ec681f3Smrg 8137ec681f3Smrgvoid PipelineBuilder::create_pipeline() { 8147ec681f3Smrg unsigned num_desc_layouts = 0; 8157ec681f3Smrg for (unsigned i = 0; i < 64; i++) { 8167ec681f3Smrg if (!(desc_layouts_used & (1ull << i))) 8177ec681f3Smrg continue; 8187ec681f3Smrg 8197ec681f3Smrg VkDescriptorSetLayoutCreateInfo desc_layout_info; 8207ec681f3Smrg desc_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 8217ec681f3Smrg desc_layout_info.pNext = NULL; 8227ec681f3Smrg desc_layout_info.flags = 0; 8237ec681f3Smrg desc_layout_info.bindingCount = num_desc_bindings[i]; 8247ec681f3Smrg desc_layout_info.pBindings = desc_bindings[i]; 8257ec681f3Smrg 8267ec681f3Smrg ASSERTED VkResult result = CreateDescriptorSetLayout(device, &desc_layout_info, NULL, &desc_layouts[num_desc_layouts]); 8277ec681f3Smrg assert(result == VK_SUCCESS); 8287ec681f3Smrg num_desc_layouts++; 8297ec681f3Smrg } 8307ec681f3Smrg 8317ec681f3Smrg VkPipelineLayoutCreateInfo pipeline_layout_info; 8327ec681f3Smrg pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 8337ec681f3Smrg pipeline_layout_info.pNext = NULL; 8347ec681f3Smrg pipeline_layout_info.flags = 0; 8357ec681f3Smrg pipeline_layout_info.pushConstantRangeCount = 1; 8367ec681f3Smrg pipeline_layout_info.pPushConstantRanges = &push_constant_range; 8377ec681f3Smrg pipeline_layout_info.setLayoutCount = num_desc_layouts; 8387ec681f3Smrg pipeline_layout_info.pSetLayouts = desc_layouts; 8397ec681f3Smrg 8407ec681f3Smrg ASSERTED VkResult result = CreatePipelineLayout(device, &pipeline_layout_info, NULL, &pipeline_layout); 8417ec681f3Smrg assert(result == VK_SUCCESS); 8427ec681f3Smrg 8437ec681f3Smrg if (is_compute()) 8447ec681f3Smrg create_compute_pipeline(); 8457ec681f3Smrg else 8467ec681f3Smrg create_graphics_pipeline(); 8477ec681f3Smrg} 8487ec681f3Smrg 8497ec681f3Smrgvoid PipelineBuilder::print_ir(VkShaderStageFlagBits stage_flags, const char *name, bool remove_encoding) 8507ec681f3Smrg{ 8517ec681f3Smrg if (!pipeline) 8527ec681f3Smrg create_pipeline(); 8537ec681f3Smrg print_pipeline_ir(device, pipeline, stage_flags, name, remove_encoding); 8547ec681f3Smrg} 855