2 * Copyright © 2020 Valve Corporation
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:
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
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
25 #include "vulkan/vk_format.h"
26 #include "llvm/ac_llvm_util.h"
29 #include <llvm-c/Target.h>
35 PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(
40 ac_shader_config config
;
41 radv_shader_info info
;
42 std::unique_ptr
<Program
> program
;
46 const char *subvariant
= "";
48 static VkInstance instance_cache
[CHIP_LAST
] = {VK_NULL_HANDLE
};
49 static VkDevice device_cache
[CHIP_LAST
] = {VK_NULL_HANDLE
};
50 static std::mutex create_device_mutex
;
52 #define FUNCTION_LIST\
54 ITEM(DestroyInstance)\
55 ITEM(EnumeratePhysicalDevices)\
56 ITEM(GetPhysicalDeviceProperties2)\
59 ITEM(CreateShaderModule)\
60 ITEM(DestroyShaderModule)\
61 ITEM(CreateGraphicsPipelines)\
62 ITEM(CreateComputePipelines)\
63 ITEM(DestroyPipeline)\
64 ITEM(CreateDescriptorSetLayout)\
65 ITEM(DestroyDescriptorSetLayout)\
66 ITEM(CreatePipelineLayout)\
67 ITEM(DestroyPipelineLayout)\
68 ITEM(CreateRenderPass)\
69 ITEM(DestroyRenderPass)\
70 ITEM(GetPipelineExecutablePropertiesKHR)\
71 ITEM(GetPipelineExecutableInternalRepresentationsKHR)
73 #define ITEM(n) PFN_vk##n n;
77 void create_program(enum chip_class chip_class
, Stage stage
, unsigned wave_size
, enum radeon_family family
)
79 memset(&config
, 0, sizeof(config
));
80 info
.wave_size
= wave_size
;
82 program
.reset(new Program
);
83 aco::init_program(program
.get(), stage
, &info
, chip_class
, family
, &config
);
85 Block
*block
= program
->create_and_insert_block();
86 block
->kind
= block_kind_top_level
;
88 bld
= Builder(program
.get(), &program
->blocks
[0]);
90 config
.float_mode
= program
->blocks
[0].fp_mode
.val
;
93 bool setup_cs(const char *input_spec
, enum chip_class chip_class
,
94 enum radeon_family family
, unsigned wave_size
)
96 const char *old_subvariant
= subvariant
;
98 if (!set_variant(chip_class
, old_subvariant
))
101 memset(&info
, 0, sizeof(info
));
102 info
.cs
.block_size
[0] = 1;
103 info
.cs
.block_size
[1] = 1;
104 info
.cs
.block_size
[2] = 1;
106 create_program(chip_class
, compute_cs
, wave_size
, family
);
109 unsigned num_inputs
= DIV_ROUND_UP(strlen(input_spec
), 3u);
110 aco_ptr
<Instruction
> startpgm
{create_instruction
<Pseudo_instruction
>(aco_opcode::p_startpgm
, Format::PSEUDO
, 0, num_inputs
+ 1)};
111 for (unsigned i
= 0; i
< num_inputs
; i
++) {
112 RegClass
cls(input_spec
[i
* 3] == 'v' ? RegType::vgpr
: RegType::sgpr
, input_spec
[i
* 3 + 1] - '0');
113 inputs
[i
] = bld
.tmp(cls
);
114 startpgm
->definitions
[i
] = Definition(inputs
[i
]);
116 exec_input
= bld
.tmp(program
->lane_mask
);
117 startpgm
->definitions
[num_inputs
] = bld
.exec(Definition(exec_input
));
118 bld
.insert(std::move(startpgm
));
124 void finish_program(Program
*program
)
126 for (Block
& BB
: program
->blocks
) {
127 for (unsigned idx
: BB
.linear_preds
)
128 program
->blocks
[idx
].linear_succs
.emplace_back(BB
.index
);
129 for (unsigned idx
: BB
.logical_preds
)
130 program
->blocks
[idx
].logical_succs
.emplace_back(BB
.index
);
133 for (Block
& block
: program
->blocks
) {
134 if (block
.linear_succs
.size() == 0) {
135 block
.kind
|= block_kind_uniform
;
136 Builder
bld(program
, &block
);
137 if (program
->wb_smem_l1_on_end
)
138 bld
.smem(aco_opcode::s_dcache_wb
, false);
139 bld
.sopp(aco_opcode::s_endpgm
);
144 void finish_validator_test()
146 finish_program(program
.get());
147 aco_print_program(program
.get(), output
);
148 fprintf(output
, "Validation results:\n");
149 if (aco::validate(program
.get(), output
))
150 fprintf(output
, "Validation passed\n");
152 fprintf(output
, "Validation failed\n");
155 void finish_opt_test()
157 finish_program(program
.get());
158 if (!aco::validate(program
.get(), output
)) {
159 fail_test("Validation before optimization failed");
162 aco::optimize(program
.get());
163 if (!aco::validate(program
.get(), output
)) {
164 fail_test("Validation after optimization failed");
167 aco_print_program(program
.get(), output
);
170 void finish_to_hw_instr_test()
172 finish_program(program
.get());
173 aco::lower_to_hw_instr(program
.get());
174 aco_print_program(program
.get(), output
);
177 void finish_assembler_test()
179 finish_program(program
.get());
180 std::vector
<uint32_t> binary
;
181 unsigned exec_size
= emit_program(program
.get(), binary
);
183 /* we could use CLRX for disassembly but that would require it to be
185 if (program
->chip_class
== GFX10_3
&& LLVM_VERSION_MAJOR
< 9) {
186 skip_test("LLVM 11 needed for GFX10_3 disassembly");
187 } else if (program
->chip_class
== GFX10
&& LLVM_VERSION_MAJOR
< 9) {
188 skip_test("LLVM 9 needed for GFX10 disassembly");
189 } else if (program
->chip_class
>= GFX8
) {
190 std::ostringstream ss
;
191 print_asm(program
.get(), binary
, exec_size
/ 4u, ss
);
193 fputs(ss
.str().c_str(), output
);
195 //TODO: maybe we should use CLRX and skip this test if it's not available?
196 for (uint32_t dword
: binary
)
197 fprintf(output
, "%.8x\n", dword
);
201 void writeout(unsigned i
, Temp tmp
)
204 bld
.pseudo(aco_opcode::p_unit_test
, Operand(i
), tmp
);
206 bld
.pseudo(aco_opcode::p_unit_test
, Operand(i
));
209 VkDevice
get_vk_device(enum chip_class chip_class
)
211 enum radeon_family family
;
212 switch (chip_class
) {
214 family
= CHIP_TAHITI
;
217 family
= CHIP_BONAIRE
;
220 family
= CHIP_POLARIS10
;
223 family
= CHIP_VEGA10
;
226 family
= CHIP_NAVI10
;
229 family
= CHIP_UNKNOWN
;
232 return get_vk_device(family
);
235 VkDevice
get_vk_device(enum radeon_family family
)
237 assert(family
!= CHIP_UNKNOWN
);
239 std::lock_guard
<std::mutex
> guard(create_device_mutex
);
241 if (device_cache
[family
])
242 return device_cache
[family
];
244 setenv("RADV_FORCE_FAMILY", ac_get_llvm_processor_name(family
), 1);
246 VkApplicationInfo app_info
= {};
247 app_info
.pApplicationName
= "aco_tests";
248 app_info
.apiVersion
= VK_API_VERSION_1_2
;
249 VkInstanceCreateInfo instance_create_info
= {};
250 instance_create_info
.pApplicationInfo
= &app_info
;
251 instance_create_info
.sType
= VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
;
252 VkResult result
= ((PFN_vkCreateInstance
)vk_icdGetInstanceProcAddr(NULL
, "vkCreateInstance"))(&instance_create_info
, NULL
, &instance_cache
[family
]);
253 assert(result
== VK_SUCCESS
);
255 #define ITEM(n) n = (PFN_vk##n)vk_icdGetInstanceProcAddr(instance_cache[family], "vk" #n);
259 uint32_t device_count
= 1;
260 VkPhysicalDevice device
= VK_NULL_HANDLE
;
261 result
= EnumeratePhysicalDevices(instance_cache
[family
], &device_count
, &device
);
262 assert(result
== VK_SUCCESS
);
263 assert(device
!= VK_NULL_HANDLE
);
265 VkDeviceCreateInfo device_create_info
= {};
266 device_create_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
;
267 static const char *extensions
[] = {"VK_KHR_pipeline_executable_properties"};
268 device_create_info
.enabledExtensionCount
= sizeof(extensions
) / sizeof(extensions
[0]);
269 device_create_info
.ppEnabledExtensionNames
= extensions
;
270 result
= CreateDevice(device
, &device_create_info
, NULL
, &device_cache
[family
]);
272 return device_cache
[family
];
275 static struct DestroyDevices
{
277 for (unsigned i
= 0; i
< CHIP_LAST
; i
++) {
278 if (!device_cache
[i
])
280 DestroyDevice(device_cache
[i
], NULL
);
281 DestroyInstance(instance_cache
[i
], NULL
);
286 void print_pipeline_ir(VkDevice device
, VkPipeline pipeline
, VkShaderStageFlagBits stages
,
287 const char *name
, bool remove_encoding
)
289 uint32_t executable_count
= 16;
290 VkPipelineExecutablePropertiesKHR executables
[16];
291 VkPipelineInfoKHR pipeline_info
;
292 pipeline_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR
;
293 pipeline_info
.pNext
= NULL
;
294 pipeline_info
.pipeline
= pipeline
;
295 VkResult result
= GetPipelineExecutablePropertiesKHR(device
, &pipeline_info
, &executable_count
, executables
);
296 assert(result
== VK_SUCCESS
);
298 uint32_t executable
= 0;
299 for (; executable
< executable_count
; executable
++) {
300 if (executables
[executable
].stages
== stages
)
303 assert(executable
!= executable_count
);
305 VkPipelineExecutableInfoKHR exec_info
;
306 exec_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR
;
307 exec_info
.pNext
= NULL
;
308 exec_info
.pipeline
= pipeline
;
309 exec_info
.executableIndex
= executable
;
311 uint32_t ir_count
= 16;
312 VkPipelineExecutableInternalRepresentationKHR ir
[16];
313 memset(ir
, 0, sizeof(ir
));
314 result
= GetPipelineExecutableInternalRepresentationsKHR(device
, &exec_info
, &ir_count
, ir
);
315 assert(result
== VK_SUCCESS
);
317 for (unsigned i
= 0; i
< ir_count
; i
++) {
318 if (strcmp(ir
[i
].name
, name
))
321 char *data
= (char*)malloc(ir
[i
].dataSize
);
323 result
= GetPipelineExecutableInternalRepresentationsKHR(device
, &exec_info
, &ir_count
, ir
);
324 assert(result
== VK_SUCCESS
);
326 if (remove_encoding
) {
327 for (char *c
= data
; *c
; c
++) {
329 for (; *c
&& *c
!= '\n'; c
++)
335 fprintf(output
, "%s", data
);
341 VkShaderModule
__qoCreateShaderModule(VkDevice dev
, const QoShaderModuleCreateInfo
*info
)
343 VkShaderModuleCreateInfo module_info
;
344 module_info
.sType
= VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO
;
345 module_info
.pNext
= NULL
;
346 module_info
.flags
= 0;
347 module_info
.codeSize
= info
->spirvSize
;
348 module_info
.pCode
= (const uint32_t*)info
->pSpirv
;
350 VkShaderModule module
;
351 VkResult result
= CreateShaderModule(dev
, &module_info
, NULL
, &module
);
352 assert(result
== VK_SUCCESS
);
357 PipelineBuilder::PipelineBuilder(VkDevice dev
) {
358 memset(this, 0, sizeof(*this));
359 topology
= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
;
363 PipelineBuilder::~PipelineBuilder()
365 DestroyPipeline(device
, pipeline
, NULL
);
367 for (unsigned i
= 0; i
< (is_compute() ? 1 : gfx_pipeline_info
.stageCount
); i
++) {
368 VkPipelineShaderStageCreateInfo
*stage_info
= &stages
[i
];
369 if (owned_stages
& stage_info
->stage
)
370 DestroyShaderModule(device
, stage_info
->module
, NULL
);
373 DestroyPipelineLayout(device
, pipeline_layout
, NULL
);
375 for (unsigned i
= 0; i
< util_bitcount64(desc_layouts_used
); i
++)
376 DestroyDescriptorSetLayout(device
, desc_layouts
[i
], NULL
);
378 DestroyRenderPass(device
, render_pass
, NULL
);
381 void PipelineBuilder::add_desc_binding(VkShaderStageFlags stage_flags
, uint32_t layout
,
382 uint32_t binding
, VkDescriptorType type
, uint32_t count
)
384 desc_layouts_used
|= 1ull << layout
;
385 desc_bindings
[layout
][num_desc_bindings
[layout
]++] = {binding
, type
, count
, stage_flags
, NULL
};
388 void PipelineBuilder::add_vertex_binding(uint32_t binding
, uint32_t stride
, VkVertexInputRate rate
)
390 vs_bindings
[vs_input
.vertexBindingDescriptionCount
++] = {binding
, stride
, rate
};
393 void PipelineBuilder::add_vertex_attribute(uint32_t location
, uint32_t binding
, VkFormat format
, uint32_t offset
)
395 vs_attributes
[vs_input
.vertexAttributeDescriptionCount
++] = {location
, binding
, format
, offset
};
398 void PipelineBuilder::add_resource_decls(QoShaderModuleCreateInfo
*module
)
400 for (unsigned i
= 0; i
< module
->declarationCount
; i
++) {
401 const QoShaderDecl
*decl
= &module
->pDeclarations
[i
];
402 switch (decl
->decl_type
) {
403 case QoShaderDeclType_ubo
:
404 add_desc_binding(module
->stage
, decl
->set
, decl
->binding
, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
);
406 case QoShaderDeclType_ssbo
:
407 add_desc_binding(module
->stage
, decl
->set
, decl
->binding
, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
);
409 case QoShaderDeclType_img_buf
:
410 add_desc_binding(module
->stage
, decl
->set
, decl
->binding
, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
);
412 case QoShaderDeclType_img
:
413 add_desc_binding(module
->stage
, decl
->set
, decl
->binding
, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
);
415 case QoShaderDeclType_tex_buf
:
416 add_desc_binding(module
->stage
, decl
->set
, decl
->binding
, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
);
418 case QoShaderDeclType_combined
:
419 add_desc_binding(module
->stage
, decl
->set
, decl
->binding
, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
);
421 case QoShaderDeclType_tex
:
422 add_desc_binding(module
->stage
, decl
->set
, decl
->binding
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
);
424 case QoShaderDeclType_samp
:
425 add_desc_binding(module
->stage
, decl
->set
, decl
->binding
, VK_DESCRIPTOR_TYPE_SAMPLER
);
433 void PipelineBuilder::add_io_decls(QoShaderModuleCreateInfo
*module
)
435 unsigned next_vtx_offset
= 0;
436 for (unsigned i
= 0; i
< module
->declarationCount
; i
++) {
437 const QoShaderDecl
*decl
= &module
->pDeclarations
[i
];
438 switch (decl
->decl_type
) {
439 case QoShaderDeclType_in
:
440 if (module
->stage
== VK_SHADER_STAGE_VERTEX_BIT
) {
441 if (!strcmp(decl
->type
, "float") || decl
->type
[0] == 'v')
442 add_vertex_attribute(decl
->location
, 0, VK_FORMAT_R32G32B32A32_SFLOAT
, next_vtx_offset
);
443 else if (decl
->type
[0] == 'u')
444 add_vertex_attribute(decl
->location
, 0, VK_FORMAT_R32G32B32A32_UINT
, next_vtx_offset
);
445 else if (decl
->type
[0] == 'i')
446 add_vertex_attribute(decl
->location
, 0, VK_FORMAT_R32G32B32A32_SINT
, next_vtx_offset
);
447 next_vtx_offset
+= 16;
450 case QoShaderDeclType_out
:
451 if (module
->stage
== VK_SHADER_STAGE_FRAGMENT_BIT
) {
452 if (!strcmp(decl
->type
, "float") || decl
->type
[0] == 'v')
453 color_outputs
[decl
->location
] = VK_FORMAT_R32G32B32A32_SFLOAT
;
454 else if (decl
->type
[0] == 'u')
455 color_outputs
[decl
->location
] = VK_FORMAT_R32G32B32A32_UINT
;
456 else if (decl
->type
[0] == 'i')
457 color_outputs
[decl
->location
] = VK_FORMAT_R32G32B32A32_SINT
;
465 add_vertex_binding(0, next_vtx_offset
);
468 void PipelineBuilder::add_stage(VkShaderStageFlagBits stage
, VkShaderModule module
, const char *name
)
470 VkPipelineShaderStageCreateInfo
*stage_info
;
471 if (stage
== VK_SHADER_STAGE_COMPUTE_BIT
)
472 stage_info
= &stages
[0];
474 stage_info
= &stages
[gfx_pipeline_info
.stageCount
++];
475 stage_info
->sType
= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
;
476 stage_info
->pNext
= NULL
;
477 stage_info
->flags
= 0;
478 stage_info
->stage
= stage
;
479 stage_info
->module
= module
;
480 stage_info
->pName
= name
;
481 stage_info
->pSpecializationInfo
= NULL
;
482 owned_stages
|= stage
;
485 void PipelineBuilder::add_vsfs(VkShaderModule vs
, VkShaderModule fs
)
487 add_stage(VK_SHADER_STAGE_VERTEX_BIT
, vs
);
488 add_stage(VK_SHADER_STAGE_FRAGMENT_BIT
, fs
);
491 void PipelineBuilder::add_vsfs(QoShaderModuleCreateInfo vs
, QoShaderModuleCreateInfo fs
)
493 add_vsfs(__qoCreateShaderModule(device
, &vs
), __qoCreateShaderModule(device
, &fs
));
494 add_resource_decls(&vs
);
496 add_resource_decls(&fs
);
500 void PipelineBuilder::add_cs(VkShaderModule cs
)
502 add_stage(VK_SHADER_STAGE_COMPUTE_BIT
, cs
);
505 void PipelineBuilder::add_cs(QoShaderModuleCreateInfo cs
)
507 add_cs(__qoCreateShaderModule(device
, &cs
));
508 add_resource_decls(&cs
);
511 bool PipelineBuilder::is_compute() {
512 return gfx_pipeline_info
.stageCount
== 0;
515 void PipelineBuilder::create_compute_pipeline() {
516 VkComputePipelineCreateInfo create_info
;
517 create_info
.sType
= VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO
;
518 create_info
.pNext
= NULL
;
519 create_info
.flags
= VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR
;
520 create_info
.stage
= stages
[0];
521 create_info
.layout
= pipeline_layout
;
522 create_info
.basePipelineHandle
= VK_NULL_HANDLE
;
523 create_info
.basePipelineIndex
= 0;
525 VkResult result
= CreateComputePipelines(device
, VK_NULL_HANDLE
, 1, &create_info
, NULL
, &pipeline
);
526 assert(result
== VK_SUCCESS
);
529 void PipelineBuilder::create_graphics_pipeline() {
530 /* create the create infos */
532 samples
= VK_SAMPLE_COUNT_1_BIT
;
534 unsigned num_color_attachments
= 0;
535 VkPipelineColorBlendAttachmentState blend_attachment_states
[16];
536 VkAttachmentReference color_attachments
[16];
537 VkAttachmentDescription attachment_descs
[17];
538 for (unsigned i
= 0; i
< 16; i
++) {
539 if (color_outputs
[i
] == VK_FORMAT_UNDEFINED
)
542 VkAttachmentDescription
*desc
= &attachment_descs
[num_color_attachments
];
544 desc
->format
= color_outputs
[i
];
545 desc
->samples
= samples
;
546 desc
->loadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
547 desc
->storeOp
= VK_ATTACHMENT_STORE_OP_STORE
;
548 desc
->stencilLoadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
549 desc
->stencilStoreOp
= VK_ATTACHMENT_STORE_OP_STORE
;
550 desc
->initialLayout
= VK_IMAGE_LAYOUT_GENERAL
;
551 desc
->finalLayout
= VK_IMAGE_LAYOUT_GENERAL
;
553 VkAttachmentReference
*ref
= &color_attachments
[num_color_attachments
];
554 ref
->attachment
= num_color_attachments
;
555 ref
->layout
= VK_IMAGE_LAYOUT_GENERAL
;
557 VkPipelineColorBlendAttachmentState
*blend
= &blend_attachment_states
[num_color_attachments
];
558 blend
->blendEnable
= false;
559 blend
->colorWriteMask
= VK_COLOR_COMPONENT_R_BIT
|
560 VK_COLOR_COMPONENT_G_BIT
|
561 VK_COLOR_COMPONENT_B_BIT
|
562 VK_COLOR_COMPONENT_A_BIT
;
564 num_color_attachments
++;
567 unsigned num_attachments
= num_color_attachments
;
568 VkAttachmentReference ds_attachment
;
569 if (ds_output
!= VK_FORMAT_UNDEFINED
) {
570 VkAttachmentDescription
*desc
= &attachment_descs
[num_attachments
];
572 desc
->format
= ds_output
;
573 desc
->samples
= samples
;
574 desc
->loadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
575 desc
->storeOp
= VK_ATTACHMENT_STORE_OP_STORE
;
576 desc
->stencilLoadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
577 desc
->stencilStoreOp
= VK_ATTACHMENT_STORE_OP_STORE
;
578 desc
->initialLayout
= VK_IMAGE_LAYOUT_GENERAL
;
579 desc
->finalLayout
= VK_IMAGE_LAYOUT_GENERAL
;
581 ds_attachment
.attachment
= num_color_attachments
;
582 ds_attachment
.layout
= VK_IMAGE_LAYOUT_GENERAL
;
587 vs_input
.sType
= VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
;
588 vs_input
.pNext
= NULL
;
590 vs_input
.pVertexBindingDescriptions
= vs_bindings
;
591 vs_input
.pVertexAttributeDescriptions
= vs_attributes
;
593 VkPipelineInputAssemblyStateCreateInfo assembly_state
;
594 assembly_state
.sType
= VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO
;
595 assembly_state
.pNext
= NULL
;
596 assembly_state
.flags
= 0;
597 assembly_state
.topology
= topology
;
598 assembly_state
.primitiveRestartEnable
= false;
600 VkPipelineTessellationStateCreateInfo tess_state
;
601 tess_state
.sType
= VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO
;
602 tess_state
.pNext
= NULL
;
603 tess_state
.flags
= 0;
604 tess_state
.patchControlPoints
= patch_size
;
606 VkPipelineViewportStateCreateInfo viewport_state
;
607 viewport_state
.sType
= VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO
;
608 viewport_state
.pNext
= NULL
;
609 viewport_state
.flags
= 0;
610 viewport_state
.viewportCount
= 1;
611 viewport_state
.pViewports
= NULL
;
612 viewport_state
.scissorCount
= 1;
613 viewport_state
.pScissors
= NULL
;
615 VkPipelineRasterizationStateCreateInfo rasterization_state
;
616 rasterization_state
.sType
= VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
;
617 rasterization_state
.pNext
= NULL
;
618 rasterization_state
.flags
= 0;
619 rasterization_state
.depthClampEnable
= false;
620 rasterization_state
.rasterizerDiscardEnable
= false;
621 rasterization_state
.polygonMode
= VK_POLYGON_MODE_FILL
;
622 rasterization_state
.cullMode
= VK_CULL_MODE_NONE
;
623 rasterization_state
.frontFace
= VK_FRONT_FACE_COUNTER_CLOCKWISE
;
624 rasterization_state
.depthBiasEnable
= false;
625 rasterization_state
.lineWidth
= 1.0;
627 VkPipelineMultisampleStateCreateInfo ms_state
;
628 ms_state
.sType
= VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
;
629 ms_state
.pNext
= NULL
;
631 ms_state
.rasterizationSamples
= samples
;
632 ms_state
.sampleShadingEnable
= sample_shading_enable
;
633 ms_state
.minSampleShading
= min_sample_shading
;
634 VkSampleMask sample_mask
= 0xffffffff;
635 ms_state
.pSampleMask
= &sample_mask
;
636 ms_state
.alphaToCoverageEnable
= false;
637 ms_state
.alphaToOneEnable
= false;
639 VkPipelineDepthStencilStateCreateInfo ds_state
;
640 ds_state
.sType
= VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
;
641 ds_state
.pNext
= NULL
;
643 ds_state
.depthTestEnable
= ds_output
!= VK_FORMAT_UNDEFINED
;
644 ds_state
.depthWriteEnable
= true;
645 ds_state
.depthCompareOp
= VK_COMPARE_OP_ALWAYS
;
646 ds_state
.depthBoundsTestEnable
= false;
647 ds_state
.stencilTestEnable
= true;
648 ds_state
.front
.failOp
= VK_STENCIL_OP_KEEP
;
649 ds_state
.front
.passOp
= VK_STENCIL_OP_REPLACE
;
650 ds_state
.front
.depthFailOp
= VK_STENCIL_OP_REPLACE
;
651 ds_state
.front
.compareOp
= VK_COMPARE_OP_ALWAYS
;
652 ds_state
.front
.compareMask
= 0xffffffff,
653 ds_state
.front
.reference
= 0;
654 ds_state
.back
= ds_state
.front
;
656 VkPipelineColorBlendStateCreateInfo color_blend_state
;
657 color_blend_state
.sType
= VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
;
658 color_blend_state
.pNext
= NULL
;
659 color_blend_state
.flags
= 0;
660 color_blend_state
.logicOpEnable
= false;
661 color_blend_state
.attachmentCount
= num_color_attachments
;
662 color_blend_state
.pAttachments
= blend_attachment_states
;
664 VkDynamicState dynamic_states
[9] = {
665 VK_DYNAMIC_STATE_VIEWPORT
,
666 VK_DYNAMIC_STATE_SCISSOR
,
667 VK_DYNAMIC_STATE_LINE_WIDTH
,
668 VK_DYNAMIC_STATE_DEPTH_BIAS
,
669 VK_DYNAMIC_STATE_BLEND_CONSTANTS
,
670 VK_DYNAMIC_STATE_DEPTH_BOUNDS
,
671 VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK
,
672 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK
,
673 VK_DYNAMIC_STATE_STENCIL_REFERENCE
676 VkPipelineDynamicStateCreateInfo dynamic_state
;
677 dynamic_state
.sType
= VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO
;
678 dynamic_state
.pNext
= NULL
;
679 dynamic_state
.flags
= 0;
680 dynamic_state
.dynamicStateCount
= sizeof(dynamic_states
) / sizeof(VkDynamicState
);
681 dynamic_state
.pDynamicStates
= dynamic_states
;
683 gfx_pipeline_info
.sType
= VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
;
684 gfx_pipeline_info
.pNext
= NULL
;
685 gfx_pipeline_info
.flags
= VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR
;
686 gfx_pipeline_info
.pVertexInputState
= &vs_input
;
687 gfx_pipeline_info
.pInputAssemblyState
= &assembly_state
;
688 gfx_pipeline_info
.pTessellationState
= &tess_state
;
689 gfx_pipeline_info
.pViewportState
= &viewport_state
;
690 gfx_pipeline_info
.pRasterizationState
= &rasterization_state
;
691 gfx_pipeline_info
.pMultisampleState
= &ms_state
;
692 gfx_pipeline_info
.pDepthStencilState
= &ds_state
;
693 gfx_pipeline_info
.pColorBlendState
= &color_blend_state
;
694 gfx_pipeline_info
.pDynamicState
= &dynamic_state
;
695 gfx_pipeline_info
.subpass
= 0;
697 /* create the objects used to create the pipeline */
698 VkSubpassDescription subpass
;
700 subpass
.pipelineBindPoint
= VK_PIPELINE_BIND_POINT_GRAPHICS
;
701 subpass
.inputAttachmentCount
= 0;
702 subpass
.pInputAttachments
= NULL
;
703 subpass
.colorAttachmentCount
= num_color_attachments
;
704 subpass
.pColorAttachments
= color_attachments
;
705 subpass
.pResolveAttachments
= NULL
;
706 subpass
.pDepthStencilAttachment
= ds_output
== VK_FORMAT_UNDEFINED
? NULL
: &ds_attachment
;
707 subpass
.preserveAttachmentCount
= 0;
708 subpass
.pPreserveAttachments
= NULL
;
710 VkRenderPassCreateInfo renderpass_info
;
711 renderpass_info
.sType
= VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
;
712 renderpass_info
.pNext
= NULL
;
713 renderpass_info
.flags
= 0;
714 renderpass_info
.attachmentCount
= num_attachments
;
715 renderpass_info
.pAttachments
= attachment_descs
;
716 renderpass_info
.subpassCount
= 1;
717 renderpass_info
.pSubpasses
= &subpass
;
718 renderpass_info
.dependencyCount
= 0;
719 renderpass_info
.pDependencies
= NULL
;
721 VkResult result
= CreateRenderPass(device
, &renderpass_info
, NULL
, &render_pass
);
722 assert(result
== VK_SUCCESS
);
724 gfx_pipeline_info
.layout
= pipeline_layout
;
725 gfx_pipeline_info
.renderPass
= render_pass
;
727 /* create the pipeline */
728 gfx_pipeline_info
.pStages
= stages
;
730 result
= CreateGraphicsPipelines(device
, VK_NULL_HANDLE
, 1, &gfx_pipeline_info
, NULL
, &pipeline
);
731 assert(result
== VK_SUCCESS
);
734 void PipelineBuilder::create_pipeline() {
735 unsigned num_desc_layouts
= 0;
736 for (unsigned i
= 0; i
< 64; i
++) {
737 if (!(desc_layouts_used
& (1ull << i
)))
740 VkDescriptorSetLayoutCreateInfo desc_layout_info
;
741 desc_layout_info
.sType
= VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
;
742 desc_layout_info
.pNext
= NULL
;
743 desc_layout_info
.flags
= 0;
744 desc_layout_info
.bindingCount
= num_desc_bindings
[i
];
745 desc_layout_info
.pBindings
= desc_bindings
[i
];
747 VkResult result
= CreateDescriptorSetLayout(device
, &desc_layout_info
, NULL
, &desc_layouts
[num_desc_layouts
]);
748 assert(result
== VK_SUCCESS
);
752 VkPipelineLayoutCreateInfo pipeline_layout_info
;
753 pipeline_layout_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
;
754 pipeline_layout_info
.pNext
= NULL
;
755 pipeline_layout_info
.flags
= 0;
756 pipeline_layout_info
.pushConstantRangeCount
= 1;
757 pipeline_layout_info
.pPushConstantRanges
= &push_constant_range
;
758 pipeline_layout_info
.setLayoutCount
= num_desc_layouts
;
759 pipeline_layout_info
.pSetLayouts
= desc_layouts
;
761 VkResult result
= CreatePipelineLayout(device
, &pipeline_layout_info
, NULL
, &pipeline_layout
);
762 assert(result
== VK_SUCCESS
);
765 create_compute_pipeline();
767 create_graphics_pipeline();
770 void PipelineBuilder::print_ir(VkShaderStageFlagBits stages
, const char *name
, bool remove_encoding
)
774 print_pipeline_ir(device
, pipeline
, stages
, name
, remove_encoding
);