diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 684593a1..4fe92bff 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -20,93 +20,18 @@ namespace dxvk { - D3D11DeviceContainer::D3D11DeviceContainer() { - - } - - - D3D11DeviceContainer::~D3D11DeviceContainer() { - delete m_d3d11VkInterop; - delete m_d3d11Presenter; - delete m_d3d11Device; - delete m_dxgiDevice; - } - - - HRESULT STDMETHODCALLTYPE D3D11DeviceContainer::QueryInterface(REFIID riid, void** ppvObject) { - *ppvObject = nullptr; - - if (riid == __uuidof(IUnknown) - || riid == __uuidof(IDXGIObject)) { - *ppvObject = ref(this); - return S_OK; - } - - if (riid == __uuidof(IDXGIDevice) - || riid == __uuidof(IDXGIDevice1) - || riid == __uuidof(IDXGIDevice2) - || riid == __uuidof(IDXGIDevice3) - || riid == __uuidof(IDXGIVkDevice)) { - *ppvObject = ref(m_dxgiDevice); - return S_OK; - } - - if (riid == __uuidof(IDXGIVkInteropDevice)) { - *ppvObject = ref(m_d3d11VkInterop); - return S_OK; - } - - if (riid == __uuidof(ID3D10Device) - || riid == __uuidof(ID3D10Device1)) { - *ppvObject = ref(m_d3d11Device->GetD3D10Interface()); - return S_OK; - } - - if (riid == __uuidof(ID3D11Device) - || riid == __uuidof(ID3D11Device1)) { - *ppvObject = ref(m_d3d11Device); - return S_OK; - } - - if (riid == __uuidof(IDXGIVkPresentDevice)) { - *ppvObject = ref(m_d3d11Presenter); - return S_OK; - } + constexpr uint32_t D3D11DXGIDevice::DefaultFrameLatency; + - if (riid == __uuidof(ID3D10Multithread)) { - *ppvObject = ref(m_d3d11Device->GetD3D10Multithread()); - return S_OK; - } - - if (riid == __uuidof(ID3D11Debug)) - return E_NOINTERFACE; - - // Undocumented interfaces that are queried by some games - if (riid == GUID{0xd56e2a4c,0x5127,0x8437,{0x65,0x8a,0x98,0xc5,0xbb,0x78,0x94,0x98}}) - return E_NOINTERFACE; - - Logger::warn("D3D11DeviceContainer::QueryInterface: Unknown interface query"); - Logger::warn(str::format(riid)); - return E_NOINTERFACE; - } - - HRESULT STDMETHODCALLTYPE D3D11DeviceContainer::GetParent( - REFIID riid, - void** ppParent) { - return m_dxgiDevice->GetParent(riid, ppParent); - } - - D3D11Device::D3D11Device( - IDXGIObject* pContainer, - IDXGIVkDevice* pDxgiDevice, + D3D11DXGIDevice* pContainer, D3D_FEATURE_LEVEL FeatureLevel, UINT FeatureFlags) : m_container (pContainer), m_featureLevel (FeatureLevel), m_featureFlags (FeatureFlags), - m_dxvkDevice (pDxgiDevice->GetDXVKDevice()), + m_dxvkDevice (pContainer->GetDXVKDevice()), m_dxvkAdapter (m_dxvkDevice->adapter()), m_d3d11Formats (m_dxvkAdapter), m_d3d11Options (m_dxvkAdapter->instance()->config()), @@ -1741,4 +1666,222 @@ namespace dxvk { : D3D_FEATURE_LEVEL_11_1; } + + + + D3D11DXGIDevice::D3D11DXGIDevice( + IDXGIAdapter* pAdapter, + DxvkAdapter* pDxvkAdapter, + D3D_FEATURE_LEVEL FeatureLevel, + UINT FeatureFlags) + : m_dxgiAdapter (pAdapter), + m_dxvkAdapter (pDxvkAdapter), + m_dxvkDevice (CreateDevice(FeatureLevel)), + m_d3d11Device (this, FeatureLevel, FeatureFlags), + m_d3d11Presenter(this, &m_d3d11Device), + m_d3d11Interop (this, &m_d3d11Device) { + for (uint32_t i = 0; i < m_frameEvents.size(); i++) + m_frameEvents[i] = new DxvkEvent(); + } + + + D3D11DXGIDevice::~D3D11DXGIDevice() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::QueryInterface(REFIID riid, void** ppvObject) { + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIDevice) + || riid == __uuidof(IDXGIDevice1) + || riid == __uuidof(IDXGIDevice2) + || riid == __uuidof(IDXGIDevice3)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(IDXGIVkInteropDevice)) { + *ppvObject = ref(&m_d3d11Interop); + return S_OK; + } + + if (riid == __uuidof(ID3D10Device) + || riid == __uuidof(ID3D10Device1)) { + *ppvObject = ref(m_d3d11Device.GetD3D10Interface()); + return S_OK; + } + + if (riid == __uuidof(ID3D11Device) + || riid == __uuidof(ID3D11Device1)) { + *ppvObject = ref(&m_d3d11Device); + return S_OK; + } + + if (riid == __uuidof(IDXGIVkPresentDevice)) { + *ppvObject = ref(&m_d3d11Presenter); + return S_OK; + } + + if (riid == __uuidof(ID3D10Multithread)) { + *ppvObject = ref(m_d3d11Device.GetD3D10Multithread()); + return S_OK; + } + + if (riid == __uuidof(ID3D11Debug)) + return E_NOINTERFACE; + + // Undocumented interfaces that are queried by some games + if (riid == GUID{0xd56e2a4c,0x5127,0x8437,{0x65,0x8a,0x98,0xc5,0xbb,0x78,0x94,0x98}}) + return E_NOINTERFACE; + + Logger::warn("D3D11DXGIDevice::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetParent( + REFIID riid, + void** ppParent) { + return m_dxgiAdapter->QueryInterface(riid, ppParent); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::CreateSurface( + const DXGI_SURFACE_DESC* pDesc, + UINT NumSurfaces, + DXGI_USAGE Usage, + const DXGI_SHARED_RESOURCE* pSharedResource, + IDXGISurface** ppSurface) { + InitReturnPtr(ppSurface); + + Logger::err("D3D11DXGIDevice::CreateSurface: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetAdapter( + IDXGIAdapter** pAdapter) { + if (pAdapter == nullptr) + return DXGI_ERROR_INVALID_CALL; + + *pAdapter = m_dxgiAdapter.ref(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetGPUThreadPriority( + INT* pPriority) { + *pPriority = 0; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::QueryResourceResidency( + IUnknown* const* ppResources, + DXGI_RESIDENCY* pResidencyStatus, + UINT NumResources) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11DXGIDevice::QueryResourceResidency: Stub"); + + if (!ppResources || !pResidencyStatus) + return E_INVALIDARG; + + for (uint32_t i = 0; i < NumResources; i++) + pResidencyStatus[i] = DXGI_RESIDENCY_FULLY_RESIDENT; + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::SetGPUThreadPriority( + INT Priority) { + if (Priority < -7 || Priority > 7) + return E_INVALIDARG; + + Logger::err("DXGI: SetGPUThreadPriority: Ignoring"); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetMaximumFrameLatency( + UINT* pMaxLatency) { + *pMaxLatency = m_frameLatency; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::SetMaximumFrameLatency( + UINT MaxLatency) { + if (MaxLatency == 0) + MaxLatency = DefaultFrameLatency; + + if (MaxLatency > m_frameEvents.size()) + MaxLatency = m_frameEvents.size(); + + m_frameLatency = MaxLatency; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::OfferResources( + UINT NumResources, + IDXGIResource* const* ppResources, + DXGI_OFFER_RESOURCE_PRIORITY Priority) { + + Logger::err("D3D11DXGIDevice::OfferResources: Not implemented"); + return DXGI_ERROR_UNSUPPORTED; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::ReclaimResources( + UINT NumResources, + IDXGIResource* const* ppResources, + BOOL* pDiscarded) { + Logger::err("D3D11DXGIDevice::ReclaimResources: Not implemented"); + return DXGI_ERROR_UNSUPPORTED; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) { + Logger::err("D3D11DXGIDevice::EnqueueSetEvent: Not implemented"); + return DXGI_ERROR_UNSUPPORTED; + } + + + void STDMETHODCALLTYPE D3D11DXGIDevice::Trim() { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11DXGIDevice::Trim: Stub"); + } + + + Rc STDMETHODCALLTYPE D3D11DXGIDevice::GetFrameSyncEvent() { + uint32_t frameLatency = m_frameLatency; + + if (m_frameLatencyCap != 0 + && m_frameLatencyCap <= frameLatency) + frameLatency = m_frameLatencyCap; + + uint32_t frameId = m_frameId++ % frameLatency; + return m_frameEvents[frameId]; + } + + + Rc STDMETHODCALLTYPE D3D11DXGIDevice::GetDXVKDevice() { + return m_dxvkDevice; + } + + + Rc D3D11DXGIDevice::CreateDevice(D3D_FEATURE_LEVEL FeatureLevel) { + DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(m_dxvkAdapter, FeatureLevel); + return m_dxvkAdapter->createDevice(deviceFeatures); + } + } diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 4049e6b2..2d9e3f78 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -16,7 +16,9 @@ #include "d3d11_counter_buffer.h" #include "d3d11_initializer.h" #include "d3d11_interfaces.h" +#include "d3d11_interop.h" #include "d3d11_options.h" +#include "d3d11_present.h" #include "d3d11_shader.h" #include "d3d11_state.h" #include "d3d11_util.h" @@ -29,43 +31,13 @@ namespace dxvk { class D3D11CommonTexture; class D3D11Counter; class D3D11DeviceContext; + class D3D11DXGIDevice; class D3D11ImmediateContext; class D3D11Predicate; - class D3D11PresentDevice; class D3D11Query; class D3D11Texture1D; class D3D11Texture2D; class D3D11Texture3D; - class D3D11VkInterop; - - /** - * \brief D3D11 device container - * - * Stores all the objects that contribute to the D3D11 - * device implementation, including the DXGI device. - */ - class D3D11DeviceContainer : public DxgiObject { - - public: - - D3D11DeviceContainer(); - ~D3D11DeviceContainer(); - - HRESULT STDMETHODCALLTYPE QueryInterface( - REFIID riid, - void** ppvObject); - - HRESULT STDMETHODCALLTYPE GetParent( - REFIID riid, - void** ppParent); - - IDXGIVkDevice* m_dxgiDevice = nullptr; - D3D11Device* m_d3d11Device = nullptr; - D3D11PresentDevice* m_d3d11Presenter = nullptr; - D3D11VkInterop* m_d3d11VkInterop = nullptr; - - }; - /** * \brief D3D11 device implementation @@ -79,10 +51,10 @@ namespace dxvk { public: D3D11Device( - IDXGIObject* pContainer, - IDXGIVkDevice* pDxgiDevice, + D3D11DXGIDevice* pContainer, D3D_FEATURE_LEVEL FeatureLevel, UINT FeatureFlags); + ~D3D11Device(); ULONG STDMETHODCALLTYPE AddRef(); @@ -418,4 +390,98 @@ namespace dxvk { }; + + /** + * \brief D3D11 device container + * + * Stores all the objects that contribute to the D3D11 + * device implementation, including the DXGI device. + */ + class D3D11DXGIDevice : public DxgiObject { + constexpr static uint32_t DefaultFrameLatency = 3; + public: + + D3D11DXGIDevice( + IDXGIAdapter* pAdapter, + DxvkAdapter* pDxvkAdapter, + D3D_FEATURE_LEVEL FeatureLevel, + UINT FeatureFlags); + + ~D3D11DXGIDevice(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent); + + HRESULT STDMETHODCALLTYPE CreateSurface( + const DXGI_SURFACE_DESC* pDesc, + UINT NumSurfaces, + DXGI_USAGE Usage, + const DXGI_SHARED_RESOURCE* pSharedResource, + IDXGISurface** ppSurface) final; + + HRESULT STDMETHODCALLTYPE GetAdapter( + IDXGIAdapter** pAdapter) final; + + HRESULT STDMETHODCALLTYPE GetGPUThreadPriority( + INT* pPriority) final; + + HRESULT STDMETHODCALLTYPE QueryResourceResidency( + IUnknown* const* ppResources, + DXGI_RESIDENCY* pResidencyStatus, + UINT NumResources) final; + + HRESULT STDMETHODCALLTYPE SetGPUThreadPriority( + INT Priority) final; + + HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency( + UINT* pMaxLatency) final; + + HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency( + UINT MaxLatency) final; + + HRESULT STDMETHODCALLTYPE OfferResources( + UINT NumResources, + IDXGIResource* const* ppResources, + DXGI_OFFER_RESOURCE_PRIORITY Priority) final; + + HRESULT STDMETHODCALLTYPE ReclaimResources( + UINT NumResources, + IDXGIResource* const* ppResources, + BOOL* pDiscarded) final; + + HRESULT STDMETHODCALLTYPE EnqueueSetEvent( + HANDLE hEvent) final; + + void STDMETHODCALLTYPE Trim() final; + + Rc STDMETHODCALLTYPE GetFrameSyncEvent(); + + Rc STDMETHODCALLTYPE GetDXVKDevice(); + + private: + + Com m_dxgiAdapter; + + Rc m_dxvkAdapter; + Rc m_dxvkDevice; + + D3D11Device m_d3d11Device; + D3D11PresentDevice m_d3d11Presenter; + D3D11VkInterop m_d3d11Interop; + + uint32_t m_frameLatencyCap = 0; + uint32_t m_frameLatency = DefaultFrameLatency; + uint32_t m_frameId = 0; + + std::array, 16> m_frameEvents; + + Rc CreateDevice(D3D_FEATURE_LEVEL FeatureLevel); + + }; + } diff --git a/src/d3d11/d3d11_main.cpp b/src/d3d11/d3d11_main.cpp index d693d0ae..d58cf6eb 100644 --- a/src/d3d11/d3d11_main.cpp +++ b/src/d3d11/d3d11_main.cpp @@ -47,7 +47,7 @@ extern "C" { // Find the highest feature level supported by the device. // This works because the feature level array is ordered. - const Rc adapter = dxvkAdapter->GetDXVKAdapter(); + Rc adapter = dxvkAdapter->GetDXVKAdapter(); UINT flId; for (flId = 0 ; flId < FeatureLevels; flId++) { @@ -67,25 +67,12 @@ extern "C" { try { Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", fl)); - Com container = new D3D11DeviceContainer(); + Com device = new D3D11DXGIDevice( + pAdapter, adapter.ptr(), fl, Flags); - const DxvkDeviceFeatures deviceFeatures - = D3D11Device::GetDeviceFeatures(adapter, fl); - - if (FAILED(dxvkAdapter->CreateDevice(container.ptr(), &deviceFeatures, &container->m_dxgiDevice))) { - Logger::err("D3D11CoreCreateDevice: Failed to create DXGI device"); - return E_FAIL; - } - - container->m_d3d11Device = new D3D11Device( - container.ptr(), container->m_dxgiDevice, fl, Flags); - container->m_d3d11Presenter = new D3D11PresentDevice( - container.ptr(), container->m_d3d11Device); - container->m_d3d11VkInterop = new D3D11VkInterop( - container.ptr(), container->m_d3d11Device); - - *ppDevice = ref(container->m_d3d11Device); - return S_OK; + return device->QueryInterface( + __uuidof(ID3D11Device), + reinterpret_cast(ppDevice)); } catch (const DxvkError& e) { Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device"); return E_FAIL; diff --git a/src/d3d11/d3d11_present.cpp b/src/d3d11/d3d11_present.cpp index 0f73eb38..14b6e4fa 100644 --- a/src/d3d11/d3d11_present.cpp +++ b/src/d3d11/d3d11_present.cpp @@ -4,9 +4,10 @@ namespace dxvk { D3D11PresentDevice::D3D11PresentDevice( - IDXGIObject* pContainer, - ID3D11Device* pDevice) - : m_container(pContainer), m_device(pDevice) { + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice) + : m_container (pContainer), + m_device (pDevice) { } @@ -39,7 +40,7 @@ namespace dxvk { try { *ppSwapChain = ref(new D3D11SwapChain( - static_cast(m_device), hWnd, pDesc)); + m_container, m_device, hWnd, pDesc)); return S_OK; } catch (const DxvkError& e) { Logger::err(e.message()); diff --git a/src/d3d11/d3d11_present.h b/src/d3d11/d3d11_present.h index d0b727ce..74272468 100644 --- a/src/d3d11/d3d11_present.h +++ b/src/d3d11/d3d11_present.h @@ -9,6 +9,7 @@ namespace dxvk { class D3D11Device; + class D3D11DXGIDevice; /** * \brief Present device @@ -21,8 +22,9 @@ namespace dxvk { public: D3D11PresentDevice( - IDXGIObject* pContainer, - ID3D11Device* pDevice); + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice); + ~D3D11PresentDevice(); ULONG STDMETHODCALLTYPE AddRef(); @@ -40,8 +42,8 @@ namespace dxvk { private: - IDXGIObject* m_container; - ID3D11Device* m_device; + D3D11DXGIDevice* m_container; + D3D11Device* m_device; }; diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index 2f56e61d..5a885f52 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -15,19 +15,16 @@ namespace dxvk { D3D11SwapChain::D3D11SwapChain( + D3D11DXGIDevice* pContainer, D3D11Device* pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc) - : m_parent (pDevice), - m_window (hWnd), - m_desc (*pDesc), - m_device (pDevice->GetDXVKDevice()), - m_context (m_device->createContext()) { - - if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIVkDevice), - reinterpret_cast(&m_dxgiDevice)))) - throw DxvkError("D3D11: Incompatible device for swap chain"); - + : m_dxgiDevice(pContainer), + m_parent (pDevice), + m_window (hWnd), + m_desc (*pDesc), + m_device (pDevice->GetDXVKDevice()), + m_context (m_device->createContext()) { if (!pDevice->GetOptions()->deferSurfaceCreation) CreatePresenter(); @@ -76,22 +73,14 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetAdapter( REFIID riid, void** ppvObject) { - Com dxgiDevice; - - HRESULT hr = GetDevice(__uuidof(IDXGIDevice), - reinterpret_cast(&dxgiDevice)); - - if (FAILED(hr)) - return hr; - - return dxgiDevice->GetParent(riid, ppvObject); + return m_dxgiDevice->GetParent(riid, ppvObject); } HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetDevice( REFIID riid, void** ppDevice) { - return m_parent->QueryInterface(riid, ppDevice); + return m_dxgiDevice->QueryInterface(riid, ppDevice); } diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h index a4d90573..f8989df3 100644 --- a/src/d3d11/d3d11_swapchain.h +++ b/src/d3d11/d3d11_swapchain.h @@ -7,6 +7,7 @@ namespace dxvk { class D3D11Device; + class D3D11DXGIDevice; /** * \brief Gamma control point @@ -24,15 +25,16 @@ namespace dxvk { public: D3D11SwapChain( - D3D11Device* pDevice, - HWND hWnd, - const DXGI_SWAP_CHAIN_DESC1* pDesc); + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc); ~D3D11SwapChain(); HRESULT STDMETHODCALLTYPE QueryInterface( - REFIID riid, - void** ppvObject); + REFIID riid, + void** ppvObject); HRESULT STDMETHODCALLTYPE GetDesc( DXGI_SWAP_CHAIN_DESC1* pDesc); @@ -76,7 +78,7 @@ namespace dxvk { GammaTex = 3, }; - Com m_dxgiDevice; + Com m_dxgiDevice; D3D11Device* m_parent; HWND m_window;