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