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