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