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