[d3d11] Move IDXGIDevice implementation to D3D11 module

Helps decouple the D3D11 module from the DXGI implementation. This
also allows us to clean up D3D11 device creation, which is much needed.

Based on zzhiyi/dxvk@fa441937f1

Co-authored-by: Zhiyi Zhang <zzhang@codeweavers.com>
This commit is contained in:
Philip Rebohle 2018-12-03 19:26:29 +01:00
parent de29174d42
commit c5deedef2d
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
7 changed files with 355 additions and 165 deletions

View File

@ -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<DxvkEvent> 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<DxvkDevice> STDMETHODCALLTYPE D3D11DXGIDevice::GetDXVKDevice() {
return m_dxvkDevice;
}
Rc<DxvkDevice> D3D11DXGIDevice::CreateDevice(D3D_FEATURE_LEVEL FeatureLevel) {
DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(m_dxvkAdapter, FeatureLevel);
return m_dxvkAdapter->createDevice(deviceFeatures);
}
}

View File

@ -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<IDXGIObject> {
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<IDXGIDevice3> {
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<DxvkEvent> STDMETHODCALLTYPE GetFrameSyncEvent();
Rc<DxvkDevice> STDMETHODCALLTYPE GetDXVKDevice();
private:
Com<IDXGIAdapter> m_dxgiAdapter;
Rc<DxvkAdapter> m_dxvkAdapter;
Rc<DxvkDevice> 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<Rc<DxvkEvent>, 16> m_frameEvents;
Rc<DxvkDevice> CreateDevice(D3D_FEATURE_LEVEL FeatureLevel);
};
}

View File

@ -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<DxvkAdapter> adapter = dxvkAdapter->GetDXVKAdapter();
Rc<DxvkAdapter> 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<D3D11DeviceContainer> container = new D3D11DeviceContainer();
Com<D3D11DXGIDevice> 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<void**>(ppDevice));
} catch (const DxvkError& e) {
Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device");
return E_FAIL;

View File

@ -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<D3D11Device*>(m_device), hWnd, pDesc));
m_container, m_device, hWnd, pDesc));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());

View File

@ -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;
};

View File

@ -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<void**>(&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<IDXGIDevice> dxgiDevice;
HRESULT hr = GetDevice(__uuidof(IDXGIDevice),
reinterpret_cast<void**>(&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);
}

View File

@ -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<IDXGIVkDevice> m_dxgiDevice;
Com<D3D11DXGIDevice> m_dxgiDevice;
D3D11Device* m_parent;
HWND m_window;