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 70static 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 91static void 92dzn_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 109VKAPI_ATTR VkResult VKAPI_CALL 110dzn_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 122static 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 136static void 137dzn_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 154static void 155dzn_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 174static VkResult 175dzn_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 248VKAPI_ATTR VkResult VKAPI_CALL 249dzn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 250 const VkAllocationCallbacks *pAllocator, 251 VkInstance *pInstance) 252{ 253 return dzn_instance_create(pCreateInfo, pAllocator, pInstance); 254} 255 256VKAPI_ATTR void VKAPI_CALL 257dzn_DestroyInstance(VkInstance instance, 258 const VkAllocationCallbacks *pAllocator) 259{ 260 dzn_instance_destroy(dzn_instance_from_handle(instance), pAllocator); 261} 262 263static void 264dzn_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 303const struct vk_pipeline_cache_object_ops *const dzn_pipeline_cache_import_ops[] = { 304 &dzn_cached_blob_ops, 305 NULL, 306}; 307 308static VkResult 309dzn_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 368static void 369dzn_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 451static void 452dzn_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 519static D3D12_HEAP_FLAGS 520dzn_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 526uint32_t 527dzn_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 549static uint32_t 550dzn_physical_device_get_max_mip_level(bool is_3d) 551{ 552 return is_3d ? 11 : 14; 553} 554 555static uint32_t 556dzn_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 563static uint32_t 564dzn_physical_device_get_max_array_layers() 565{ 566 return dzn_physical_device_get_max_extent(false); 567} 568 569static ID3D12Device2 * 570dzn_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 587D3D12_FEATURE_DATA_FORMAT_SUPPORT 588dzn_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 655static void 656dzn_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 757static VkResult 758dzn_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 926VKAPI_ATTR void VKAPI_CALL 927dzn_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 936VKAPI_ATTR VkResult VKAPI_CALL 937dzn_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 946VKAPI_ATTR VkResult VKAPI_CALL 947dzn_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 973VKAPI_ATTR void VKAPI_CALL 974dzn_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 986VKAPI_ATTR void VKAPI_CALL 987dzn_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, 988 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, 989 uint32_t *pPropertyCount, 990 VkSparseImageFormatProperties2 *pProperties) 991{ 992 *pPropertyCount = 0; 993} 994 995VKAPI_ATTR void VKAPI_CALL 996dzn_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, 997 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, 998 VkExternalBufferProperties *pExternalBufferProperties) 999{ 1000 pExternalBufferProperties->externalMemoryProperties = 1001 (VkExternalMemoryProperties) { 1002 .compatibleHandleTypes = (VkExternalMemoryHandleTypeFlags)pExternalBufferInfo->handleType, 1003 }; 1004} 1005 1006VkResult 1007dzn_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 1018VKAPI_ATTR VkResult VKAPI_CALL 1019dzn_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 1047VKAPI_ATTR VkResult VKAPI_CALL 1048dzn_EnumerateInstanceVersion(uint32_t *pApiVersion) 1049{ 1050 *pApiVersion = DZN_API_VERSION; 1051 return VK_SUCCESS; 1052} 1053 1054static bool 1055dzn_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 1073static bool 1074dzn_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 1098static bool 1099dzn_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 1106VKAPI_ATTR void VKAPI_CALL 1107dzn_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 1280VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1281dzn_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 */ 1299PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1300vk_icdGetInstanceProcAddr(VkInstance instance, 1301 const char *pName); 1302 1303PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1304vk_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 */ 1313PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1314vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, 1315 const char *pName); 1316 1317VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1318vk_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 */ 1328PUBLIC VKAPI_ATTR VkResult VKAPI_CALL 1329vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion); 1330 1331PUBLIC VKAPI_ATTR VkResult VKAPI_CALL 1332vk_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 1378VKAPI_ATTR void VKAPI_CALL 1379dzn_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 1671VKAPI_ATTR void VKAPI_CALL 1672dzn_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 1693VKAPI_ATTR void VKAPI_CALL 1694dzn_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 1704VKAPI_ATTR void VKAPI_CALL 1705dzn_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 1716VKAPI_ATTR VkResult VKAPI_CALL 1717dzn_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 1728static VkResult 1729dzn_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 1748static VkResult 1749dzn_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 1769static VkResult 1770dzn_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 1850static void 1851dzn_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 1862static VkResult 1863dzn_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 1903static VkResult 1904check_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 1924static VkResult 1925dzn_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 1934static VkResult 1935dzn_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 1972static void 1973dzn_device_query_finish(struct dzn_device *device) 1974{ 1975 if (device->queries.refs) 1976 ID3D12Resource_Release(device->queries.refs); 1977} 1978 1979static void 1980dzn_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 2004static VkResult 2005dzn_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 2015static VkResult 2016dzn_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 2132ID3D12RootSignature * 2133dzn_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 2161out: 2162 if (error) 2163 ID3D10Blob_Release(error); 2164 2165 if (sig) 2166 ID3D10Blob_Release(sig); 2167 2168 return root_sig; 2169} 2170 2171VKAPI_ATTR VkResult VKAPI_CALL 2172dzn_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 2202VKAPI_ATTR void VKAPI_CALL 2203dzn_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 2213static void 2214dzn_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 2235static VkResult 2236dzn_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 2360VKAPI_ATTR VkResult VKAPI_CALL 2361dzn_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 2370VKAPI_ATTR void VKAPI_CALL 2371dzn_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 2378VKAPI_ATTR VkResult VKAPI_CALL 2379dzn_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 2423VKAPI_ATTR void VKAPI_CALL 2424dzn_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 2439VKAPI_ATTR VkResult VKAPI_CALL 2440dzn_FlushMappedMemoryRanges(VkDevice _device, 2441 uint32_t memoryRangeCount, 2442 const VkMappedMemoryRange *pMemoryRanges) 2443{ 2444 return VK_SUCCESS; 2445} 2446 2447VKAPI_ATTR VkResult VKAPI_CALL 2448dzn_InvalidateMappedMemoryRanges(VkDevice _device, 2449 uint32_t memoryRangeCount, 2450 const VkMappedMemoryRange *pMemoryRanges) 2451{ 2452 return VK_SUCCESS; 2453} 2454 2455static void 2456dzn_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 2470static VkResult 2471dzn_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 2511DXGI_FORMAT 2512dzn_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 2519D3D12_TEXTURE_COPY_LOCATION 2520dzn_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 2561D3D12_TEXTURE_COPY_LOCATION 2562dzn_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 2606bool 2607dzn_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 2613VKAPI_ATTR VkResult VKAPI_CALL 2614dzn_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 2623VKAPI_ATTR void VKAPI_CALL 2624dzn_DestroyBuffer(VkDevice device, 2625 VkBuffer buffer, 2626 const VkAllocationCallbacks *pAllocator) 2627{ 2628 dzn_buffer_destroy(dzn_buffer_from_handle(buffer), pAllocator); 2629} 2630 2631VKAPI_ATTR void VKAPI_CALL 2632dzn_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 2680VKAPI_ATTR VkResult VKAPI_CALL 2681dzn_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 2706static void 2707dzn_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 2723static VkResult 2724dzn_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 2748VKAPI_ATTR VkResult VKAPI_CALL 2749dzn_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 2758VKAPI_ATTR void VKAPI_CALL 2759dzn_DestroyEvent(VkDevice device, 2760 VkEvent event, 2761 const VkAllocationCallbacks *pAllocator) 2762{ 2763 dzn_event_destroy(dzn_event_from_handle(event), pAllocator); 2764} 2765 2766VKAPI_ATTR VkResult VKAPI_CALL 2767dzn_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 2779VKAPI_ATTR VkResult VKAPI_CALL 2780dzn_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 2792VKAPI_ATTR VkResult VKAPI_CALL 2793dzn_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 2802VKAPI_ATTR void VKAPI_CALL 2803dzn_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 2813VKAPI_ATTR VkResult VKAPI_CALL 2814dzn_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 2824static D3D12_TEXTURE_ADDRESS_MODE 2825dzn_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 2836static void 2837dzn_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 2850static VkResult 2851dzn_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 2927VKAPI_ATTR VkResult VKAPI_CALL 2928dzn_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 2937VKAPI_ATTR void VKAPI_CALL 2938dzn_DestroySampler(VkDevice device, 2939 VkSampler sampler, 2940 const VkAllocationCallbacks *pAllocator) 2941{ 2942 dzn_sampler_destroy(dzn_sampler_from_handle(sampler), pAllocator); 2943} 2944 2945VKAPI_ATTR void VKAPI_CALL 2946dzn_GetDeviceGroupPeerMemoryFeatures(VkDevice device, 2947 uint32_t heapIndex, 2948 uint32_t localDeviceIndex, 2949 uint32_t remoteDeviceIndex, 2950 VkPeerMemoryFeatureFlags *pPeerMemoryFeatures) 2951{ 2952 *pPeerMemoryFeatures = 0; 2953} 2954 2955VKAPI_ATTR void VKAPI_CALL 2956dzn_GetImageSparseMemoryRequirements2(VkDevice device, 2957 const VkImageSparseMemoryRequirementsInfo2* pInfo, 2958 uint32_t *pSparseMemoryRequirementCount, 2959 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements) 2960{ 2961 *pSparseMemoryRequirementCount = 0; 2962} 2963 2964VKAPI_ATTR VkResult VKAPI_CALL 2965dzn_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 2974VKAPI_ATTR void VKAPI_CALL 2975dzn_DestroySamplerYcbcrConversion(VkDevice device, 2976 VkSamplerYcbcrConversion YcbcrConversion, 2977 const VkAllocationCallbacks *pAllocator) 2978{ 2979 unreachable("Ycbcr sampler conversion is not supported"); 2980} 2981