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