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 #include "nir_to_dxil.h"
28 
29 #include "dxil_nir.h"
30 #include "dxil_nir_lower_int_samplers.h"
31 
32 static void
dzn_meta_compile_shader(dzn_device * device,nir_shader * nir,D3D12_SHADER_BYTECODE * slot)33 dzn_meta_compile_shader(dzn_device *device, nir_shader *nir,
34                         D3D12_SHADER_BYTECODE *slot)
35 {
36    dzn_instance *instance =
37       container_of(device->vk.physical->instance, dzn_instance, vk);
38    IDxcValidator *validator = instance->dxc.validator;
39    IDxcLibrary *library = instance->dxc.library;
40    IDxcCompiler *compiler = instance->dxc.compiler;
41 
42    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
43 
44    if ((instance->debug_flags & DZN_DEBUG_NIR) &&
45        (instance->debug_flags & DZN_DEBUG_INTERNAL))
46       nir_print_shader(nir, stderr);
47 
48    struct nir_to_dxil_options opts = { .environment = DXIL_ENVIRONMENT_VULKAN };
49    struct blob dxil_blob;
50    bool ret = nir_to_dxil(nir, &opts, &dxil_blob);
51    assert(ret);
52 
53    dzn_shader_blob blob(dxil_blob.data, dxil_blob.size);
54    ComPtr<IDxcOperationResult> result;
55    validator->Validate(&blob, DxcValidatorFlags_InPlaceEdit, &result);
56    if ((instance->debug_flags & DZN_DEBUG_DXIL) &&
57        (instance->debug_flags & DZN_DEBUG_INTERNAL)) {
58       IDxcBlobEncoding *disassembly;
59       compiler->Disassemble(&blob, &disassembly);
60       ComPtr<IDxcBlobEncoding> blobUtf8;
61       library->GetBlobAsUtf8(disassembly, blobUtf8.GetAddressOf());
62       char *disasm = reinterpret_cast<char*>(blobUtf8->GetBufferPointer());
63       disasm[blobUtf8->GetBufferSize() - 1] = 0;
64       fprintf(stderr,
65               "== BEGIN SHADER ============================================\n"
66               "%s\n"
67               "== END SHADER ==============================================\n",
68               disasm);
69       disassembly->Release();
70    }
71 
72    HRESULT validationStatus;
73    result->GetStatus(&validationStatus);
74    if (FAILED(validationStatus)) {
75       if ((instance->debug_flags & DZN_DEBUG_DXIL) &&
76           (instance->debug_flags & DZN_DEBUG_INTERNAL)) {
77          ComPtr<IDxcBlobEncoding> printBlob, printBlobUtf8;
78          result->GetErrorBuffer(&printBlob);
79          library->GetBlobAsUtf8(printBlob.Get(), printBlobUtf8.GetAddressOf());
80 
81          char *errorString;
82          if (printBlobUtf8) {
83             errorString = reinterpret_cast<char*>(printBlobUtf8->GetBufferPointer());
84             errorString[printBlobUtf8->GetBufferSize() - 1] = 0;
85             fprintf(stderr,
86                     "== VALIDATION ERROR =============================================\n"
87                     "%s\n"
88                     "== END ==========================================================\n",
89                     errorString);
90          }
91       }
92    }
93    assert(!FAILED(validationStatus));
94 
95    void *data;
96    size_t size;
97    blob_finish_get_buffer(&dxil_blob, &data, &size);
98    slot->pShaderBytecode = data;
99    slot->BytecodeLength = size;
100 }
101 
102 #define DZN_META_INDIRECT_DRAW_MAX_PARAM_COUNT 4
103 
104 static void
dzn_meta_indirect_draw_finish(dzn_device * device,enum dzn_indirect_draw_type type)105 dzn_meta_indirect_draw_finish(dzn_device *device, enum dzn_indirect_draw_type type)
106 {
107    dzn_meta_indirect_draw *meta = &device->indirect_draws[type];
108 
109    if (meta->root_sig)
110       meta->root_sig->Release();
111 
112    if (meta->pipeline_state)
113       meta->pipeline_state->Release();
114 }
115 
116 static VkResult
dzn_meta_indirect_draw_init(dzn_device * device,enum dzn_indirect_draw_type type)117 dzn_meta_indirect_draw_init(dzn_device *device,
118                             enum dzn_indirect_draw_type type)
119 {
120    dzn_meta_indirect_draw *meta = &device->indirect_draws[type];
121    dzn_instance *instance =
122       container_of(device->vk.physical->instance, dzn_instance, vk);
123    VkResult ret = VK_SUCCESS;
124 
125    glsl_type_singleton_init_or_ref();
126 
127    nir_shader *nir = dzn_nir_indirect_draw_shader(type);
128    bool triangle_fan = type == DZN_INDIRECT_DRAW_TRIANGLE_FAN ||
129                        type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
130    uint32_t shader_params_size =
131       triangle_fan ?
132       sizeof(struct dzn_indirect_draw_triangle_fan_rewrite_params) :
133       sizeof(struct dzn_indirect_draw_rewrite_params);
134 
135    uint32_t root_param_count = 0;
136    D3D12_ROOT_PARAMETER1 root_params[DZN_META_INDIRECT_DRAW_MAX_PARAM_COUNT];
137 
138    root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
139       .ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
140       .Constants = {
141          .ShaderRegister = 0,
142          .RegisterSpace = 0,
143          .Num32BitValues = shader_params_size / 4,
144       },
145       .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
146    };
147 
148    root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
149       .ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV,
150       .Descriptor = {
151          .ShaderRegister = 1,
152          .RegisterSpace = 0,
153          .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
154       },
155       .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
156    };
157 
158    root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
159       .ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV,
160       .Descriptor = {
161          .ShaderRegister = 2,
162          .RegisterSpace = 0,
163          .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
164       },
165       .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
166    };
167 
168 
169    if (triangle_fan) {
170       root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
171          .ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV,
172          .Descriptor = {
173             .ShaderRegister = 3,
174             .RegisterSpace = 0,
175             .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
176          },
177          .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
178       };
179    }
180 
181    assert(root_param_count <= ARRAY_SIZE(root_params));
182 
183    D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc = {
184       .Version = D3D_ROOT_SIGNATURE_VERSION_1_1,
185       .Desc_1_1 = {
186          .NumParameters = root_param_count,
187          .pParameters = root_params,
188          .Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE,
189       },
190    };
191 
192    D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {
193       .Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
194    };
195 
196    meta->root_sig =
197       dzn_device_create_root_sig(device, &root_sig_desc);
198    if (!meta->root_sig) {
199       ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
200       goto out;
201    }
202 
203    desc.pRootSignature = meta->root_sig;
204    dzn_meta_compile_shader(device, nir, &desc.CS);
205    assert(desc.CS.pShaderBytecode);
206 
207    if (FAILED(device->dev->CreateComputePipelineState(&desc,
208                                                       IID_PPV_ARGS(&meta->pipeline_state))))
209       ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
210 
211 out:
212    if (ret != VK_SUCCESS)
213       dzn_meta_indirect_draw_finish(device, type);
214 
215    free((void *)desc.CS.pShaderBytecode);
216    ralloc_free(nir);
217    glsl_type_singleton_decref();
218 
219    return ret;
220 }
221 
222 #define DZN_META_TRIANGLE_FAN_REWRITE_IDX_MAX_PARAM_COUNT 3
223 
224 static void
dzn_meta_triangle_fan_rewrite_index_finish(dzn_device * device,enum dzn_index_type old_index_type)225 dzn_meta_triangle_fan_rewrite_index_finish(dzn_device *device,
226                                            enum dzn_index_type old_index_type)
227 {
228    dzn_meta_triangle_fan_rewrite_index *meta =
229       &device->triangle_fan[old_index_type];
230 
231    if (meta->root_sig)
232       meta->root_sig->Release();
233    if (meta->pipeline_state)
234       meta->pipeline_state->Release();
235    if (meta->cmd_sig)
236       meta->cmd_sig->Release();
237 }
238 
239 static VkResult
dzn_meta_triangle_fan_rewrite_index_init(dzn_device * device,enum dzn_index_type old_index_type)240 dzn_meta_triangle_fan_rewrite_index_init(dzn_device *device,
241                                          enum dzn_index_type old_index_type)
242 {
243    dzn_meta_triangle_fan_rewrite_index *meta =
244       &device->triangle_fan[old_index_type];
245    dzn_instance *instance =
246       container_of(device->vk.physical->instance, dzn_instance, vk);
247    VkResult ret = VK_SUCCESS;
248 
249    glsl_type_singleton_init_or_ref();
250 
251    uint8_t old_index_size = dzn_index_size(old_index_type);
252 
253    nir_shader *nir = dzn_nir_triangle_fan_rewrite_index_shader(old_index_size);
254 
255    uint32_t root_param_count = 0;
256    D3D12_ROOT_PARAMETER1 root_params[DZN_META_TRIANGLE_FAN_REWRITE_IDX_MAX_PARAM_COUNT];
257 
258    root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
259       .ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV,
260       .Descriptor = {
261          .ShaderRegister = 1,
262          .RegisterSpace = 0,
263          .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
264       },
265       .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
266    };
267 
268    root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
269       .ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
270       .Constants = {
271          .ShaderRegister = 0,
272          .RegisterSpace = 0,
273          .Num32BitValues = sizeof(struct dzn_triangle_fan_rewrite_index_params) / 4,
274       },
275       .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
276    };
277 
278    if (old_index_type != DZN_NO_INDEX) {
279       root_params[root_param_count++] = D3D12_ROOT_PARAMETER1 {
280          .ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV,
281          .Descriptor = {
282             .ShaderRegister = 2,
283             .RegisterSpace = 0,
284             .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
285          },
286          .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
287       };
288    }
289 
290    assert(root_param_count <= ARRAY_SIZE(root_params));
291 
292    D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc = {
293       .Version = D3D_ROOT_SIGNATURE_VERSION_1_1,
294       .Desc_1_1 = {
295          .NumParameters = root_param_count,
296          .pParameters = root_params,
297          .Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE,
298       },
299    };
300 
301    D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {
302       .Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
303    };
304 
305    D3D12_INDIRECT_ARGUMENT_DESC cmd_args[] = {
306       {
307          .Type = D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW,
308          .UnorderedAccessView = {
309             .RootParameterIndex = 0,
310          },
311       },
312       {
313          .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
314          .Constant = {
315             .RootParameterIndex = 1,
316             .DestOffsetIn32BitValues = 0,
317             .Num32BitValuesToSet = sizeof(struct dzn_triangle_fan_rewrite_index_params) / 4,
318          },
319       },
320       {
321          .Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
322       },
323    };
324 
325    D3D12_COMMAND_SIGNATURE_DESC cmd_sig_desc = {
326       .ByteStride = sizeof(struct dzn_indirect_triangle_fan_rewrite_index_exec_params),
327       .NumArgumentDescs = ARRAY_SIZE(cmd_args),
328       .pArgumentDescs = cmd_args,
329    };
330 
331    assert((cmd_sig_desc.ByteStride & 7) == 0);
332 
333    meta->root_sig = dzn_device_create_root_sig(device, &root_sig_desc);
334    if (!meta->root_sig) {
335       ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
336       goto out;
337    }
338 
339 
340    desc.pRootSignature = meta->root_sig;
341    dzn_meta_compile_shader(device, nir, &desc.CS);
342 
343    if (FAILED(device->dev->CreateComputePipelineState(&desc,
344                                                       IID_PPV_ARGS(&meta->pipeline_state)))) {
345       ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
346       goto out;
347    }
348 
349    if (FAILED(device->dev->CreateCommandSignature(&cmd_sig_desc,
350                                                   meta->root_sig,
351                                                   IID_PPV_ARGS(&meta->cmd_sig))))
352       ret = vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
353 
354 out:
355    if (ret != VK_SUCCESS)
356       dzn_meta_triangle_fan_rewrite_index_finish(device, old_index_type);
357 
358    free((void *)desc.CS.pShaderBytecode);
359    ralloc_free(nir);
360    glsl_type_singleton_decref();
361 
362    return ret;
363 }
364 
365 static const D3D12_SHADER_BYTECODE *
dzn_meta_blits_get_vs(dzn_device * device)366 dzn_meta_blits_get_vs(dzn_device *device)
367 {
368    dzn_meta_blits *meta = &device->blits;
369    D3D12_SHADER_BYTECODE *out;
370 
371    mtx_lock(&meta->shaders_lock);
372 
373    if (meta->vs.pShaderBytecode == NULL) {
374       nir_shader *nir = dzn_nir_blit_vs();
375 
376       NIR_PASS_V(nir, nir_lower_system_values);
377 
378       gl_system_value system_values[] = {
379          SYSTEM_VALUE_FIRST_VERTEX,
380          SYSTEM_VALUE_BASE_VERTEX,
381       };
382 
383       NIR_PASS_V(nir, dxil_nir_lower_system_values_to_zero, system_values,
384                 ARRAY_SIZE(system_values));
385 
386       D3D12_SHADER_BYTECODE bc;
387 
388       dzn_meta_compile_shader(device, nir, &bc);
389       meta->vs.pShaderBytecode =
390          vk_alloc(&device->vk.alloc, bc.BytecodeLength, 8,
391                   VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
392       if (meta->vs.pShaderBytecode) {
393          meta->vs.BytecodeLength = bc.BytecodeLength;
394          memcpy((void *)meta->vs.pShaderBytecode, bc.pShaderBytecode, bc.BytecodeLength);
395          out = &meta->vs;
396       }
397       free((void *)bc.pShaderBytecode);
398       ralloc_free(nir);
399    } else {
400       out = &meta->vs;
401    }
402 
403    mtx_unlock(&meta->shaders_lock);
404 
405    return &meta->vs;
406 }
407 
408 static const D3D12_SHADER_BYTECODE *
dzn_meta_blits_get_fs(dzn_device * device,const struct dzn_nir_blit_info * info)409 dzn_meta_blits_get_fs(dzn_device *device,
410                       const struct dzn_nir_blit_info *info)
411 {
412    dzn_meta_blits *meta = &device->blits;
413    D3D12_SHADER_BYTECODE *out = NULL;
414 
415    mtx_lock(&meta->shaders_lock);
416 
417    STATIC_ASSERT(sizeof(struct dzn_nir_blit_info) == sizeof(uint32_t));
418 
419    struct hash_entry *he =
420       _mesa_hash_table_search(meta->fs, (void *)(uintptr_t)info->hash_key);
421 
422    if (!he) {
423       nir_shader *nir = dzn_nir_blit_fs(info);
424 
425       if (info->out_type != GLSL_TYPE_FLOAT) {
426          dxil_wrap_sampler_state wrap_state = {
427             .is_int_sampler = 1,
428             .is_linear_filtering = 0,
429             .skip_boundary_conditions = 1,
430          };
431          dxil_lower_sample_to_txf_for_integer_tex(nir, &wrap_state, NULL, 0);
432       }
433 
434       D3D12_SHADER_BYTECODE bc;
435 
436       dzn_meta_compile_shader(device, nir, &bc);
437 
438       out = (D3D12_SHADER_BYTECODE *)
439          vk_alloc(&device->vk.alloc,
440                   sizeof(D3D12_SHADER_BYTECODE) + bc.BytecodeLength, 8,
441                   VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
442       if (out) {
443          out->pShaderBytecode = (void *)(out + 1);
444          memcpy((void *)out->pShaderBytecode, bc.pShaderBytecode, bc.BytecodeLength);
445          out->BytecodeLength = bc.BytecodeLength;
446          _mesa_hash_table_insert(meta->fs, &info->hash_key, out);
447       }
448       free((void *)bc.pShaderBytecode);
449       ralloc_free(nir);
450    } else {
451       out = (D3D12_SHADER_BYTECODE *)he->data;
452    }
453 
454    mtx_unlock(&meta->shaders_lock);
455 
456    return out;
457 }
458 
459 static void
dzn_meta_blit_destroy(dzn_device * device,dzn_meta_blit * blit)460 dzn_meta_blit_destroy(dzn_device *device, dzn_meta_blit *blit)
461 {
462    if (!blit)
463       return;
464 
465    if (blit->root_sig)
466       blit->root_sig->Release();
467    if (blit->pipeline_state)
468       blit->pipeline_state->Release();
469 
470    vk_free(&device->vk.alloc, blit);
471 }
472 
473 static dzn_meta_blit *
dzn_meta_blit_create(dzn_device * device,const dzn_meta_blit_key * key)474 dzn_meta_blit_create(dzn_device *device, const dzn_meta_blit_key *key)
475 {
476    dzn_meta_blits *blits = &device->blits;
477    dzn_meta_blit *blit = (dzn_meta_blit *)
478       vk_zalloc(&device->vk.alloc, sizeof(*blit), 8,
479                 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
480 
481    if (!blit)
482       return NULL;
483 
484    D3D12_DESCRIPTOR_RANGE1 ranges[] = {
485       {
486          .RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
487          .NumDescriptors = 1,
488          .BaseShaderRegister = 0,
489          .RegisterSpace = 0,
490          .Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS,
491          .OffsetInDescriptorsFromTableStart = 0,
492       },
493    };
494 
495    D3D12_STATIC_SAMPLER_DESC samplers[] = {
496       {
497          .Filter = key->linear_filter ?
498                    D3D12_FILTER_MIN_MAG_MIP_LINEAR :
499                    D3D12_FILTER_MIN_MAG_MIP_POINT,
500          .AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
501          .AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
502          .AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
503          .MipLODBias = 0,
504          .MaxAnisotropy = 0,
505          .MinLOD = 0,
506          .MaxLOD = D3D12_FLOAT32_MAX,
507          .ShaderRegister = 0,
508          .RegisterSpace = 0,
509          .ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL,
510       },
511    };
512 
513    D3D12_ROOT_PARAMETER1 root_params[] = {
514       {
515          .ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
516          .DescriptorTable = {
517             .NumDescriptorRanges = ARRAY_SIZE(ranges),
518             .pDescriptorRanges = ranges,
519          },
520          .ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL,
521       },
522       {
523          .ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
524          .Constants = {
525             .ShaderRegister = 0,
526             .RegisterSpace = 0,
527             .Num32BitValues = 17,
528          },
529          .ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX,
530       },
531    };
532 
533    D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc = {
534       .Version = D3D_ROOT_SIGNATURE_VERSION_1_1,
535       .Desc_1_1 = {
536          .NumParameters = ARRAY_SIZE(root_params),
537          .pParameters = root_params,
538          .NumStaticSamplers = ARRAY_SIZE(samplers),
539          .pStaticSamplers = samplers,
540          .Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE,
541       },
542    };
543 
544    D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {
545       .SampleMask = key->resolve ? 1 : (1ULL << key->samples) - 1,
546       .RasterizerState = {
547          .FillMode = D3D12_FILL_MODE_SOLID,
548          .CullMode = D3D12_CULL_MODE_NONE,
549          .DepthClipEnable = TRUE,
550       },
551       .PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
552       .SampleDesc = {
553          .Count = key->resolve ? 1 : key->samples,
554          .Quality = 0,
555       },
556       .Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
557    };
558 
559    struct dzn_nir_blit_info blit_fs_info = {
560       .src_samples = key->samples,
561       .loc = key->loc,
562       .out_type = key->out_type,
563       .sampler_dim = key->sampler_dim,
564       .src_is_array = key->src_is_array,
565       .resolve = key->resolve,
566       .padding = 0,
567    };
568 
569    blit->root_sig = dzn_device_create_root_sig(device, &root_sig_desc);
570    if (!blit->root_sig) {
571       dzn_meta_blit_destroy(device, blit);
572       return NULL;
573    }
574 
575    desc.pRootSignature = blit->root_sig;
576 
577    const D3D12_SHADER_BYTECODE *vs, *fs;
578 
579    vs = dzn_meta_blits_get_vs(device);
580    if (!vs) {
581       dzn_meta_blit_destroy(device, blit);
582       return NULL;
583    }
584 
585    desc.VS = *vs;
586    assert(desc.VS.pShaderBytecode);
587 
588    fs = dzn_meta_blits_get_fs(device, &blit_fs_info);
589    if (!fs) {
590       dzn_meta_blit_destroy(device, blit);
591       return NULL;
592    }
593 
594    desc.PS = *fs;
595    assert(desc.PS.pShaderBytecode);
596 
597    assert(key->loc == FRAG_RESULT_DATA0 ||
598           key->loc == FRAG_RESULT_DEPTH ||
599           key->loc == FRAG_RESULT_STENCIL);
600 
601    if (key->loc == FRAG_RESULT_DATA0) {
602       desc.NumRenderTargets = 1;
603       desc.RTVFormats[0] = key->out_format;
604       desc.BlendState.RenderTarget[0].RenderTargetWriteMask = 0xf;
605    } else {
606       desc.DSVFormat = key->out_format;
607       if (key->loc == FRAG_RESULT_DEPTH) {
608          desc.DepthStencilState.DepthEnable = TRUE;
609          desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
610          desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
611       } else {
612          assert(key->loc == FRAG_RESULT_STENCIL);
613          desc.DepthStencilState.StencilEnable = TRUE;
614          desc.DepthStencilState.StencilWriteMask = 0xff;
615          desc.DepthStencilState.FrontFace.StencilFailOp = D3D12_STENCIL_OP_REPLACE;
616          desc.DepthStencilState.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_REPLACE;
617          desc.DepthStencilState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE;
618          desc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
619          desc.DepthStencilState.BackFace = desc.DepthStencilState.FrontFace;
620       }
621    }
622 
623    if (FAILED(device->dev->CreateGraphicsPipelineState(&desc,
624                                                        IID_PPV_ARGS(&blit->pipeline_state)))) {
625       dzn_meta_blit_destroy(device, blit);
626       return NULL;
627    }
628 
629    return blit;
630 }
631 
632 const dzn_meta_blit *
dzn_meta_blits_get_context(dzn_device * device,const dzn_meta_blit_key * key)633 dzn_meta_blits_get_context(dzn_device *device,
634                            const dzn_meta_blit_key *key)
635 {
636    dzn_meta_blit *out = NULL;
637 
638    STATIC_ASSERT(sizeof(key) == sizeof(uint64_t));
639 
640    mtx_lock(&device->blits.contexts_lock);
641 
642    out = (dzn_meta_blit *)
643       _mesa_hash_table_u64_search(device->blits.contexts, key->u64);
644    if (!out) {
645       out = dzn_meta_blit_create(device, key);
646 
647       if (out)
648          _mesa_hash_table_u64_insert(device->blits.contexts, key->u64, out);
649    }
650 
651    mtx_unlock(&device->blits.contexts_lock);
652 
653    return out;
654 }
655 
656 static void
dzn_meta_blits_finish(dzn_device * device)657 dzn_meta_blits_finish(dzn_device *device)
658 {
659    dzn_meta_blits *meta = &device->blits;
660 
661    vk_free(&device->vk.alloc, (void *)meta->vs.pShaderBytecode);
662 
663    if (meta->fs) {
664       hash_table_foreach(meta->fs, he)
665          vk_free(&device->vk.alloc, he->data);
666       _mesa_hash_table_destroy(meta->fs, NULL);
667    }
668 
669    if (meta->contexts) {
670       hash_table_foreach(meta->contexts->table, he)
671          dzn_meta_blit_destroy(device, (dzn_meta_blit *)he->data);
672       _mesa_hash_table_u64_destroy(meta->contexts);
673    }
674 
675    mtx_destroy(&meta->shaders_lock);
676    mtx_destroy(&meta->contexts_lock);
677 }
678 
679 static VkResult
dzn_meta_blits_init(dzn_device * device)680 dzn_meta_blits_init(dzn_device *device)
681 {
682    dzn_instance *instance =
683       container_of(device->vk.physical->instance, dzn_instance, vk);
684    dzn_meta_blits *meta = &device->blits;
685 
686    mtx_init(&meta->shaders_lock, mtx_plain);
687    mtx_init(&meta->contexts_lock, mtx_plain);
688 
689    meta->fs = _mesa_hash_table_create_u32_keys(NULL);
690    if (!meta->fs) {
691       dzn_meta_blits_finish(device);
692       return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
693    }
694 
695    meta->contexts = _mesa_hash_table_u64_create(NULL);
696    if (!meta->contexts) {
697       dzn_meta_blits_finish(device);
698       return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
699    }
700 
701    return VK_SUCCESS;
702 }
703 
704 void
dzn_meta_finish(dzn_device * device)705 dzn_meta_finish(dzn_device *device)
706 {
707    for (uint32_t i = 0; i < ARRAY_SIZE(device->triangle_fan); i++)
708       dzn_meta_triangle_fan_rewrite_index_finish(device, (enum dzn_index_type)i);
709 
710    for (uint32_t i = 0; i < ARRAY_SIZE(device->indirect_draws); i++)
711       dzn_meta_indirect_draw_finish(device, (enum dzn_indirect_draw_type)i);
712 
713    dzn_meta_blits_finish(device);
714 }
715 
716 VkResult
dzn_meta_init(dzn_device * device)717 dzn_meta_init(dzn_device *device)
718 {
719    VkResult result = dzn_meta_blits_init(device);
720    if (result != VK_SUCCESS)
721       goto out;
722 
723    for (uint32_t i = 0; i < ARRAY_SIZE(device->indirect_draws); i++) {
724       VkResult result =
725          dzn_meta_indirect_draw_init(device, (enum dzn_indirect_draw_type)i);
726       if (result != VK_SUCCESS)
727          goto out;
728    }
729 
730    for (uint32_t i = 0; i < ARRAY_SIZE(device->triangle_fan); i++) {
731       VkResult result =
732          dzn_meta_triangle_fan_rewrite_index_init(device, (enum dzn_index_type)i);
733       if (result != VK_SUCCESS)
734          goto out;
735    }
736 
737 out:
738    if (result != VK_SUCCESS) {
739       dzn_meta_finish(device);
740       return result;
741    }
742 
743    return VK_SUCCESS;
744 }
745