~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/microsoft/vulkan/dzn_pipeline.cpp

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © Microsoft 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 "dzn_private.h"
25
 
 
26
 
#include "spirv_to_dxil.h"
27
 
 
28
 
#include "dxil_validator.h"
29
 
 
30
 
#include "vk_alloc.h"
31
 
#include "vk_util.h"
32
 
#include "vk_format.h"
33
 
 
34
 
#include "util/u_debug.h"
35
 
 
36
 
static dxil_spirv_shader_stage
37
 
to_dxil_shader_stage(VkShaderStageFlagBits in)
38
 
{
39
 
   switch (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");
47
 
   }
48
 
}
49
 
 
50
 
static VkResult
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)
58
 
{
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;
64
 
 
65
 
   /* convert VkSpecializationInfo */
66
 
   struct dxil_spirv_specialization *spec = NULL;
67
 
   uint32_t num_spec = 0;
68
 
 
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);
74
 
      if (!spec)
75
 
         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
76
 
 
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) {
83
 
         case 8:
84
 
            spec[i].value.u64 = *(const uint64_t *)data;
85
 
            break;
86
 
         case 4:
87
 
            spec[i].value.u32 = *(const uint32_t *)data;
88
 
            break;
89
 
         case 2:
90
 
            spec[i].value.u16 = *(const uint16_t *)data;
91
 
            break;
92
 
         case 1:
93
 
            spec[i].value.u8 = *(const uint8_t *)data;
94
 
            break;
95
 
         default:
96
 
            assert(!"Invalid spec constant size");
97
 
            break;
98
 
         }
99
 
 
100
 
         spec[i].defined_on_module = false;
101
 
      }
102
 
 
103
 
      num_spec = spec_info->mapEntryCount;
104
 
   }
105
 
 
106
 
   struct dxil_spirv_runtime_conf conf = {
107
 
      .runtime_data_cbv = {
108
 
         .register_space = DZN_REGISTER_SPACE_SYSVALS,
109
 
         .base_shader_register = 0,
110
 
      },
111
 
      .push_constant_cbv = {
112
 
         .register_space = DZN_REGISTER_SPACE_PUSH_CONSTANT,
113
 
         .base_shader_register = 0,
114
 
      },
115
 
      .descriptor_set_count = layout->set_count,
116
 
      .descriptor_sets = layout->binding_translation,
117
 
      .zero_based_vertex_instance_id = false,
118
 
      .yz_flip = {
119
 
         .mode = yz_flip_mode,
120
 
         .y_mask = y_flip_mask,
121
 
         .z_mask = z_flip_mask,
122
 
      },
123
 
      .read_only_images_as_srvs = true,
124
 
   };
125
 
 
126
 
   struct dxil_spirv_debug_options dbg_opts = {
127
 
      .dump_nir = !!(instance->debug_flags & DZN_DEBUG_NIR),
128
 
   };
129
 
 
130
 
   /* TODO: Extend spirv_to_dxil() to allow passing a custom allocator */
131
 
   bool success =
132
 
      spirv_to_dxil((uint32_t *)module->data, module->size / sizeof(uint32_t),
133
 
                    spec, num_spec,
134
 
                    to_dxil_shader_stage(stage_info->stage),
135
 
                    stage_info->pName, &dbg_opts, &conf, &dxil_object);
136
 
 
137
 
   vk_free2(&device->vk.alloc, alloc, spec);
138
 
 
139
 
   if (!success)
140
 
      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
141
 
 
142
 
   char *err;
143
 
   bool res = dxil_validate_module(instance->dxil_validator,
144
 
                                   dxil_object.binary.buffer,
145
 
                                   dxil_object.binary.size, &err);
146
 
 
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);
151
 
      if (disasm) {
152
 
         fprintf(stderr,
153
 
                 "== BEGIN SHADER ============================================\n"
154
 
                 "%s\n"
155
 
                 "== END SHADER ==============================================\n",
156
 
                  disasm);
157
 
         ralloc_free(disasm);
158
 
      }
159
 
   }
160
 
 
161
 
   if (!res) {
162
 
      if (err) {
163
 
         fprintf(stderr,
164
 
               "== VALIDATION ERROR =============================================\n"
165
 
               "%s\n"
166
 
               "== END ==========================================================\n",
167
 
               err);
168
 
         ralloc_free(err);
169
 
      }
170
 
      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
171
 
   }
