From 509371f893c3260993fd35771a792070b6516fe3 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 3 Dec 2024 23:03:21 -0800 Subject: [PATCH] [d3d9] Add interop GetDeviceCreateInfo function --- src/d3d9/d3d9_interfaces.h | 42 +++++++++++++++++++++++++++ src/d3d9/d3d9_interop.cpp | 58 +++++++++++++++++++++++++++++++++++++ src/d3d9/d3d9_interop.h | 4 +++ src/dxvk/dxvk_device_info.h | 3 ++ 4 files changed, 107 insertions(+) diff --git a/src/d3d9/d3d9_interfaces.h b/src/d3d9/d3d9_interfaces.h index 1d8bdb1e106..0e0cdfb99c0 100644 --- a/src/d3d9/d3d9_interfaces.h +++ b/src/d3d9/d3d9_interfaces.h @@ -3,8 +3,40 @@ #include "d3d9_include.h" #include "../vulkan/vulkan_loader.h" +#include "../dxvk/dxvk_device_info.h" + using D3D9VkQueueLockCallback = void(bool); +/** + * \brief Device create info + */ +struct D3D9VkDeviceCreateInfo { + VkDeviceCreateInfo info; + dxvk::DxvkDeviceFeatures features; + uint32_t graphicsQueueFamily; + uint32_t transferQueueFamily; + uint32_t sparseQueueFamily; + VkDeviceQueueCreateInfo* pQueueCreateInfos; + const char** ppEnabledExtensionNames; + + D3D9VkDeviceCreateInfo() + : info() + , features() + , graphicsQueueFamily(VK_QUEUE_FAMILY_IGNORED) + , transferQueueFamily(VK_QUEUE_FAMILY_IGNORED) + , sparseQueueFamily(VK_QUEUE_FAMILY_IGNORED) + , pQueueCreateInfos(nullptr) + , ppEnabledExtensionNames(nullptr) { + } + + ~D3D9VkDeviceCreateInfo() { + if (pQueueCreateInfos != nullptr) + delete[] pQueueCreateInfos; + if (ppEnabledExtensionNames != nullptr) + delete[] ppEnabledExtensionNames; + } +}; + /** * \brief Device import info */ @@ -60,6 +92,16 @@ ID3D9VkInteropInterface : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetInstanceExtensions( UINT* pExtensionCount, const char** ppExtensions) = 0; + + /** + * \brief Gets the device creation info for a D3D9 adapter + * + * \param [in] Adapter Adapter ordinal + * \param [out] pCreateInfo Valid pointer to a D3D9VkDeviceCreateInfo struct + */ + virtual HRESULT STDMETHODCALLTYPE GetDeviceCreateInfo( + UINT Adapter, + D3D9VkDeviceCreateInfo* pCreateInfo) = 0; /** * \brief Create a D3D9 device for an existing Vulkan device diff --git a/src/d3d9/d3d9_interop.cpp b/src/d3d9/d3d9_interop.cpp index dee364ba2f6..926a1e730c8 100644 --- a/src/d3d9/d3d9_interop.cpp +++ b/src/d3d9/d3d9_interop.cpp @@ -86,6 +86,64 @@ namespace dxvk { } } + HRESULT STDMETHODCALLTYPE D3D9VkInteropInterface::GetDeviceCreateInfo( + UINT Adapter, + D3D9VkDeviceCreateInfo* pCreateInfo) { + if (unlikely(pCreateInfo == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(pCreateInfo->pQueueCreateInfos != nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(pCreateInfo->ppEnabledExtensionNames != nullptr)) + return D3DERR_INVALIDCALL; + + auto* adapter = m_interface->GetAdapter(Adapter); + if (unlikely(adapter == nullptr)) + return D3DERR_INVALIDCALL; + + auto dxvkAdapter = adapter->GetDXVKAdapter(); + + pCreateInfo->features = D3D9DeviceEx::GetDeviceFeatures(dxvkAdapter); + + DxvkDeviceCreateExtInfo extInfo; + DxvkDeviceCreateQueueInfo queueInfo; + bool success = dxvkAdapter->getDeviceCreateInfo( + m_interface->GetInstance(), + pCreateInfo->info, + pCreateInfo->features, + extInfo, + queueInfo); + + if (!success) + return D3DERR_INVALIDCALL; + + // Queue family indices + pCreateInfo->graphicsQueueFamily = queueInfo.queueFamilies.graphics; + pCreateInfo->transferQueueFamily = queueInfo.queueFamilies.transfer; + pCreateInfo->sparseQueueFamily = queueInfo.queueFamilies.sparse; + + // Queue create infos + const size_t queueCount = queueInfo.queueInfos.size(); + pCreateInfo->pQueueCreateInfos = queueCount ? new VkDeviceQueueCreateInfo[queueCount] : nullptr; + for (int i = 0; i < queueCount; i++) { + pCreateInfo->pQueueCreateInfos[i] = queueInfo.queueInfos[i]; + } + pCreateInfo->info.pQueueCreateInfos = pCreateInfo->pQueueCreateInfos; + pCreateInfo->info.queueCreateInfoCount = queueCount; + + // Extension names + const uint32_t extCount = extInfo.extensionNameList.count(); + pCreateInfo->ppEnabledExtensionNames = extCount > 0 ? new const char*[extCount] : nullptr; + for (uint32_t i = 0; i < extCount; i++) { + pCreateInfo->ppEnabledExtensionNames[i] = extInfo.extensionNameList.name(i); + } + pCreateInfo->info.ppEnabledExtensionNames = pCreateInfo->ppEnabledExtensionNames; + pCreateInfo->info.enabledExtensionCount = extCount; + + return D3D_OK; + } + HRESULT STDMETHODCALLTYPE D3D9VkInteropInterface::ImportDevice( UINT Adapter, D3DDEVTYPE DeviceType, diff --git a/src/d3d9/d3d9_interop.h b/src/d3d9/d3d9_interop.h index 8db049a3cc9..2a15d0f5999 100644 --- a/src/d3d9/d3d9_interop.h +++ b/src/d3d9/d3d9_interop.h @@ -38,6 +38,10 @@ namespace dxvk { UINT* pExtensionCount, const char** ppExtensions); + HRESULT STDMETHODCALLTYPE GetDeviceCreateInfo( + UINT Adapter, + D3D9VkDeviceCreateInfo* pCreateInfo); + HRESULT STDMETHODCALLTYPE ImportDevice( UINT Adapter, D3DDEVTYPE DeviceType, diff --git a/src/dxvk/dxvk_device_info.h b/src/dxvk/dxvk_device_info.h index 87f444a9d66..1ace4c5bbe8 100644 --- a/src/dxvk/dxvk_device_info.h +++ b/src/dxvk/dxvk_device_info.h @@ -38,6 +38,9 @@ namespace dxvk { * Stores core features and extension-specific features. * If the respective extensions are not available, the * extended features will be marked as unsupported. + * + * NOTE: This struct is exposed by interop interfaces, please add + * new fields at the end of the struct to maintain compatibility. */ struct DxvkDeviceFeatures { VkPhysicalDeviceFeatures2 core;