diff --git a/src/dxgi/dxgi_adapter.cpp b/src/dxgi/dxgi_adapter.cpp index e067ad05..bdff44d4 100644 --- a/src/dxgi/dxgi_adapter.cpp +++ b/src/dxgi/dxgi_adapter.cpp @@ -24,6 +24,7 @@ namespace dxvk { HRESULT DxgiAdapter::QueryInterface( REFIID riid, void **ppvObject) { + COM_QUERY_IFACE(riid, ppvObject, IDXVKAdapter); COM_QUERY_IFACE(riid, ppvObject, IDXGIAdapter); Logger::warn("DxgiAdapter::QueryInterface: Unknown interface query"); @@ -102,4 +103,9 @@ namespace dxvk { return S_OK; } + + Rc DxgiAdapter::GetDXVKAdapter() { + return m_adapter; + } + } diff --git a/src/dxgi/dxgi_adapter.h b/src/dxgi/dxgi_adapter.h index 972ecd6f..cd33ccde 100644 --- a/src/dxgi/dxgi_adapter.h +++ b/src/dxgi/dxgi_adapter.h @@ -5,6 +5,7 @@ #include +#include "dxgi_interfaces.h" #include "dxgi_object.h" namespace dxvk { @@ -12,7 +13,7 @@ namespace dxvk { class DxgiFactory; class DxgiOutput; - class DxgiAdapter : public DxgiObject { + class DxgiAdapter : public DxgiObject { public: @@ -40,10 +41,12 @@ namespace dxvk { HRESULT GetDesc( DXGI_ADAPTER_DESC *pDesc) final; + Rc GetDXVKAdapter() final; + private: - DxgiFactory* m_factory; - Rc m_adapter; + Com m_factory; + Rc m_adapter; }; diff --git a/src/dxgi/dxgi_device.cpp b/src/dxgi/dxgi_device.cpp new file mode 100644 index 00000000..d6bd5c8a --- /dev/null +++ b/src/dxgi/dxgi_device.cpp @@ -0,0 +1,106 @@ +#include "dxgi_device.h" +#include "dxgi_factory.h" + +namespace dxvk { + + DxgiDevice::DxgiDevice(IDXVKAdapter* adapter) + : m_adapter(adapter) { + TRACE(this, adapter); + m_device = m_adapter->GetDXVKAdapter()->createDevice(); + } + + + DxgiDevice::~DxgiDevice() { + TRACE(this); + } + + + HRESULT DxgiDevice::QueryInterface(REFIID riid, void** ppvObject) { + COM_QUERY_IFACE(riid, ppvObject, IDXVKDevice); + COM_QUERY_IFACE(riid, ppvObject, IDXGIDevice); + + if (m_layer != nullptr) + return m_layer->QueryInterface(riid, ppvObject); + + Logger::warn("DxgiDevice::QueryInterface: Unknown interface query"); + return E_NOINTERFACE; + } + + + HRESULT DxgiDevice::GetParent(REFIID riid, void** ppParent) { + return m_adapter->QueryInterface(riid, ppParent); + } + + + HRESULT DxgiDevice::CreateSurface( + const DXGI_SURFACE_DESC* pDesc, + UINT NumSurfaces, + DXGI_USAGE Usage, + const DXGI_SHARED_RESOURCE* pSharedResource, + IDXGISurface** ppSurface) { + Logger::err("DxgiDevice::CreateSurface: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT DxgiDevice::GetAdapter( + IDXGIAdapter** pAdapter) { + *pAdapter = static_cast(m_adapter.ref()); + return S_OK; + } + + + HRESULT DxgiDevice::GetGPUThreadPriority( + INT* pPriority) { + *pPriority = 0; + return S_OK; + } + + + HRESULT DxgiDevice::QueryResourceResidency( + IUnknown* const* ppResources, + DXGI_RESIDENCY* pResidencyStatus, + UINT NumResources) { + Logger::err("DxgiDevice::QueryResourceResidency: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT DxgiDevice::SetGPUThreadPriority( + INT Priority) { + if (Priority < -7 || Priority > 7) + return E_INVALIDARG; + + Logger::err("DxgiDevice::SetGPUThreadPriority: Ignoring"); + return S_OK; + } + + + void DxgiDevice::SetDeviceLayer(IUnknown* layer) { + TRACE(this, layer); + m_layer = layer; + } + + + Rc DxgiDevice::GetDXVKDevice() { + return m_device; + } + +} + + +extern "C" { + + DLLEXPORT HRESULT __stdcall DXGICreateDXVKDevice( + IDXVKAdapter* pAdapter, + IDXVKDevice** ppDevice) { + try { + *ppDevice = dxvk::ref(new dxvk::DxgiDevice(pAdapter)); + return S_OK; + } catch (const dxvk::DxvkError& e) { + dxvk::Logger::err(e.message()); + return DXGI_ERROR_UNSUPPORTED; + } + } + +} \ No newline at end of file diff --git a/src/dxgi/dxgi_device.h b/src/dxgi/dxgi_device.h new file mode 100644 index 00000000..b4d5203f --- /dev/null +++ b/src/dxgi/dxgi_device.h @@ -0,0 +1,71 @@ +#pragma once + +#include + +#include "dxgi_adapter.h" +#include "dxgi_interfaces.h" + +namespace dxvk { + + class DxgiFactory; + + class DxgiDevice : public DxgiObject { + + public: + + DxgiDevice(IDXVKAdapter* adapter); + ~DxgiDevice(); + + HRESULT QueryInterface( + REFIID riid, + void **ppvObject) final; + + HRESULT GetParent( + REFIID riid, + void **ppParent) final; + + HRESULT CreateSurface( + const DXGI_SURFACE_DESC* pDesc, + UINT NumSurfaces, + DXGI_USAGE Usage, + const DXGI_SHARED_RESOURCE* pSharedResource, + IDXGISurface** ppSurface) final; + + HRESULT GetAdapter( + IDXGIAdapter** pAdapter) final; + + HRESULT GetGPUThreadPriority( + INT* pPriority) final; + + HRESULT QueryResourceResidency( + IUnknown* const* ppResources, + DXGI_RESIDENCY* pResidencyStatus, + UINT NumResources) final; + + HRESULT SetGPUThreadPriority( + INT Priority) final; + + void SetDeviceLayer( + IUnknown* layer) final; + + Rc GetDXVKDevice() final; + + private: + + Com m_adapter; + Rc m_device; + + IUnknown* m_layer = nullptr; + + }; + +} + + +extern "C" { + + DLLEXPORT HRESULT __stdcall DXGICreateDXVKDevice( + IDXVKAdapter* pAdapter, + IDXVKDevice** ppDevice); + +} \ No newline at end of file diff --git a/src/dxgi/dxgi_factory.cpp b/src/dxgi/dxgi_factory.cpp index 82d92de5..0beb1a31 100644 --- a/src/dxgi/dxgi_factory.cpp +++ b/src/dxgi/dxgi_factory.cpp @@ -4,12 +4,9 @@ namespace dxvk { DxgiFactory::DxgiFactory() - : m_instance(new DxvkInstance()) { + : m_instance(new DxvkInstance()), + m_adapters(m_instance->enumAdapters()) { TRACE(this); - - auto adapters = m_instance->enumAdapters(); - for (auto a : adapters) - m_adapters.push_back(new DxgiAdapter(this, a)); } @@ -64,7 +61,8 @@ namespace dxvk { if (Adapter >= m_adapters.size()) return DXGI_ERROR_NOT_FOUND; - *ppAdapter = m_adapters.at(Adapter).ref(); + *ppAdapter = ref(new DxgiAdapter( + this, m_adapters.at(Adapter))); return S_OK; } diff --git a/src/dxgi/dxgi_factory.h b/src/dxgi/dxgi_factory.h index 6903dc45..7744469e 100644 --- a/src/dxgi/dxgi_factory.h +++ b/src/dxgi/dxgi_factory.h @@ -46,7 +46,7 @@ namespace dxvk { private: Rc m_instance; - std::vector> m_adapters; + std::vector> m_adapters; HWND m_associatedWindow = nullptr; diff --git a/src/dxgi/dxgi_include.h b/src/dxgi/dxgi_include.h index 5fab09b3..ebdeba6a 100644 --- a/src/dxgi/dxgi_include.h +++ b/src/dxgi/dxgi_include.h @@ -9,6 +9,9 @@ #include "../util/log/log.h" #include "../util/log/log_debug.h" +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" + #include "../util/util_enum.h" #include "../util/util_error.h" #include "../util/util_string.h" diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h new file mode 100644 index 00000000..3e8d9291 --- /dev/null +++ b/src/dxgi/dxgi_interfaces.h @@ -0,0 +1,45 @@ +#pragma once + +#include "dxgi_include.h" + +namespace dxvk { + class DxgiAdapter; + class DxvkAdapter; + class DxvkDevice; +} + +/** + * \brief DXVK adapter + * + * The implementation of \c IDXGIAdapter holds a + * \ref DxvkAdapter which can be retrieved using + * this interface. + */ +MIDL_INTERFACE("907bf281-ea3c-43b4-a8e4-9f231107b4ff") +IDXVKAdapter : public IDXGIAdapter { + static const GUID guid; + + virtual dxvk::Rc GetDXVKAdapter() = 0; +}; + + +/** + * \brief DXVK device + * + * The implementation of \c IDXGIDevice stores a + * \ref DxvkDevice which can be retrieved using + * this interface. + */ +MIDL_INTERFACE("7a622cf6-627a-46b2-b52f-360ef3da831c") +IDXVKDevice : public IDXGIDevice { + static const GUID guid; + + virtual void SetDeviceLayer( + IUnknown* layer) = 0; + + virtual dxvk::Rc GetDXVKDevice() = 0; +}; + + +template<> inline GUID const& __mingw_uuidof() { return IDXVKAdapter::guid; } +template<> inline GUID const& __mingw_uuidof () { return IDXVKDevice ::guid; } diff --git a/src/dxgi/dxgi_object.h b/src/dxgi/dxgi_object.h index e14a32e6..c51b58ad 100644 --- a/src/dxgi/dxgi_object.h +++ b/src/dxgi/dxgi_object.h @@ -6,8 +6,8 @@ namespace dxvk { - template - class DxgiObject : public ComObject { + template + class DxgiObject : public ComObject { public: diff --git a/src/dxgi/dxgi_output.h b/src/dxgi/dxgi_output.h index 0abf323a..e92a96f5 100644 --- a/src/dxgi/dxgi_output.h +++ b/src/dxgi/dxgi_output.h @@ -66,8 +66,8 @@ namespace dxvk { private: - DxgiAdapter* m_adapter; - UINT m_display; + Com m_adapter; + UINT m_display; }; diff --git a/src/dxgi/meson.build b/src/dxgi/meson.build index 0bee8ffe..fb8590cd 100644 --- a/src/dxgi/meson.build +++ b/src/dxgi/meson.build @@ -1,5 +1,6 @@ dxgi_src = [ 'dxgi_adapter.cpp', + 'dxgi_device.cpp', 'dxgi_factory.cpp', 'dxgi_main.cpp', 'dxgi_output.cpp', @@ -7,9 +8,11 @@ dxgi_src = [ ] dxgi_dll = shared_library('dxgi', dxgi_src, + name_prefix : '', link_with : [ util_lib ], dependencies : [ dxvk_dep ], - include_directories : dxvk_include_path) + include_directories : dxvk_include_path, + install : true) dxgi_dep = declare_dependency( link_with : [ dxgi_dll ], diff --git a/src/util/com/com_guid.cpp b/src/util/com/com_guid.cpp index 2b81f756..e308a8e8 100644 --- a/src/util/com/com_guid.cpp +++ b/src/util/com/com_guid.cpp @@ -1,5 +1,10 @@ #include "com_guid.h" +#include "../../dxgi/dxgi_interfaces.h" + +const GUID IDXVKAdapter::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}}; +const GUID IDXVKDevice::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}}; + std::ostream& operator << (std::ostream& os, REFIID guid) { os.width(8); os << std::hex << guid.Data1 << '-'; diff --git a/src/util/com/com_object.h b/src/util/com/com_object.h index 4b6b7d1d..9a6e7958 100644 --- a/src/util/com/com_object.h +++ b/src/util/com/com_object.h @@ -5,11 +5,13 @@ #include "com_include.h" #define COM_QUERY_IFACE(riid, ppvObject, Iface) \ - if (riid == __uuidof(Iface)) { \ - this->AddRef(); \ - *ppvObject = static_cast(this); \ - return S_OK; \ - } + do { \ + if (riid == __uuidof(Iface)) { \ + this->AddRef(); \ + *ppvObject = static_cast(this); \ + return S_OK; \ + } \ + } while (0) namespace dxvk {