172
 
 
173
 
   slot->pShaderBytecode = dxil_object.binary.buffer;
174
 
   slot->BytecodeLength = dxil_object.binary.size;
175
 
   return VK_SUCCESS;
176
 
}
177
 
 
178
 
static D3D12_SHADER_BYTECODE *
179
 
dzn_pipeline_get_gfx_shader_slot(D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,
180
 
                                 VkShaderStageFlagBits in)
181
 
{
182
 
   switch (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");
189
 
   }
190
 
}
191
 
 
192
 
static VkResult
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)
198
 
{
199
 
   dzn_device *device =
200
 
      container_of(pipeline->base.base.device, dzn_device, vk);
201
 
   const VkPipelineVertexInputStateCreateInfo *in_vi =
202
 
      in->pVertexInputState;
203
 
 
204
 
   if (!in_vi->vertexAttributeDescriptionCount) {
205
 
      out->InputLayout.pInputElementDescs = NULL;
206
 
      out->InputLayout.NumElements = 0;
207
 
      *input_elems = NULL;
208
 
      return VK_SUCCESS;
209
 
   }
210
 
 
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);
215
 
   if (!*input_elems)
216
 
      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
217
 
 
218
 
   D3D12_INPUT_ELEMENT_DESC *inputs = *input_elems;
219
 
   D3D12_INPUT_CLASSIFICATION slot_class[MAX_VBS];
220
 
 
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];
225
 
 
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;
230
 
      } else {
231
 
         assert(bdesc->inputRate == VK_VERTEX_INPUT_RATE_VERTEX);
232
 
         slot_class[bdesc->binding] = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
233
 
      }
234
 
   }
235
 
 
236
 
   for (uint32_t i = 0; i < in_vi->vertexAttributeDescriptionCount; i++) {
237
 
      const VkVertexInputAttributeDescription *attr =
238
 
         &in_vi->pVertexAttributeDescriptions[i];
239
 
 
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;
249
 
   }
250
 
 
251
 
   out->InputLayout.pInputElementDescs = inputs;
252
 
   out->InputLayout.NumElements = in_vi->vertexAttributeDescriptionCount;
253
 
   return VK_SUCCESS;
254
 
}
255
 
 
256
 
static D3D12_PRIMITIVE_TOPOLOGY_TYPE
257
 
to_prim_topology_type(VkPrimitiveTopology in)
258
 
{
259
 
   switch (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");
276
 
   }
277
 
}
278
 
 
279
 
static D3D12_PRIMITIVE_TOPOLOGY
280
 
to_prim_topology(VkPrimitiveTopology in, unsigned patch_control_points)
281
 
{
282
 
   switch (in) {
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");
298
 
   }
299
 
}
300
 
 
301
 
static void
302
 
dzn_graphics_pipeline_translate_ia(dzn_graphics_pipeline *pipeline,
303
 
                                   D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
304
 
                                   const VkGraphicsPipelineCreateInfo *in)
305
 
{
306
 
   const VkPipelineInputAssemblyStateCreateInfo *in_ia =
307
 
      in->pInputAssemblyState;
308
 
   const VkPipelineTessellationStateCreateInfo *in_tes =
309
 
      (out->DS.pShaderBytecode && out->HS.pShaderBytecode) ?
310
 
      in->pTessellationState : NULL;
311
 
 
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);
316
 
 
317
 
   /* FIXME: does that work for u16 index buffers? */
318
 
   if (in_ia->primitiveRestartEnable)
319
 
      out->IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;
320
 
   else
321
 
      out->IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
322
 
}
323
 
 
324
 
static D3D12_FILL_MODE
325
 
translate_polygon_mode(VkPolygonMode in)
326
 
{
327
 
   switch (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");
331
 
   }
332
 
}
333
 
 
334
 
static D3D12_CULL_MODE
335
 
translate_cull_mode(VkCullModeFlags in)
336
 
{
337
 
   switch (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");
344
 
   }
345
 
}
346
 
 
347
 
static void
348
 
dzn_graphics_pipeline_translate_rast(dzn_graphics_pipeline *pipeline,
349
 
                                     D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
350
 
                                     const VkGraphicsPipelineCreateInfo *in)
351
 
{
352
 
   const VkPipelineRasterizationStateCreateInfo *in_rast =
353
 
      in->pRasterizationState;
354
 
   const VkPipelineViewportStateCreateInfo *in_vp =
355
 
      in_rast->rasterizerDiscardEnable ? NULL : in->pViewportState;
356
 
 
357
 
   if (in_vp) {
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]);
362
 
      }
