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 "vk_alloc.h"
27 #include "vk_common_entrypoints.h"
28 #include "vk_cmd_enqueue_entrypoints.h"
29 #include "vk_debug_report.h"
30 #include "vk_format.h"
31 #include "vk_sync_dummy.h"
32 #include "vk_util.h"
33
34 #include "util/debug.h"
35 #include "util/macros.h"
36
37 #include "glsl_types.h"
38
39 #include <string.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42
43 #include <windows.h>
44 #include <directx/d3d12sdklayers.h>
45
46 #if defined(VK_USE_PLATFORM_WIN32_KHR) || \
47 defined(VK_USE_PLATFORM_DISPLAY_KHR)
48 #define DZN_USE_WSI_PLATFORM
49 #endif
50
51 #define DZN_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION)
52
53 static const vk_instance_extension_table instance_extensions = {
54 .KHR_get_physical_device_properties2 = true,
55 #ifdef DZN_USE_WSI_PLATFORM
56 .KHR_surface = true,
57 #endif
58 #ifdef VK_USE_PLATFORM_WIN32_KHR
59 .KHR_win32_surface = true,
60 #endif
61 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
62 .KHR_display = true,
63 .KHR_get_display_properties2 = true,
64 .EXT_direct_mode_display = true,
65 .EXT_display_surface_counter = true,
66 #endif
67 .EXT_debug_report = true,
68 .EXT_debug_utils = true,
69 };
70
71 static void
dzn_physical_device_get_extensions(dzn_physical_device * pdev)72 dzn_physical_device_get_extensions(dzn_physical_device *pdev)
73 {
74 pdev->vk.supported_extensions = vk_device_extension_table {
75 #ifdef DZN_USE_WSI_PLATFORM
76 .KHR_swapchain = true,
77 #endif
78 };
79 }
80
81 VKAPI_ATTR VkResult VKAPI_CALL
dzn_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)82 dzn_EnumerateInstanceExtensionProperties(const char *pLayerName,
83 uint32_t *pPropertyCount,
84 VkExtensionProperties *pProperties)
85 {
86 /* We don't support any layers */
87 if (pLayerName)
88 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
89
90 return vk_enumerate_instance_extension_properties(
91 &instance_extensions, pPropertyCount, pProperties);
92 }
93
94 static const struct debug_control dzn_debug_options[] = {
95 { "sync", DZN_DEBUG_SYNC },
96 { "nir", DZN_DEBUG_NIR },
97 { "dxil", DZN_DEBUG_DXIL },
98 { "warp", DZN_DEBUG_WARP },
99 { "internal", DZN_DEBUG_INTERNAL },
100 { "signature", DZN_DEBUG_SIG },
101 { "gbv", DZN_DEBUG_GBV },
102 { NULL, 0 }
103 };
104
105 static void
dzn_physical_device_destroy(dzn_physical_device * pdev)106 dzn_physical_device_destroy(dzn_physical_device *pdev)
107 {
108 dzn_instance *instance = container_of(pdev->vk.instance, dzn_instance, vk);
109
110 list_del(&pdev->link);
111
112 if (pdev->dev)
113 pdev->dev->Release();
114
115 if (pdev->adapter)
116 pdev->adapter->Release();
117
118 dzn_wsi_finish(pdev);
119 vk_physical_device_finish(&pdev->vk);
120 vk_free(&instance->vk.alloc, pdev);
121 }
122
123 static void
dzn_instance_destroy(dzn_instance * instance,const VkAllocationCallbacks * alloc)124 dzn_instance_destroy(dzn_instance *instance, const VkAllocationCallbacks *alloc)
125 {
126 if (!instance)
127 return;
128
129 if (instance->dxc.validator)
130 instance->dxc.validator->Release();
131
132 if (instance->dxc.library)
133 instance->dxc.library->Release();
134
135 if (instance->dxc.compiler)
136 instance->dxc.compiler->Release();
137
138 list_for_each_entry_safe(dzn_physical_device, pdev,
139 &instance->physical_devices, link) {
140 dzn_physical_device_destroy(pdev);
141 }
142
143 vk_instance_finish(&instance->vk);
144 vk_free2(vk_default_allocator(), alloc, instance);
145 }
146
147 static VkResult
dzn_instance_create(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * out)148 dzn_instance_create(const VkInstanceCreateInfo *pCreateInfo,
149 const VkAllocationCallbacks *pAllocator,
150 VkInstance *out)
151 {
152 dzn_instance *instance = (dzn_instance *)
153 vk_zalloc2(vk_default_allocator(), pAllocator, sizeof(*instance), 8,
154 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
155 if (!instance)
156 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
157
158 vk_instance_dispatch_table dispatch_table;
159 vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
160 &dzn_instance_entrypoints,
161 true);
162
163 VkResult result =
164 vk_instance_init(&instance->vk, &instance_extensions,
165 &dispatch_table, pCreateInfo,
166 pAllocator ? pAllocator : vk_default_allocator());
167 if (result != VK_SUCCESS) {
168 vk_free2(vk_default_allocator(), pAllocator, instance);
169 return result;
170 }
171
172 list_inithead(&instance->physical_devices);
173 instance->physical_devices_enumerated = false;
174 instance->debug_flags =
175 parse_debug_string(getenv("DZN_DEBUG"), dzn_debug_options);
176
177 instance->dxc.validator = dxil_get_validator();
178 instance->dxc.library = dxc_get_library();
179 instance->dxc.compiler = dxc_get_compiler();
180 instance->d3d12.serialize_root_sig = d3d12_get_serialize_root_sig();
181
182 if (!instance->dxc.validator ||
183 !instance->dxc.library ||
184 !instance->dxc.compiler ||
185 !instance->d3d12.serialize_root_sig) {
186 dzn_instance_destroy(instance, pAllocator);
187 return vk_error(NULL, VK_ERROR_INITIALIZATION_FAILED);
188 }
189
190 d3d12_enable_debug_layer();
191 if (instance->debug_flags & DZN_DEBUG_GBV)
192 d3d12_enable_gpu_validation();
193
194 *out = dzn_instance_to_handle(instance);
195 return VK_SUCCESS;
196 }
197
198 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)199 dzn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
200 const VkAllocationCallbacks *pAllocator,
201 VkInstance *pInstance)
202 {
203 return dzn_instance_create(pCreateInfo, pAllocator, pInstance);
204 }
205
206 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)207 dzn_DestroyInstance(VkInstance instance,
208 const VkAllocationCallbacks *pAllocator)
209 {
210 dzn_instance_destroy(dzn_instance_from_handle(instance), pAllocator);
211 }
212
213 static VkResult
dzn_physical_device_create(dzn_instance * instance,IDXGIAdapter1 * adapter,const DXGI_ADAPTER_DESC1 * adapter_desc)214 dzn_physical_device_create(dzn_instance *instance,
215 IDXGIAdapter1 *adapter,
216 const DXGI_ADAPTER_DESC1 *adapter_desc)
217 {
218 dzn_physical_device *pdev = (dzn_physical_device *)
219 vk_zalloc(&instance->vk.alloc, sizeof(*pdev), 8,
220 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
221
222 if (!pdev)
223 return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
224
225 vk_physical_device_dispatch_table dispatch_table;
226 vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
227 &dzn_physical_device_entrypoints,
228 true);
229 vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
230 &wsi_physical_device_entrypoints,
231 false);
232
233 VkResult result =
234 vk_physical_device_init(&pdev->vk, &instance->vk,
235 NULL, /* We set up extensions later */
236 &dispatch_table);
237 if (result != VK_SUCCESS) {
238 vk_free(&instance->vk.alloc, pdev);
239 return result;
240 }
241
242 mtx_init(&pdev->dev_lock, mtx_plain);
243 pdev->adapter_desc = *adapter_desc;
244 pdev->adapter = adapter;
245 adapter->AddRef();
246 list_addtail(&pdev->link, &instance->physical_devices);
247
248 vk_warn_non_conformant_implementation("dzn");
249
250 /* TODO: correct UUIDs */
251 memset(pdev->pipeline_cache_uuid, 0, VK_UUID_SIZE);
252 memset(pdev->driver_uuid, 0, VK_UUID_SIZE);
253 memset(pdev->device_uuid, 0, VK_UUID_SIZE);
254
255 /* TODO: something something queue families */
256
257 result = dzn_wsi_init(pdev);
258 if (result != VK_SUCCESS) {
259 dzn_physical_device_destroy(pdev);
260 return result;
261 }
262
263 dzn_physical_device_get_extensions(pdev);
264
265 uint32_t num_sync_types = 0;
266 pdev->sync_types[num_sync_types++] = &dzn_sync_type;
267 pdev->sync_types[num_sync_types++] = &vk_sync_dummy_type;
268 pdev->sync_types[num_sync_types] = NULL;
269 assert(num_sync_types <= MAX_SYNC_TYPES);
270 pdev->vk.supported_sync_types = pdev->sync_types;
271
272 return VK_SUCCESS;
273 }
274
275 static void
dzn_physical_device_cache_caps(dzn_physical_device * pdev)276 dzn_physical_device_cache_caps(dzn_physical_device *pdev)
277 {
278 D3D_FEATURE_LEVEL checklist[] = {
279 D3D_FEATURE_LEVEL_11_0,
280 D3D_FEATURE_LEVEL_11_1,
281 D3D_FEATURE_LEVEL_12_0,
282 D3D_FEATURE_LEVEL_12_1,
283 D3D_FEATURE_LEVEL_12_2,
284 };
285
286 D3D12_FEATURE_DATA_FEATURE_LEVELS levels = {
287 .NumFeatureLevels = ARRAY_SIZE(checklist),
288 .pFeatureLevelsRequested = checklist,
289 };
290
291 pdev->dev->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &levels, sizeof(levels));
292 pdev->feature_level = levels.MaxSupportedFeatureLevel;
293
294 pdev->dev->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE1, &pdev->architecture, sizeof(pdev->architecture));
295 pdev->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &pdev->options, sizeof(pdev->options));
296
297 pdev->queue_families[pdev->queue_family_count++] = {
298 .props = {
299 .queueFlags = VK_QUEUE_GRAPHICS_BIT |
300 VK_QUEUE_COMPUTE_BIT |
301 VK_QUEUE_TRANSFER_BIT,
302 .queueCount = 1,
303 .timestampValidBits = 64,
304 .minImageTransferGranularity = { 0, 0, 0 },
305 },
306 .desc = {
307 .Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
308 },
309 };
310
311 pdev->queue_families[pdev->queue_family_count++] = {
312 .props = {
313 .queueFlags = VK_QUEUE_COMPUTE_BIT |
314 VK_QUEUE_TRANSFER_BIT,
315 .queueCount = 8,
316 .timestampValidBits = 64,
317 .minImageTransferGranularity = { 0, 0, 0 },
318 },
319 .desc = {
320 .Type = D3D12_COMMAND_LIST_TYPE_COMPUTE,
321 },
322 };
323
324 pdev->queue_families[pdev->queue_family_count++] = {
325 .props = {
326 .queueFlags = VK_QUEUE_TRANSFER_BIT,
327 .queueCount = 1,
328 .timestampValidBits = 0,
329 .minImageTransferGranularity = { 0, 0, 0 },
330 },
331 .desc = {
332 .Type = D3D12_COMMAND_LIST_TYPE_COPY,
333 },
334 };
335
336 assert(pdev->queue_family_count <= ARRAY_SIZE(pdev->queue_families));
337
338 D3D12_COMMAND_QUEUE_DESC queue_desc = {
339 .Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
340 .Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
341 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
342 .NodeMask = 0,
343 };
344
345 ComPtr<ID3D12CommandQueue> cmdqueue;
346
347 pdev->dev->CreateCommandQueue(&queue_desc,
348 IID_PPV_ARGS(&cmdqueue));
349
350 uint64_t ts_freq;
351 cmdqueue->GetTimestampFrequency(&ts_freq);
352 pdev->timestamp_period = 1000000000.0f / ts_freq;
353 }
354
355 static void
dzn_physical_device_init_memory(dzn_physical_device * pdev)356 dzn_physical_device_init_memory(dzn_physical_device *pdev)
357 {
358 VkPhysicalDeviceMemoryProperties *mem = &pdev->memory;
359 const DXGI_ADAPTER_DESC1 *desc = &pdev->adapter_desc;
360
361 mem->memoryHeapCount = 1;
362 mem->memoryHeaps[0] = VkMemoryHeap {
363 .size = desc->SharedSystemMemory,
364 .flags = 0,
365 };
366
367 mem->memoryTypes[mem->memoryTypeCount++] = VkMemoryType {
368 .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
369 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
370 .heapIndex = 0,
371 };
372 mem->memoryTypes[mem->memoryTypeCount++] = VkMemoryType {
373 .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
374 VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
375 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
376 .heapIndex = 0,
377 };
378
379 if (!pdev->architecture.UMA) {
380 mem->memoryHeaps[mem->memoryHeapCount++] = VkMemoryHeap {
381 .size = desc->DedicatedVideoMemory,
382 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
383 };
384 mem->memoryTypes[mem->memoryTypeCount++] = VkMemoryType {
385 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
386 .heapIndex = mem->memoryHeapCount - 1,
387 };
388 } else {
389 mem->memoryHeaps[0].flags |= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
390 mem->memoryTypes[0].propertyFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
391 mem->memoryTypes[1].propertyFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
392 }
393
394 constexpr unsigned MaxTier2MemoryTypes = 3;
395 assert(mem->memoryTypeCount <= MaxTier2MemoryTypes);
396
397 if (pdev->options.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1) {
398 unsigned oldMemoryTypeCount = mem->memoryTypeCount;
399 VkMemoryType oldMemoryTypes[MaxTier2MemoryTypes];
400
401 memcpy(oldMemoryTypes, mem->memoryTypes, oldMemoryTypeCount * sizeof(VkMemoryType));
402
403 mem->memoryTypeCount = 0;
404 for (unsigned oldMemoryTypeIdx = 0; oldMemoryTypeIdx < oldMemoryTypeCount; ++oldMemoryTypeIdx) {
405 D3D12_HEAP_FLAGS flags[] = {
406 D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS,
407 D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES,
408 /* Note: Vulkan requires *all* images to come from the same memory type as long as
409 * the tiling property (and a few other misc properties) are the same. So, this
410 * non-RT/DS texture flag will only be used for TILING_LINEAR textures, which
411 * can't be render targets.
412 */
413 D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES
414 };
415 for (D3D12_HEAP_FLAGS flag : flags) {
416 pdev->heap_flags_for_mem_type[mem->memoryTypeCount] = flag;
417 mem->memoryTypes[mem->memoryTypeCount] = oldMemoryTypes[oldMemoryTypeIdx];
418 mem->memoryTypeCount++;
419 }
420 }
421 }
422 }
423
424 static D3D12_HEAP_FLAGS
dzn_physical_device_get_heap_flags_for_mem_type(const dzn_physical_device * pdev,uint32_t mem_type)425 dzn_physical_device_get_heap_flags_for_mem_type(const dzn_physical_device *pdev,
426 uint32_t mem_type)
427 {
428 return pdev->heap_flags_for_mem_type[mem_type];
429 }
430
431 uint32_t
dzn_physical_device_get_mem_type_mask_for_resource(const dzn_physical_device * pdev,const D3D12_RESOURCE_DESC * desc)432 dzn_physical_device_get_mem_type_mask_for_resource(const dzn_physical_device *pdev,
433 const D3D12_RESOURCE_DESC *desc)
434 {
435 if (pdev->options.ResourceHeapTier > D3D12_RESOURCE_HEAP_TIER_1)
436 return (1u << pdev->memory.memoryTypeCount) - 1;
437
438 D3D12_HEAP_FLAGS deny_flag;
439 if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
440 deny_flag = D3D12_HEAP_FLAG_DENY_BUFFERS;
441 else if (desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
442 deny_flag = D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES;
443 else
444 deny_flag = D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES;
445
446 uint32_t mask = 0;
447 for (unsigned i = 0; i < pdev->memory.memoryTypeCount; ++i) {
448 if ((pdev->heap_flags_for_mem_type[i] & deny_flag) == D3D12_HEAP_FLAG_NONE)
449 mask |= (1 << i);
450 }
451 return mask;
452 }
453
454 static uint32_t
dzn_physical_device_get_max_mip_levels(bool is_3d)455 dzn_physical_device_get_max_mip_levels(bool is_3d)
456 {
457 return is_3d ? 11 : 14;
458 }
459
460 static uint32_t
dzn_physical_device_get_max_extent(bool is_3d)461 dzn_physical_device_get_max_extent(bool is_3d)
462 {
463 uint32_t max_mip = dzn_physical_device_get_max_mip_levels(is_3d);
464
465 return 1 << max_mip;
466 }
467
468 static uint32_t
dzn_physical_device_get_max_array_layers()469 dzn_physical_device_get_max_array_layers()
470 {
471 return dzn_physical_device_get_max_extent(false);
472 }
473
474 static ID3D12Device1 *
dzn_physical_device_get_d3d12_dev(dzn_physical_device * pdev)475 dzn_physical_device_get_d3d12_dev(dzn_physical_device *pdev)
476 {
477 dzn_instance *instance = container_of(pdev->vk.instance, dzn_instance, vk);
478
479 mtx_lock(&pdev->dev_lock);
480 if (!pdev->dev) {
481 pdev->dev = d3d12_create_device(pdev->adapter, instance->dxc.validator == nullptr);
482
483 dzn_physical_device_cache_caps(pdev);
484 dzn_physical_device_init_memory(pdev);
485 }
486 mtx_unlock(&pdev->dev_lock);
487
488 return pdev->dev;
489 }
490
491 D3D12_FEATURE_DATA_FORMAT_SUPPORT
dzn_physical_device_get_format_support(dzn_physical_device * pdev,VkFormat format)492 dzn_physical_device_get_format_support(dzn_physical_device *pdev,
493 VkFormat format)
494 {
495 VkImageUsageFlags usage =
496 vk_format_is_depth_or_stencil(format) ?
497 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0;
498 VkImageAspectFlags aspects = 0;
499
500 if (vk_format_has_depth(format))
501 aspects = VK_IMAGE_ASPECT_DEPTH_BIT;
502 if (vk_format_has_stencil(format))
503 aspects = VK_IMAGE_ASPECT_STENCIL_BIT;
504
505 D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info = {
506 .Format = dzn_image_get_dxgi_format(format, usage, aspects),
507 };
508
509 ID3D12Device *dev = dzn_physical_device_get_d3d12_dev(pdev);
510 HRESULT hres =
511 dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
512 &dfmt_info, sizeof(dfmt_info));
513 assert(!FAILED(hres));
514
515 if (usage != VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
516 return dfmt_info;
517
518 /* Depth/stencil resources have different format when they're accessed
519 * as textures, query the capabilities for this format too.
520 */
521 dzn_foreach_aspect(aspect, aspects) {
522 D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info2 = {
523 .Format = dzn_image_get_dxgi_format(format, 0, aspect),
524 };
525
526 hres = dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
527 &dfmt_info2, sizeof(dfmt_info2));
528 assert(!FAILED(hres));
529
530 #define DS_SRV_FORMAT_SUPPORT1_MASK \
531 (D3D12_FORMAT_SUPPORT1_SHADER_LOAD | \
532 D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE | \
533 D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_COMPARISON | \
534 D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_MONO_TEXT | \
535 D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE | \
536 D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD | \
537 D3D12_FORMAT_SUPPORT1_SHADER_GATHER | \
538 D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW | \
539 D3D12_FORMAT_SUPPORT1_SHADER_GATHER_COMPARISON)
540
541 dfmt_info.Support1 |= dfmt_info2.Support1 & DS_SRV_FORMAT_SUPPORT1_MASK;
542 dfmt_info.Support2 |= dfmt_info2.Support2;
543 }
544
545 return dfmt_info;
546 }
547
548 void
dzn_physical_device_get_format_properties(dzn_physical_device * pdev,VkFormat format,VkFormatProperties2 * properties)549 dzn_physical_device_get_format_properties(dzn_physical_device *pdev,
550 VkFormat format,
551 VkFormatProperties2 *properties)
552 {
553 D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info =
554 dzn_physical_device_get_format_support(pdev, format);
555 VkFormatProperties *base_props = &properties->formatProperties;
556
557 vk_foreach_struct(ext, properties->pNext) {
558 dzn_debug_ignored_stype(ext->sType);
559 }
560
561 if (dfmt_info.Format == DXGI_FORMAT_UNKNOWN) {
562 *base_props = VkFormatProperties { };
563 return;
564 }
565
566 ID3D12Device *dev = dzn_physical_device_get_d3d12_dev(pdev);
567
568 *base_props = VkFormatProperties {
569 .linearTilingFeatures = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
570 .optimalTilingFeatures = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
571 .bufferFeatures = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
572 };
573
574 if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER)
575 base_props->bufferFeatures |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
576
577 #define TEX_FLAGS (D3D12_FORMAT_SUPPORT1_TEXTURE1D | \
578 D3D12_FORMAT_SUPPORT1_TEXTURE2D | \
579 D3D12_FORMAT_SUPPORT1_TEXTURE3D | \
580 D3D12_FORMAT_SUPPORT1_TEXTURECUBE)
581 if (dfmt_info.Support1 & TEX_FLAGS) {
582 base_props->optimalTilingFeatures |=
583 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT;
584 }
585
586 if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE) {
587 base_props->optimalTilingFeatures |=
588 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
589 }
590
591 if ((dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD) &&
592 (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW)) {
593 base_props->optimalTilingFeatures |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
594 base_props->bufferFeatures |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
595 }
596
597 #define ATOMIC_FLAGS (D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_ADD | \
598 D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS | \
599 D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE | \
600 D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE | \
601 D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX | \
602 D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX)
603 if ((dfmt_info.Support2 & ATOMIC_FLAGS) == ATOMIC_FLAGS) {
604 base_props->optimalTilingFeatures |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
605 base_props->bufferFeatures |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
606 }
607
608 if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD)
609 base_props->bufferFeatures |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
610
611 /* Color/depth/stencil attachment cap implies input attachement cap, and input
612 * attachment loads are lowered to texture loads in dozen, hence the requirement
613 * to have shader-load support.
614 */
615 if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD) {
616 if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET) {
617 base_props->optimalTilingFeatures |=
618 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
619 }
620
621 if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_BLENDABLE)
622 base_props->optimalTilingFeatures |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
623
624 if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL) {
625 base_props->optimalTilingFeatures |=
626 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
627 }
628 }
629
630 /* B4G4R4A4 support is required, but d3d12 doesn't support it. We map this
631 * format to R4G4B4A4 and adjust the SRV component-mapping to fake
632 * B4G4R4A4, but that forces us to limit the usage to sampling, which,
633 * luckily, is exactly what we need to support the required features.
634 */
635 if (format == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
636 VkFormatFeatureFlags bgra4_req_features =
637 VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
638 VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
639 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
640 VK_FORMAT_FEATURE_BLIT_SRC_BIT |
641 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
642 base_props->optimalTilingFeatures &= bgra4_req_features;
643 base_props->bufferFeatures =
644 VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
645 }
646 }
647
648 VkResult
dzn_physical_device_get_image_format_properties(dzn_physical_device * pdev,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties2 * properties)649 dzn_physical_device_get_image_format_properties(dzn_physical_device *pdev,
650 const VkPhysicalDeviceImageFormatInfo2 *info,
651 VkImageFormatProperties2 *properties)
652 {
653 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
654 VkExternalImageFormatProperties *external_props = NULL;
655
656 *properties = VkImageFormatProperties2 {
657 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
658 };
659
660 /* Extract input structs */
661 vk_foreach_struct_const(s, info->pNext) {
662 switch (s->sType) {
663 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
664 external_info = (const VkPhysicalDeviceExternalImageFormatInfo *)s;
665 break;
666 default:
667 dzn_debug_ignored_stype(s->sType);
668 break;
669 }
670 }
671
672 assert(info->tiling == VK_IMAGE_TILING_OPTIMAL || info->tiling == VK_IMAGE_TILING_LINEAR);
673
674 /* Extract output structs */
675 vk_foreach_struct(s, properties->pNext) {
676 switch (s->sType) {
677 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
678 external_props = (VkExternalImageFormatProperties *)s;
679 break;
680 default:
681 dzn_debug_ignored_stype(s->sType);
682 break;
683 }
684 }
685
686 assert((external_props != NULL) == (external_info != NULL));
687
688 /* TODO: support image import */
689 if (external_info && external_info->handleType != 0)
690 return VK_ERROR_FORMAT_NOT_SUPPORTED;
691
692 if (info->tiling != VK_IMAGE_TILING_OPTIMAL &&
693 (info->usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)))
694 return VK_ERROR_FORMAT_NOT_SUPPORTED;
695
696 if (info->tiling != VK_IMAGE_TILING_OPTIMAL &&
697 vk_format_is_depth_or_stencil(info->format))
698 return VK_ERROR_FORMAT_NOT_SUPPORTED;
699
700 D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info =
701 dzn_physical_device_get_format_support(pdev, info->format);
702 if (dfmt_info.Format == DXGI_FORMAT_UNKNOWN)
703 return VK_ERROR_FORMAT_NOT_SUPPORTED;
704
705 bool is_bgra4 = info->format == VK_FORMAT_B4G4R4A4_UNORM_PACK16;
706 ID3D12Device *dev = dzn_physical_device_get_d3d12_dev(pdev);
707
708 if ((info->type == VK_IMAGE_TYPE_1D && !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE1D)) ||
709 (info->type == VK_IMAGE_TYPE_2D && !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D)) ||
710 (info->type == VK_IMAGE_TYPE_3D && !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE3D)) ||
711 ((info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
712 !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURECUBE)))
713 return VK_ERROR_FORMAT_NOT_SUPPORTED;
714
715 if ((info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) &&
716 !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE))
717 return VK_ERROR_FORMAT_NOT_SUPPORTED;
718
719 if ((info->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) &&
720 (!(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD) || is_bgra4))
721 return VK_ERROR_FORMAT_NOT_SUPPORTED;
722
723 if ((info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) &&
724 (!(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET) || is_bgra4))
725 return VK_ERROR_FORMAT_NOT_SUPPORTED;
726
727 if ((info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) &&
728 (!(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL) || is_bgra4))
729 return VK_ERROR_FORMAT_NOT_SUPPORTED;
730
731 if ((info->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
732 (!(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW) || is_bgra4))
733 return VK_ERROR_FORMAT_NOT_SUPPORTED;
734
735 bool is_3d = info->type == VK_IMAGE_TYPE_3D;
736 uint32_t max_extent = dzn_physical_device_get_max_extent(is_3d);
737
738 if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
739 dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_MIP)
740 properties->imageFormatProperties.maxMipLevels = dzn_physical_device_get_max_mip_levels(is_3d);
741 else
742 properties->imageFormatProperties.maxMipLevels = 1;
743
744 if (info->tiling == VK_IMAGE_TILING_OPTIMAL)
745 properties->imageFormatProperties.maxArrayLayers = dzn_physical_device_get_max_array_layers();
746 else
747 properties->imageFormatProperties.maxArrayLayers = 1;
748
749 switch (info->type) {
750 case VK_IMAGE_TYPE_1D:
751 properties->imageFormatProperties.maxExtent.width = max_extent;
752 properties->imageFormatProperties.maxExtent.height = 1;
753 properties->imageFormatProperties.maxExtent.depth = 1;
754 break;
755 case VK_IMAGE_TYPE_2D:
756 properties->imageFormatProperties.maxExtent.width = max_extent;
757 properties->imageFormatProperties.maxExtent.height = max_extent;
758 properties->imageFormatProperties.maxExtent.depth = 1;
759 break;
760 case VK_IMAGE_TYPE_3D:
761 if (info->tiling != VK_IMAGE_TILING_OPTIMAL)
762 return VK_ERROR_FORMAT_NOT_SUPPORTED;
763
764 properties->imageFormatProperties.maxExtent.width = max_extent;
765 properties->imageFormatProperties.maxExtent.height = max_extent;
766 properties->imageFormatProperties.maxExtent.depth = max_extent;
767 break;
768 default:
769 unreachable("bad VkImageType");
770 }
771
772 /* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:
773 *
774 * sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the
775 * following conditions is true:
776 *
777 * - tiling is VK_IMAGE_TILING_LINEAR
778 * - type is not VK_IMAGE_TYPE_2D
779 * - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
780 * - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
781 * VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
782 * VkFormatProperties::optimalTilingFeatures returned by
783 * vkGetPhysicalDeviceFormatProperties is set.
784 *
785 * D3D12 has a few more constraints:
786 * - no UAVs on multisample resources
787 */
788 bool rt_or_ds_cap =
789 dfmt_info.Support1 &
790 (D3D12_FORMAT_SUPPORT1_RENDER_TARGET | D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL);
791
792 properties->imageFormatProperties.sampleCounts = VK_SAMPLE_COUNT_1_BIT;
793 if (info->tiling != VK_IMAGE_TILING_LINEAR &&
794 info->type == VK_IMAGE_TYPE_2D &&
795 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
796 rt_or_ds_cap &&
797 !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
798 for (uint32_t s = VK_SAMPLE_COUNT_2_BIT; s < VK_SAMPLE_COUNT_64_BIT; s <<= 1) {
799 D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS ms_info = {
800 .Format = dfmt_info.Format,
801 .SampleCount = s,
802 };
803
804 HRESULT hres =
805 dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
806 &ms_info, sizeof(ms_info));
807 if (!FAILED(hres) && ms_info.NumQualityLevels > 0)
808 properties->imageFormatProperties.sampleCounts |= s;
809 }
810 }
811
812 /* TODO: set correct value here */
813 properties->imageFormatProperties.maxResourceSize = UINT32_MAX;
814
815 return VK_SUCCESS;
816 }
817
818 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)819 dzn_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
820 VkFormat format,
821 VkFormatProperties2 *pFormatProperties)
822 {
823 VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
824
825 dzn_physical_device_get_format_properties(pdev, format, pFormatProperties);
826 }
827
828 VKAPI_ATTR VkResult VKAPI_CALL
dzn_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties2 * props)829 dzn_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
830 const VkPhysicalDeviceImageFormatInfo2 *info,
831 VkImageFormatProperties2 *props)
832 {
833 VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
834
835 return dzn_physical_device_get_image_format_properties(pdev, info, props);
836 }
837
838 VKAPI_ATTR VkResult VKAPI_CALL
dzn_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags createFlags,VkImageFormatProperties * pImageFormatProperties)839 dzn_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,
840 VkFormat format,
841 VkImageType type,
842 VkImageTiling tiling,
843 VkImageUsageFlags usage,
844 VkImageCreateFlags createFlags,
845 VkImageFormatProperties *pImageFormatProperties)
846 {
847 const VkPhysicalDeviceImageFormatInfo2 info = {
848 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
849 .format = format,
850 .type = type,
851 .tiling = tiling,
852 .usage = usage,
853 .flags = createFlags,
854 };
855
856 VkImageFormatProperties2 props = {};
857
858 VkResult result =
859 dzn_GetPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &props);
860 *pImageFormatProperties = props.imageFormatProperties;
861
862 return result;
863 }
864
865 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkSampleCountFlagBits samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pPropertyCount,VkSparseImageFormatProperties * pProperties)866 dzn_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,
867 VkFormat format,
868 VkImageType type,
869 VkSampleCountFlagBits samples,
870 VkImageUsageFlags usage,
871 VkImageTiling tiling,
872 uint32_t *pPropertyCount,
873 VkSparseImageFormatProperties *pProperties)
874 {
875 *pPropertyCount = 0;
876 }
877
878 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)879 dzn_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,
880 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
881 uint32_t *pPropertyCount,
882 VkSparseImageFormatProperties2 *pProperties)
883 {
884 *pPropertyCount = 0;
885 }
886
887 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)888 dzn_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,
889 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
890 VkExternalBufferProperties *pExternalBufferProperties)
891 {
892 pExternalBufferProperties->externalMemoryProperties =
893 VkExternalMemoryProperties {
894 .compatibleHandleTypes = (VkExternalMemoryHandleTypeFlags)pExternalBufferInfo->handleType,
895 };
896 }
897
898 VKAPI_ATTR VkResult VKAPI_CALL
dzn_EnumeratePhysicalDevices(VkInstance inst,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)899 dzn_EnumeratePhysicalDevices(VkInstance inst,
900 uint32_t *pPhysicalDeviceCount,
901 VkPhysicalDevice *pPhysicalDevices)
902 {
903 VK_FROM_HANDLE(dzn_instance, instance, inst);
904
905 if (!instance->physical_devices_enumerated) {
906 ComPtr<IDXGIFactory4> factory = dxgi_get_factory(false);
907 ComPtr<IDXGIAdapter1> adapter(NULL);
908 for (UINT i = 0; SUCCEEDED(factory->EnumAdapters1(i, &adapter)); ++i) {
909 DXGI_ADAPTER_DESC1 desc;
910 adapter->GetDesc1(&desc);
911 if (instance->debug_flags & DZN_DEBUG_WARP) {
912 if ((desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0)
913 continue;
914 }
915
916 VkResult result =
917 dzn_physical_device_create(instance, adapter.Get(), &desc);
918 if (result != VK_SUCCESS)
919 return result;
920 }
921 }
922
923 VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, pPhysicalDevices,
924 pPhysicalDeviceCount);
925
926 list_for_each_entry(dzn_physical_device, pdev, &instance->physical_devices, link) {
927 vk_outarray_append_typed(VkPhysicalDevice, &out, i)
928 *i = dzn_physical_device_to_handle(pdev);
929 }
930
931 instance->physical_devices_enumerated = true;
932 return vk_outarray_status(&out);
933 }
934
935 VKAPI_ATTR VkResult VKAPI_CALL
dzn_EnumerateInstanceVersion(uint32_t * pApiVersion)936 dzn_EnumerateInstanceVersion(uint32_t *pApiVersion)
937 {
938 *pApiVersion = DZN_API_VERSION;
939 return VK_SUCCESS;
940 }
941
942 bool
dzn_physical_device_supports_compressed_format(dzn_physical_device * pdev,const VkFormat * formats,uint32_t format_count)943 dzn_physical_device_supports_compressed_format(dzn_physical_device *pdev,
944 const VkFormat *formats,
945 uint32_t format_count)
946 {
947 #define REQUIRED_COMPRESSED_CAPS \
948 (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | \
949 VK_FORMAT_FEATURE_BLIT_SRC_BIT | \
950 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)
951 for (uint32_t i = 0; i < format_count; i++) {
952 VkFormatProperties2 props = {};
953 dzn_physical_device_get_format_properties(pdev, formats[i], &props);
954 if ((props.formatProperties.optimalTilingFeatures & REQUIRED_COMPRESSED_CAPS) != REQUIRED_COMPRESSED_CAPS)
955 return false;
956 }
957
958 return true;
959 }
960
961 bool
dzn_physical_device_supports_bc(dzn_physical_device * pdev)962 dzn_physical_device_supports_bc(dzn_physical_device *pdev)
963 {
964 static const VkFormat formats[] = {
965 VK_FORMAT_BC1_RGB_UNORM_BLOCK,
966 VK_FORMAT_BC1_RGB_SRGB_BLOCK,
967 VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
968 VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
969 VK_FORMAT_BC2_UNORM_BLOCK,
970 VK_FORMAT_BC2_SRGB_BLOCK,
971 VK_FORMAT_BC3_UNORM_BLOCK,
972 VK_FORMAT_BC3_SRGB_BLOCK,
973 VK_FORMAT_BC4_UNORM_BLOCK,
974 VK_FORMAT_BC4_SNORM_BLOCK,
975 VK_FORMAT_BC5_UNORM_BLOCK,
976 VK_FORMAT_BC5_SNORM_BLOCK,
977 VK_FORMAT_BC6H_UFLOAT_BLOCK,
978 VK_FORMAT_BC6H_SFLOAT_BLOCK,
979 VK_FORMAT_BC7_UNORM_BLOCK,
980 VK_FORMAT_BC7_SRGB_BLOCK,
981 };
982
983 return dzn_physical_device_supports_compressed_format(pdev, formats, ARRAY_SIZE(formats));
984 }
985
986 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures * pFeatures)987 dzn_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
988 VkPhysicalDeviceFeatures *pFeatures)
989 {
990 VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
991
992 *pFeatures = VkPhysicalDeviceFeatures {
993 .robustBufferAccess = true, /* This feature is mandatory */
994 .fullDrawIndexUint32 = false,
995 .imageCubeArray = true,
996 .independentBlend = false,
997 .geometryShader = false,
998 .tessellationShader = false,
999 .sampleRateShading = false,
1000 .dualSrcBlend = false,
1001 .logicOp = false,
1002 .multiDrawIndirect = false,
1003 .drawIndirectFirstInstance = false,
1004 .depthClamp = false,
1005 .depthBiasClamp = false,
1006 .fillModeNonSolid = false,
1007 .depthBounds = false,
1008 .wideLines = false,
1009 .largePoints = false,
1010 .alphaToOne = false,
1011 .multiViewport = false,
1012 .samplerAnisotropy = false,
1013 .textureCompressionETC2 = false,
1014 .textureCompressionASTC_LDR = false,
1015 .textureCompressionBC = dzn_physical_device_supports_bc(pdev),
1016 .occlusionQueryPrecise = true,
1017 .pipelineStatisticsQuery = true,
1018 .vertexPipelineStoresAndAtomics = true,
1019 .fragmentStoresAndAtomics = true,
1020 .shaderTessellationAndGeometryPointSize = false,
1021 .shaderImageGatherExtended = false,
1022 .shaderStorageImageExtendedFormats = false,
1023 .shaderStorageImageMultisample = false,
1024 .shaderStorageImageReadWithoutFormat = false,
1025 .shaderStorageImageWriteWithoutFormat = false,
1026 .shaderUniformBufferArrayDynamicIndexing = false,
1027 .shaderSampledImageArrayDynamicIndexing = false,
1028 .shaderStorageBufferArrayDynamicIndexing = false,
1029 .shaderStorageImageArrayDynamicIndexing = false,
1030 .shaderClipDistance = false,
1031 .shaderCullDistance = false,
1032 .shaderFloat64 = false,
1033 .shaderInt64 = false,
1034 .shaderInt16 = false,
1035 .shaderResourceResidency = false,
1036 .shaderResourceMinLod = false,
1037 .sparseBinding = false,
1038 .sparseResidencyBuffer = false,
1039 .sparseResidencyImage2D = false,
1040 .sparseResidencyImage3D = false,
1041 .sparseResidency2Samples = false,
1042 .sparseResidency4Samples = false,
1043 .sparseResidency8Samples = false,
1044 .sparseResidency16Samples = false,
1045 .sparseResidencyAliased = false,
1046 .variableMultisampleRate = false,
1047 .inheritedQueries = false,
1048 };
1049 }
1050
1051 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures2 * pFeatures)1052 dzn_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
1053 VkPhysicalDeviceFeatures2 *pFeatures)
1054 {
1055 dzn_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
1056
1057 vk_foreach_struct(ext, pFeatures->pNext) {
1058 dzn_debug_ignored_stype(ext->sType);
1059 }
1060 }
1061
1062
1063 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
dzn_GetInstanceProcAddr(VkInstance _instance,const char * pName)1064 dzn_GetInstanceProcAddr(VkInstance _instance,
1065 const char *pName)
1066 {
1067 VK_FROM_HANDLE(dzn_instance, instance, _instance);
1068 return vk_instance_get_proc_addr(&instance->vk,
1069 &dzn_instance_entrypoints,
1070 pName);
1071 }
1072
1073 /* Windows will use a dll definition file to avoid build errors. */
1074 #ifdef _WIN32
1075 #undef PUBLIC
1076 #define PUBLIC
1077 #endif
1078
1079 /* With version 1+ of the loader interface the ICD should expose
1080 * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
1081 */
1082 PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1083 vk_icdGetInstanceProcAddr(VkInstance instance,
1084 const char *pName);
1085
1086 PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,const char * pName)1087 vk_icdGetInstanceProcAddr(VkInstance instance,
1088 const char *pName)
1089 {
1090 return dzn_GetInstanceProcAddr(instance, pName);
1091 }
1092
1093 /* With version 4+ of the loader interface the ICD should expose
1094 * vk_icdGetPhysicalDeviceProcAddr()
1095 */
1096 PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1097 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
1098 const char* pName);
1099
1100 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,const char * pName)1101 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
1102 const char* pName)
1103 {
1104 VK_FROM_HANDLE(dzn_instance, instance, _instance);
1105 return vk_instance_get_physical_device_proc_addr(&instance->vk, pName);
1106 }
1107
1108 /* vk_icd.h does not declare this function, so we declare it here to
1109 * suppress Wmissing-prototypes.
1110 */
1111 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
1112 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
1113
1114 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)1115 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion)
1116 {
1117 /* For the full details on loader interface versioning, see
1118 * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
1119 * What follows is a condensed summary, to help you navigate the large and
1120 * confusing official doc.
1121 *
1122 * - Loader interface v0 is incompatible with later versions. We don't
1123 * support it.
1124 *
1125 * - In loader interface v1:
1126 * - The first ICD entrypoint called by the loader is
1127 * vk_icdGetInstanceProcAddr(). The ICD must statically expose this
1128 * entrypoint.
1129 * - The ICD must statically expose no other Vulkan symbol unless it is
1130 * linked with -Bsymbolic.
1131 * - Each dispatchable Vulkan handle created by the ICD must be
1132 * a pointer to a struct whose first member is VK_LOADER_DATA. The
1133 * ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC.
1134 * - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
1135 * vkDestroySurfaceKHR(). The ICD must be capable of working with
1136 * such loader-managed surfaces.
1137 *
1138 * - Loader interface v2 differs from v1 in:
1139 * - The first ICD entrypoint called by the loader is
1140 * vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
1141 * statically expose this entrypoint.
1142 *
1143 * - Loader interface v3 differs from v2 in:
1144 * - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
1145 * vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
1146 * because the loader no longer does so.
1147 *
1148 * - Loader interface v4 differs from v3 in:
1149 * - The ICD must implement vk_icdGetPhysicalDeviceProcAddr().
1150 */
1151 *pSupportedVersion = MIN2(*pSupportedVersion, 4u);
1152 return VK_SUCCESS;
1153 }
1154
1155 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties * pProperties)1156 dzn_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1157 VkPhysicalDeviceProperties *pProperties)
1158 {
1159 VK_FROM_HANDLE(dzn_physical_device, pdevice, physicalDevice);
1160
1161 /* minimum from the spec */
1162 const VkSampleCountFlags supported_sample_counts =
1163 VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
1164
1165 /* FIXME: this is mostly bunk for now */
1166 VkPhysicalDeviceLimits limits = {
1167
1168 /* TODO: support older feature levels */
1169 .maxImageDimension1D = (1 << 14),
1170 .maxImageDimension2D = (1 << 14),
1171 .maxImageDimension3D = (1 << 11),
1172 .maxImageDimensionCube = (1 << 14),
1173 .maxImageArrayLayers = (1 << 11),
1174
1175 /* from here on, we simply use the minimum values from the spec for now */
1176 .maxTexelBufferElements = 65536,
1177 .maxUniformBufferRange = 16384,
1178 .maxStorageBufferRange = (1ul << 27),
1179 .maxPushConstantsSize = 128,
1180 .maxMemoryAllocationCount = 4096,
1181 .maxSamplerAllocationCount = 4000,
1182 .bufferImageGranularity = 131072,
1183 .sparseAddressSpaceSize = 0,
1184 .maxBoundDescriptorSets = MAX_SETS,
1185 .maxPerStageDescriptorSamplers = 16,
1186 .maxPerStageDescriptorUniformBuffers = 12,
1187 .maxPerStageDescriptorStorageBuffers = 4,
1188 .maxPerStageDescriptorSampledImages = 16,
1189 .maxPerStageDescriptorStorageImages = 4,
1190 .maxPerStageDescriptorInputAttachments = 4,
1191 .maxPerStageResources = 128,
1192 .maxDescriptorSetSamplers = 96,
1193 .maxDescriptorSetUniformBuffers = 72,
1194 .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
1195 .maxDescriptorSetStorageBuffers = 24,
1196 .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
1197 .maxDescriptorSetSampledImages = 96,
1198 .maxDescriptorSetStorageImages = 24,
1199 .maxDescriptorSetInputAttachments = 4,
1200 .maxVertexInputAttributes = 16,
1201 .maxVertexInputBindings = 16,
1202 .maxVertexInputAttributeOffset = 2047,
1203 .maxVertexInputBindingStride = 2048,
1204 .maxVertexOutputComponents = 64,
1205 .maxTessellationGenerationLevel = 0,
1206 .maxTessellationPatchSize = 0,
1207 .maxTessellationControlPerVertexInputComponents = 0,
1208 .maxTessellationControlPerVertexOutputComponents = 0,
1209 .maxTessellationControlPerPatchOutputComponents = 0,
1210 .maxTessellationControlTotalOutputComponents = 0,
1211 .maxTessellationEvaluationInputComponents = 0,
1212 .maxTessellationEvaluationOutputComponents = 0,
1213 .maxGeometryShaderInvocations = 0,
1214 .maxGeometryInputComponents = 0,
1215 .maxGeometryOutputComponents = 0,
1216 .maxGeometryOutputVertices = 0,
1217 .maxGeometryTotalOutputComponents = 0,
1218 .maxFragmentInputComponents = 64,
1219 .maxFragmentOutputAttachments = 4,
1220 .maxFragmentDualSrcAttachments = 0,
1221 .maxFragmentCombinedOutputResources = 4,
1222 .maxComputeSharedMemorySize = 16384,
1223 .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
1224 .maxComputeWorkGroupInvocations = 128,
1225 .maxComputeWorkGroupSize = { 128, 128, 64 },
1226 .subPixelPrecisionBits = 4,
1227 .subTexelPrecisionBits = 4,
1228 .mipmapPrecisionBits = 4,
1229 .maxDrawIndexedIndexValue = 0x00ffffff,
1230 .maxDrawIndirectCount = 1,
1231 .maxSamplerLodBias = 2.0f,
1232 .maxSamplerAnisotropy = 1.0f,
1233 .maxViewports = 1,
1234 .maxViewportDimensions = { 4096, 4096 },
1235 .viewportBoundsRange = { -8192, 8191 },
1236 .viewportSubPixelBits = 0,
1237 .minMemoryMapAlignment = 64,
1238 .minTexelBufferOffsetAlignment = 256,
1239 .minUniformBufferOffsetAlignment = 256,
1240 .minStorageBufferOffsetAlignment = 256,
1241 .minTexelOffset = -8,
1242 .maxTexelOffset = 7,
1243 .minTexelGatherOffset = 0,
1244 .maxTexelGatherOffset = 0,
1245 .minInterpolationOffset = 0.0f,
1246 .maxInterpolationOffset = 0.0f,
1247 .subPixelInterpolationOffsetBits = 0,
1248 .maxFramebufferWidth = 4096,
1249 .maxFramebufferHeight = 4096,
1250 .maxFramebufferLayers = 256,
1251 .framebufferColorSampleCounts = supported_sample_counts,
1252 .framebufferDepthSampleCounts = supported_sample_counts,
1253 .framebufferStencilSampleCounts = supported_sample_counts,
1254 .framebufferNoAttachmentsSampleCounts = supported_sample_counts,
1255 .maxColorAttachments = 4,
1256 .sampledImageColorSampleCounts = supported_sample_counts,
1257 .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
1258 .sampledImageDepthSampleCounts = supported_sample_counts,
1259 .sampledImageStencilSampleCounts = supported_sample_counts,
1260 .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
1261 .maxSampleMaskWords = 1,
1262 .timestampComputeAndGraphics = true,
1263 .timestampPeriod = pdevice->timestamp_period,
1264 .maxClipDistances = 8,
1265 .maxCullDistances = 8,
1266 .maxCombinedClipAndCullDistances = 8,
1267 .discreteQueuePriorities = 2,
1268 .pointSizeRange = { 1.0f, 1.0f },
1269 .lineWidthRange = { 1.0f, 1.0f },
1270 .pointSizeGranularity = 0.0f,
1271 .lineWidthGranularity = 0.0f,
1272 .strictLines = 0,
1273 .standardSampleLocations = false,
1274 .optimalBufferCopyOffsetAlignment = 1,
1275 .optimalBufferCopyRowPitchAlignment = 1,
1276 .nonCoherentAtomSize = 256,
1277 };
1278
1279 const DXGI_ADAPTER_DESC1& desc = pdevice->adapter_desc;
1280
1281 VkPhysicalDeviceType devtype = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
1282 if (desc.Flags == DXGI_ADAPTER_FLAG_SOFTWARE)
1283 devtype = VK_PHYSICAL_DEVICE_TYPE_CPU;
1284 else if (false) { // TODO: detect discreete GPUs
1285 /* This is a tad tricky to get right, because we need to have the
1286 * actual ID3D12Device before we can query the
1287 * D3D12_FEATURE_DATA_ARCHITECTURE structure... So for now, let's
1288 * just pretend everything is integrated, because... well, that's
1289 * what I have at hand right now ;)
1290 */
1291 devtype = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
1292 }
1293
1294 *pProperties = VkPhysicalDeviceProperties {
1295 .apiVersion = DZN_API_VERSION,
1296 .driverVersion = vk_get_driver_version(),
1297
1298 .vendorID = desc.VendorId,
1299 .deviceID = desc.DeviceId,
1300 .deviceType = devtype,
1301
1302 .limits = limits,
1303 .sparseProperties = { 0 },
1304 };
1305
1306 snprintf(pProperties->deviceName, sizeof(pProperties->deviceName),
1307 "Microsoft Direct3D12 (%S)", desc.Description);
1308
1309 memcpy(pProperties->pipelineCacheUUID,
1310 pdevice->pipeline_cache_uuid, VK_UUID_SIZE);
1311 }
1312
1313 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties2 * pProperties)1314 dzn_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1315 VkPhysicalDeviceProperties2 *pProperties)
1316 {
1317 VK_FROM_HANDLE(dzn_physical_device, pdevice, physicalDevice);
1318
1319 dzn_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
1320
1321 vk_foreach_struct(ext, pProperties->pNext) {
1322 switch (ext->sType) {
1323 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
1324 VkPhysicalDeviceIDProperties *id_props =
1325 (VkPhysicalDeviceIDProperties *)ext;
1326 memcpy(id_props->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
1327 memcpy(id_props->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
1328 /* The LUID is for Windows. */
1329 id_props->deviceLUIDValid = false;
1330 break;
1331 }
1332 default:
1333 dzn_debug_ignored_stype(ext->sType);
1334 break;
1335 }
1336 }
1337 }
1338
1339 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2 * pQueueFamilyProperties)1340 dzn_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
1341 uint32_t *pQueueFamilyPropertyCount,
1342 VkQueueFamilyProperties2 *pQueueFamilyProperties)
1343 {
1344 VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
1345 VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, out,
1346 pQueueFamilyProperties, pQueueFamilyPropertyCount);
1347
1348 (void)dzn_physical_device_get_d3d12_dev(pdev);
1349
1350 for (uint32_t i = 0; i < pdev->queue_family_count; i++) {
1351 vk_outarray_append_typed(VkQueueFamilyProperties2, &out, p) {
1352 p->queueFamilyProperties = pdev->queue_families[i].props;
1353
1354 vk_foreach_struct(ext, pQueueFamilyProperties->pNext) {
1355 dzn_debug_ignored_stype(ext->sType);
1356 }
1357 }
1358 }
1359 }
1360
1361 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties * pMemoryProperties)1362 dzn_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
1363 VkPhysicalDeviceMemoryProperties *pMemoryProperties)
1364 {
1365 VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
1366
1367 // Ensure memory caps are up-to-date
1368 (void)dzn_physical_device_get_d3d12_dev(pdev);
1369 *pMemoryProperties = pdev->memory;
1370 }
1371
1372 VKAPI_ATTR void VKAPI_CALL
dzn_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties2 * pMemoryProperties)1373 dzn_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
1374 VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
1375 {
1376 dzn_GetPhysicalDeviceMemoryProperties(physicalDevice,
1377 &pMemoryProperties->memoryProperties);
1378
1379 vk_foreach_struct(ext, pMemoryProperties->pNext) {
1380 dzn_debug_ignored_stype(ext->sType);
1381 }
1382 }
1383
1384 VKAPI_ATTR VkResult VKAPI_CALL
dzn_EnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)1385 dzn_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1386 VkLayerProperties *pProperties)
1387 {
1388 if (pProperties == NULL) {
1389 *pPropertyCount = 0;
1390 return VK_SUCCESS;
1391 }
1392
1393 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1394 }
1395
1396 static VkResult
dzn_queue_sync_wait(dzn_queue * queue,const struct vk_sync_wait * wait)1397 dzn_queue_sync_wait(dzn_queue *queue, const struct vk_sync_wait *wait)
1398 {
1399 if (wait->sync->type == &vk_sync_dummy_type)
1400 return VK_SUCCESS;
1401
1402 dzn_device *device = container_of(queue->vk.base.device, dzn_device, vk);
1403 assert(wait->sync->type == &dzn_sync_type);
1404 dzn_sync *sync = container_of(wait->sync, dzn_sync, vk);
1405 uint64_t value =
1406 (sync->vk.flags & VK_SYNC_IS_TIMELINE) ? wait->wait_value : 1;
1407
1408 assert(sync->fence != NULL);
1409
1410 if (value > 0 && FAILED(queue->cmdqueue->Wait(sync->fence, value)))
1411 return vk_error(device, VK_ERROR_UNKNOWN);
1412
1413 return VK_SUCCESS;
1414 }
1415
1416 static VkResult
dzn_queue_sync_signal(dzn_queue * queue,const struct vk_sync_signal * signal)1417 dzn_queue_sync_signal(dzn_queue *queue, const struct vk_sync_signal *signal)
1418 {
1419 if (signal->sync->type == &vk_sync_dummy_type)
1420 return VK_SUCCESS;
1421
1422 dzn_device *device = container_of(queue->vk.base.device, dzn_device, vk);
1423 assert(signal->sync->type == &dzn_sync_type);
1424 dzn_sync *sync = container_of(signal->sync, dzn_sync, vk);
1425 uint64_t value =
1426 (sync->vk.flags & VK_SYNC_IS_TIMELINE) ? signal->signal_value : 1;
1427 assert(value > 0);
1428
1429 assert(sync->fence != NULL);
1430
1431 if (FAILED(queue->cmdqueue->Signal(sync->fence, value)))
1432 return vk_error(device, VK_ERROR_UNKNOWN);
1433
1434 return VK_SUCCESS;
1435 }
1436
1437 static VkResult
dzn_queue_submit(struct vk_queue * q,struct vk_queue_submit * info)1438 dzn_queue_submit(struct vk_queue *q,
1439 struct vk_queue_submit *info)
1440 {
1441 dzn_queue *queue = container_of(q, dzn_queue, vk);
1442 dzn_device *device = container_of(q->base.device, dzn_device, vk);
1443 VkResult result = VK_SUCCESS;
1444
1445 for (uint32_t i = 0; i < info->wait_count; i++) {
1446 result = dzn_queue_sync_wait(queue, &info->waits[i]);
1447 if (result != VK_SUCCESS)
1448 return result;
1449 }
1450
1451 for (uint32_t i = 0; i < info->command_buffer_count; i++) {
1452 dzn_cmd_buffer *cmd_buffer =
1453 container_of(info->command_buffers[i], dzn_cmd_buffer, vk);
1454
1455 ID3D12CommandList *cmdlists[] = { cmd_buffer->cmdlist };
1456
1457 util_dynarray_foreach(&cmd_buffer->events.wait, dzn_event *, evt) {
1458 if (FAILED(queue->cmdqueue->Wait((*evt)->fence, 1)))
1459 return vk_error(device, VK_ERROR_UNKNOWN);
1460 }
1461
1462 util_dynarray_foreach(&cmd_buffer->queries.wait, dzn_cmd_buffer_query_range, range) {
1463 mtx_lock(&range->qpool->queries_lock);
1464 for (uint32_t q = range->start; q < range->start + range->count; q++) {
1465 struct dzn_query *query = &range->qpool->queries[q];
1466
1467 if (query->fence &&
1468 FAILED(queue->cmdqueue->Wait(query->fence, query->fence_value)))
1469 return vk_error(device, VK_ERROR_UNKNOWN);
1470 }
1471 mtx_unlock(&range->qpool->queries_lock);
1472 }
1473
1474 util_dynarray_foreach(&cmd_buffer->queries.reset, dzn_cmd_buffer_query_range, range) {
1475 mtx_lock(&range->qpool->queries_lock);
1476 for (uint32_t q = range->start; q < range->start + range->count; q++) {
1477 struct dzn_query *query = &range->qpool->queries[q];
1478 if (query->fence) {
1479 query->fence->Release();
1480 query->fence = NULL;
1481 }
1482 query->fence_value = 0;
1483 }
1484 mtx_unlock(&range->qpool->queries_lock);
1485 }
1486
1487 queue->cmdqueue->ExecuteCommandLists(1, cmdlists);
1488
1489 util_dynarray_foreach(&cmd_buffer->events.signal, dzn_cmd_event_signal, evt) {
1490 if (FAILED(queue->cmdqueue->Signal(evt->event->fence, evt->value ? 1 : 0)))
1491 return vk_error(device, VK_ERROR_UNKNOWN);
1492 }
1493
1494 util_dynarray_foreach(&cmd_buffer->queries.signal, dzn_cmd_buffer_query_range, range) {
1495 mtx_lock(&range->qpool->queries_lock);
1496 for (uint32_t q = range->start; q < range->start + range->count; q++) {
1497 struct dzn_query *query = &range->qpool->queries[q];
1498 query->fence_value = queue->fence_point + 1;
1499 query->fence = queue->fence;
1500 query->fence->AddRef();
1501 }
1502 mtx_unlock(&range->qpool->queries_lock);
1503 }
1504 }
1505
1506 for (uint32_t i = 0; i < info->signal_count; i++) {
1507 result = dzn_queue_sync_signal(queue, &info->signals[i]);
1508 if (result != VK_SUCCESS)
1509 return vk_error(device, VK_ERROR_UNKNOWN);
1510 }
1511
1512 if (FAILED(queue->cmdqueue->Signal(queue->fence, ++queue->fence_point)))
1513 return vk_error(device, VK_ERROR_UNKNOWN);
1514
1515 return VK_SUCCESS;
1516 }
1517
1518 static void
dzn_queue_finish(dzn_queue * queue)1519 dzn_queue_finish(dzn_queue *queue)
1520 {
1521 if (queue->cmdqueue)
1522 queue->cmdqueue->Release();
1523
1524 if (queue->fence)
1525 queue->fence->Release();
1526
1527 vk_queue_finish(&queue->vk);
1528 }
1529
1530 static VkResult
dzn_queue_init(dzn_queue * queue,dzn_device * device,const VkDeviceQueueCreateInfo * pCreateInfo,uint32_t index_in_family)1531 dzn_queue_init(dzn_queue *queue,
1532 dzn_device *device,
1533 const VkDeviceQueueCreateInfo *pCreateInfo,
1534 uint32_t index_in_family)
1535 {
1536 dzn_physical_device *pdev = container_of(device->vk.physical, dzn_physical_device, vk);
1537
1538 VkResult result = vk_queue_init(&queue->vk, &device->vk, pCreateInfo, index_in_family);
1539 if (result != VK_SUCCESS)
1540 return result;
1541
1542 queue->vk.driver_submit = dzn_queue_submit;
1543
1544 assert(pCreateInfo->queueFamilyIndex < pdev->queue_family_count);
1545
1546 D3D12_COMMAND_QUEUE_DESC queue_desc =
1547 pdev->queue_families[pCreateInfo->queueFamilyIndex].desc;
1548
1549 queue_desc.Priority =
1550 (INT)(pCreateInfo->pQueuePriorities[index_in_family] * (float)D3D12_COMMAND_QUEUE_PRIORITY_HIGH);
1551 queue_desc.NodeMask = 0;
1552
1553 if (FAILED(device->dev->CreateCommandQueue(&queue_desc,
1554 IID_PPV_ARGS(&queue->cmdqueue)))) {
1555 dzn_queue_finish(queue);
1556 return vk_error(device->vk.physical->instance, VK_ERROR_INITIALIZATION_FAILED);
1557 }
1558
1559 if (FAILED(device->dev->CreateFence(0, D3D12_FENCE_FLAG_NONE,
1560 IID_PPV_ARGS(&queue->fence)))) {
1561 dzn_queue_finish(queue);
1562 return vk_error(device->vk.physical->instance, VK_ERROR_INITIALIZATION_FAILED);
1563 }
1564
1565 return VK_SUCCESS;
1566 }
1567
1568 static VkResult
check_physical_device_features(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceFeatures * features)1569 check_physical_device_features(VkPhysicalDevice physicalDevice,
1570 const VkPhysicalDeviceFeatures *features)
1571 {
1572 VkPhysicalDeviceFeatures supported_features;
1573 dzn_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
1574 VkBool32 *supported_feature = (VkBool32 *)&supported_features;
1575 VkBool32 *enabled_feature = (VkBool32 *)features;
1576 unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
1577 for (uint32_t i = 0; i < num_features; i++) {
1578 if (enabled_feature[i] && !supported_feature[i])
1579 return VK_ERROR_FEATURE_NOT_PRESENT;
1580 }
1581
1582 return VK_SUCCESS;
1583 }
1584
1585 static VkResult
dzn_device_create_sync_for_memory(struct vk_device * device,VkDeviceMemory memory,bool signal_memory,struct vk_sync ** sync_out)1586 dzn_device_create_sync_for_memory(struct vk_device *device,
1587 VkDeviceMemory memory,
1588 bool signal_memory,
1589 struct vk_sync **sync_out)
1590 {
1591 return vk_sync_create(device, &vk_sync_dummy_type,
1592 (enum vk_sync_flags)0, 1, sync_out);
1593 }
1594
1595 static void
dzn_device_ref_pipeline_layout(struct vk_device * dev,VkPipelineLayout layout)1596 dzn_device_ref_pipeline_layout(struct vk_device *dev, VkPipelineLayout layout)
1597 {
1598 VK_FROM_HANDLE(dzn_pipeline_layout, playout, layout);
1599
1600 dzn_pipeline_layout_ref(playout);
1601 }
1602
1603 static void
dzn_device_unref_pipeline_layout(struct vk_device * dev,VkPipelineLayout layout)1604 dzn_device_unref_pipeline_layout(struct vk_device *dev, VkPipelineLayout layout)
1605 {
1606 VK_FROM_HANDLE(dzn_pipeline_layout, playout, layout);
1607
1608 dzn_pipeline_layout_unref(playout);
1609 }
1610
1611 static VkResult
dzn_device_query_init(dzn_device * device)1612 dzn_device_query_init(dzn_device *device)
1613 {
1614 /* FIXME: create the resource in the default heap */
1615 D3D12_HEAP_PROPERTIES hprops =
1616 device->dev->GetCustomHeapProperties(0, D3D12_HEAP_TYPE_UPLOAD);
1617 D3D12_RESOURCE_DESC rdesc = {
1618 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
1619 .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1620 .Width = DZN_QUERY_REFS_RES_SIZE,
1621 .Height = 1,
1622 .DepthOrArraySize = 1,
1623 .MipLevels = 1,
1624 .Format = DXGI_FORMAT_UNKNOWN,
1625 .SampleDesc = { .Count = 1, .Quality = 0 },
1626 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
1627 .Flags = D3D12_RESOURCE_FLAG_NONE,
1628 };
1629
1630 if (FAILED(device->dev->CreateCommittedResource(&hprops,
1631 D3D12_HEAP_FLAG_NONE,
1632 &rdesc,
1633 D3D12_RESOURCE_STATE_GENERIC_READ,
1634 NULL,
1635 IID_PPV_ARGS(&device->queries.refs))))
1636 return vk_error(device->vk.physical, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1637
1638 uint8_t *queries_ref;
1639 if (FAILED(device->queries.refs->Map(0, NULL, (void **)&queries_ref)))
1640 return vk_error(device->vk.physical, VK_ERROR_OUT_OF_HOST_MEMORY);
1641
1642 memset(queries_ref + DZN_QUERY_REFS_ALL_ONES_OFFSET, 0xff, DZN_QUERY_REFS_SECTION_SIZE);
1643 memset(queries_ref + DZN_QUERY_REFS_ALL_ZEROS_OFFSET, 0x0, DZN_QUERY_REFS_SECTION_SIZE);
1644 device->queries.refs->Unmap(0, NULL);
1645
1646 return VK_SUCCESS;
1647 }
1648
1649 static void
dzn_device_query_finish(dzn_device * device)1650 dzn_device_query_finish(dzn_device *device)
1651 {
1652 if (device->queries.refs)
1653 device->queries.refs->Release();
1654 }
1655
1656 static void
dzn_device_destroy(dzn_device * device,const VkAllocationCallbacks * pAllocator)1657 dzn_device_destroy(dzn_device *device, const VkAllocationCallbacks *pAllocator)
1658 {
1659 if (!device)
1660 return;
1661
1662 dzn_instance *instance =
1663 container_of(device->vk.physical->instance, dzn_instance, vk);
1664
1665 vk_foreach_queue_safe(q, &device->vk) {
1666 dzn_queue *queue = container_of(q, dzn_queue, vk);
1667
1668 dzn_queue_finish(queue);
1669 }
1670
1671 dzn_device_query_finish(device);
1672 dzn_meta_finish(device);
1673
1674 if (device->dev)
1675 device->dev->Release();
1676
1677 vk_device_finish(&device->vk);
1678 vk_free2(&instance->vk.alloc, pAllocator, device);
1679 }
1680
1681 static VkResult
dzn_device_create(dzn_physical_device * pdev,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * out)1682 dzn_device_create(dzn_physical_device *pdev,
1683 const VkDeviceCreateInfo *pCreateInfo,
1684 const VkAllocationCallbacks *pAllocator,
1685 VkDevice *out)
1686 {
1687 dzn_instance *instance = container_of(pdev->vk.instance, dzn_instance, vk);
1688
1689 uint32_t queue_count = 0;
1690 for (uint32_t qf = 0; qf < pCreateInfo->queueCreateInfoCount; qf++) {
1691 const VkDeviceQueueCreateInfo *qinfo = &pCreateInfo->pQueueCreateInfos[qf];
1692 queue_count += qinfo->queueCount;
1693 }
1694
1695 VK_MULTIALLOC(ma);
1696 VK_MULTIALLOC_DECL(&ma, dzn_device, device, 1);
1697 VK_MULTIALLOC_DECL(&ma, dzn_queue, queues, queue_count);
1698
1699 if (!vk_multialloc_zalloc2(&ma, &instance->vk.alloc, pAllocator,
1700 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))
1701 return vk_error(pdev, VK_ERROR_OUT_OF_HOST_MEMORY);
1702
1703 vk_device_dispatch_table dispatch_table;
1704
1705 /* For secondary command buffer support, overwrite any command entrypoints
1706 * in the main device-level dispatch table with
1707 * vk_cmd_enqueue_unless_primary_Cmd*.
1708 */
1709 vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1710 &vk_cmd_enqueue_unless_primary_device_entrypoints, true);
1711 vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1712 &dzn_device_entrypoints, false);
1713 vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1714 &wsi_device_entrypoints, false);
1715
1716 /* Populate our primary cmd_dispatch table. */
1717 vk_device_dispatch_table_from_entrypoints(&device->cmd_dispatch,
1718 &dzn_device_entrypoints, true);
1719 vk_device_dispatch_table_from_entrypoints(&device->cmd_dispatch,
1720 &vk_common_device_entrypoints,
1721 false);
1722
1723 VkResult result =
1724 vk_device_init(&device->vk, &pdev->vk, &dispatch_table, pCreateInfo, pAllocator);
1725 if (result != VK_SUCCESS) {
1726 vk_free2(&device->vk.alloc, pAllocator, device);
1727 return result;
1728 }
1729
1730 /* Must be done after vk_device_init() because this function memset(0) the
1731 * whole struct.
1732 */
1733 device->vk.command_dispatch_table = &device->cmd_dispatch;
1734 device->vk.ref_pipeline_layout = dzn_device_ref_pipeline_layout;
1735 device->vk.unref_pipeline_layout = dzn_device_unref_pipeline_layout;
1736 device->vk.create_sync_for_memory = dzn_device_create_sync_for_memory;
1737
1738 device->dev = dzn_physical_device_get_d3d12_dev(pdev);
1739 if (!device->dev) {
1740 dzn_device_destroy(device, pAllocator);
1741 return vk_error(pdev, VK_ERROR_INITIALIZATION_FAILED);
1742 }
1743
1744 device->dev->AddRef();
1745
1746 ID3D12InfoQueue *info_queue;
1747 if (SUCCEEDED(device->dev->QueryInterface(IID_PPV_ARGS(&info_queue)))) {
1748 D3D12_MESSAGE_SEVERITY severities[] = {
1749 D3D12_MESSAGE_SEVERITY_INFO,
1750 D3D12_MESSAGE_SEVERITY_WARNING,
1751 };
1752
1753 D3D12_MESSAGE_ID msg_ids[] = {
1754 D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,
1755 };
1756
1757 D3D12_INFO_QUEUE_FILTER NewFilter = {};
1758 NewFilter.DenyList.NumSeverities = ARRAY_SIZE(severities);
1759 NewFilter.DenyList.pSeverityList = severities;
1760 NewFilter.DenyList.NumIDs = ARRAY_SIZE(msg_ids);
1761 NewFilter.DenyList.pIDList = msg_ids;
1762
1763 info_queue->PushStorageFilter(&NewFilter);
1764 }
1765
1766 result = dzn_meta_init(device);
1767 if (result != VK_SUCCESS) {
1768 dzn_device_destroy(device, pAllocator);
1769 return result;
1770 }
1771
1772 result = dzn_device_query_init(device);
1773 if (result != VK_SUCCESS) {
1774 dzn_device_destroy(device, pAllocator);
1775 return result;
1776 }
1777
1778 uint32_t qindex = 0;
1779 for (uint32_t qf = 0; qf < pCreateInfo->queueCreateInfoCount; qf++) {
1780 const VkDeviceQueueCreateInfo *qinfo = &pCreateInfo->pQueueCreateInfos[qf];
1781
1782 for (uint32_t q = 0; q < qinfo->queueCount; q++) {
1783 result =
1784 dzn_queue_init(&queues[qindex++], device, qinfo, q);
1785 if (result != VK_SUCCESS) {
1786 dzn_device_destroy(device, pAllocator);
1787 return result;
1788 }
1789 }
1790 }
1791
1792 assert(queue_count == qindex);
1793 *out = dzn_device_to_handle(device);
1794 return VK_SUCCESS;
1795 }
1796
1797 ID3D12RootSignature *
dzn_device_create_root_sig(dzn_device * device,const D3D12_VERSIONED_ROOT_SIGNATURE_DESC * desc)1798 dzn_device_create_root_sig(dzn_device *device,
1799 const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc)
1800 {
1801 dzn_instance *instance =
1802 container_of(device->vk.physical->instance, dzn_instance, vk);
1803 ComPtr<ID3DBlob> sig, error;
1804
1805 if (FAILED(instance->d3d12.serialize_root_sig(desc,
1806 &sig, &error))) {
1807 if (instance->debug_flags & DZN_DEBUG_SIG) {
1808 const char* error_msg = (const char*)error->GetBufferPointer();
1809 fprintf(stderr,
1810 "== SERIALIZE ROOT SIG ERROR =============================================\n"
1811 "%s\n"
1812 "== END ==========================================================\n",
1813 error_msg);
1814 }
1815
1816 return NULL;
1817 }
1818
1819 ID3D12RootSignature *root_sig;
1820 if (FAILED(device->dev->CreateRootSignature(0,
1821 sig->GetBufferPointer(),
1822 sig->GetBufferSize(),
1823 IID_PPV_ARGS(&root_sig))))
1824 return NULL;
1825
1826 return root_sig;
1827 }
1828
1829 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)1830 dzn_CreateDevice(VkPhysicalDevice physicalDevice,
1831 const VkDeviceCreateInfo *pCreateInfo,
1832 const VkAllocationCallbacks *pAllocator,
1833 VkDevice *pDevice)
1834 {
1835 VK_FROM_HANDLE(dzn_physical_device, physical_device, physicalDevice);
1836 dzn_instance *instance =
1837 container_of(physical_device->vk.instance, dzn_instance, vk);
1838 VkResult result;
1839
1840 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
1841
1842 /* Check enabled features */
1843 if (pCreateInfo->pEnabledFeatures) {
1844 result = check_physical_device_features(physicalDevice,
1845 pCreateInfo->pEnabledFeatures);
1846 if (result != VK_SUCCESS)
1847 return vk_error(physical_device, result);
1848 }
1849
1850 /* Check requested queues and fail if we are requested to create any
1851 * queues with flags we don't support.
1852 */
1853 assert(pCreateInfo->queueCreateInfoCount > 0);
1854 for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1855 if (pCreateInfo->pQueueCreateInfos[i].flags != 0)
1856 return vk_error(physical_device, VK_ERROR_INITIALIZATION_FAILED);
1857 }
1858
1859 return dzn_device_create(physical_device, pCreateInfo, pAllocator, pDevice);
1860 }
1861
1862 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyDevice(VkDevice dev,const VkAllocationCallbacks * pAllocator)1863 dzn_DestroyDevice(VkDevice dev,
1864 const VkAllocationCallbacks *pAllocator)
1865 {
1866 VK_FROM_HANDLE(dzn_device, device, dev);
1867
1868 device->vk.dispatch_table.DeviceWaitIdle(dev);
1869
1870 dzn_device_destroy(device, pAllocator);
1871 }
1872
1873 static void
dzn_device_memory_destroy(dzn_device_memory * mem,const VkAllocationCallbacks * pAllocator)1874 dzn_device_memory_destroy(dzn_device_memory *mem,
1875 const VkAllocationCallbacks *pAllocator)
1876 {
1877 if (!mem)
1878 return;
1879
1880 dzn_device *device = container_of(mem->base.device, dzn_device, vk);
1881
1882 if (mem->map)
1883 mem->map_res->Unmap(0, NULL);
1884
1885 if (mem->map_res)
1886 mem->map_res->Release();
1887
1888 if (mem->heap)
1889 mem->heap->Release();
1890
1891 vk_object_base_finish(&mem->base);
1892 vk_free2(&device->vk.alloc, pAllocator, mem);
1893 }
1894
1895 static VkResult
dzn_device_memory_create(dzn_device * device,const VkMemoryAllocateInfo * pAllocateInfo,const VkAllocationCallbacks * pAllocator,VkDeviceMemory * out)1896 dzn_device_memory_create(dzn_device *device,
1897 const VkMemoryAllocateInfo *pAllocateInfo,
1898 const VkAllocationCallbacks *pAllocator,
1899 VkDeviceMemory *out)
1900 {
1901 dzn_physical_device *pdevice =
1902 container_of(device->vk.physical, dzn_physical_device, vk);
1903
1904 dzn_device_memory *mem = (dzn_device_memory *)
1905 vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*mem), 8,
1906 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1907 if (!mem)
1908 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1909
1910 vk_object_base_init(&device->vk, &mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY);
1911
1912 /* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */
1913 assert(pAllocateInfo->allocationSize > 0);
1914
1915 mem->size = pAllocateInfo->allocationSize;
1916
1917 #if 0
1918 const VkExportMemoryAllocateInfo *export_info = NULL;
1919 VkMemoryAllocateFlags vk_flags = 0;
1920 #endif
1921
1922 vk_foreach_struct_const(ext, pAllocateInfo->pNext) {
1923 dzn_debug_ignored_stype(ext->sType);
1924 }
1925
1926 const VkMemoryType *mem_type =
1927 &pdevice->memory.memoryTypes[pAllocateInfo->memoryTypeIndex];
1928
1929 D3D12_HEAP_DESC heap_desc = {};
1930 // TODO: fix all of these:
1931 heap_desc.SizeInBytes = pAllocateInfo->allocationSize;
1932 heap_desc.Alignment =
1933 heap_desc.SizeInBytes >= D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT ?
1934 D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT :
1935 D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
1936 heap_desc.Flags =
1937 dzn_physical_device_get_heap_flags_for_mem_type(pdevice,
1938 pAllocateInfo->memoryTypeIndex);
1939
1940 /* TODO: Unsure about this logic??? */
1941 mem->initial_state = D3D12_RESOURCE_STATE_COMMON;
1942 heap_desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM;
1943 heap_desc.Properties.MemoryPoolPreference =
1944 ((mem_type->propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) &&
1945 !pdevice->architecture.UMA) ?
1946 D3D12_MEMORY_POOL_L1 : D3D12_MEMORY_POOL_L0;
1947 if (mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
1948 heap_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
1949 } else if (mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1950 heap_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE;
1951 } else {
1952 heap_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE;
1953 }
1954
1955 if (FAILED(device->dev->CreateHeap(&heap_desc, IID_PPV_ARGS(&mem->heap)))) {
1956 dzn_device_memory_destroy(mem, pAllocator);
1957 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1958 }
1959
1960 if ((mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) &&
1961 !(heap_desc.Flags & D3D12_HEAP_FLAG_DENY_BUFFERS)){
1962 D3D12_RESOURCE_DESC res_desc = {};
1963 res_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
1964 res_desc.Format = DXGI_FORMAT_UNKNOWN;
1965 res_desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
1966 res_desc.Width = heap_desc.SizeInBytes;
1967 res_desc.Height = 1;
1968 res_desc.DepthOrArraySize = 1;
1969 res_desc.MipLevels = 1;
1970 res_desc.SampleDesc.Count = 1;
1971 res_desc.SampleDesc.Quality = 0;
1972 res_desc.Flags = D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
1973 res_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
1974 HRESULT hr = device->dev->CreatePlacedResource(mem->heap, 0, &res_desc,
1975 mem->initial_state,
1976 NULL, IID_PPV_ARGS(&mem->map_res));
1977 if (FAILED(hr)) {
1978 dzn_device_memory_destroy(mem, pAllocator);
1979 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1980 }
1981 }
1982
1983 *out = dzn_device_memory_to_handle(mem);
1984 return VK_SUCCESS;
1985 }
1986
1987 VKAPI_ATTR VkResult VKAPI_CALL
dzn_AllocateMemory(VkDevice device,const VkMemoryAllocateInfo * pAllocateInfo,const VkAllocationCallbacks * pAllocator,VkDeviceMemory * pMem)1988 dzn_AllocateMemory(VkDevice device,
1989 const VkMemoryAllocateInfo *pAllocateInfo,
1990 const VkAllocationCallbacks *pAllocator,
1991 VkDeviceMemory *pMem)
1992 {
1993 return dzn_device_memory_create(dzn_device_from_handle(device),
1994 pAllocateInfo, pAllocator, pMem);
1995 }
1996
1997 VKAPI_ATTR void VKAPI_CALL
dzn_FreeMemory(VkDevice device,VkDeviceMemory mem,const VkAllocationCallbacks * pAllocator)1998 dzn_FreeMemory(VkDevice device,
1999 VkDeviceMemory mem,
2000 const VkAllocationCallbacks *pAllocator)
2001 {
2002 dzn_device_memory_destroy(dzn_device_memory_from_handle(mem), pAllocator);
2003 }
2004
2005 VKAPI_ATTR VkResult VKAPI_CALL
dzn_MapMemory(VkDevice _device,VkDeviceMemory _memory,VkDeviceSize offset,VkDeviceSize size,VkMemoryMapFlags flags,void ** ppData)2006 dzn_MapMemory(VkDevice _device,
2007 VkDeviceMemory _memory,
2008 VkDeviceSize offset,
2009 VkDeviceSize size,
2010 VkMemoryMapFlags flags,
2011 void **ppData)
2012 {
2013 VK_FROM_HANDLE(dzn_device, device, _device);
2014 VK_FROM_HANDLE(dzn_device_memory, mem, _memory);
2015
2016 if (mem == NULL) {
2017 *ppData = NULL;
2018 return VK_SUCCESS;
2019 }
2020
2021 if (size == VK_WHOLE_SIZE)
2022 size = mem->size - offset;
2023
2024 /* From the Vulkan spec version 1.0.32 docs for MapMemory:
2025 *
2026 * * If size is not equal to VK_WHOLE_SIZE, size must be greater than 0
2027 * assert(size != 0);
2028 * * If size is not equal to VK_WHOLE_SIZE, size must be less than or
2029 * equal to the size of the memory minus offset
2030 */
2031 assert(size > 0);
2032 assert(offset + size <= mem->size);
2033
2034 assert(mem->map_res);
2035 D3D12_RANGE range = {};
2036 range.Begin = offset;
2037 range.End = offset + size;
2038 void *map = NULL;
2039 if (FAILED(mem->map_res->Map(0, &range, &map)))
2040 return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED);
2041
2042 mem->map = map;
2043 mem->map_size = size;
2044
2045 *ppData = ((uint8_t*) map) + offset;
2046
2047 return VK_SUCCESS;
2048 }
2049
2050 VKAPI_ATTR void VKAPI_CALL
dzn_UnmapMemory(VkDevice _device,VkDeviceMemory _memory)2051 dzn_UnmapMemory(VkDevice _device,
2052 VkDeviceMemory _memory)
2053 {
2054 VK_FROM_HANDLE(dzn_device, device, _device);
2055 VK_FROM_HANDLE(dzn_device_memory, mem, _memory);
2056
2057 if (mem == NULL)
2058 return;
2059
2060 assert(mem->map_res);
2061 mem->map_res->Unmap(0, NULL);
2062
2063 mem->map = NULL;
2064 mem->map_size = 0;
2065 }
2066
2067 VKAPI_ATTR VkResult VKAPI_CALL
dzn_FlushMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)2068 dzn_FlushMappedMemoryRanges(VkDevice _device,
2069 uint32_t memoryRangeCount,
2070 const VkMappedMemoryRange *pMemoryRanges)
2071 {
2072 return VK_SUCCESS;
2073 }
2074
2075 VKAPI_ATTR VkResult VKAPI_CALL
dzn_InvalidateMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)2076 dzn_InvalidateMappedMemoryRanges(VkDevice _device,
2077 uint32_t memoryRangeCount,
2078 const VkMappedMemoryRange *pMemoryRanges)
2079 {
2080 return VK_SUCCESS;
2081 }
2082
2083 static void
dzn_buffer_destroy(dzn_buffer * buf,const VkAllocationCallbacks * pAllocator)2084 dzn_buffer_destroy(dzn_buffer *buf, const VkAllocationCallbacks *pAllocator)
2085 {
2086 if (!buf)
2087 return;
2088
2089 dzn_device *device = container_of(buf->base.device, dzn_device, vk);
2090
2091 if (buf->res)
2092 buf->res->Release();
2093
2094 vk_object_base_finish(&buf->base);
2095 vk_free2(&device->vk.alloc, pAllocator, buf);
2096 }
2097
2098 static VkResult
dzn_buffer_create(dzn_device * device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * out)2099 dzn_buffer_create(dzn_device *device,
2100 const VkBufferCreateInfo *pCreateInfo,
2101 const VkAllocationCallbacks *pAllocator,
2102 VkBuffer *out)
2103 {
2104 dzn_buffer *buf = (dzn_buffer *)
2105 vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*buf), 8,
2106 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2107 if (!buf)
2108 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2109
2110 vk_object_base_init(&device->vk, &buf->base, VK_OBJECT_TYPE_BUFFER);
2111 buf->create_flags = pCreateInfo->flags;
2112 buf->size = pCreateInfo->size;
2113 buf->usage = pCreateInfo->usage;
2114
2115 if (buf->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
2116 buf->size = ALIGN_POT(buf->size, 256);
2117
2118 buf->desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
2119 buf->desc.Format = DXGI_FORMAT_UNKNOWN;
2120 buf->desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
2121 buf->desc.Width = buf->size;
2122 buf->desc.Height = 1;
2123 buf->desc.DepthOrArraySize = 1;
2124 buf->desc.MipLevels = 1;
2125 buf->desc.SampleDesc.Count = 1;
2126 buf->desc.SampleDesc.Quality = 0;
2127 buf->desc.Flags = D3D12_RESOURCE_FLAG_NONE;
2128 buf->desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
2129
2130 if (buf->usage &
2131 (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
2132 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
2133 buf->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
2134
2135 *out = dzn_buffer_to_handle(buf);
2136 return VK_SUCCESS;
2137 }
2138
2139 DXGI_FORMAT
dzn_buffer_get_dxgi_format(VkFormat format)2140 dzn_buffer_get_dxgi_format(VkFormat format)
2141 {
2142 enum pipe_format pfmt = vk_format_to_pipe_format(format);
2143
2144 return dzn_pipe_to_dxgi_format(pfmt);
2145 }
2146
2147 D3D12_TEXTURE_COPY_LOCATION
dzn_buffer_get_copy_loc(const dzn_buffer * buf,VkFormat format,const VkBufferImageCopy2KHR * region,VkImageAspectFlagBits aspect,uint32_t layer)2148 dzn_buffer_get_copy_loc(const dzn_buffer *buf,
2149 VkFormat format,
2150 const VkBufferImageCopy2KHR *region,
2151 VkImageAspectFlagBits aspect,
2152 uint32_t layer)
2153 {
2154 const uint32_t buffer_row_length =
2155 region->bufferRowLength ? region->bufferRowLength : region->imageExtent.width;
2156 const uint32_t buffer_image_height =
2157 region->bufferImageHeight ? region->bufferImageHeight : region->imageExtent.height;
2158
2159 VkFormat plane_format = dzn_image_get_plane_format(format, aspect);
2160
2161 enum pipe_format pfmt = vk_format_to_pipe_format(plane_format);
2162 uint32_t blksz = util_format_get_blocksize(pfmt);
2163 uint32_t blkw = util_format_get_blockwidth(pfmt);
2164 uint32_t blkh = util_format_get_blockheight(pfmt);
2165
2166 D3D12_TEXTURE_COPY_LOCATION loc = {
2167 .pResource = buf->res,
2168 .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
2169 .PlacedFootprint = {
2170 .Footprint = {
2171 .Format =
2172 dzn_image_get_placed_footprint_format(format, aspect),
2173 .Width = region->imageExtent.width,
2174 .Height = region->imageExtent.height,
2175 .Depth = region->imageExtent.depth,
2176 .RowPitch = blksz * DIV_ROUND_UP(buffer_row_length, blkw),
2177 },
2178 },
2179 };
2180
2181 uint32_t buffer_layer_stride =
2182 loc.PlacedFootprint.Footprint.RowPitch *
2183 DIV_ROUND_UP(loc.PlacedFootprint.Footprint.Height, blkh);
2184
2185 loc.PlacedFootprint.Offset =
2186 region->bufferOffset + (layer * buffer_layer_stride);
2187
2188 return loc;
2189 }
2190
2191 D3D12_TEXTURE_COPY_LOCATION
dzn_buffer_get_line_copy_loc(const dzn_buffer * buf,VkFormat format,const VkBufferImageCopy2KHR * region,const D3D12_TEXTURE_COPY_LOCATION * loc,uint32_t y,uint32_t z,uint32_t * start_x)2192 dzn_buffer_get_line_copy_loc(const dzn_buffer *buf, VkFormat format,
2193 const VkBufferImageCopy2KHR *region,
2194 const D3D12_TEXTURE_COPY_LOCATION *loc,
2195 uint32_t y, uint32_t z, uint32_t *start_x)
2196 {
2197 uint32_t buffer_row_length =
2198 region->bufferRowLength ? region->bufferRowLength : region->imageExtent.width;
2199 uint32_t buffer_image_height =
2200 region->bufferImageHeight ? region->bufferImageHeight : region->imageExtent.height;
2201
2202 format = dzn_image_get_plane_format(format, region->imageSubresource.aspectMask);
2203
2204 enum pipe_format pfmt = vk_format_to_pipe_format(format);
2205 uint32_t blksz = util_format_get_blocksize(pfmt);
2206 uint32_t blkw = util_format_get_blockwidth(pfmt);
2207 uint32_t blkh = util_format_get_blockheight(pfmt);
2208 uint32_t blkd = util_format_get_blockdepth(pfmt);
2209 D3D12_TEXTURE_COPY_LOCATION new_loc = *loc;
2210 uint32_t buffer_row_stride =
2211 DIV_ROUND_UP(buffer_row_length, blkw) * blksz;
2212 uint32_t buffer_layer_stride =
2213 buffer_row_stride *
2214 DIV_ROUND_UP(buffer_image_height, blkh);
2215
2216 uint64_t tex_offset =
2217 ((y / blkh) * buffer_row_stride) +
2218 ((z / blkd) * buffer_layer_stride);
2219 uint64_t offset = loc->PlacedFootprint.Offset + tex_offset;
2220 uint32_t offset_alignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
2221
2222 while (offset_alignment % blksz)
2223 offset_alignment += D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
2224
2225 new_loc.PlacedFootprint.Footprint.Height = blkh;
2226 new_loc.PlacedFootprint.Footprint.Depth = 1;
2227 new_loc.PlacedFootprint.Offset = (offset / offset_alignment) * offset_alignment;
2228 *start_x = ((offset % offset_alignment) / blksz) * blkw;
2229 new_loc.PlacedFootprint.Footprint.Width = *start_x + region->imageExtent.width;
2230 new_loc.PlacedFootprint.Footprint.RowPitch =
2231 ALIGN_POT(DIV_ROUND_UP(new_loc.PlacedFootprint.Footprint.Width, blkw) * blksz,
2232 D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
2233 return new_loc;
2234 }
2235
2236 bool
dzn_buffer_supports_region_copy(const D3D12_TEXTURE_COPY_LOCATION * loc)2237 dzn_buffer_supports_region_copy(const D3D12_TEXTURE_COPY_LOCATION *loc)
2238 {
2239 return !(loc->PlacedFootprint.Offset & (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT - 1)) &&
2240 !(loc->PlacedFootprint.Footprint.RowPitch & (D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1));
2241 }
2242
2243 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateBuffer(VkDevice device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * pBuffer)2244 dzn_CreateBuffer(VkDevice device,
2245 const VkBufferCreateInfo *pCreateInfo,
2246 const VkAllocationCallbacks *pAllocator,
2247 VkBuffer *pBuffer)
2248 {
2249 return dzn_buffer_create(dzn_device_from_handle(device),
2250 pCreateInfo, pAllocator, pBuffer);
2251 }
2252
2253 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyBuffer(VkDevice device,VkBuffer buffer,const VkAllocationCallbacks * pAllocator)2254 dzn_DestroyBuffer(VkDevice device,
2255 VkBuffer buffer,
2256 const VkAllocationCallbacks *pAllocator)
2257 {
2258 dzn_buffer_destroy(dzn_buffer_from_handle(buffer), pAllocator);
2259 }
2260
2261 VKAPI_ATTR void VKAPI_CALL
dzn_GetBufferMemoryRequirements2(VkDevice dev,const VkBufferMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)2262 dzn_GetBufferMemoryRequirements2(VkDevice dev,
2263 const VkBufferMemoryRequirementsInfo2 *pInfo,
2264 VkMemoryRequirements2 *pMemoryRequirements)
2265 {
2266 VK_FROM_HANDLE(dzn_device, device, dev);
2267 VK_FROM_HANDLE(dzn_buffer, buffer, pInfo->buffer);
2268 dzn_physical_device *pdev =
2269 container_of(device->vk.physical, dzn_physical_device, vk);
2270
2271 /* uh, this is grossly over-estimating things */
2272 uint32_t alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
2273 VkDeviceSize size = buffer->size;
2274
2275 if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) {
2276 alignment = MAX2(alignment, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
2277 size = ALIGN_POT(size, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
2278 }
2279
2280 pMemoryRequirements->memoryRequirements.size = size;
2281 pMemoryRequirements->memoryRequirements.alignment = alignment;
2282 pMemoryRequirements->memoryRequirements.memoryTypeBits =
2283 dzn_physical_device_get_mem_type_mask_for_resource(pdev, &buffer->desc);
2284
2285 vk_foreach_struct(ext, pMemoryRequirements->pNext) {
2286 switch (ext->sType) {
2287 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
2288 VkMemoryDedicatedRequirements *requirements =
2289 (VkMemoryDedicatedRequirements *)ext;
2290 /* TODO: figure out dedicated allocations */
2291 requirements->prefersDedicatedAllocation = false;
2292 requirements->requiresDedicatedAllocation = false;
2293 break;
2294 }
2295
2296 default:
2297 dzn_debug_ignored_stype(ext->sType);
2298 break;
2299 }
2300 }
2301
2302 #if 0
2303 D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo(
2304 UINT visibleMask,
2305 UINT numResourceDescs,
2306 const D3D12_RESOURCE_DESC *pResourceDescs);
2307 #endif
2308 }
2309
2310 VKAPI_ATTR VkResult VKAPI_CALL
dzn_BindBufferMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindBufferMemoryInfo * pBindInfos)2311 dzn_BindBufferMemory2(VkDevice _device,
2312 uint32_t bindInfoCount,
2313 const VkBindBufferMemoryInfo *pBindInfos)
2314 {
2315 VK_FROM_HANDLE(dzn_device, device, _device);
2316
2317 for (uint32_t i = 0; i < bindInfoCount; i++) {
2318 assert(pBindInfos[i].sType == VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO);
2319
2320 VK_FROM_HANDLE(dzn_device_memory, mem, pBindInfos[i].memory);
2321 VK_FROM_HANDLE(dzn_buffer, buffer, pBindInfos[i].buffer);
2322
2323 if (FAILED(device->dev->CreatePlacedResource(mem->heap,
2324 pBindInfos[i].memoryOffset,
2325 &buffer->desc,
2326 mem->initial_state,
2327 NULL, IID_PPV_ARGS(&buffer->res))))
2328 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2329 }
2330
2331 return VK_SUCCESS;
2332 }
2333
2334 static VkResult
dzn_framebuffer_create(dzn_device * device,const VkFramebufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFramebuffer * out)2335 dzn_framebuffer_create(dzn_device *device,
2336 const VkFramebufferCreateInfo *pCreateInfo,
2337 const VkAllocationCallbacks *pAllocator,
2338 VkFramebuffer *out)
2339 {
2340 VK_MULTIALLOC(ma);
2341 VK_MULTIALLOC_DECL(&ma, dzn_framebuffer, framebuffer, 1);
2342 VK_MULTIALLOC_DECL(&ma, dzn_image_view *, attachments, pCreateInfo->attachmentCount);
2343
2344 if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, pAllocator,
2345 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
2346 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2347
2348 framebuffer->width = pCreateInfo->width;
2349 framebuffer->height = pCreateInfo->height;
2350 framebuffer->layers = pCreateInfo->layers;
2351
2352 framebuffer->attachments = attachments;
2353 framebuffer->attachment_count = pCreateInfo->attachmentCount;
2354 for (uint32_t i = 0; i < framebuffer->attachment_count; i++) {
2355 VK_FROM_HANDLE(dzn_image_view, iview, pCreateInfo->pAttachments[i]);
2356 framebuffer->attachments[i] = iview;
2357 }
2358
2359 vk_object_base_init(&device->vk, &framebuffer->base, VK_OBJECT_TYPE_FRAMEBUFFER);
2360 *out = dzn_framebuffer_to_handle(framebuffer);
2361 return VK_SUCCESS;
2362 }
2363
2364 static void
dzn_framebuffer_destroy(dzn_framebuffer * framebuffer,const VkAllocationCallbacks * pAllocator)2365 dzn_framebuffer_destroy(dzn_framebuffer *framebuffer,
2366 const VkAllocationCallbacks *pAllocator)
2367 {
2368 if (!framebuffer)
2369 return;
2370
2371 dzn_device *device =
2372 container_of(framebuffer->base.device, dzn_device, vk);
2373
2374 vk_object_base_finish(&framebuffer->base);
2375 vk_free2(&device->vk.alloc, pAllocator, framebuffer);
2376 }
2377
2378 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateFramebuffer(VkDevice device,const VkFramebufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFramebuffer * pFramebuffer)2379 dzn_CreateFramebuffer(VkDevice device,
2380 const VkFramebufferCreateInfo *pCreateInfo,
2381 const VkAllocationCallbacks *pAllocator,
2382 VkFramebuffer *pFramebuffer)
2383 {
2384 return dzn_framebuffer_create(dzn_device_from_handle(device),
2385 pCreateInfo, pAllocator, pFramebuffer);
2386 }
2387
2388 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyFramebuffer(VkDevice device,VkFramebuffer fb,const VkAllocationCallbacks * pAllocator)2389 dzn_DestroyFramebuffer(VkDevice device,
2390 VkFramebuffer fb,
2391 const VkAllocationCallbacks *pAllocator)
2392 {
2393 dzn_framebuffer_destroy(dzn_framebuffer_from_handle(fb), pAllocator);
2394 }
2395
2396 static void
dzn_event_destroy(dzn_event * event,const VkAllocationCallbacks * pAllocator)2397 dzn_event_destroy(dzn_event *event,
2398 const VkAllocationCallbacks *pAllocator)
2399 {
2400 if (!event)
2401 return;
2402
2403 dzn_device *device =
2404 container_of(event->base.device, dzn_device, vk);
2405
2406 if (event->fence)
2407 event->fence->Release();
2408
2409 vk_object_base_finish(&event->base);
2410 vk_free2(&device->vk.alloc, pAllocator, event);
2411 }
2412
2413 static VkResult
dzn_event_create(dzn_device * device,const VkEventCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkEvent * out)2414 dzn_event_create(dzn_device *device,
2415 const VkEventCreateInfo *pCreateInfo,
2416 const VkAllocationCallbacks *pAllocator,
2417 VkEvent *out)
2418 {
2419 dzn_event *event = (dzn_event *)
2420 vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*event), 8,
2421 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2422 if (!event)
2423 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2424
2425 vk_object_base_init(&device->vk, &event->base, VK_OBJECT_TYPE_EVENT);
2426
2427 if (FAILED(device->dev->CreateFence(0, D3D12_FENCE_FLAG_NONE,
2428 IID_PPV_ARGS(&event->fence)))) {
2429 dzn_event_destroy(event, pAllocator);
2430 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2431 }
2432
2433 *out = dzn_event_to_handle(event);
2434 return VK_SUCCESS;
2435 }
2436
2437 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateEvent(VkDevice device,const VkEventCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkEvent * pEvent)2438 dzn_CreateEvent(VkDevice device,
2439 const VkEventCreateInfo *pCreateInfo,
2440 const VkAllocationCallbacks *pAllocator,
2441 VkEvent *pEvent)
2442 {
2443 return dzn_event_create(dzn_device_from_handle(device),
2444 pCreateInfo, pAllocator, pEvent);
2445 }
2446
2447 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyEvent(VkDevice device,VkEvent event,const VkAllocationCallbacks * pAllocator)2448 dzn_DestroyEvent(VkDevice device,
2449 VkEvent event,
2450 const VkAllocationCallbacks *pAllocator)
2451 {
2452 return dzn_event_destroy(dzn_event_from_handle(event), pAllocator);
2453 }
2454
2455 VKAPI_ATTR VkResult VKAPI_CALL
dzn_ResetEvent(VkDevice dev,VkEvent evt)2456 dzn_ResetEvent(VkDevice dev,
2457 VkEvent evt)
2458 {
2459 VK_FROM_HANDLE(dzn_device, device, dev);
2460 VK_FROM_HANDLE(dzn_event, event, evt);
2461
2462 if (FAILED(event->fence->Signal(0)))
2463 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2464
2465 return VK_SUCCESS;
2466 }
2467
2468 VKAPI_ATTR VkResult VKAPI_CALL
dzn_SetEvent(VkDevice dev,VkEvent evt)2469 dzn_SetEvent(VkDevice dev,
2470 VkEvent evt)
2471 {
2472 VK_FROM_HANDLE(dzn_device, device, dev);
2473 VK_FROM_HANDLE(dzn_event, event, evt);
2474
2475 if (FAILED(event->fence->Signal(1)))
2476 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2477
2478 return VK_SUCCESS;
2479 }
2480
2481 VKAPI_ATTR VkResult VKAPI_CALL
dzn_GetEventStatus(VkDevice device,VkEvent evt)2482 dzn_GetEventStatus(VkDevice device,
2483 VkEvent evt)
2484 {
2485 VK_FROM_HANDLE(dzn_event, event, evt);
2486
2487 return event->fence->GetCompletedValue() == 0 ?
2488 VK_EVENT_RESET : VK_EVENT_SET;
2489 }
2490
2491 VKAPI_ATTR void VKAPI_CALL
dzn_GetDeviceMemoryCommitment(VkDevice device,VkDeviceMemory memory,VkDeviceSize * pCommittedMemoryInBytes)2492 dzn_GetDeviceMemoryCommitment(VkDevice device,
2493 VkDeviceMemory memory,
2494 VkDeviceSize *pCommittedMemoryInBytes)
2495 {
2496 VK_FROM_HANDLE(dzn_device_memory, mem, memory);
2497
2498 // TODO: find if there's a way to query/track actual heap residency
2499 *pCommittedMemoryInBytes = mem->size;
2500 }
2501
2502 VKAPI_ATTR VkResult VKAPI_CALL
dzn_QueueBindSparse(VkQueue queue,uint32_t bindInfoCount,const VkBindSparseInfo * pBindInfo,VkFence fence)2503 dzn_QueueBindSparse(VkQueue queue,
2504 uint32_t bindInfoCount,
2505 const VkBindSparseInfo *pBindInfo,
2506 VkFence fence)
2507 {
2508 // FIXME: add proper implem
2509 dzn_stub();
2510 return VK_SUCCESS;
2511 }
2512
2513 static D3D12_TEXTURE_ADDRESS_MODE
dzn_sampler_translate_addr_mode(VkSamplerAddressMode in)2514 dzn_sampler_translate_addr_mode(VkSamplerAddressMode in)
2515 {
2516 switch (in) {
2517 case VK_SAMPLER_ADDRESS_MODE_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
2518 case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
2519 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
2520 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
2521 default: unreachable("Invalid address mode");
2522 }
2523 }
2524
2525 static void
dzn_sampler_destroy(dzn_sampler * sampler,const VkAllocationCallbacks * pAllocator)2526 dzn_sampler_destroy(dzn_sampler *sampler,
2527 const VkAllocationCallbacks *pAllocator)
2528 {
2529 if (!sampler)
2530 return;
2531
2532 dzn_device *device =
2533 container_of(sampler->base.device, dzn_device, vk);
2534
2535 vk_object_base_finish(&sampler->base);
2536 vk_free2(&device->vk.alloc, pAllocator, sampler);
2537 }
2538
2539 static VkResult
dzn_sampler_create(dzn_device * device,const VkSamplerCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSampler * out)2540 dzn_sampler_create(dzn_device *device,
2541 const VkSamplerCreateInfo *pCreateInfo,
2542 const VkAllocationCallbacks *pAllocator,
2543 VkSampler *out)
2544 {
2545 dzn_sampler *sampler = (dzn_sampler *)
2546 vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*sampler), 8,
2547 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2548 if (!sampler)
2549 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2550
2551 vk_object_base_init(&device->vk, &sampler->base, VK_OBJECT_TYPE_SAMPLER);
2552
2553 const VkSamplerCustomBorderColorCreateInfoEXT *pBorderColor = (const VkSamplerCustomBorderColorCreateInfoEXT *)
2554 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);
2555
2556 /* TODO: have a sampler pool to allocate shader-invisible descs which we
2557 * can copy to the desc_set when UpdateDescriptorSets() is called.
2558 */
2559 sampler->desc.Filter = dzn_translate_sampler_filter(pCreateInfo);
2560 sampler->desc.AddressU = dzn_sampler_translate_addr_mode(pCreateInfo->addressModeU);
2561 sampler->desc.AddressV = dzn_sampler_translate_addr_mode(pCreateInfo->addressModeV);
2562 sampler->desc.AddressW = dzn_sampler_translate_addr_mode(pCreateInfo->addressModeW);
2563 sampler->desc.MipLODBias = pCreateInfo->mipLodBias;
2564 sampler->desc.MaxAnisotropy = pCreateInfo->maxAnisotropy;
2565 sampler->desc.MinLOD = pCreateInfo->minLod;
2566 sampler->desc.MaxLOD = pCreateInfo->maxLod;
2567
2568 if (pCreateInfo->compareEnable)
2569 sampler->desc.ComparisonFunc = dzn_translate_compare_op(pCreateInfo->compareOp);
2570
2571 bool reads_border_color =
2572 pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
2573 pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
2574 pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
2575
2576 if (reads_border_color) {
2577 switch (pCreateInfo->borderColor) {
2578 case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
2579 case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
2580 sampler->desc.BorderColor[0] = 0.0f;
2581 sampler->desc.BorderColor[1] = 0.0f;
2582 sampler->desc.BorderColor[2] = 0.0f;
2583 sampler->desc.BorderColor[3] =
2584 pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK ? 0.0f : 1.0f;
2585 sampler->static_border_color =
2586 pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK ?
2587 D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK :
2588 D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
2589 break;
2590 case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
2591 sampler->desc.BorderColor[0] = sampler->desc.BorderColor[1] = 1.0f;
2592 sampler->desc.BorderColor[2] = sampler->desc.BorderColor[3] = 1.0f;
2593 sampler->static_border_color = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;
2594 break;
2595 case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT:
2596 sampler->static_border_color = (D3D12_STATIC_BORDER_COLOR)-1;
2597 for (unsigned i = 0; i < ARRAY_SIZE(sampler->desc.BorderColor); i++)
2598 sampler->desc.BorderColor[i] = pBorderColor->customBorderColor.float32[i];
2599 break;
2600 case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
2601 case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
2602 case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
2603 case VK_BORDER_COLOR_INT_CUSTOM_EXT:
2604 /* FIXME: sampling from integer textures is not supported yet. */
2605 sampler->static_border_color = (D3D12_STATIC_BORDER_COLOR)-1;
2606 break;
2607 default:
2608 unreachable("Unsupported border color");
2609 }
2610 }
2611
2612 *out = dzn_sampler_to_handle(sampler);
2613 return VK_SUCCESS;
2614 }
2615
2616 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateSampler(VkDevice device,const VkSamplerCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSampler * pSampler)2617 dzn_CreateSampler(VkDevice device,
2618 const VkSamplerCreateInfo *pCreateInfo,
2619 const VkAllocationCallbacks *pAllocator,
2620 VkSampler *pSampler)
2621 {
2622 return dzn_sampler_create(dzn_device_from_handle(device),
2623 pCreateInfo, pAllocator, pSampler);
2624 }
2625
2626 VKAPI_ATTR void VKAPI_CALL
dzn_DestroySampler(VkDevice device,VkSampler sampler,const VkAllocationCallbacks * pAllocator)2627 dzn_DestroySampler(VkDevice device,
2628 VkSampler sampler,
2629 const VkAllocationCallbacks *pAllocator)
2630 {
2631 return dzn_sampler_destroy(dzn_sampler_from_handle(sampler), pAllocator);
2632 }
2633