Path: blob/21.2-virgl/src/amd/compiler/tests/helpers.cpp
7099 views
/*1* Copyright © 2020 Valve Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*22*/23#include "helpers.h"24#include "vulkan/vk_format.h"25#include "common/amd_family.h"26#include <stdio.h>27#include <sstream>28#include <llvm-c/Target.h>29#include <mutex>3031using namespace aco;3233extern "C" {34PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(35VkInstance instance,36const char* pName);37}3839ac_shader_config config;40radv_shader_info info;41std::unique_ptr<Program> program;42Builder bld(NULL);43Temp inputs[16];4445static VkInstance instance_cache[CHIP_LAST] = {VK_NULL_HANDLE};46static VkDevice device_cache[CHIP_LAST] = {VK_NULL_HANDLE};47static std::mutex create_device_mutex;4849#define FUNCTION_LIST\50ITEM(CreateInstance)\51ITEM(DestroyInstance)\52ITEM(EnumeratePhysicalDevices)\53ITEM(GetPhysicalDeviceProperties2)\54ITEM(CreateDevice)\55ITEM(DestroyDevice)\56ITEM(CreateShaderModule)\57ITEM(DestroyShaderModule)\58ITEM(CreateGraphicsPipelines)\59ITEM(CreateComputePipelines)\60ITEM(DestroyPipeline)\61ITEM(CreateDescriptorSetLayout)\62ITEM(DestroyDescriptorSetLayout)\63ITEM(CreatePipelineLayout)\64ITEM(DestroyPipelineLayout)\65ITEM(CreateRenderPass)\66ITEM(DestroyRenderPass)\67ITEM(GetPipelineExecutablePropertiesKHR)\68ITEM(GetPipelineExecutableInternalRepresentationsKHR)6970#define ITEM(n) PFN_vk##n n;71FUNCTION_LIST72#undef ITEM7374void create_program(enum chip_class chip_class, Stage stage, unsigned wave_size, enum radeon_family family)75{76memset(&config, 0, sizeof(config));77info.wave_size = wave_size;7879program.reset(new Program);80aco::init_program(program.get(), stage, &info, chip_class, family, false, &config);81program->workgroup_size = UINT_MAX;82calc_min_waves(program.get());8384program->debug.func = nullptr;85program->debug.private_data = nullptr;8687program->debug.output = output;88program->debug.shorten_messages = true;89program->debug.func = nullptr;90program->debug.private_data = nullptr;9192Block *block = program->create_and_insert_block();93block->kind = block_kind_top_level;9495bld = Builder(program.get(), &program->blocks[0]);9697config.float_mode = program->blocks[0].fp_mode.val;98}99100bool setup_cs(const char *input_spec, enum chip_class chip_class,101enum radeon_family family, const char* subvariant,102unsigned wave_size)103{104if (!set_variant(chip_class, subvariant))105return false;106107memset(&info, 0, sizeof(info));108info.cs.block_size[0] = 1;109info.cs.block_size[1] = 1;110info.cs.block_size[2] = 1;111112create_program(chip_class, compute_cs, wave_size, family);113114if (input_spec) {115unsigned num_inputs = DIV_ROUND_UP(strlen(input_spec), 3u);116aco_ptr<Instruction> startpgm{create_instruction<Pseudo_instruction>(aco_opcode::p_startpgm, Format::PSEUDO, 0, num_inputs)};117for (unsigned i = 0; i < num_inputs; i++) {118RegClass cls(input_spec[i * 3] == 'v' ? RegType::vgpr : RegType::sgpr, input_spec[i * 3 + 1] - '0');119inputs[i] = bld.tmp(cls);120startpgm->definitions[i] = Definition(inputs[i]);121}122bld.insert(std::move(startpgm));123}124125return true;126}127128void finish_program(Program *prog)129{130for (Block& BB : prog->blocks) {131for (unsigned idx : BB.linear_preds)132prog->blocks[idx].linear_succs.emplace_back(BB.index);133for (unsigned idx : BB.logical_preds)134prog->blocks[idx].logical_succs.emplace_back(BB.index);135}136137for (Block& block : prog->blocks) {138if (block.linear_succs.size() == 0) {139block.kind |= block_kind_uniform;140Builder(prog, &block).sopp(aco_opcode::s_endpgm);141}142}143}144145void finish_validator_test()146{147finish_program(program.get());148aco_print_program(program.get(), output);149fprintf(output, "Validation results:\n");150if (aco::validate_ir(program.get()))151fprintf(output, "Validation passed\n");152else153fprintf(output, "Validation failed\n");154}155156void finish_opt_test()157{158finish_program(program.get());159if (!aco::validate_ir(program.get())) {160fail_test("Validation before optimization failed");161return;162}163aco::optimize(program.get());164if (!aco::validate_ir(program.get())) {165fail_test("Validation after optimization failed");166return;167}168aco_print_program(program.get(), output);169}170171void finish_ra_test(ra_test_policy policy)172{173finish_program(program.get());174if (!aco::validate_ir(program.get())) {175fail_test("Validation before register allocation failed");176return;177}178179program->workgroup_size = program->wave_size;180aco::live live_vars = aco::live_var_analysis(program.get());181aco::register_allocation(program.get(), live_vars.live_out, policy);182183if (aco::validate_ra(program.get())) {184fail_test("Validation after register allocation failed");185return;186}187188finish_program(program.get());189aco::optimize_postRA(program.get());190}191192void finish_optimizer_postRA_test()193{194finish_program(program.get());195aco::optimize_postRA(program.get());196aco_print_program(program.get(), output);197}198199void finish_to_hw_instr_test()200{201finish_program(program.get());202aco::lower_to_hw_instr(program.get());203aco_print_program(program.get(), output);204}205206void finish_insert_nops_test()207{208finish_program(program.get());209aco::insert_NOPs(program.get());210aco_print_program(program.get(), output);211}212213void finish_form_hard_clause_test()214{215finish_program(program.get());216aco::form_hard_clauses(program.get());217aco_print_program(program.get(), output);218}219220void finish_assembler_test()221{222finish_program(program.get());223std::vector<uint32_t> binary;224unsigned exec_size = emit_program(program.get(), binary);225226/* we could use CLRX for disassembly but that would require it to be227* installed */228if (program->chip_class >= GFX8) {229print_asm(program.get(), binary, exec_size / 4u, output);230} else {231//TODO: maybe we should use CLRX and skip this test if it's not available?232for (uint32_t dword : binary)233fprintf(output, "%.8x\n", dword);234}235}236237void writeout(unsigned i, Temp tmp)238{239if (tmp.id())240bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), tmp);241else242bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i));243}244245void writeout(unsigned i, aco::Builder::Result res)246{247bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), res);248}249250void writeout(unsigned i, Operand op)251{252bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), op);253}254255void writeout(unsigned i, Operand op0, Operand op1)256{257bld.pseudo(aco_opcode::p_unit_test, Operand::c32(i), op0, op1);258}259260Temp fneg(Temp src)261{262return bld.vop2(aco_opcode::v_mul_f32, bld.def(v1), Operand::c32(0xbf800000u), src);263}264265Temp fabs(Temp src)266{267Builder::Result res =268bld.vop2_e64(aco_opcode::v_mul_f32, bld.def(v1), Operand::c32(0x3f800000u), src);269res.instr->vop3().abs[1] = true;270return res;271}272273VkDevice get_vk_device(enum chip_class chip_class)274{275enum radeon_family family;276switch (chip_class) {277case GFX6:278family = CHIP_TAHITI;279break;280case GFX7:281family = CHIP_BONAIRE;282break;283case GFX8:284family = CHIP_POLARIS10;285break;286case GFX9:287family = CHIP_VEGA10;288break;289case GFX10:290family = CHIP_NAVI10;291break;292case GFX10_3:293family = CHIP_SIENNA_CICHLID;294break;295default:296family = CHIP_UNKNOWN;297break;298}299return get_vk_device(family);300}301302VkDevice get_vk_device(enum radeon_family family)303{304assert(family != CHIP_UNKNOWN);305306std::lock_guard<std::mutex> guard(create_device_mutex);307308if (device_cache[family])309return device_cache[family];310311setenv("RADV_FORCE_FAMILY", ac_get_family_name(family), 1);312313VkApplicationInfo app_info = {};314app_info.pApplicationName = "aco_tests";315app_info.apiVersion = VK_API_VERSION_1_2;316VkInstanceCreateInfo instance_create_info = {};317instance_create_info.pApplicationInfo = &app_info;318instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;319ASSERTED VkResult result = ((PFN_vkCreateInstance)vk_icdGetInstanceProcAddr(NULL, "vkCreateInstance"))(&instance_create_info, NULL, &instance_cache[family]);320assert(result == VK_SUCCESS);321322#define ITEM(n) n = (PFN_vk##n)vk_icdGetInstanceProcAddr(instance_cache[family], "vk" #n);323FUNCTION_LIST324#undef ITEM325326uint32_t device_count = 1;327VkPhysicalDevice device = VK_NULL_HANDLE;328result = EnumeratePhysicalDevices(instance_cache[family], &device_count, &device);329assert(result == VK_SUCCESS);330assert(device != VK_NULL_HANDLE);331332VkDeviceCreateInfo device_create_info = {};333device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;334static const char *extensions[] = {"VK_KHR_pipeline_executable_properties"};335device_create_info.enabledExtensionCount = sizeof(extensions) / sizeof(extensions[0]);336device_create_info.ppEnabledExtensionNames = extensions;337result = CreateDevice(device, &device_create_info, NULL, &device_cache[family]);338339return device_cache[family];340}341342static struct DestroyDevices {343~DestroyDevices() {344for (unsigned i = 0; i < CHIP_LAST; i++) {345if (!device_cache[i])346continue;347DestroyDevice(device_cache[i], NULL);348DestroyInstance(instance_cache[i], NULL);349}350}351} destroy_devices;352353void print_pipeline_ir(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits stages,354const char *name, bool remove_encoding)355{356uint32_t executable_count = 16;357VkPipelineExecutablePropertiesKHR executables[16];358VkPipelineInfoKHR pipeline_info;359pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR;360pipeline_info.pNext = NULL;361pipeline_info.pipeline = pipeline;362ASSERTED VkResult result = GetPipelineExecutablePropertiesKHR(device, &pipeline_info, &executable_count, executables);363assert(result == VK_SUCCESS);364365uint32_t executable = 0;366for (; executable < executable_count; executable++) {367if (executables[executable].stages == stages)368break;369}370assert(executable != executable_count);371372VkPipelineExecutableInfoKHR exec_info;373exec_info.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR;374exec_info.pNext = NULL;375exec_info.pipeline = pipeline;376exec_info.executableIndex = executable;377378uint32_t ir_count = 16;379VkPipelineExecutableInternalRepresentationKHR ir[16];380memset(ir, 0, sizeof(ir));381result = GetPipelineExecutableInternalRepresentationsKHR(device, &exec_info, &ir_count, ir);382assert(result == VK_SUCCESS);383384for (unsigned i = 0; i < ir_count; i++) {385if (strcmp(ir[i].name, name))386continue;387388char *data = (char*)malloc(ir[i].dataSize);389ir[i].pData = data;390result = GetPipelineExecutableInternalRepresentationsKHR(device, &exec_info, &ir_count, ir);391assert(result == VK_SUCCESS);392393if (remove_encoding) {394for (char *c = data; *c; c++) {395if (*c == ';') {396for (; *c && *c != '\n'; c++)397*c = ' ';398}399}400}401402fprintf(output, "%s", data);403free(data);404return;405}406}407408VkShaderModule __qoCreateShaderModule(VkDevice dev, const QoShaderModuleCreateInfo *module_info)409{410VkShaderModuleCreateInfo vk_module_info;411vk_module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;412vk_module_info.pNext = NULL;413vk_module_info.flags = 0;414vk_module_info.codeSize = module_info->spirvSize;415vk_module_info.pCode = (const uint32_t*)module_info->pSpirv;416417VkShaderModule module;418ASSERTED VkResult result = CreateShaderModule(dev, &vk_module_info, NULL, &module);419assert(result == VK_SUCCESS);420421return module;422}423424PipelineBuilder::PipelineBuilder(VkDevice dev) {425memset(this, 0, sizeof(*this));426topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;427device = dev;428}429430PipelineBuilder::~PipelineBuilder()431{432DestroyPipeline(device, pipeline, NULL);433434for (unsigned i = 0; i < (is_compute() ? 1 : gfx_pipeline_info.stageCount); i++) {435VkPipelineShaderStageCreateInfo *stage_info = &stages[i];436if (owned_stages & stage_info->stage)437DestroyShaderModule(device, stage_info->module, NULL);438}439440DestroyPipelineLayout(device, pipeline_layout, NULL);441442for (unsigned i = 0; i < util_bitcount64(desc_layouts_used); i++)443DestroyDescriptorSetLayout(device, desc_layouts[i], NULL);444445DestroyRenderPass(device, render_pass, NULL);446}447448void PipelineBuilder::add_desc_binding(VkShaderStageFlags stage_flags, uint32_t layout,449uint32_t binding, VkDescriptorType type, uint32_t count)450{451desc_layouts_used |= 1ull << layout;452desc_bindings[layout][num_desc_bindings[layout]++] = {binding, type, count, stage_flags, NULL};453}454455void PipelineBuilder::add_vertex_binding(uint32_t binding, uint32_t stride, VkVertexInputRate rate)456{457vs_bindings[vs_input.vertexBindingDescriptionCount++] = {binding, stride, rate};458}459460void PipelineBuilder::add_vertex_attribute(uint32_t location, uint32_t binding, VkFormat format, uint32_t offset)461{462vs_attributes[vs_input.vertexAttributeDescriptionCount++] = {location, binding, format, offset};463}464465void PipelineBuilder::add_resource_decls(QoShaderModuleCreateInfo *module)466{467for (unsigned i = 0; i < module->declarationCount; i++) {468const QoShaderDecl *decl = &module->pDeclarations[i];469switch (decl->decl_type) {470case QoShaderDeclType_ubo:471add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);472break;473case QoShaderDeclType_ssbo:474add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);475break;476case QoShaderDeclType_img_buf:477add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);478break;479case QoShaderDeclType_img:480add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);481break;482case QoShaderDeclType_tex_buf:483add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);484break;485case QoShaderDeclType_combined:486add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);487break;488case QoShaderDeclType_tex:489add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);490break;491case QoShaderDeclType_samp:492add_desc_binding(module->stage, decl->set, decl->binding, VK_DESCRIPTOR_TYPE_SAMPLER);493break;494default:495break;496}497}498}499500void PipelineBuilder::add_io_decls(QoShaderModuleCreateInfo *module)501{502unsigned next_vtx_offset = 0;503for (unsigned i = 0; i < module->declarationCount; i++) {504const QoShaderDecl *decl = &module->pDeclarations[i];505switch (decl->decl_type) {506case QoShaderDeclType_in:507if (module->stage == VK_SHADER_STAGE_VERTEX_BIT) {508if (!strcmp(decl->type, "float") || decl->type[0] == 'v')509add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_SFLOAT, next_vtx_offset);510else if (decl->type[0] == 'u')511add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_UINT, next_vtx_offset);512else if (decl->type[0] == 'i')513add_vertex_attribute(decl->location, 0, VK_FORMAT_R32G32B32A32_SINT, next_vtx_offset);514next_vtx_offset += 16;515}516break;517case QoShaderDeclType_out:518if (module->stage == VK_SHADER_STAGE_FRAGMENT_BIT) {519if (!strcmp(decl->type, "float") || decl->type[0] == 'v')520color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_SFLOAT;521else if (decl->type[0] == 'u')522color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_UINT;523else if (decl->type[0] == 'i')524color_outputs[decl->location] = VK_FORMAT_R32G32B32A32_SINT;525}526break;527default:528break;529}530}531if (next_vtx_offset)532add_vertex_binding(0, next_vtx_offset);533}534535void PipelineBuilder::add_stage(VkShaderStageFlagBits stage, VkShaderModule module, const char *name)536{537VkPipelineShaderStageCreateInfo *stage_info;538if (stage == VK_SHADER_STAGE_COMPUTE_BIT)539stage_info = &stages[0];540else541stage_info = &stages[gfx_pipeline_info.stageCount++];542stage_info->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;543stage_info->pNext = NULL;544stage_info->flags = 0;545stage_info->stage = stage;546stage_info->module = module;547stage_info->pName = name;548stage_info->pSpecializationInfo = NULL;549owned_stages |= stage;550}551552void PipelineBuilder::add_stage(VkShaderStageFlagBits stage, QoShaderModuleCreateInfo module, const char *name)553{554add_stage(stage, __qoCreateShaderModule(device, &module), name);555add_resource_decls(&module);556add_io_decls(&module);557}558559void PipelineBuilder::add_vsfs(VkShaderModule vs, VkShaderModule fs)560{561add_stage(VK_SHADER_STAGE_VERTEX_BIT, vs);562add_stage(VK_SHADER_STAGE_FRAGMENT_BIT, fs);563}564565void PipelineBuilder::add_vsfs(QoShaderModuleCreateInfo vs, QoShaderModuleCreateInfo fs)566{567add_stage(VK_SHADER_STAGE_VERTEX_BIT, vs);568add_stage(VK_SHADER_STAGE_FRAGMENT_BIT, fs);569}570571void PipelineBuilder::add_cs(VkShaderModule cs)572{573add_stage(VK_SHADER_STAGE_COMPUTE_BIT, cs);574}575576void PipelineBuilder::add_cs(QoShaderModuleCreateInfo cs)577{578add_stage(VK_SHADER_STAGE_COMPUTE_BIT, cs);579}580581bool PipelineBuilder::is_compute() {582return gfx_pipeline_info.stageCount == 0;583}584585void PipelineBuilder::create_compute_pipeline() {586VkComputePipelineCreateInfo create_info;587create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;588create_info.pNext = NULL;589create_info.flags = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;590create_info.stage = stages[0];591create_info.layout = pipeline_layout;592create_info.basePipelineHandle = VK_NULL_HANDLE;593create_info.basePipelineIndex = 0;594595ASSERTED VkResult result = CreateComputePipelines(device, VK_NULL_HANDLE, 1, &create_info, NULL, &pipeline);596assert(result == VK_SUCCESS);597}598599void PipelineBuilder::create_graphics_pipeline() {600/* create the create infos */601if (!samples)602samples = VK_SAMPLE_COUNT_1_BIT;603604unsigned num_color_attachments = 0;605VkPipelineColorBlendAttachmentState blend_attachment_states[16];606VkAttachmentReference color_attachments[16];607VkAttachmentDescription attachment_descs[17];608for (unsigned i = 0; i < 16; i++) {609if (color_outputs[i] == VK_FORMAT_UNDEFINED)610continue;611612VkAttachmentDescription *desc = &attachment_descs[num_color_attachments];613desc->flags = 0;614desc->format = color_outputs[i];615desc->samples = samples;616desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;617desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;618desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;619desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;620desc->initialLayout = VK_IMAGE_LAYOUT_GENERAL;621desc->finalLayout = VK_IMAGE_LAYOUT_GENERAL;622623VkAttachmentReference *ref = &color_attachments[num_color_attachments];624ref->attachment = num_color_attachments;625ref->layout = VK_IMAGE_LAYOUT_GENERAL;626627VkPipelineColorBlendAttachmentState *blend = &blend_attachment_states[num_color_attachments];628blend->blendEnable = false;629blend->colorWriteMask = VK_COLOR_COMPONENT_R_BIT |630VK_COLOR_COMPONENT_G_BIT |631VK_COLOR_COMPONENT_B_BIT |632VK_COLOR_COMPONENT_A_BIT;633634num_color_attachments++;635}636637unsigned num_attachments = num_color_attachments;638VkAttachmentReference ds_attachment;639if (ds_output != VK_FORMAT_UNDEFINED) {640VkAttachmentDescription *desc = &attachment_descs[num_attachments];641desc->flags = 0;642desc->format = ds_output;643desc->samples = samples;644desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;645desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;646desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;647desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;648desc->initialLayout = VK_IMAGE_LAYOUT_GENERAL;649desc->finalLayout = VK_IMAGE_LAYOUT_GENERAL;650651ds_attachment.attachment = num_color_attachments;652ds_attachment.layout = VK_IMAGE_LAYOUT_GENERAL;653654num_attachments++;655}656657vs_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;658vs_input.pNext = NULL;659vs_input.flags = 0;660vs_input.pVertexBindingDescriptions = vs_bindings;661vs_input.pVertexAttributeDescriptions = vs_attributes;662663VkPipelineInputAssemblyStateCreateInfo assembly_state;664assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;665assembly_state.pNext = NULL;666assembly_state.flags = 0;667assembly_state.topology = topology;668assembly_state.primitiveRestartEnable = false;669670VkPipelineTessellationStateCreateInfo tess_state;671tess_state.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;672tess_state.pNext = NULL;673tess_state.flags = 0;674tess_state.patchControlPoints = patch_size;675676VkPipelineViewportStateCreateInfo viewport_state;677viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;678viewport_state.pNext = NULL;679viewport_state.flags = 0;680viewport_state.viewportCount = 1;681viewport_state.pViewports = NULL;682viewport_state.scissorCount = 1;683viewport_state.pScissors = NULL;684685VkPipelineRasterizationStateCreateInfo rasterization_state;686rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;687rasterization_state.pNext = NULL;688rasterization_state.flags = 0;689rasterization_state.depthClampEnable = false;690rasterization_state.rasterizerDiscardEnable = false;691rasterization_state.polygonMode = VK_POLYGON_MODE_FILL;692rasterization_state.cullMode = VK_CULL_MODE_NONE;693rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;694rasterization_state.depthBiasEnable = false;695rasterization_state.lineWidth = 1.0;696697VkPipelineMultisampleStateCreateInfo ms_state;698ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;699ms_state.pNext = NULL;700ms_state.flags = 0;701ms_state.rasterizationSamples = samples;702ms_state.sampleShadingEnable = sample_shading_enable;703ms_state.minSampleShading = min_sample_shading;704VkSampleMask sample_mask = 0xffffffff;705ms_state.pSampleMask = &sample_mask;706ms_state.alphaToCoverageEnable = false;707ms_state.alphaToOneEnable = false;708709VkPipelineDepthStencilStateCreateInfo ds_state;710ds_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;711ds_state.pNext = NULL;712ds_state.flags = 0;713ds_state.depthTestEnable = ds_output != VK_FORMAT_UNDEFINED;714ds_state.depthWriteEnable = true;715ds_state.depthCompareOp = VK_COMPARE_OP_ALWAYS;716ds_state.depthBoundsTestEnable = false;717ds_state.stencilTestEnable = true;718ds_state.front.failOp = VK_STENCIL_OP_KEEP;719ds_state.front.passOp = VK_STENCIL_OP_REPLACE;720ds_state.front.depthFailOp = VK_STENCIL_OP_REPLACE;721ds_state.front.compareOp = VK_COMPARE_OP_ALWAYS;722ds_state.front.compareMask = 0xffffffff,723ds_state.front.writeMask = 0;724ds_state.front.reference = 0;725ds_state.back = ds_state.front;726727VkPipelineColorBlendStateCreateInfo color_blend_state;728color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;729color_blend_state.pNext = NULL;730color_blend_state.flags = 0;731color_blend_state.logicOpEnable = false;732color_blend_state.attachmentCount = num_color_attachments;733color_blend_state.pAttachments = blend_attachment_states;734735VkDynamicState dynamic_states[9] = {736VK_DYNAMIC_STATE_VIEWPORT,737VK_DYNAMIC_STATE_SCISSOR,738VK_DYNAMIC_STATE_LINE_WIDTH,739VK_DYNAMIC_STATE_DEPTH_BIAS,740VK_DYNAMIC_STATE_BLEND_CONSTANTS,741VK_DYNAMIC_STATE_DEPTH_BOUNDS,742VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,743VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,744VK_DYNAMIC_STATE_STENCIL_REFERENCE745};746747VkPipelineDynamicStateCreateInfo dynamic_state;748dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;749dynamic_state.pNext = NULL;750dynamic_state.flags = 0;751dynamic_state.dynamicStateCount = sizeof(dynamic_states) / sizeof(VkDynamicState);752dynamic_state.pDynamicStates = dynamic_states;753754gfx_pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;755gfx_pipeline_info.pNext = NULL;756gfx_pipeline_info.flags = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;757gfx_pipeline_info.pVertexInputState = &vs_input;758gfx_pipeline_info.pInputAssemblyState = &assembly_state;759gfx_pipeline_info.pTessellationState = &tess_state;760gfx_pipeline_info.pViewportState = &viewport_state;761gfx_pipeline_info.pRasterizationState = &rasterization_state;762gfx_pipeline_info.pMultisampleState = &ms_state;763gfx_pipeline_info.pDepthStencilState = &ds_state;764gfx_pipeline_info.pColorBlendState = &color_blend_state;765gfx_pipeline_info.pDynamicState = &dynamic_state;766gfx_pipeline_info.subpass = 0;767768/* create the objects used to create the pipeline */769VkSubpassDescription subpass;770subpass.flags = 0;771subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;772subpass.inputAttachmentCount = 0;773subpass.pInputAttachments = NULL;774subpass.colorAttachmentCount = num_color_attachments;775subpass.pColorAttachments = color_attachments;776subpass.pResolveAttachments = NULL;777subpass.pDepthStencilAttachment = ds_output == VK_FORMAT_UNDEFINED ? NULL : &ds_attachment;778subpass.preserveAttachmentCount = 0;779subpass.pPreserveAttachments = NULL;780781VkRenderPassCreateInfo renderpass_info;782renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;783renderpass_info.pNext = NULL;784renderpass_info.flags = 0;785renderpass_info.attachmentCount = num_attachments;786renderpass_info.pAttachments = attachment_descs;787renderpass_info.subpassCount = 1;788renderpass_info.pSubpasses = &subpass;789renderpass_info.dependencyCount = 0;790renderpass_info.pDependencies = NULL;791792ASSERTED VkResult result = CreateRenderPass(device, &renderpass_info, NULL, &render_pass);793assert(result == VK_SUCCESS);794795gfx_pipeline_info.layout = pipeline_layout;796gfx_pipeline_info.renderPass = render_pass;797798/* create the pipeline */799gfx_pipeline_info.pStages = stages;800801result = CreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &gfx_pipeline_info, NULL, &pipeline);802assert(result == VK_SUCCESS);803}804805void PipelineBuilder::create_pipeline() {806unsigned num_desc_layouts = 0;807for (unsigned i = 0; i < 64; i++) {808if (!(desc_layouts_used & (1ull << i)))809continue;810811VkDescriptorSetLayoutCreateInfo desc_layout_info;812desc_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;813desc_layout_info.pNext = NULL;814desc_layout_info.flags = 0;815desc_layout_info.bindingCount = num_desc_bindings[i];816desc_layout_info.pBindings = desc_bindings[i];817818ASSERTED VkResult result = CreateDescriptorSetLayout(device, &desc_layout_info, NULL, &desc_layouts[num_desc_layouts]);819assert(result == VK_SUCCESS);820num_desc_layouts++;821}822823VkPipelineLayoutCreateInfo pipeline_layout_info;824pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;825pipeline_layout_info.pNext = NULL;826pipeline_layout_info.flags = 0;827pipeline_layout_info.pushConstantRangeCount = 1;828pipeline_layout_info.pPushConstantRanges = &push_constant_range;829pipeline_layout_info.setLayoutCount = num_desc_layouts;830pipeline_layout_info.pSetLayouts = desc_layouts;831832ASSERTED VkResult result = CreatePipelineLayout(device, &pipeline_layout_info, NULL, &pipeline_layout);833assert(result == VK_SUCCESS);834835if (is_compute())836create_compute_pipeline();837else838create_graphics_pipeline();839}840841void PipelineBuilder::print_ir(VkShaderStageFlagBits stage_flags, const char *name, bool remove_encoding)842{843if (!pipeline)844create_pipeline();845print_pipeline_ir(device, pipeline, stage_flags, name, remove_encoding);846}847848849