363
 
 
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]);
368
 
      }
369
 
   }
370
 
 
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;
380
 
   }
381
 
 
382
 
   assert(in_rast->lineWidth == 1.0f);
383
 
}
384
 
 
385
 
static void
386
 
dzn_graphics_pipeline_translate_ms(dzn_graphics_pipeline *pipeline,
387
 
                                   D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
388
 
                                   const VkGraphicsPipelineCreateInfo *in)
389
 
{
390
 
   const VkPipelineRasterizationStateCreateInfo *in_rast =
391
 
      in->pRasterizationState;
392
 
   const VkPipelineMultisampleStateCreateInfo *in_ms =
393
 
      in_rast->rasterizerDiscardEnable ? NULL : in->pMultisampleState;
394
 
 
395
 
   /* TODO: sampleShadingEnable, minSampleShading,
396
 
    *       alphaToOneEnable
397
 
    */
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;
403
 
}
404
 
 
405
 
static D3D12_STENCIL_OP
406
 
translate_stencil_op(VkStencilOp in)
407
 
{
408
 
   switch (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");
418
 
   }
419
 
}
420
 
 
421
 
static void
422
 
translate_stencil_test(dzn_graphics_pipeline *pipeline,
423
 
                       D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
424
 
                       const VkGraphicsPipelineCreateInfo *in)
425
 
{
426
 
   const VkPipelineDepthStencilStateCreateInfo *in_zsa =
427
 
      in->pDepthStencilState;
428
 
 
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);
441
 
 
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;
446
 
   else
447
 
      pipeline->zsa.stencil_test.front.compare_mask = 0;
448
 
 
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;
453
 
   else
454
 
      pipeline->zsa.stencil_test.back.compare_mask = 0;
455
 
 
456
 
   bool diff_wr_mask =
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);
460
 
   bool diff_ref =
461
 
      in->pRasterizationState->cullMode == VK_CULL_MODE_NONE &&
462
 
      (pipeline->zsa.stencil_test.dynamic_ref ||
463
 
       in_zsa->back.reference != in_zsa->front.reference);
464
 
   bool diff_cmp_mask =
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);
468
 
 
469
 
   if (diff_cmp_mask || diff_wr_mask)
470
 
      pipeline->zsa.stencil_test.independent_front_back = true;
471
 
 
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);
492
 
 
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;
501
 
 
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;
504
 
 
505
 
   if (diff_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;
509
 
 
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;
514
 
 
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.
518
 
    */
519
 
   out->DepthStencilState.StencilReadMask =
520
 
      front_test_uses_ref ?
521
 
      pipeline->zsa.stencil_test.front.compare_mask :
522
 
      back_test_uses_ref ?
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;
528
 
 
529
 
   assert(!pipeline->zsa.stencil_test.independent_front_back);
530
 
}
531
 
 
532
 
static void
533
 
dzn_graphics_pipeline_translate_zsa(dzn_graphics_pipeline *pipeline,
534
 
                                    D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
535
 
                                    const VkGraphicsPipelineCreateInfo *in)
536
 
{
537
 
   const VkPipelineRasterizationStateCreateInfo *in_rast =
538
 
      in->pRasterizationState;
539
 
   const VkPipelineDepthStencilStateCreateInfo *in_zsa =
540
 
      in_rast->rasterizerDiscardEnable ? NULL : in->pDepthStencilState;
541
 
 
542
 
   if (!in_zsa)
543
 
      return;
544
 
 
545
 
   /* TODO: depthBoundsTestEnable */
546
 
 
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);
571
 
 
572
 
      pipeline->zsa.stencil_test.enable = true;
573
 
 
574
 
      translate_stencil_test(pipeline, out, in);
575
 
   }
576
 
}
577
 
 
578
 
static D3D12_BLEND
579
 
translate_blend_factor(VkBlendFactor in, bool is_alpha)
580
 
{
581
 
   switch (in) {
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");
611
 
   }
612
 
}
613
 
 
614
 
static D3D12_BLEND_OP
615
 
translate_blend_op(VkBlendOp in)
616
 
{
617
 
   switch (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");
624
 
   }
625
 
}
626
 
 
627
 
static D3D12_LOGIC_OP
628
 
