From f0569cdba013cf048129b76b448ba6f241972616 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Fri, 5 May 2023 13:02:41 -0700 Subject: [PATCH] dzn: VK_EXT_external_memory_host When ID3D12Device13 is available, we can support importing host memory. Imported host memory can be used to back buffers and linear textures. Part-of: --- src/microsoft/vulkan/dzn_device.c | 144 +++++++++++++++++++++++++++++++++++-- src/microsoft/vulkan/dzn_image.c | 6 +- src/microsoft/vulkan/dzn_private.h | 9 +++ 3 files changed, 151 insertions(+), 8 deletions(-) diff --git a/src/microsoft/vulkan/dzn_device.c b/src/microsoft/vulkan/dzn_device.c index 1e49f88..a0ba831 100644 --- a/src/microsoft/vulkan/dzn_device.c +++ b/src/microsoft/vulkan/dzn_device.c @@ -147,6 +147,9 @@ dzn_physical_device_get_extensions(struct dzn_physical_device *pdev) .KHR_timeline_semaphore = true, .KHR_uniform_buffer_standard_layout = true, .EXT_descriptor_indexing = pdev->shader_model >= D3D_SHADER_MODEL_6_6, +#if defined(_WIN32) && D3D12_SDK_VERSION >= 611 + .EXT_external_memory_host = pdev->dev13, +#endif .EXT_scalar_block_layout = true, .EXT_separate_stencil_usage = true, .EXT_shader_subgroup_ballot = true, @@ -203,6 +206,11 @@ dzn_physical_device_destroy(struct vk_physical_device *physical) if (pdev->dev12) ID3D12Device1_Release(pdev->dev12); +#if D3D12_SDK_VERSION >= 611 + if (pdev->dev13) + ID3D12Device1_Release(pdev->dev13); +#endif + if (pdev->adapter) IUnknown_Release(pdev->adapter); @@ -826,6 +834,10 @@ dzn_physical_device_create(struct vk_instance *instance, pdev->dev11 = NULL; if (FAILED(ID3D12Device1_QueryInterface(pdev->dev, &IID_ID3D12Device12, (void **)&pdev->dev12))) pdev->dev12 = NULL; +#if D3D12_SDK_VERSION >= 611 + if (FAILED(ID3D12Device1_QueryInterface(pdev->dev, &IID_ID3D12Device13, (void **)&pdev->dev13))) + pdev->dev13 = NULL; +#endif dzn_physical_device_cache_caps(pdev); dzn_physical_device_init_memory(pdev); dzn_physical_device_init_uuids(pdev); @@ -1129,12 +1141,24 @@ dzn_physical_device_get_image_format_properties(struct dzn_physical_device *pdev external_props->externalMemoryProperties.exportFromImportedHandleTypes = d3d11_texture_handle_types; external_props->externalMemoryProperties.externalMemoryFeatures = import_export_feature_flags; break; +#if defined(_WIN32) && D3D12_SDK_VERSION >= 611 + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + if (pdev->dev13) { + external_props->externalMemoryProperties.compatibleHandleTypes = + external_props->externalMemoryProperties.exportFromImportedHandleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT | opaque_external_flag; + external_props->externalMemoryProperties.externalMemoryFeatures = import_export_feature_flags; + break; + } + FALLTHROUGH; +#endif default: return VK_ERROR_FORMAT_NOT_SUPPORTED; } /* Linear textures not supported, but there's nothing else we can deduce from just a handle type */ - if (info->tiling != VK_IMAGE_TILING_OPTIMAL) + if (info->tiling != VK_IMAGE_TILING_OPTIMAL && + external_info->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT) return VK_ERROR_FORMAT_NOT_SUPPORTED; } @@ -1340,6 +1364,10 @@ dzn_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, VkExternalBufferProperties *pExternalBufferProperties) { +#if defined(_WIN32) && D3D12_SDK_VERSION >= 611 + VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice); +#endif + const VkExternalMemoryHandleTypeFlags d3d12_resource_handle_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT | opaque_external_flag; const VkExternalMemoryFeatureFlags import_export_feature_flags = @@ -1368,6 +1396,17 @@ dzn_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT | d3d12_resource_handle_types; pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = import_export_feature_flags; break; +#if defined(_WIN32) && D3D12_SDK_VERSION >= 611 + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + if (pdev->dev13) { + pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = + pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT | opaque_external_flag; + pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = import_export_feature_flags; + break; + } + FALLTHROUGH; +#endif default: pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties){ 0 }; break; @@ -1912,6 +1951,14 @@ dzn_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, attr_div->maxVertexAttribDivisor = UINT32_MAX; break; } +#ifdef _WIN32 + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: { + VkPhysicalDeviceExternalMemoryHostPropertiesEXT *host_props = + (VkPhysicalDeviceExternalMemoryHostPropertiesEXT *)ext; + host_props->minImportedHostPointerAlignment = 65536; + break; + } +#endif default: dzn_debug_ignored_stype(ext->sType); break; @@ -2231,6 +2278,11 @@ dzn_device_destroy(struct dzn_device *device, const VkAllocationCallbacks *pAllo if (device->dev12) ID3D12Device1_Release(device->dev12); +#if D3D12_SDK_VERSION >= 611 + if (device->dev13) + ID3D12Device1_Release(device->dev13); +#endif + vk_device_finish(&device->vk); vk_free2(&instance->vk.alloc, pAllocator, device); } @@ -2332,6 +2384,13 @@ dzn_device_create(struct dzn_physical_device *pdev, ID3D12Device1_AddRef(device->dev12); } +#if D3D12_SDK_VERSION >= 611 + if (pdev->dev13) { + device->dev13 = pdev->dev13; + ID3D12Device1_AddRef(device->dev13); + } +#endif + ID3D12InfoQueue *info_queue; if (SUCCEEDED(ID3D12Device1_QueryInterface(device->dev, &IID_ID3D12InfoQueue, @@ -2534,7 +2593,7 @@ dzn_device_memory_destroy(struct dzn_device_memory *mem, struct dzn_device *device = container_of(mem->base.device, struct dzn_device, vk); - if (mem->map) + if (mem->map && mem->map_res) ID3D12Resource_Unmap(mem->map_res, 0, NULL); if (mem->map_res) @@ -2593,6 +2652,7 @@ dzn_device_memory_create(struct dzn_device *device, VkExternalMemoryHandleTypeFlags export_flags = 0; HANDLE import_handle = NULL; bool imported_from_d3d11 = false; + void *host_pointer = NULL; #ifdef _WIN32 const wchar_t *import_name = NULL; const VkExportMemoryWin32HandleInfoKHR *win32_export = NULL; @@ -2628,6 +2688,12 @@ dzn_device_memory_create(struct dzn_device *device, case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR: win32_export = (const VkExportMemoryWin32HandleInfoKHR *)ext; break; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT: { + const VkImportMemoryHostPointerInfoEXT *imp = + (const VkImportMemoryHostPointerInfoEXT *)ext; + host_pointer = imp->pHostPointer; + break; + } #else case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: { const VkImportMemoryFdInfoKHR *imp = @@ -2716,7 +2782,7 @@ dzn_device_memory_create(struct dzn_device *device, heap_desc.Properties = deduce_heap_properties_from_memory(pdevice, mem_type); if (export_flags) { heap_desc.Flags |= D3D12_HEAP_FLAG_SHARED; - assert(heap_desc.Properties.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE); + assert(host_pointer || heap_desc.Properties.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE); } VkResult error = VK_ERROR_OUT_OF_DEVICE_MEMORY; @@ -2732,7 +2798,31 @@ dzn_device_memory_create(struct dzn_device *device, } #endif - if (import_handle) { + if (host_pointer) { + error = VK_ERROR_INVALID_EXTERNAL_HANDLE; + +#if defined(_WIN32) && D3D12_SDK_VERSION >= 611 + if (!device->dev13) + goto cleanup; + + if (FAILED(ID3D12Device13_OpenExistingHeapFromAddress1(device->dev13, host_pointer, heap_desc.SizeInBytes, &IID_ID3D12Heap, &mem->heap))) + goto cleanup; + + D3D12_HEAP_DESC desc = dzn_ID3D12Heap_GetDesc(mem->heap); + if (desc.Properties.Type != D3D12_HEAP_TYPE_CUSTOM) + desc.Properties = dzn_ID3D12Device4_GetCustomHeapProperties(device->dev, 0, desc.Properties.Type); + + if ((heap_desc.Flags & ~desc.Flags) || + desc.Properties.CPUPageProperty != heap_desc.Properties.CPUPageProperty || + desc.Properties.MemoryPoolPreference != heap_desc.Properties.MemoryPoolPreference) + goto cleanup; + + mem->map = host_pointer; + mem->res_flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER; +#else + goto cleanup; +#endif + } else if (import_handle) { error = VK_ERROR_INVALID_EXTERNAL_HANDLE; if (image || buffer) { if (FAILED(ID3D12Device_OpenSharedHandle(device->dev, import_handle, &IID_ID3D12Resource, (void **)&mem->dedicated_res))) @@ -2830,7 +2920,8 @@ dzn_device_memory_create(struct dzn_device *device, } if ((mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && - !(heap_desc.Flags & D3D12_HEAP_FLAG_DENY_BUFFERS)){ + !(heap_desc.Flags & D3D12_HEAP_FLAG_DENY_BUFFERS) && + !mem->map){ assert(!image); if (buffer) { mem->map_res = mem->dedicated_res; @@ -2920,6 +3011,11 @@ dzn_MapMemory(VkDevice _device, return VK_SUCCESS; } + if (mem->map && !mem->map_res) { + *ppData = ((uint8_t *)mem->map) + offset; + return VK_SUCCESS; + } + if (size == VK_WHOLE_SIZE) size = mem->size - offset; @@ -2958,7 +3054,9 @@ dzn_UnmapMemory(VkDevice _device, if (mem == NULL) return; - assert(mem->map_res); + if (!mem->map_res) + return; + ID3D12Resource_Unmap(mem->map_res, 0, NULL); mem->map = NULL; @@ -3273,6 +3371,8 @@ dzn_BindBufferMemory2(VkDevice _device, buffer->res = mem->dedicated_res; ID3D12Resource_AddRef(buffer->res); } else { + D3D12_RESOURCE_DESC desc = buffer->desc; + desc.Flags |= mem->res_flags; if (FAILED(ID3D12Device1_CreatePlacedResource(device->dev, mem->heap, pBindInfos[i].memoryOffset, &buffer->desc, @@ -3805,3 +3905,35 @@ cleanup: ID3D12Heap_Release(heap); return result; } + +#if defined(_WIN32) && D3D12_SDK_VERSION >= 611 +VKAPI_ATTR VkResult VKAPI_CALL +dzn_GetMemoryHostPointerPropertiesEXT(VkDevice _device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void *pHostPointer, + VkMemoryHostPointerPropertiesEXT *pMemoryHostPointerProperties) +{ + VK_FROM_HANDLE(dzn_device, device, _device); + + if (!device->dev13) + return VK_ERROR_FEATURE_NOT_PRESENT; + + ID3D12Heap *heap; + if (FAILED(ID3D12Device13_OpenExistingHeapFromAddress1(device->dev13, pHostPointer, 1, &IID_ID3D12Heap, &heap))) + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + + struct dzn_physical_device *pdev = container_of(device->vk.physical, struct dzn_physical_device, vk); + D3D12_HEAP_DESC heap_desc = dzn_ID3D12Heap_GetDesc(heap); + for (uint32_t i = 0; i < pdev->memory.memoryTypeCount; ++i) { + const VkMemoryType *mem_type = &pdev->memory.memoryTypes[i]; + D3D12_HEAP_PROPERTIES required_props = deduce_heap_properties_from_memory(pdev, mem_type); + if (heap_desc.Properties.CPUPageProperty != required_props.CPUPageProperty || + heap_desc.Properties.MemoryPoolPreference != required_props.MemoryPoolPreference) + continue; + + pMemoryHostPointerProperties->memoryTypeBits |= (1 << i); + } + ID3D12Heap_Release(heap); + return VK_SUCCESS; +} +#endif diff --git a/src/microsoft/vulkan/dzn_image.c b/src/microsoft/vulkan/dzn_image.c index 407696c..c948e59 100644 --- a/src/microsoft/vulkan/dzn_image.c +++ b/src/microsoft/vulkan/dzn_image.c @@ -843,7 +843,7 @@ dzn_BindImageMemory2(VkDevice dev, .Format = image->desc.Format, .SampleDesc = image->desc.SampleDesc, .Layout = image->desc.Layout, - .Flags = image->desc.Flags, + .Flags = image->desc.Flags | mem->res_flags, }; hres = ID3D12Device10_CreatePlacedResource2(device->dev10, mem->heap, @@ -856,9 +856,11 @@ dzn_BindImageMemory2(VkDevice dev, &IID_ID3D12Resource, (void **)&image->res); } else { + D3D12_RESOURCE_DESC desc = image->desc; + desc.Flags |= mem->res_flags; hres = ID3D12Device1_CreatePlacedResource(device->dev, mem->heap, bind_info->memoryOffset, - &image->desc, + &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h index f3bf3d9..e879699 100644 --- a/src/microsoft/vulkan/dzn_private.h +++ b/src/microsoft/vulkan/dzn_private.h @@ -202,6 +202,9 @@ struct dzn_physical_device { ID3D12Device10 *dev10; ID3D12Device11 *dev11; ID3D12Device12 *dev12; +#if D3D12_SDK_VERSION >= 611 + ID3D12Device13 *dev13; +#endif D3D_FEATURE_LEVEL feature_level; D3D_SHADER_MODEL shader_model; D3D_ROOT_SIGNATURE_VERSION root_sig_version; @@ -287,6 +290,9 @@ struct dzn_device { ID3D12Device10 *dev10; ID3D12Device11 *dev11; ID3D12Device12 *dev12; +#if D3D12_SDK_VERSION >= 611 + ID3D12Device13 *dev13; +#endif ID3D12DeviceConfiguration *dev_config; struct dzn_meta_indirect_draw indirect_draws[DZN_NUM_INDIRECT_DRAW_TYPES]; @@ -345,6 +351,9 @@ struct dzn_device_memory { /* If the resource is exportable, this is the pre-created handle for that */ HANDLE export_handle; + + /* These flags need to be added into all resources created on this heap */ + D3D12_RESOURCE_FLAGS res_flags; }; enum dzn_cmd_bindpoint_dirty { -- 2.7.4