2
* Copyright © Microsoft 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
24
#include "dzn_private.h"
26
#include "spirv_to_dxil.h"
28
#include "dxil_validator.h"
32
#include "vk_format.h"
34
#include "util/u_debug.h"
36
static dxil_spirv_shader_stage
37
to_dxil_shader_stage(VkShaderStageFlagBits in)
40
case VK_SHADER_STAGE_VERTEX_BIT: return DXIL_SPIRV_SHADER_VERTEX;
41
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return DXIL_SPIRV_SHADER_TESS_CTRL;
42
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return DXIL_SPIRV_SHADER_TESS_EVAL;
43
case VK_SHADER_STAGE_GEOMETRY_BIT: return DXIL_SPIRV_SHADER_GEOMETRY;
44
case VK_SHADER_STAGE_FRAGMENT_BIT: return DXIL_SPIRV_SHADER_FRAGMENT;
45
case VK_SHADER_STAGE_COMPUTE_BIT: return DXIL_SPIRV_SHADER_COMPUTE;
46
default: unreachable("Unsupported stage");
51
dzn_pipeline_compile_shader(dzn_device *device,
52
const VkAllocationCallbacks *alloc,
53
dzn_pipeline_layout *layout,
54
const VkPipelineShaderStageCreateInfo *stage_info,
55
enum dxil_spirv_yz_flip_mode yz_flip_mode,
56
uint16_t y_flip_mask, uint16_t z_flip_mask,
57
D3D12_SHADER_BYTECODE *slot)
59
dzn_instance *instance =
60
container_of(device->vk.physical->instance, dzn_instance, vk);
61
const VkSpecializationInfo *spec_info = stage_info->pSpecializationInfo;
62
VK_FROM_HANDLE(vk_shader_module, module, stage_info->module);
63
struct dxil_spirv_object dxil_object;
65
/* convert VkSpecializationInfo */
66
struct dxil_spirv_specialization *spec = NULL;
67
uint32_t num_spec = 0;
69
if (spec_info && spec_info->mapEntryCount) {
70
spec = (struct dxil_spirv_specialization *)
71
vk_alloc2(&device->vk.alloc, alloc,
72
spec_info->mapEntryCount * sizeof(*spec), 8,
73
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
75
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
77
for (uint32_t i = 0; i < spec_info->mapEntryCount; i++) {
78
const VkSpecializationMapEntry *entry = &spec_info->pMapEntries[i];
79
const uint8_t *data = (const uint8_t *)spec_info->pData + entry->offset;
80
assert(data + entry->size <= (const uint8_t *)spec_info->pData + spec_info->dataSize);
81
spec[i].id = entry->constantID;
82
switch (entry->size) {
84
spec[i].value.u64 = *(const uint64_t *)data;
87
spec[i].value.u32 = *(const uint32_t *)data;
90
spec[i].value.u16 = *(const uint16_t *)data;
93
spec[i].value.u8 = *(const uint8_t *)data;
96
assert(!"Invalid spec constant size");
100
spec[i].defined_on_module = false;
103
num_spec = spec_info->mapEntryCount;
106
struct dxil_spirv_runtime_conf conf = {
107
.runtime_data_cbv = {
108
.register_space = DZN_REGISTER_SPACE_SYSVALS,
109
.base_shader_register = 0,
111
.push_constant_cbv = {
112
.register_space = DZN_REGISTER_SPACE_PUSH_CONSTANT,
113
.base_shader_register = 0,
115
.descriptor_set_count = layout->set_count,
116
.descriptor_sets = layout->binding_translation,
117
.zero_based_vertex_instance_id = false,
119
.mode = yz_flip_mode,
120
.y_mask = y_flip_mask,
121
.z_mask = z_flip_mask,
123
.read_only_images_as_srvs = true,
126
struct dxil_spirv_debug_options dbg_opts = {
127
.dump_nir = !!(instance->debug_flags & DZN_DEBUG_NIR),
130
/* TODO: Extend spirv_to_dxil() to allow passing a custom allocator */
132
spirv_to_dxil((uint32_t *)module->data, module->size / sizeof(uint32_t),
134
to_dxil_shader_stage(stage_info->stage),
135
stage_info->pName, &dbg_opts, &conf, &dxil_object);
137
vk_free2(&device->vk.alloc, alloc, spec);
140
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
143
bool res = dxil_validate_module(instance->dxil_validator,
144
dxil_object.binary.buffer,
145
dxil_object.binary.size, &err);
147
if (instance->debug_flags & DZN_DEBUG_DXIL) {
148
char *disasm = dxil_disasm_module(instance->dxil_validator,
149
dxil_object.binary.buffer,
150
dxil_object.binary.size);
153
"== BEGIN SHADER ============================================\n"
155
"== END SHADER ==============================================\n",
164
"== VALIDATION ERROR =============================================\n"
166
"== END ==========================================================\n",
170
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
173
slot->pShaderBytecode = dxil_object.binary.buffer;
174
slot->BytecodeLength = dxil_object.binary.size;
178
static D3D12_SHADER_BYTECODE *
179
dzn_pipeline_get_gfx_shader_slot(D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,
180
VkShaderStageFlagBits in)
183
case VK_SHADER_STAGE_VERTEX_BIT: return &desc->VS;
184
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return &desc->DS;
185
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return &desc->HS;
186
case VK_SHADER_STAGE_GEOMETRY_BIT: return &desc->GS;
187
case VK_SHADER_STAGE_FRAGMENT_BIT: return &desc->PS;
188
default: unreachable("Unsupported stage");
193
dzn_graphics_pipeline_translate_vi(dzn_graphics_pipeline *pipeline,
194
const VkAllocationCallbacks *alloc,
195
D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
196
const VkGraphicsPipelineCreateInfo *in,
197
D3D12_INPUT_ELEMENT_DESC **input_elems)
200
container_of(pipeline->base.base.device, dzn_device, vk);
201
const VkPipelineVertexInputStateCreateInfo *in_vi =
202
in->pVertexInputState;
204
if (!in_vi->vertexAttributeDescriptionCount) {
205
out->InputLayout.pInputElementDescs = NULL;
206
out->InputLayout.NumElements = 0;
211
*input_elems = (D3D12_INPUT_ELEMENT_DESC *)
212
vk_alloc2(&device->vk.alloc, alloc,
213
sizeof(**input_elems) * in_vi->vertexAttributeDescriptionCount, 8,
214
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
216
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
218
D3D12_INPUT_ELEMENT_DESC *inputs = *input_elems;
219
D3D12_INPUT_CLASSIFICATION slot_class[MAX_VBS];
221
pipeline->vb.count = 0;
222
for (uint32_t i = 0; i < in_vi->vertexBindingDescriptionCount; i++) {
223
const struct VkVertexInputBindingDescription *bdesc =
224
&in_vi->pVertexBindingDescriptions[i];
226
pipeline->vb.count = MAX2(pipeline->vb.count, bdesc->binding + 1);
227
pipeline->vb.strides[bdesc->binding] = bdesc->stride;
228
if (bdesc->inputRate == VK_VERTEX_INPUT_RATE_INSTANCE) {
229
slot_class[bdesc->binding] = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
231
assert(bdesc->inputRate == VK_VERTEX_INPUT_RATE_VERTEX);
232
slot_class[bdesc->binding] = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
236
for (uint32_t i = 0; i < in_vi->vertexAttributeDescriptionCount; i++) {
237
const VkVertexInputAttributeDescription *attr =
238
&in_vi->pVertexAttributeDescriptions[i];
240
/* nir_to_dxil() name all vertex inputs as TEXCOORDx */
241
inputs[i].SemanticName = "TEXCOORD";
242
inputs[i].SemanticIndex = attr->location;
243
inputs[i].Format = dzn_buffer_get_dxgi_format(attr->format);
244
inputs[i].InputSlot = attr->binding;
245
inputs[i].InputSlotClass = slot_class[attr->binding];
246
inputs[i].InstanceDataStepRate =
247
inputs[i].InputSlotClass == D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA ? 1 : 0;
248
inputs[i].AlignedByteOffset = attr->offset;
251
out->InputLayout.pInputElementDescs = inputs;
252
out->InputLayout.NumElements = in_vi->vertexAttributeDescriptionCount;
256
static D3D12_PRIMITIVE_TOPOLOGY_TYPE
257
to_prim_topology_type(VkPrimitiveTopology in)
260
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
261
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
262
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
263
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
264
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
265
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
266
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
267
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
268
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
269
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
270
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
271
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
272
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
273
case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
274
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
275
default: unreachable("Invalid primitive topology");
279
static D3D12_PRIMITIVE_TOPOLOGY
280
to_prim_topology(VkPrimitiveTopology in, unsigned patch_control_points)
283
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
284
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
285
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
286
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
287
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;
288
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
289
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
290
/* Triangle fans are emulated using an intermediate index buffer. */
291
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
292
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;
293
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;
294
case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
295
assert(patch_control_points);
296
return (D3D12_PRIMITIVE_TOPOLOGY)(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + patch_control_points - 1);
297
default: unreachable("Invalid primitive topology");
302
dzn_graphics_pipeline_translate_ia(dzn_graphics_pipeline *pipeline,
303
D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
304
const VkGraphicsPipelineCreateInfo *in)
306
const VkPipelineInputAssemblyStateCreateInfo *in_ia =
307
in->pInputAssemblyState;
308
const VkPipelineTessellationStateCreateInfo *in_tes =
309
(out->DS.pShaderBytecode && out->HS.pShaderBytecode) ?
310
in->pTessellationState : NULL;
312
out->PrimitiveTopologyType = to_prim_topology_type(in_ia->topology);
313
pipeline->ia.triangle_fan = in_ia->topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
314
pipeline->ia.topology =
315
to_prim_topology(in_ia->topology, in_tes ? in_tes->patchControlPoints : 0);
317
/* FIXME: does that work for u16 index buffers? */
318
if (in_ia->primitiveRestartEnable)
319
out->IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;
321
out->IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
324
static D3D12_FILL_MODE
325
translate_polygon_mode(VkPolygonMode in)
328
case VK_POLYGON_MODE_FILL: return D3D12_FILL_MODE_SOLID;
329
case VK_POLYGON_MODE_LINE: return D3D12_FILL_MODE_WIREFRAME;
330
default: unreachable("Unsupported polygon mode");
334
static D3D12_CULL_MODE
335
translate_cull_mode(VkCullModeFlags in)
338
case VK_CULL_MODE_NONE: return D3D12_CULL_MODE_NONE;
339
case VK_CULL_MODE_FRONT_BIT: return D3D12_CULL_MODE_FRONT;
340
case VK_CULL_MODE_BACK_BIT: return D3D12_CULL_MODE_BACK;
341
/* Front+back face culling is equivalent to 'rasterization disabled' */
342
case VK_CULL_MODE_FRONT_AND_BACK: return D3D12_CULL_MODE_NONE;
343
default: unreachable("Unsupported cull mode");
348
dzn_graphics_pipeline_translate_rast(dzn_graphics_pipeline *pipeline,
349
D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
350
const VkGraphicsPipelineCreateInfo *in)
352
const VkPipelineRasterizationStateCreateInfo *in_rast =
353
in->pRasterizationState;
354
const VkPipelineViewportStateCreateInfo *in_vp =
355
in_rast->rasterizerDiscardEnable ? NULL : in->pViewportState;
358
pipeline->vp.count = in_vp->viewportCount;
359
if (in_vp->pViewports) {
360
for (uint32_t i = 0; in_vp->pViewports && i < in_vp->viewportCount; i++)
361
dzn_translate_viewport(&pipeline->vp.desc[i], &in_vp->pViewports[i]);
364
pipeline->scissor.count = in_vp->scissorCount;
365
if (in_vp->pScissors) {
366
for (uint32_t i = 0; i < in_vp->scissorCount; i++)
367
dzn_translate_rect(&pipeline->scissor.desc[i], &in_vp->pScissors[i]);
371
out->RasterizerState.DepthClipEnable = !in_rast->depthClampEnable;
372
out->RasterizerState.FillMode = translate_polygon_mode(in_rast->polygonMode);
373
out->RasterizerState.CullMode = translate_cull_mode(in_rast->cullMode);
374
out->RasterizerState.FrontCounterClockwise =
375
in_rast->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE;
376
if (in_rast->depthBiasEnable) {
377
out->RasterizerState.DepthBias = in_rast->depthBiasConstantFactor;
378
out->RasterizerState.SlopeScaledDepthBias = in_rast->depthBiasSlopeFactor;
379
out->RasterizerState.DepthBiasClamp = in_rast->depthBiasClamp;
382
assert(in_rast->lineWidth == 1.0f);
386
dzn_graphics_pipeline_translate_ms(dzn_graphics_pipeline *pipeline,
387
D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
388
const VkGraphicsPipelineCreateInfo *in)
390
const VkPipelineRasterizationStateCreateInfo *in_rast =
391
in->pRasterizationState;
392
const VkPipelineMultisampleStateCreateInfo *in_ms =
393
in_rast->rasterizerDiscardEnable ? NULL : in->pMultisampleState;
395
/* TODO: sampleShadingEnable, minSampleShading,
398
out->SampleDesc.Count = in_ms ? in_ms->rasterizationSamples : 1;
399
out->SampleDesc.Quality = 0;
400
out->SampleMask = in_ms && in_ms->pSampleMask ?
401
*in_ms->pSampleMask :
402
(1 << out->SampleDesc.Count) - 1;
405
static D3D12_STENCIL_OP
406
translate_stencil_op(VkStencilOp in)
409
case VK_STENCIL_OP_KEEP: return D3D12_STENCIL_OP_KEEP;
410
case VK_STENCIL_OP_ZERO: return D3D12_STENCIL_OP_ZERO;
411
case VK_STENCIL_OP_REPLACE: return D3D12_STENCIL_OP_REPLACE;
412
case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return D3D12_STENCIL_OP_INCR_SAT;
413
case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return D3D12_STENCIL_OP_DECR_SAT;
414
case VK_STENCIL_OP_INCREMENT_AND_WRAP: return D3D12_STENCIL_OP_INCR;
415
case VK_STENCIL_OP_DECREMENT_AND_WRAP: return D3D12_STENCIL_OP_DECR;
416
case VK_STENCIL_OP_INVERT: return D3D12_STENCIL_OP_INVERT;
417
default: unreachable("Invalid stencil op");
422
translate_stencil_test(dzn_graphics_pipeline *pipeline,
423
D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
424
const VkGraphicsPipelineCreateInfo *in)
426
const VkPipelineDepthStencilStateCreateInfo *in_zsa =
427
in->pDepthStencilState;
429
bool front_test_uses_ref =
430
!(in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT) &&
431
in_zsa->front.compareOp != VK_COMPARE_OP_NEVER &&
432
in_zsa->front.compareOp != VK_COMPARE_OP_ALWAYS &&
433
(pipeline->zsa.stencil_test.dynamic_compare_mask ||
434
in_zsa->front.compareMask != 0);
435
bool back_test_uses_ref =
436
!(in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT) &&
437
in_zsa->back.compareOp != VK_COMPARE_OP_NEVER &&
438
in_zsa->back.compareOp != VK_COMPARE_OP_ALWAYS &&
439
(pipeline->zsa.stencil_test.dynamic_compare_mask ||
440
in_zsa->back.compareMask != 0);
442
if (front_test_uses_ref && pipeline->zsa.stencil_test.dynamic_compare_mask)
443
pipeline->zsa.stencil_test.front.compare_mask = UINT32_MAX;
444
else if (front_test_uses_ref)
445
pipeline->zsa.stencil_test.front.compare_mask = in_zsa->front.compareMask;
447
pipeline->zsa.stencil_test.front.compare_mask = 0;
449
if (back_test_uses_ref && pipeline->zsa.stencil_test.dynamic_compare_mask)
450
pipeline->zsa.stencil_test.back.compare_mask = UINT32_MAX;
451
else if (back_test_uses_ref)
452
pipeline->zsa.stencil_test.back.compare_mask = in_zsa->back.compareMask;
454
pipeline->zsa.stencil_test.back.compare_mask = 0;
457
in->pRasterizationState->cullMode == VK_CULL_MODE_NONE &&
458
(pipeline->zsa.stencil_test.dynamic_write_mask ||
459
in_zsa->back.writeMask != in_zsa->front.writeMask);
461
in->pRasterizationState->cullMode == VK_CULL_MODE_NONE &&
462
(pipeline->zsa.stencil_test.dynamic_ref ||
463
in_zsa->back.reference != in_zsa->front.reference);
465
back_test_uses_ref && front_test_uses_ref &&
466
(pipeline->zsa.stencil_test.dynamic_compare_mask ||
467
pipeline->zsa.stencil_test.front.compare_mask != pipeline->zsa.stencil_test.back.compare_mask);
469
if (diff_cmp_mask || diff_wr_mask)
470
pipeline->zsa.stencil_test.independent_front_back = true;
472
bool back_wr_uses_ref =
473
!(in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT) &&
474
(in_zsa->back.compareOp != VK_COMPARE_OP_ALWAYS &&
475
in_zsa->back.failOp == VK_STENCIL_OP_REPLACE) ||
476
(in_zsa->back.compareOp != VK_COMPARE_OP_NEVER &&
477
(!in_zsa->depthTestEnable || in_zsa->depthCompareOp != VK_COMPARE_OP_NEVER) &&
478
in_zsa->back.passOp == VK_STENCIL_OP_REPLACE) ||
479
(in_zsa->depthTestEnable &&
480
in_zsa->depthCompareOp != VK_COMPARE_OP_ALWAYS &&
481
in_zsa->back.depthFailOp == VK_STENCIL_OP_REPLACE);
482
bool front_wr_uses_ref =
483
!(in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT) &&
484
(in_zsa->front.compareOp != VK_COMPARE_OP_ALWAYS &&
485
in_zsa->front.failOp == VK_STENCIL_OP_REPLACE) ||
486
(in_zsa->front.compareOp != VK_COMPARE_OP_NEVER &&
487
(!in_zsa->depthTestEnable || in_zsa->depthCompareOp != VK_COMPARE_OP_NEVER) &&
488
in_zsa->front.passOp == VK_STENCIL_OP_REPLACE) ||
489
(in_zsa->depthTestEnable &&
490
in_zsa->depthCompareOp != VK_COMPARE_OP_ALWAYS &&
491
in_zsa->front.depthFailOp == VK_STENCIL_OP_REPLACE);
493
pipeline->zsa.stencil_test.front.write_mask =
494
(pipeline->zsa.stencil_test.dynamic_write_mask ||
495
(in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT)) ?
496
0 : in_zsa->front.writeMask;
497
pipeline->zsa.stencil_test.back.write_mask =
498
(pipeline->zsa.stencil_test.dynamic_write_mask ||
499
(in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT)) ?
500
0 : in_zsa->back.writeMask;
502
pipeline->zsa.stencil_test.front.uses_ref = front_test_uses_ref || front_wr_uses_ref;
503
pipeline->zsa.stencil_test.back.uses_ref = back_test_uses_ref || back_wr_uses_ref;
506
pipeline->zsa.stencil_test.front.uses_ref &&
507
pipeline->zsa.stencil_test.back.uses_ref)
508
pipeline->zsa.stencil_test.independent_front_back = true;
510
pipeline->zsa.stencil_test.front.ref =
511
pipeline->zsa.stencil_test.dynamic_ref ? 0 : in_zsa->front.reference;
512
pipeline->zsa.stencil_test.back.ref =
513
pipeline->zsa.stencil_test.dynamic_ref ? 0 : in_zsa->back.reference;
515
/* FIXME: We don't support independent {compare,write}_mask and stencil
516
* reference. Until we have proper support for independent front/back
517
* stencil test, let's prioritize the front setup when both are active.
519
out->DepthStencilState.StencilReadMask =
520
front_test_uses_ref ?
521
pipeline->zsa.stencil_test.front.compare_mask :
523
pipeline->zsa.stencil_test.back.compare_mask : 0;
524
out->DepthStencilState.StencilWriteMask =
525
pipeline->zsa.stencil_test.front.write_mask ?
526
pipeline->zsa.stencil_test.front.write_mask :
527
pipeline->zsa.stencil_test.back.write_mask;
529
assert(!pipeline->zsa.stencil_test.independent_front_back);
533
dzn_graphics_pipeline_translate_zsa(dzn_graphics_pipeline *pipeline,
534
D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
535
const VkGraphicsPipelineCreateInfo *in)
537
const VkPipelineRasterizationStateCreateInfo *in_rast =
538
in->pRasterizationState;
539
const VkPipelineDepthStencilStateCreateInfo *in_zsa =
540
in_rast->rasterizerDiscardEnable ? NULL : in->pDepthStencilState;
545
/* TODO: depthBoundsTestEnable */
547
out->DepthStencilState.DepthEnable = in_zsa->depthTestEnable;
548
out->DepthStencilState.DepthWriteMask =
549
in_zsa->depthWriteEnable ?
550
D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
551
out->DepthStencilState.DepthFunc =
552
dzn_translate_compare_op(in_zsa->depthCompareOp);
553
out->DepthStencilState.StencilEnable = in_zsa->stencilTestEnable;
554
if (in_zsa->stencilTestEnable) {
555
out->DepthStencilState.FrontFace.StencilFailOp =
556
translate_stencil_op(in_zsa->front.failOp);
557
out->DepthStencilState.FrontFace.StencilDepthFailOp =
558
translate_stencil_op(in_zsa->front.depthFailOp);
559
out->DepthStencilState.FrontFace.StencilPassOp =
560
translate_stencil_op(in_zsa->front.passOp);
561
out->DepthStencilState.FrontFace.StencilFunc =
562
dzn_translate_compare_op(in_zsa->front.compareOp);
563
out->DepthStencilState.BackFace.StencilFailOp =
564
translate_stencil_op(in_zsa->back.failOp);
565
out->DepthStencilState.BackFace.StencilDepthFailOp =
566
translate_stencil_op(in_zsa->back.depthFailOp);
567
out->DepthStencilState.BackFace.StencilPassOp =
568
translate_stencil_op(in_zsa->back.passOp);
569
out->DepthStencilState.BackFace.StencilFunc =
570
dzn_translate_compare_op(in_zsa->back.compareOp);
572
pipeline->zsa.stencil_test.enable = true;
574
translate_stencil_test(pipeline, out, in);
579
translate_blend_factor(VkBlendFactor in, bool is_alpha)
582
case VK_BLEND_FACTOR_ZERO: return D3D12_BLEND_ZERO;
583
case VK_BLEND_FACTOR_ONE: return D3D12_BLEND_ONE;
584
case VK_BLEND_FACTOR_SRC_COLOR:
585
return is_alpha ? D3D12_BLEND_SRC_ALPHA : D3D12_BLEND_SRC_COLOR;
586
case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
587
return is_alpha ? D3D12_BLEND_INV_SRC_ALPHA : D3D12_BLEND_INV_SRC_COLOR;
588
case VK_BLEND_FACTOR_DST_COLOR:
589
return is_alpha ? D3D12_BLEND_DEST_ALPHA : D3D12_BLEND_DEST_COLOR;
590
case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
591
return is_alpha ? D3D12_BLEND_INV_DEST_ALPHA : D3D12_BLEND_INV_DEST_COLOR;
592
case VK_BLEND_FACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA;
593
case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA;
594
case VK_BLEND_FACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA;
595
case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA;
596
/* FIXME: no way to isolate the alpla and color constants */
597
case VK_BLEND_FACTOR_CONSTANT_COLOR:
598
case VK_BLEND_FACTOR_CONSTANT_ALPHA:
599
return D3D12_BLEND_BLEND_FACTOR;
600
case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
601
case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
602
return D3D12_BLEND_INV_BLEND_FACTOR;
603
case VK_BLEND_FACTOR_SRC1_COLOR:
604
return is_alpha ? D3D12_BLEND_SRC1_ALPHA : D3D12_BLEND_SRC1_COLOR;
605
case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
606
return is_alpha ? D3D12_BLEND_INV_SRC1_ALPHA : D3D12_BLEND_INV_SRC1_COLOR;
607
case VK_BLEND_FACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA;
608
case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA;
609
case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT;
610
default: unreachable("Invalid blend factor");
614
static D3D12_BLEND_OP
615
translate_blend_op(VkBlendOp in)
618
case VK_BLEND_OP_ADD: return D3D12_BLEND_OP_ADD;
619
case VK_BLEND_OP_SUBTRACT: return D3D12_BLEND_OP_SUBTRACT;
620
case VK_BLEND_OP_REVERSE_SUBTRACT: return D3D12_BLEND_OP_REV_SUBTRACT;
621
case VK_BLEND_OP_MIN: return D3D12_BLEND_OP_MIN;
622
case VK_BLEND_OP_MAX: return D3D12_BLEND_OP_MAX;
623
default: unreachable("Invalid blend op");
627
static D3D12_LOGIC_OP
628
translate_logic_op(VkLogicOp in)
631
case VK_LOGIC_OP_CLEAR: return D3D12_LOGIC_OP_CLEAR;
632
case VK_LOGIC_OP_AND: return D3D12_LOGIC_OP_AND;
633
case VK_LOGIC_OP_AND_REVERSE: return D3D12_LOGIC_OP_AND_REVERSE;
634
case VK_LOGIC_OP_COPY: return D3D12_LOGIC_OP_COPY;
635
case VK_LOGIC_OP_AND_INVERTED: return D3D12_LOGIC_OP_AND_INVERTED;
636
case VK_LOGIC_OP_NO_OP: return D3D12_LOGIC_OP_NOOP;
637
case VK_LOGIC_OP_XOR: return D3D12_LOGIC_OP_XOR;
638
case VK_LOGIC_OP_OR: return D3D12_LOGIC_OP_OR;
639
case VK_LOGIC_OP_NOR: return D3D12_LOGIC_OP_NOR;
640
case VK_LOGIC_OP_EQUIVALENT: return D3D12_LOGIC_OP_EQUIV;
641
case VK_LOGIC_OP_INVERT: return D3D12_LOGIC_OP_INVERT;
642
case VK_LOGIC_OP_OR_REVERSE: return D3D12_LOGIC_OP_OR_REVERSE;
643
case VK_LOGIC_OP_COPY_INVERTED: return D3D12_LOGIC_OP_COPY_INVERTED;
644
case VK_LOGIC_OP_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED;
645
case VK_LOGIC_OP_NAND: return D3D12_LOGIC_OP_NAND;
646
case VK_LOGIC_OP_SET: return D3D12_LOGIC_OP_SET;
647
default: unreachable("Invalid logic op");
652
dzn_graphics_pipeline_translate_blend(dzn_graphics_pipeline *pipeline,
653
D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
654
const VkGraphicsPipelineCreateInfo *in)
656
const VkPipelineRasterizationStateCreateInfo *in_rast =
657
in->pRasterizationState;
658
const VkPipelineColorBlendStateCreateInfo *in_blend =
659
in_rast->rasterizerDiscardEnable ? NULL : in->pColorBlendState;
660
const VkPipelineMultisampleStateCreateInfo *in_ms =
661
in_rast->rasterizerDiscardEnable ? NULL : in->pMultisampleState;
663
if (!in_blend || !in_ms)
666
D3D12_LOGIC_OP logicop =
667
in_blend->logicOpEnable ?
668
translate_logic_op(in_blend->logicOp) : D3D12_LOGIC_OP_NOOP;
669
out->BlendState.AlphaToCoverageEnable = in_ms->alphaToCoverageEnable;
670
memcpy(pipeline->blend.constants, in_blend->blendConstants,
671
sizeof(pipeline->blend.constants));
673
for (uint32_t i = 0; i < in_blend->attachmentCount; i++) {
675
!memcmp(&in_blend->pAttachments[i - 1], &in_blend->pAttachments[i],
676
sizeof(*in_blend->pAttachments)))
677
out->BlendState.IndependentBlendEnable = true;
679
out->BlendState.RenderTarget[i].BlendEnable =
680
in_blend->pAttachments[i].blendEnable;
681
in_blend->logicOpEnable;
682
out->BlendState.RenderTarget[i].RenderTargetWriteMask =
683
in_blend->pAttachments[i].colorWriteMask;
685
if (in_blend->logicOpEnable) {
686
out->BlendState.RenderTarget[i].LogicOpEnable = true;
687
out->BlendState.RenderTarget[i].LogicOp = logicop;
689
out->BlendState.RenderTarget[i].SrcBlend =
690
translate_blend_factor(in_blend->pAttachments[i].srcColorBlendFactor, false);
691
out->BlendState.RenderTarget[i].DestBlend =
692
translate_blend_factor(in_blend->pAttachments[i].dstColorBlendFactor, false);
693
out->BlendState.RenderTarget[i].BlendOp =
694
translate_blend_op(in_blend->pAttachments[i].colorBlendOp);
695
out->BlendState.RenderTarget[i].SrcBlendAlpha =
696
translate_blend_factor(in_blend->pAttachments[i].srcAlphaBlendFactor, true);
697
out->BlendState.RenderTarget[i].DestBlendAlpha =
698
translate_blend_factor(in_blend->pAttachments[i].dstAlphaBlendFactor, true);
699
out->BlendState.RenderTarget[i].BlendOpAlpha =
700
translate_blend_op(in_blend->pAttachments[i].alphaBlendOp);
707
dzn_pipeline_init(dzn_pipeline *pipeline,
709
VkPipelineBindPoint type,
710
dzn_pipeline_layout *layout)
712
pipeline->type = type;
713
pipeline->root.sets_param_count = layout->root.sets_param_count;
714
pipeline->root.sysval_cbv_param_idx = layout->root.sysval_cbv_param_idx;
715
pipeline->root.push_constant_cbv_param_idx = layout->root.push_constant_cbv_param_idx;
716
STATIC_ASSERT(sizeof(pipeline->root.type) == sizeof(layout->root.type));
717
memcpy(pipeline->root.type, layout->root.type, sizeof(pipeline->root.type));
718
pipeline->root.sig = layout->root.sig;
719
pipeline->root.sig->AddRef();
721
STATIC_ASSERT(sizeof(layout->desc_count) == sizeof(pipeline->desc_count));
722
memcpy(pipeline->desc_count, layout->desc_count, sizeof(pipeline->desc_count));
724
STATIC_ASSERT(sizeof(layout->sets) == sizeof(pipeline->sets));
725
memcpy(pipeline->sets, layout->sets, sizeof(pipeline->sets));
726
vk_object_base_init(&device->vk, &pipeline->base, VK_OBJECT_TYPE_PIPELINE);
730
dzn_pipeline_finish(dzn_pipeline *pipeline)
733
pipeline->state->Release();
734
if (pipeline->root.sig)
735
pipeline->root.sig->Release();
737
vk_object_base_finish(&pipeline->base);
741
dzn_graphics_pipeline_destroy(dzn_graphics_pipeline *pipeline,
742
const VkAllocationCallbacks *alloc)
747
for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->indirect_cmd_sigs); i++) {
748
if (pipeline->indirect_cmd_sigs[i])
749
pipeline->indirect_cmd_sigs[i]->Release();
752
dzn_pipeline_finish(&pipeline->base);
753
vk_free2(&pipeline->base.base.device->alloc, alloc, pipeline);
757
dzn_graphics_pipeline_create(dzn_device *device,
758
VkPipelineCache cache,
759
const VkGraphicsPipelineCreateInfo *pCreateInfo,
760
const VkAllocationCallbacks *pAllocator,
763
VK_FROM_HANDLE(dzn_render_pass, pass, pCreateInfo->renderPass);
764
VK_FROM_HANDLE(dzn_pipeline_layout, layout, pCreateInfo->layout);
765
const dzn_subpass *subpass = &pass->subpasses[pCreateInfo->subpass];
766
uint32_t stage_mask = 0;
770
dzn_graphics_pipeline *pipeline = (dzn_graphics_pipeline *)
771
vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8,
772
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
774
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
776
dzn_pipeline_init(&pipeline->base, device,
777
VK_PIPELINE_BIND_POINT_GRAPHICS,
779
D3D12_INPUT_ELEMENT_DESC *inputs = NULL;
780
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {
781
.pRootSignature = pipeline->base.root.sig,
782
.Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
785
const VkPipelineViewportStateCreateInfo *vp_info =
786
pCreateInfo->pRasterizationState->rasterizerDiscardEnable ?
787
NULL : pCreateInfo->pViewportState;
790
ret = dzn_graphics_pipeline_translate_vi(pipeline, pAllocator, &desc, pCreateInfo, &inputs);
791
if (ret != VK_SUCCESS)
794
if (pCreateInfo->pDynamicState) {
795
for (uint32_t i = 0; i < pCreateInfo->pDynamicState->dynamicStateCount; i++) {
796
switch (pCreateInfo->pDynamicState->pDynamicStates[i]) {
797
case VK_DYNAMIC_STATE_VIEWPORT:
798
pipeline->vp.dynamic = true;
800
case VK_DYNAMIC_STATE_SCISSOR:
801
pipeline->scissor.dynamic = true;
803
case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
804
pipeline->zsa.stencil_test.dynamic_ref = true;
806
case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
807
pipeline->zsa.stencil_test.dynamic_compare_mask = true;
809
case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
810
pipeline->zsa.stencil_test.dynamic_write_mask = true;
812
case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
813
pipeline->blend.dynamic_constants = true;
815
default: unreachable("Unsupported dynamic state");
820
dzn_graphics_pipeline_translate_ia(pipeline, &desc, pCreateInfo);
821
dzn_graphics_pipeline_translate_rast(pipeline, &desc, pCreateInfo);
822
dzn_graphics_pipeline_translate_ms(pipeline, &desc, pCreateInfo);
823
dzn_graphics_pipeline_translate_zsa(pipeline, &desc, pCreateInfo);
824
dzn_graphics_pipeline_translate_blend(pipeline, &desc, pCreateInfo);
826
desc.NumRenderTargets = subpass->color_count;
827
for (uint32_t i = 0; i < subpass->color_count; i++) {
828
uint32_t idx = subpass->colors[i].idx;
830
if (idx == VK_ATTACHMENT_UNUSED) continue;
832
const struct dzn_attachment *attachment = &pass->attachments[idx];
835
dzn_image_get_dxgi_format(attachment->format,
836
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
837
VK_IMAGE_ASPECT_COLOR_BIT);
840
if (subpass->zs.idx != VK_ATTACHMENT_UNUSED) {
841
const struct dzn_attachment *attachment =
842
&pass->attachments[subpass->zs.idx];
845
dzn_image_get_dxgi_format(attachment->format,
846
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
847
VK_IMAGE_ASPECT_DEPTH_BIT |
848
VK_IMAGE_ASPECT_STENCIL_BIT);
851
for (uint32_t i = 0; i < pCreateInfo->stageCount; i++)
852
stage_mask |= pCreateInfo->pStages[i].stage;
854
for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
855
if (pCreateInfo->pStages[i].stage == VK_SHADER_STAGE_FRAGMENT_BIT &&
856
pCreateInfo->pRasterizationState &&
857
(pCreateInfo->pRasterizationState->rasterizerDiscardEnable ||
858
pCreateInfo->pRasterizationState->cullMode == VK_CULL_MODE_FRONT_AND_BACK)) {
859
/* Disable rasterization (AKA leave fragment shader NULL) when
860
* front+back culling or discard is set.
865
D3D12_SHADER_BYTECODE *slot =
866
dzn_pipeline_get_gfx_shader_slot(&desc, pCreateInfo->pStages[i].stage);
867
enum dxil_spirv_yz_flip_mode yz_flip_mode = DXIL_SPIRV_YZ_FLIP_NONE;
868
uint16_t y_flip_mask = 0, z_flip_mask = 0;
870
if (pCreateInfo->pStages[i].stage == VK_SHADER_STAGE_GEOMETRY_BIT ||
871
(pCreateInfo->pStages[i].stage == VK_SHADER_STAGE_VERTEX_BIT &&
872
!(stage_mask & VK_SHADER_STAGE_GEOMETRY_BIT))) {
873
if (pipeline->vp.dynamic) {
874
yz_flip_mode = DXIL_SPIRV_YZ_FLIP_CONDITIONAL;
875
} else if (vp_info) {
876
for (uint32_t i = 0; vp_info->pViewports && i < vp_info->viewportCount; i++) {
877
if (vp_info->pViewports[i].height > 0)
878
y_flip_mask |= BITFIELD_BIT(i);
880
if (vp_info->pViewports[i].minDepth > vp_info->pViewports[i].maxDepth)
881
z_flip_mask |= BITFIELD_BIT(i);
884
if (y_flip_mask && z_flip_mask)
885
yz_flip_mode = DXIL_SPIRV_YZ_FLIP_UNCONDITIONAL;
886
else if (z_flip_mask)
887
yz_flip_mode = DXIL_SPIRV_Z_FLIP_UNCONDITIONAL;
888
else if (y_flip_mask)
889
yz_flip_mode = DXIL_SPIRV_Y_FLIP_UNCONDITIONAL;
893
ret = dzn_pipeline_compile_shader(device, pAllocator,
894
layout, &pCreateInfo->pStages[i],
895
yz_flip_mode, y_flip_mask, z_flip_mask, slot);
896
if (ret != VK_SUCCESS)
901
hres = device->dev->CreateGraphicsPipelineState(&desc,
902
IID_PPV_ARGS(&pipeline->base.state));
904
ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
911
for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
912
D3D12_SHADER_BYTECODE *slot =
913
dzn_pipeline_get_gfx_shader_slot(&desc, pCreateInfo->pStages[i].stage);
914
free((void *)slot->pShaderBytecode);
917
vk_free2(&device->vk.alloc, pAllocator, inputs);
918
if (ret != VK_SUCCESS)
919
dzn_graphics_pipeline_destroy(pipeline, pAllocator);
921
*out = dzn_graphics_pipeline_to_handle(pipeline);
926
#define DZN_INDIRECT_CMD_SIG_MAX_ARGS 3
928
ID3D12CommandSignature *
929
dzn_graphics_pipeline_get_indirect_cmd_sig(dzn_graphics_pipeline *pipeline,
930
enum dzn_indirect_draw_cmd_sig_type type)
932
assert(type < DZN_NUM_INDIRECT_DRAW_CMD_SIGS);
935
container_of(pipeline->base.base.device, dzn_device, vk);
936
ID3D12CommandSignature *cmdsig = pipeline->indirect_cmd_sigs[type];
941
bool triangle_fan = type == DZN_INDIRECT_DRAW_TRIANGLE_FAN_CMD_SIG;
942
bool indexed = type == DZN_INDIRECT_INDEXED_DRAW_CMD_SIG || triangle_fan;
944
uint32_t cmd_arg_count = 0;
945
D3D12_INDIRECT_ARGUMENT_DESC cmd_args[DZN_INDIRECT_CMD_SIG_MAX_ARGS];
948
cmd_args[cmd_arg_count++] = D3D12_INDIRECT_ARGUMENT_DESC {
949
.Type = D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW,
953
cmd_args[cmd_arg_count++] = D3D12_INDIRECT_ARGUMENT_DESC {
954
.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
956
.RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx,
957
.DestOffsetIn32BitValues = offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex) / 4,
958
.Num32BitValuesToSet = 2,
962
cmd_args[cmd_arg_count++] = D3D12_INDIRECT_ARGUMENT_DESC {
964
D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED :
965
D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,
968
assert(cmd_arg_count <= ARRAY_SIZE(cmd_args));
969
assert(offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex) == 0);
971
D3D12_COMMAND_SIGNATURE_DESC cmd_sig_desc = {
974
sizeof(struct dzn_indirect_triangle_fan_draw_exec_params) :
975
sizeof(struct dzn_indirect_draw_exec_params),
976
.NumArgumentDescs = cmd_arg_count,
977
.pArgumentDescs = cmd_args,
980
device->dev->CreateCommandSignature(&cmd_sig_desc,
981
pipeline->base.root.sig,
982
IID_PPV_ARGS(&cmdsig));
986
pipeline->indirect_cmd_sigs[type] = cmdsig;
990
VKAPI_ATTR VkResult VKAPI_CALL
991
dzn_CreateGraphicsPipelines(VkDevice dev,
992
VkPipelineCache pipelineCache,
994
const VkGraphicsPipelineCreateInfo *pCreateInfos,
995
const VkAllocationCallbacks *pAllocator,
996
VkPipeline *pPipelines)
998
VK_FROM_HANDLE(dzn_device, device, dev);
999
VkResult result = VK_SUCCESS;
1002
for (i = 0; i < count; i++) {
1003
result = dzn_graphics_pipeline_create(device,
1008
if (result != VK_SUCCESS) {
1009
pPipelines[i] = VK_NULL_HANDLE;
1011
/* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED_EX as it
1012
* is not obvious what error should be report upon 2 different failures.
1014
if (result != VK_PIPELINE_COMPILE_REQUIRED_EXT)
1017
if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT)
1022
for (; i < count; i++)
1023
pPipelines[i] = VK_NULL_HANDLE;
1029
dzn_compute_pipeline_destroy(dzn_compute_pipeline *pipeline,
1030
const VkAllocationCallbacks *alloc)
1035
if (pipeline->indirect_cmd_sig)
1036
pipeline->indirect_cmd_sig->Release();
1038
dzn_pipeline_finish(&pipeline->base);
1039
vk_free2(&pipeline->base.base.device->alloc, alloc, pipeline);
1043
dzn_compute_pipeline_create(dzn_device *device,
1044
VkPipelineCache cache,
1045
const VkComputePipelineCreateInfo *pCreateInfo,
1046
const VkAllocationCallbacks *pAllocator,
1049
VK_FROM_HANDLE(dzn_pipeline_layout, layout, pCreateInfo->layout);
1051
dzn_compute_pipeline *pipeline = (dzn_compute_pipeline *)
1052
vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8,
1053
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1055
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1057
dzn_pipeline_init(&pipeline->base, device,
1058
VK_PIPELINE_BIND_POINT_COMPUTE,
1061
D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {
1062
.pRootSignature = pipeline->base.root.sig,
1063
.Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
1067
dzn_pipeline_compile_shader(device, pAllocator, layout,
1068
&pCreateInfo->stage,
1069
DXIL_SPIRV_YZ_FLIP_NONE, 0, 0,
1071
if (ret != VK_SUCCESS)
1074
if (FAILED(device->dev->CreateComputePipelineState(&desc,
1075
IID_PPV_ARGS(&pipeline->base.state)))) {
1076
ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1081
free((void *)desc.CS.pShaderBytecode);
1082
if (ret != VK_SUCCESS)
1083
dzn_compute_pipeline_destroy(pipeline, pAllocator);
1085
*out = dzn_compute_pipeline_to_handle(pipeline);
1090
ID3D12CommandSignature *
1091
dzn_compute_pipeline_get_indirect_cmd_sig(dzn_compute_pipeline *pipeline)
1093
if (pipeline->indirect_cmd_sig)
1094
return pipeline->indirect_cmd_sig;
1096
dzn_device *device =
1097
container_of(pipeline->base.base.device, dzn_device, vk);
1099
D3D12_INDIRECT_ARGUMENT_DESC indirect_dispatch_args[] = {
1101
.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
1103
.RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx,
1104
.DestOffsetIn32BitValues = 0,
1105
.Num32BitValuesToSet = 3,
1109
.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
1113
D3D12_COMMAND_SIGNATURE_DESC indirect_dispatch_desc = {
1114
.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS) * 2,
1115
.NumArgumentDescs = ARRAY_SIZE(indirect_dispatch_args),
1116
.pArgumentDescs = indirect_dispatch_args,
1120
device->dev->CreateCommandSignature(&indirect_dispatch_desc,
1121
pipeline->base.root.sig,
1122
IID_PPV_ARGS(&pipeline->indirect_cmd_sig));
1126
return pipeline->indirect_cmd_sig;
1129
VKAPI_ATTR VkResult VKAPI_CALL
1130
dzn_CreateComputePipelines(VkDevice dev,
1131
VkPipelineCache pipelineCache,
1133
const VkComputePipelineCreateInfo *pCreateInfos,
1134
const VkAllocationCallbacks *pAllocator,
1135
VkPipeline *pPipelines)
1137
VK_FROM_HANDLE(dzn_device, device, dev);
1138
VkResult result = VK_SUCCESS;
1141
for (i = 0; i < count; i++) {
1142
result = dzn_compute_pipeline_create(device,
1147
if (result != VK_SUCCESS) {
1148
pPipelines[i] = VK_NULL_HANDLE;
1150
/* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED_EX as it
1151
* is not obvious what error should be report upon 2 different failures.
1153
if (result != VK_PIPELINE_COMPILE_REQUIRED_EXT)
1156
if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT)
1161
for (; i < count; i++)
1162
pPipelines[i] = VK_NULL_HANDLE;
1167
VKAPI_ATTR void VKAPI_CALL
1168
dzn_DestroyPipeline(VkDevice device,
1169
VkPipeline pipeline,
1170
const VkAllocationCallbacks *pAllocator)
1172
VK_FROM_HANDLE(dzn_pipeline, pipe, pipeline);
1177
if (pipe->type == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1178
dzn_graphics_pipeline *gfx = container_of(pipe, dzn_graphics_pipeline, base);
1179
dzn_graphics_pipeline_destroy(gfx, pAllocator);
1181
assert(pipe->type == VK_PIPELINE_BIND_POINT_COMPUTE);
1182
dzn_compute_pipeline *compute = container_of(pipe, dzn_compute_pipeline, base);
1183
dzn_compute_pipeline_destroy(compute, pAllocator);