translate_logic_op(VkLogicOp in)
629
 
{
630
 
   switch (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");
648
 
   }
649
 
}
650
 
 
651
 
static void
652
 
dzn_graphics_pipeline_translate_blend(dzn_graphics_pipeline *pipeline,
653
 
                                      D3D12_GRAPHICS_PIPELINE_STATE_DESC *out,
654
 
                                      const VkGraphicsPipelineCreateInfo *in)
655
 
{
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;
662
 
 
663
 
   if (!in_blend || !in_ms)
664
 
      return;
665
 
 
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));
672
 
 
673
 
   for (uint32_t i = 0; i < in_blend->attachmentCount; i++) {
674
 
      if (i > 0 &&
675
 
          !memcmp(&in_blend->pAttachments[i - 1], &in_blend->pAttachments[i],
676
 
                  sizeof(*in_blend->pAttachments)))
677
 
         out->BlendState.IndependentBlendEnable = true;
678
 
 
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;
684
 
 
685
 
      if (in_blend->logicOpEnable) {
686
 
         out->BlendState.RenderTarget[i].LogicOpEnable = true;
687
 
         out->BlendState.RenderTarget[i].LogicOp = logicop;
688
 
      } else {
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);
701
 
      }
702
 
   }
703
 
}
704
 
 
705
 
 
706
 
static void
707
 
dzn_pipeline_init(dzn_pipeline *pipeline,
708
 
                  dzn_device *device,
709
 
                  VkPipelineBindPoint type,
710
 
                  dzn_pipeline_layout *layout)
711
 
{
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();
720
 
 
721
 
   STATIC_ASSERT(sizeof(layout->desc_count) == sizeof(pipeline->desc_count));
722
 
   memcpy(pipeline->desc_count, layout->desc_count, sizeof(pipeline->desc_count));
723
 
 
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);
727
 
}
728
 
 
729
 
static void
730
 
dzn_pipeline_finish(dzn_pipeline *pipeline)
731
 
{
732
 
   if (pipeline->state)
733
 
      pipeline->state->Release();
734
 
   if (pipeline->root.sig)
735
 
      pipeline->root.sig->Release();
736
 
 
737
 
   vk_object_base_finish(&pipeline->base);
738
 
}
739
 
 
740
 
static void
741
 
dzn_graphics_pipeline_destroy(dzn_graphics_pipeline *pipeline,
742
 
                              const VkAllocationCallbacks *alloc)
743
 
{
744
 
   if (!pipeline)
745
 
      return;
746
 
 
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();
750
 
   }
751
 
 
752
 
   dzn_pipeline_finish(&pipeline->base);
753
 
   vk_free2(&pipeline->base.base.device->alloc, alloc, pipeline);
754
 
}
755
 
 
756
 
static VkResult
757
 
dzn_graphics_pipeline_create(dzn_device *device,
758
 
                             VkPipelineCache cache,
759
 
                             const VkGraphicsPipelineCreateInfo *pCreateInfo,
760
 
                             const VkAllocationCallbacks *pAllocator,
761
 
                             VkPipeline *out)
762
 
{
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;
767
 
   VkResult ret;
768
 
   HRESULT hres = 0;
769
 
 
770
 
   dzn_graphics_pipeline *pipeline = (dzn_graphics_pipeline *)
771
 
      vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8,
772
 
                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
773
 
   if (!pipeline)
774
 
      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
775
 
 
776
 
   dzn_pipeline_init(&pipeline->base, device,
777
 
                     VK_PIPELINE_BIND_POINT_GRAPHICS,
778
 
                     layout);
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,
783
 
   };
784
 
 
785
 
   const VkPipelineViewportStateCreateInfo *vp_info =
786
 
      pCreateInfo->pRasterizationState->rasterizerDiscardEnable ?
787
 
      NULL : pCreateInfo->pViewportState;
788
 
 
789
 
 
790
 
   ret = dzn_graphics_pipeline_translate_vi(pipeline, pAllocator, &desc, pCreateInfo, &inputs);
791
 
   if (ret != VK_SUCCESS)
792
 
      goto out;
793
 
 
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;
799
 
            break;
800
 
         case VK_DYNAMIC_STATE_SCISSOR:
801
 
            pipeline->scissor.dynamic = true;
802
 
            break;
803
 
         case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
804
 
            pipeline->zsa.stencil_test.dynamic_ref = true;
805
 
            break;
806
 
         case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
807
 
            pipeline->zsa.stencil_test.dynamic_compare_mask = true;
808
 
            break;
809
 
         case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
810
 
            pipeline->zsa.stencil_test.dynamic_write_mask = true;
811
 
            break;
812
 
         case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
813
 
            pipeline->blend.dynamic_constants = true;
814
 
            break;
815
 
         default: unreachable("Unsupported dynamic state");
816
 
         }
817
 
      }
818
 
   }
819
 
 
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);
825
 
 
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;
829
 
 
830
 
      if (idx == VK_ATTACHMENT_UNUSED) continue;
831
 
 
832
 
      const struct dzn_attachment *attachment = &pass->attachments[idx];
833
 
 
834
 
      desc.RTVFormats[i] =
835
 
         dzn_image_get_dxgi_format(attachment->format,
836
 
                                   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
837
 
                                   VK_IMAGE_ASPECT_COLOR_BIT);
838
 
   }
839
 
 
840
 
   if (subpass->zs.idx != VK_ATTACHMENT_UNUSED) {
841
 
      const struct dzn_attachment *attachment =
842
 
         &pass->attachments[subpass->zs.idx];
843
 
 
844
 
      desc.DSVFormat =
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);
849
 
   }
850
 
 
851
 
   for (uint32_t i = 0; i < pCreateInfo->stageCount; i++)
852
 
      stage_mask |= pCreateInfo->pStages[i].stage;
853
 
 
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.
861
 
          */
862
 
         continue;
863
 
      }
864
 
 
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;
869
 
 
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);
879
 
 
880
 
               if (vp_info->pViewports[i].minDepth > vp_info->pViewports[i].maxDepth)
881
 
                  z_flip_mask |= BITFIELD_BIT(i);
882
 
            }
883
 
 
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;
890
 
         }
891
 
      }
892
 
 
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)
897
 
         goto out;
898
 
   }
899
 
 
900
 
 
901
 
   hres = device->dev->CreateGraphicsPipelineState(&desc,
902
 
                                                   IID_PPV_ARGS(&pipeline->base.state));
903
 
   if (FAILED(hres)) {
904
 
      ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
905
 
      goto out;
906
 
   }
907
 
 
908
 
   ret = VK_SUCCESS;
909
 
 
910
 
out:
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);
915
 
   }
916
 
 
917
 
   vk_free2(&device->vk.alloc, pAllocator, inputs);
918
 
   if (ret != VK_SUCCESS)
919
 
      dzn_graphics_pipeline_destroy(pipeline, pAllocator);
920
 
   else
921
 
      *out = dzn_graphics_pipeline_to_handle(pipeline);
922
 
 
923
 
   return ret;
924
 
}
925
 
 
926
 
#define DZN_INDIRECT_CMD_SIG_MAX_ARGS 3
927
 
 
928
 
ID3D12CommandSignature *
929
 
dzn_graphics_pipeline_get_indirect_cmd_sig(dzn_graphics_pipeline *pipeline,
930
 
                                           enum dzn_indirect_draw_cmd_sig_type type)
931
 
{
932
 
   assert(type < DZN_NUM_INDIRECT_DRAW_CMD_SIGS);
933
 
 
934
 
   dzn_device *device =
935
 
      container_of(pipeline->base.base.device, dzn_device, vk);
936
 
   ID3D12CommandSignature *cmdsig = pipeline->indirect_cmd_sigs[type];
937
 
 
938
 
   if (cmdsig)
939
 
      return cmdsig;
940
 
 
941
 
   bool triangle_fan = type == DZN_INDIRECT_DRAW_TRIANGLE_FAN_CMD_SIG;
942
 
   bool indexed = type == DZN_INDIRECT_INDEXED_DRAW_CMD_SIG || triangle_fan;
943
 
 
944
 
   uint32_t cmd_arg_count = 0;
945
 
   D3D12_INDIRECT_ARGUMENT_DESC cmd_args[DZN_INDIRECT_CMD_SIG_MAX_ARGS];
946
 
 
947
 
   if (triangle_fan) {
948
 
      cmd_args[cmd_arg_count++] = D3D12_INDIRECT_ARGUMENT_DESC {
949
 
         .Type = D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW,
950
 
      };
951
 
   }
952
 
 
953
 
   cmd_args[cmd_arg_count++] = D3D12_INDIRECT_ARGUMENT_DESC {
954
 
      .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
955
 
      .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,
959
 
      },
960
 
   };
961
 
 
962
 
   cmd_args[cmd_arg_count++] = D3D12_INDIRECT_ARGUMENT_DESC {
963
 
      .Type = indexed ?
964
 
              D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED :
965
 
              D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,
966
 
   };
967
 
 
968
 
   assert(cmd_arg_count <= ARRAY_SIZE(cmd_args));
969
 
   assert(offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex) == 0);
970
 
 
971
 
   D3D12_COMMAND_SIGNATURE_DESC cmd_sig_desc = {
972
 
      .ByteStride =
973
 
         triangle_fan ?
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,
978
 
   };
979
 
   HRESULT hres =
980
 
      device->dev->CreateCommandSignature(&cmd_sig_desc,
981
 
                                          pipeline->base.root.sig,
982
 
                                          IID_PPV_ARGS(&cmdsig));
983
 
   if (FAILED(hres))
984
 
      return NULL;
985
 
 
986
 
   pipeline->indirect_cmd_sigs[type] = cmdsig;
987
 
   return cmdsig;
988
 
}
989
 
 
990
 
VKAPI_ATTR VkResult VKAPI_CALL
991
 
dzn_CreateGraphicsPipelines(VkDevice dev,
992
 
                            VkPipelineCache pipelineCache,
993
 
                            uint32_t count,
994
 
                            const VkGraphicsPipelineCreateInfo *pCreateInfos,
995
 
                            const VkAllocationCallbacks *pAllocator,
996
 
                            VkPipeline *pPipelines)
997
 
{
998
 
   VK_FROM_HANDLE(dzn_device, device, dev);
999
 
   VkResult result = VK_SUCCESS;
1000
 
 
1001
 
   unsigned i;
1002
 
   for (i = 0; i < count; i++) {
1003
 
      result = dzn_graphics_pipeline_create(device,
1004
 
                                            pipelineCache,
1005
 
                                            &pCreateInfos[i],
1006
 
                                            pAllocator,
1007
 
                                            &pPipelines[i]);
1008
 
      if (result != VK_SUCCESS) {
1009
 
         pPipelines[i] = VK_NULL_HANDLE;
1010
 
 
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.
1013
 
          */
1014
 
         if (result != VK_PIPELINE_COMPILE_REQUIRED_EXT)
1015
 
            break;
1016
 
 
1017
 
         if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT)
1018
 
            break;
1019
 
      }
1020
 
   }
1021
 
 
1022
 
   for (; i < count; i++)
1023
 
      pPipelines[i] = VK_NULL_HANDLE;
1024
 
 
1025
 
   return result;
1026
 
}
1027
 
 
1028
 
static void
1029
 
dzn_compute_pipeline_destroy(dzn_compute_pipeline *pipeline,
1030
 
                             const VkAllocationCallbacks *alloc)
1031
 
{
1032
 
   if (!pipeline)
1033
 
      return;
1034
 
 
1035
 
   if (pipeline->indirect_cmd_sig)
1036
 
      pipeline->indirect_cmd_sig->Release();
1037
 
 
1038
 
   dzn_pipeline_finish(&pipeline->base);
1039
 
   vk_free2(&pipeline->base.base.device->alloc, alloc, pipeline);
1040
 
}
1041
 
 
1042
 
static VkResult
1043
 
dzn_compute_pipeline_create(dzn_device *device,
1044
 
                            VkPipelineCache cache,
1045
 
                            const VkComputePipelineCreateInfo *pCreateInfo,
1046
 
                            const VkAllocationCallbacks *pAllocator,
1047
 
                            VkPipeline *out)
1048
 
{
1049
 
   VK_FROM_HANDLE(dzn_pipeline_layout, layout, pCreateInfo->layout);
1050
 
 
1051
 
   dzn_compute_pipeline *pipeline = (dzn_compute_pipeline *)
1052
 
      vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8,
1053
 
                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1054
 
   if (!pipeline)
1055
 
      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1056
 
 
1057
 
   dzn_pipeline_init(&pipeline->base, device,
1058
 
                     VK_PIPELINE_BIND_POINT_COMPUTE,
1059
 
                     layout);
1060
 
 
1061
 
   D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {
1062
 
      .pRootSignature = pipeline->base.root.sig,
1063
 
      .Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
1064
 
   };
1065
 
 
1066
 
   VkResult ret =
1067
 
      dzn_pipeline_compile_shader(device, pAllocator, layout,
1068
 
                                  &pCreateInfo->stage,
1069
 
                                  DXIL_SPIRV_YZ_FLIP_NONE, 0, 0,
1070
 
                                  &desc.CS);
1071
 
   if (ret != VK_SUCCESS)
1072
 
      goto out;
1073
 
 
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);
1077
 
      goto out;
1078
 
   }
1079
 
 
1080
 
out:
1081
 
   free((void *)desc.CS.pShaderBytecode);
1082
 
   if (ret != VK_SUCCESS)
1083
 
      dzn_compute_pipeline_destroy(pipeline, pAllocator);
1084
 
   else
1085
 
      *out = dzn_compute_pipeline_to_handle(pipeline);
1086
 
 
1087
 
   return ret;
1088
 
}
1089
 
 
1090
 
ID3D12CommandSignature *
1091
 
dzn_compute_pipeline_get_indirect_cmd_sig(dzn_compute_pipeline *pipeline)
1092
 
{
1093
 
   if (pipeline->indirect_cmd_sig)
1094
 
      return pipeline->indirect_cmd_sig;
1095
 
 
1096
 
   dzn_device *device =
1097
 
      container_of(pipeline->base.base.device, dzn_device, vk);
1098
 
 
1099
 
   D3D12_INDIRECT_ARGUMENT_DESC indirect_dispatch_args[] = {
1100
 
      {
1101
 
         .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
1102
 
         .Constant = {
1103
 
            .RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx,
1104
 
            .DestOffsetIn32BitValues = 0,
1105
 
            .Num32BitValuesToSet = 3,
1106
 
         },
1107
 
      },
1108
 
      {
1109
 
         .Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
1110
 
      },
1111
 
   };
1112
 
 
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,
1117
 
   };
1118
 
 
1119
 
   HRESULT hres =
1120
 
      device->dev->CreateCommandSignature(&indirect_dispatch_desc,
1121
 
                                          pipeline->base.root.sig,
1122
 
                                          IID_PPV_ARGS(&pipeline->indirect_cmd_sig));
1123
 
   if (FAILED(hres))
1124
 
      return NULL;
1125
 
 
1126
 
   return pipeline->indirect_cmd_sig;
1127
 
}
1128
 
 
1129
 
VKAPI_ATTR VkResult VKAPI_CALL
1130
 
dzn_CreateComputePipelines(VkDevice dev,
1131
 
                           VkPipelineCache pipelineCache,
1132
 
                           uint32_t count,
1133
 
                           const VkComputePipelineCreateInfo *pCreateInfos,
1134
 
                           const VkAllocationCallbacks *pAllocator,
1135
 
                           VkPipeline *pPipelines)
1136
 
{
1137
 
   VK_FROM_HANDLE(dzn_device, device, dev);
1138
 
   VkResult result = VK_SUCCESS;
1139
 
 
1140
 
   unsigned i;
1141
 
   for (i = 0; i < count; i++) {
1142
 
      result = dzn_compute_pipeline_create(device,
1143
 
                                           pipelineCache,
1144
 
                                           &pCreateInfos[i],
1145
 
                                           pAllocator,
1146
 
                                           &pPipelines[i]);
1147
 
      if (result != VK_SUCCESS) {
1148
 
         pPipelines[i] = VK_NULL_HANDLE;
1149
 
 
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.
1152
 
          */
1153
 
         if (result != VK_PIPELINE_COMPILE_REQUIRED_EXT)
1154
 
            break;
1155
 
 
1156
 
         if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT)
1157
 
            break;
1158
 
      }
1159
 
   }
1160
 
 
1161
 
   for (; i < count; i++)
1162
 
      pPipelines[i] = VK_NULL_HANDLE;
1163
 
 
1164
 
   return result;
1165
 
}
1166
 
 
1167
 
VKAPI_ATTR void VKAPI_CALL
1168
 
dzn_DestroyPipeline(VkDevice device,
1169
 
                    VkPipeline pipeline,
1170
 
                    const VkAllocationCallbacks *pAllocator)
1171
 
{
1172
 
   VK_FROM_HANDLE(dzn_pipeline, pipe, pipeline);
1173
 
 
1174
 
   if (!pipe)
1175
 
      return;
1176
 
 
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);
1180
 
   } else {
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);
1184
 
   }
1185
 
}