Add support for capturing programs using new D3D12 DLL selection API

* We also use it for replay when available instead of self-function-hooking
This commit is contained in:
baldurk
2024-05-02 18:10:57 +01:00
parent 2b0d898b34
commit 87a905b0e6
10 changed files with 767 additions and 113 deletions
+36 -20
View File
@@ -256,22 +256,46 @@ void BarrierSet::Unapply(ID3D12GraphicsCommandListX *list)
RDCASSERT(newToOldBarriers.empty());
}
bool EnableD3D12DebugLayer(PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface)
bool EnableD3D12DebugLayer(D3D12DevConfiguration *devConfig,
PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface)
{
if(!getDebugInterface)
getDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(GetModuleHandleA("d3d12.dll"),
"D3D12GetDebugInterface");
if(!getDebugInterface)
ID3D12Debug *debug = NULL;
if(devConfig)
{
RDCERR("Couldn't find D3D12GetDebugInterface!");
return false;
if(devConfig->debug)
{
debug = devConfig->debug;
debug->AddRef();
}
}
else
{
if(!getDebugInterface)
getDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(
GetModuleHandleA("d3d12.dll"), "D3D12GetDebugInterface");
if(!getDebugInterface)
{
RDCERR("Couldn't find D3D12GetDebugInterface!");
return false;
}
HRESULT hr = getDebugInterface(__uuidof(ID3D12Debug), (void **)&debug);
if(FAILED(hr))
SAFE_RELEASE(debug);
if(hr == DXGI_ERROR_SDK_COMPONENT_MISSING)
{
RDCWARN("Debug layer not available: DXGI_ERROR_SDK_COMPONENT_MISSING");
}
else if(FAILED(hr))
{
RDCERR("Couldn't enable debug layer: %x", hr);
}
}
ID3D12Debug *debug = NULL;
HRESULT hr = getDebugInterface(__uuidof(ID3D12Debug), (void **)&debug);
if(SUCCEEDED(hr) && debug)
if(debug)
{
debug->EnableDebugLayer();
@@ -298,14 +322,6 @@ bool EnableD3D12DebugLayer(PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface)
return true;
}
else if(hr == DXGI_ERROR_SDK_COMPONENT_MISSING)
{
RDCWARN("Debug layer not available: DXGI_ERROR_SDK_COMPONENT_MISSING");
}
else
{
RDCERR("Couldn't enable debug layer: %x", hr);
}
return false;
}
+94 -3
View File
@@ -56,11 +56,21 @@ struct D3D12MarkerRegion
ID3D12CommandQueue *queue = NULL;
};
bool EnableD3D12DebugLayer(PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface = NULL);
struct D3D12DevConfiguration
{
ID3D12SDKConfiguration1 *sdkconfig = NULL;
ID3D12DeviceFactory *devfactory = NULL;
ID3D12DeviceConfiguration *devconfig = NULL;
ID3D12Debug *debug = NULL;
};
bool EnableD3D12DebugLayer(D3D12DevConfiguration *devConfig,
PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface);
HRESULT EnumAdapterByLuid(IDXGIFactory1 *factory, LUID luid, IDXGIAdapter **pAdapter);
void D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion, bytebuf d3d12core,
bytebuf d3d12sdklayers, HMODULE d3d12lib);
D3D12DevConfiguration *D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion,
bytebuf d3d12core, bytebuf d3d12sdklayers,
HMODULE d3d12lib);
void D3D12_CleanupReplaySDK();
inline void SetObjName(ID3D12Object *obj, const rdcstr &utf8name)
@@ -335,6 +345,87 @@ public:
}
};
class WrappedID3D12DeviceConfiguration : public ID3D12DeviceConfiguration
{
private:
ID3D12DeviceConfiguration *m_pReal = NULL;
IUnknown *wrappedParent = NULL;
public:
WrappedID3D12DeviceConfiguration(IUnknown *real, IUnknown *wrapped)
{
wrappedParent = wrapped;
if(real)
{
HRESULT hr = real->QueryInterface(__uuidof(ID3D12DeviceConfiguration), (void **)&m_pReal);
if(FAILED(hr))
SAFE_RELEASE(m_pReal);
}
}
~WrappedID3D12DeviceConfiguration() { SAFE_RELEASE(m_pReal); }
bool IsValid() { return m_pReal != NULL; }
//////////////////////////////
// Implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return wrappedParent->AddRef(); }
ULONG STDMETHODCALLTYPE Release() { return wrappedParent->Release(); }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
{
*ppvObject = (IUnknown *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D12DeviceConfiguration) && m_pReal)
{
*ppvObject = (ID3D12DeviceConfiguration *)this;
AddRef();
return S_OK;
}
return wrappedParent->QueryInterface(riid, ppvObject);
}
//////////////////////////////
// Implement ID3D12DeviceConfiguration
#if defined(_MSC_VER) || !defined(_WIN32)
virtual D3D12_DEVICE_CONFIGURATION_DESC STDMETHODCALLTYPE GetDesc(void)
{
return m_pReal->GetDesc();
}
#else
virtual D3D12_DEVICE_CONFIGURATION_DESC *STDMETHODCALLTYPE
GetDesc(D3D12_DEVICE_CONFIGURATION_DESC *RetVal)
{
return m_pReal->GetDesc(RetVal);
}
#endif
virtual HRESULT STDMETHODCALLTYPE GetEnabledExperimentalFeatures(_Out_writes_(NumGuids)
GUID *pGuids,
UINT NumGuids)
{
return m_pReal->GetEnabledExperimentalFeatures(pGuids, NumGuids);
}
virtual HRESULT STDMETHODCALLTYPE SerializeVersionedRootSignature(
_In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *pDesc, _COM_Outptr_ ID3DBlob **ppResult,
_Always_(_Outptr_opt_result_maybenull_) ID3DBlob **ppError)
{
return m_pReal->SerializeVersionedRootSignature(pDesc, ppResult, ppError);
}
virtual HRESULT STDMETHODCALLTYPE
CreateVersionedRootSignatureDeserializer(_In_reads_bytes_(Size) const void *pBlob, SIZE_T Size,
REFIID riid, _COM_Outptr_ void **ppvDeserializer)
{
return m_pReal->CreateVersionedRootSignatureDeserializer(pBlob, Size, riid, ppvDeserializer);
}
};
struct D3D12RootSignatureParameter : D3D12_ROOT_PARAMETER1
{
D3D12RootSignatureParameter()
+20 -2
View File
@@ -65,6 +65,13 @@ rdcstr WrappedID3D12Device::GetChunkName(uint32_t idx)
return ToStr((D3D12Chunk)idx);
}
D3D12ShaderCache *WrappedID3D12Device::GetShaderCache()
{
if(m_ShaderCache == NULL)
m_ShaderCache = new D3D12ShaderCache(this);
return m_ShaderCache;
}
D3D12DebugManager *WrappedID3D12Device::GetDebugManager()
{
return m_Replay->GetDebugManager();
@@ -504,6 +511,7 @@ BOOL STDMETHODCALLTYPE WrappedAGS12::ExtensionsSupported()
WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitParams params,
bool enabledDebugLayer)
: m_RefCounter(realDevice, false),
m_DevConfig(realDevice, this),
m_SoftRefCounter(NULL, false),
m_pDevice(realDevice),
m_debugLayerEnabled(enabledDebugLayer),
@@ -1222,6 +1230,17 @@ HRESULT WrappedID3D12Device::QueryInterface(REFIID riid, void **ppvObject)
return E_NOINTERFACE;
}
}
else if(riid == __uuidof(ID3D12DeviceConfiguration))
{
if(m_DevConfig.IsValid())
{
*ppvObject = (ID3D12DeviceConfiguration *)&m_DevConfig;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
else if(riid == __uuidof(ID3D12DeviceDownlevel))
{
if(m_pDownlevel)
@@ -4116,8 +4135,7 @@ void WrappedID3D12Device::CreateInternalResources()
m_GPUSyncCounter = 0;
if(m_ShaderCache == NULL)
m_ShaderCache = new D3D12ShaderCache(this);
GetShaderCache()->SetDevConfiguration(m_Replay->GetDevConfiguration());
if(m_TextRenderer == NULL)
m_TextRenderer = new D3D12TextRenderer(this);
+3 -1
View File
@@ -606,6 +606,8 @@ private:
ID3D12Device12 *m_pDevice12;
ID3D12DeviceDownlevel *m_pDownlevel;
WrappedID3D12DeviceConfiguration m_DevConfig;
// list of all queues being captured
rdcarray<WrappedID3D12CommandQueue *> m_Queues;
rdcarray<ID3D12Fence *> m_QueueFences;
@@ -886,7 +888,7 @@ public:
ID3D12Device9 *GetReal9() const { return m_pDevice9; }
static rdcstr GetChunkName(uint32_t idx);
D3D12ResourceManager *GetResourceManager() { return m_ResourceManager; }
D3D12ShaderCache *GetShaderCache() { return m_ShaderCache; }
D3D12ShaderCache *GetShaderCache();
D3D12DebugManager *GetDebugManager();
ResourceId GetResourceID() { return m_ResourceID; }
Threading::RWLock &GetCapTransitionLock() { return m_CapTransitionLock; }
+433 -46
View File
@@ -192,6 +192,297 @@ public:
virtual void STDMETHODCALLTYPE SetForceLegacyBarrierValidation(BOOL Enable) {}
};
class WrappedID3D12Tools : public RefCounter12<ID3D12Tools>, public ID3D12Tools
{
BOOL m_Instrumentation = FALSE;
public:
WrappedID3D12Tools() : RefCounter12(NULL) {}
virtual ~WrappedID3D12Tools() {}
//////////////////////////////
// Implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter12::AddRef(); }
ULONG STDMETHODCALLTYPE Release() { return RefCounter12::Release(); }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
{
*ppvObject = (IUnknown *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D12Tools))
{
*ppvObject = (ID3D12Tools *)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
//////////////////////////////
// Implement ID3D12Tools
virtual void STDMETHODCALLTYPE EnableShaderInstrumentation(BOOL bEnable)
{
m_Instrumentation = bEnable;
}
virtual BOOL STDMETHODCALLTYPE ShaderInstrumentationEnabled(void) { return m_Instrumentation; }
};
class WrappedID3D12DeviceRemovedExtendedData : public RefCounter12<ID3D12DeviceRemovedExtendedData1>,
public ID3D12DeviceRemovedExtendedData1
{
public:
WrappedID3D12DeviceRemovedExtendedData() : RefCounter12(NULL) {}
virtual ~WrappedID3D12DeviceRemovedExtendedData() {}
//////////////////////////////
// Implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter12::AddRef(); }
ULONG STDMETHODCALLTYPE Release() { return RefCounter12::Release(); }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
{
*ppvObject = (IUnknown *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D12DeviceRemovedExtendedData))
{
*ppvObject = (ID3D12DeviceRemovedExtendedData *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D12DeviceRemovedExtendedData1))
{
*ppvObject = (ID3D12DeviceRemovedExtendedData1 *)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
//////////////////////////////
// Implement ID3D12DeviceRemovedExtendedData
virtual HRESULT STDMETHODCALLTYPE
GetAutoBreadcrumbsOutput(_Out_ D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT *pOutput)
{
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
virtual HRESULT STDMETHODCALLTYPE
GetPageFaultAllocationOutput(_Out_ D3D12_DRED_PAGE_FAULT_OUTPUT *pOutput)
{
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
//////////////////////////////
// Implement ID3D12DeviceRemovedExtendedData1
virtual HRESULT STDMETHODCALLTYPE
GetAutoBreadcrumbsOutput1(_Out_ D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT1 *pOutput)
{
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
virtual HRESULT STDMETHODCALLTYPE
GetPageFaultAllocationOutput1(_Out_ D3D12_DRED_PAGE_FAULT_OUTPUT1 *pOutput)
{
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
};
class WrappedID3D12DeviceFactory : public RefCounter12<ID3D12DeviceFactory>, public ID3D12DeviceFactory
{
WrappedID3D12DeviceConfiguration config;
public:
WrappedID3D12DeviceFactory(ID3D12DeviceFactory *real) : RefCounter12(real), config(real, this) {}
virtual ~WrappedID3D12DeviceFactory() {}
//////////////////////////////
// Implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter12::AddRef(); }
ULONG STDMETHODCALLTYPE Release() { return RefCounter12::Release(); }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
{
*ppvObject = (IUnknown *)(ID3D12DeviceFactory *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D12DeviceFactory))
{
*ppvObject = (ID3D12DeviceFactory *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D12DeviceConfiguration) && config.IsValid())
{
*ppvObject = (ID3D12DeviceConfiguration *)&config;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
//////////////////////////////
// Implement ID3D12DeviceFactory
virtual HRESULT STDMETHODCALLTYPE InitializeFromGlobalState(void)
{
return m_pReal->InitializeFromGlobalState();
}
virtual HRESULT STDMETHODCALLTYPE ApplyToGlobalState(void)
{
return m_pReal->ApplyToGlobalState();
}
virtual HRESULT STDMETHODCALLTYPE SetFlags(D3D12_DEVICE_FACTORY_FLAGS flags)
{
return m_pReal->SetFlags(flags);
}
virtual D3D12_DEVICE_FACTORY_FLAGS STDMETHODCALLTYPE GetFlags(void)
{
return m_pReal->GetFlags();
}
virtual HRESULT STDMETHODCALLTYPE GetConfigurationInterface(REFCLSID clsid, REFIID iid,
_COM_Outptr_ void **ppv);
virtual HRESULT STDMETHODCALLTYPE
EnableExperimentalFeatures(UINT NumFeatures, _In_reads_(NumFeatures) const IID *pIIDs,
_In_reads_opt_(NumFeatures) void *pConfigurationStructs,
_In_reads_opt_(NumFeatures) UINT *pConfigurationStructSizes)
{
rdcarray<IID> allowedIIDs;
// allow enabling unsigned DXIL.
for(UINT i = 0; i < NumFeatures; i++)
{
if(pIIDs[i] == D3D12ExperimentalShaderModels)
allowedIIDs.push_back(D3D12ExperimentalShaderModels);
}
// there's no "partially successful" error code, so we just lie to the application and pretend
// that any filtered IIDs also succeeded
if(!allowedIIDs.empty())
return m_pReal->EnableExperimentalFeatures((UINT)allowedIIDs.size(), allowedIIDs.data(), NULL,
NULL);
// header says "The call returns E_NOINTERFACE if an unrecognized feature is passed in or
// Windows Developer mode is not on." so this is the most appropriate error for if no IIDs are
// allowed.
return E_NOINTERFACE;
}
virtual HRESULT STDMETHODCALLTYPE CreateDevice(_In_opt_ IUnknown *adapter,
D3D_FEATURE_LEVEL FeatureLevel, REFIID riid,
_COM_Outptr_opt_ void **ppvDevice)
{
if(RenderDoc::Inst().GetCaptureOptions().apiValidation)
{
D3D12DevConfiguration tmpConfig = {};
HRESULT hr = m_pReal->GetConfigurationInterface(CLSID_D3D12Debug, __uuidof(ID3D12Debug),
(void **)&tmpConfig.debug);
if(SUCCEEDED(hr))
{
EnableD3D12DebugLayer(&tmpConfig, NULL);
SAFE_RELEASE(tmpConfig.debug);
}
}
return CreateD3D12_Internal(
[this](IUnknown *pAdapter, D3D_FEATURE_LEVEL MinimumFeatureLevel, REFIID riid,
void **ppDevice) {
return m_pReal->CreateDevice(pAdapter, MinimumFeatureLevel, riid, ppDevice);
},
adapter, FeatureLevel, riid, ppvDevice);
}
};
class WrappedID3D12SDKConfiguration : public RefCounter12<ID3D12SDKConfiguration>,
public ID3D12SDKConfiguration1
{
ID3D12SDKConfiguration1 *m_pReal1 = NULL;
public:
WrappedID3D12SDKConfiguration(ID3D12SDKConfiguration *real, ID3D12SDKConfiguration1 *real1)
: RefCounter12(real)
{
if(!real1)
real->QueryInterface(__uuidof(ID3D12SDKConfiguration1), (void **)&real1);
m_pReal1 = real1;
}
virtual ~WrappedID3D12SDKConfiguration()
{
SAFE_RELEASE(m_pReal);
SAFE_RELEASE(m_pReal1);
}
//////////////////////////////
// Implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter12::AddRef(); }
ULONG STDMETHODCALLTYPE Release() { return RefCounter12::Release(); }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
{
*ppvObject = (IUnknown *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D12SDKConfiguration))
{
*ppvObject = (ID3D12SDKConfiguration *)this;
AddRef();
return S_OK;
}
if(riid == __uuidof(ID3D12SDKConfiguration1))
{
*ppvObject = (ID3D12SDKConfiguration1 *)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
//////////////////////////////
// Implement ID3D12SDKConfiguration
virtual HRESULT STDMETHODCALLTYPE SetSDKVersion(UINT SDKVersion, _In_z_ LPCSTR SDKPath)
{
return m_pReal->SetSDKVersion(SDKVersion, SDKPath);
}
//////////////////////////////
// Implement ID3D12SDKConfiguration1
virtual HRESULT STDMETHODCALLTYPE CreateDeviceFactory(UINT SDKVersion, _In_ LPCSTR SDKPath,
REFIID riid, _COM_Outptr_ void **ppvFactory)
{
if(riid != __uuidof(ID3D12DeviceFactory))
{
RDCERR("Unexpected uuid to CreateDeviceFactory: %s", ToStr(riid).c_str());
return E_NOINTERFACE;
}
ID3D12DeviceFactory *realFactory = NULL;
HRESULT hr = m_pReal1->CreateDeviceFactory(SDKVersion, SDKPath, riid, (void **)&realFactory);
if(SUCCEEDED(hr))
{
RDCASSERT(realFactory);
*ppvFactory = (ID3D12DeviceFactory *)(new WrappedID3D12DeviceFactory(realFactory));
return hr;
}
SAFE_RELEASE(realFactory);
return hr;
}
virtual void STDMETHODCALLTYPE FreeUnusedSDKs(void) { return m_pReal1->FreeUnusedSDKs(); }
};
class D3D12Hook : LibraryHook
{
public:
@@ -212,6 +503,7 @@ public:
CreateDevice.Register("d3d12.dll", "D3D12CreateDevice", D3D12CreateDevice_hook);
GetDebugInterface.Register("d3d12.dll", "D3D12GetDebugInterface", D3D12GetDebugInterface_hook);
GetInterface.Register("d3d12.dll", "D3D12GetInterface", D3D12GetInterface_hook);
EnableExperimentalFeatures.Register("d3d12.dll", "D3D12EnableExperimentalFeatures",
D3D12EnableExperimentalFeatures_hook);
GetD3D11On12On7.Register("d3d11on12.dll", "GetD3D11On12On7Interface",
@@ -221,10 +513,99 @@ public:
Threading::SetTLSValue(m_RecurseSlot, NULL);
}
static HRESULT GetWrappedInterface(IUnknown *realUnk, REFIID riid, void **ppvInterface)
{
if(riid == __uuidof(ID3D12Debug))
{
*ppvInterface = (ID3D12Debug *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug1))
{
*ppvInterface = (ID3D12Debug1 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug2))
{
*ppvInterface = (ID3D12Debug2 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug3))
{
*ppvInterface = (ID3D12Debug3 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug4))
{
*ppvInterface = (ID3D12Debug4 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug5))
{
*ppvInterface = (ID3D12Debug5 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug6))
{
*ppvInterface = (ID3D12Debug6 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Tools))
{
*ppvInterface = (ID3D12Tools *)(new WrappedID3D12Tools());
return S_OK;
}
else if(riid == __uuidof(ID3D12DeviceRemovedExtendedData))
{
*ppvInterface =
(ID3D12DeviceRemovedExtendedData *)(new WrappedID3D12DeviceRemovedExtendedData());
return S_OK;
}
else if(riid == __uuidof(ID3D12DeviceRemovedExtendedData1))
{
*ppvInterface =
(ID3D12DeviceRemovedExtendedData1 *)(new WrappedID3D12DeviceRemovedExtendedData());
return S_OK;
}
else if(riid == __uuidof(ID3D12DeviceRemovedExtendedData2))
{
*ppvInterface =
(ID3D12DeviceRemovedExtendedData2 *)(new WrappedID3D12DeviceRemovedExtendedData());
return S_OK;
}
else if(riid == __uuidof(ID3D12SDKConfiguration))
{
ID3D12SDKConfiguration *real = (ID3D12SDKConfiguration *)realUnk;
if(real)
{
// take a reference ourselves, realUnk is a transient pointer and will be released after this function returns
real->AddRef();
*ppvInterface = (ID3D12SDKConfiguration *)(new WrappedID3D12SDKConfiguration(real, NULL));
return S_OK;
}
}
else if(riid == __uuidof(ID3D12SDKConfiguration1))
{
ID3D12SDKConfiguration1 *real1 = (ID3D12SDKConfiguration1 *)realUnk;
if(real1)
{
// take a reference ourselves, realUnk is a transient pointer and will be released after this function returns
real1->AddRef();
ID3D12SDKConfiguration *real = NULL;
real1->QueryInterface(__uuidof(ID3D12SDKConfiguration), (void **)&real);
*ppvInterface = (ID3D12SDKConfiguration1 *)(new WrappedID3D12SDKConfiguration(real, real1));
return S_OK;
}
}
return E_NOINTERFACE;
}
private:
static D3D12Hook d3d12hooks;
HookedFunction<PFN_D3D12_GET_DEBUG_INTERFACE> GetDebugInterface;
HookedFunction<PFN_D3D12_GET_INTERFACE> GetInterface;
HookedFunction<PFN_D3D12_CREATE_DEVICE> CreateDevice;
HookedFunction<PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES> EnableExperimentalFeatures;
HookedFunction<PFNGetD3D11On12On7Interface> GetD3D11On12On7;
@@ -276,7 +657,7 @@ private:
bool EnableDebugLayer = false;
if(RenderDoc::Inst().GetCaptureOptions().apiValidation)
EnableDebugLayer = EnableD3D12DebugLayer(GetDebugInterface());
EnableDebugLayer = EnableD3D12DebugLayer(NULL, GetDebugInterface());
RDCDEBUG("Calling real createdevice...");
@@ -460,54 +841,40 @@ private:
static HRESULT WINAPI D3D12GetDebugInterface_hook(REFIID riid, void **ppvDebug)
{
if(riid == __uuidof(ID3D12Debug))
{
*ppvDebug = (ID3D12Debug *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug1))
{
*ppvDebug = (ID3D12Debug1 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug2))
{
*ppvDebug = (ID3D12Debug2 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug3))
{
*ppvDebug = (ID3D12Debug3 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug4))
{
*ppvDebug = (ID3D12Debug4 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug5))
{
*ppvDebug = (ID3D12Debug5 *)(new WrappedID3D12Debug());
return S_OK;
}
else if(riid == __uuidof(ID3D12Debug6))
{
*ppvDebug = (ID3D12Debug6 *)(new WrappedID3D12Debug());
return S_OK;
}
else
{
IUnknown *releaseme = NULL;
HRESULT real = d3d12hooks.GetDebugInterface()(riid, (void **)&releaseme);
IUnknown *realUnk = NULL;
HRESULT real = d3d12hooks.GetDebugInterface()(riid, (void **)&realUnk);
if(releaseme)
releaseme->Release();
HRESULT hr = GetWrappedInterface(realUnk, riid, ppvDebug);
RDCWARN("Unknown UUID passed to D3D12GetDebugInterface: %s. Real call %s succeed (%x).",
ToStr(riid).c_str(), SUCCEEDED(real) ? "did" : "did not", real);
if(realUnk)
realUnk->Release();
return E_NOINTERFACE;
}
if(SUCCEEDED(hr))
return hr;
RDCWARN("Unknown UUID passed to D3D12GetDebugInterface: %s. Real call %s succeed (%x).",
ToStr(riid).c_str(), SUCCEEDED(real) ? "did" : "did not", real);
return E_NOINTERFACE;
}
static HRESULT WINAPI D3D12GetInterface_hook(REFCLSID rclsid, REFIID riid, void **ppvDebug)
{
IUnknown *realUnk = NULL;
HRESULT real = d3d12hooks.GetInterface()(rclsid, riid, (void **)&realUnk);
HRESULT hr = GetWrappedInterface(realUnk, riid, ppvDebug);
if(realUnk)
realUnk->Release();
if(SUCCEEDED(hr))
return hr;
RDCWARN("Unknown UUID passed to D3D12GetInterface: %s (clsid %s). Real call %s succeed (%x).",
ToStr(riid).c_str(), ToStr(rclsid).c_str(), SUCCEEDED(real) ? "did" : "did not", real);
return E_NOINTERFACE;
}
};
@@ -518,3 +885,23 @@ HRESULT CreateD3D12_Internal(RealD3D12CreateFunction real, IUnknown *pAdapter,
{
return D3D12Hook::d3d12hooks.Create_Internal(real, pAdapter, MinimumFeatureLevel, riid, ppDevice);
}
HRESULT STDMETHODCALLTYPE WrappedID3D12DeviceFactory::GetConfigurationInterface(
REFCLSID clsid, REFIID iid, _COM_Outptr_ void **ppv)
{
IUnknown *realUnk = NULL;
HRESULT real = m_pReal->GetConfigurationInterface(clsid, iid, (void **)&realUnk);
HRESULT hr = D3D12Hook::GetWrappedInterface(realUnk, iid, ppv);
if(realUnk)
realUnk->Release();
if(SUCCEEDED(hr))
return hr;
RDCWARN("Unknown UUID passed to D3D12GetDebugInterface: %s. Real call %s succeed (%x).",
ToStr(iid).c_str(), SUCCEEDED(real) ? "did" : "did not", real);
return E_NOINTERFACE;
}
+29 -7
View File
@@ -73,6 +73,18 @@ void D3D12Replay::Shutdown()
SAFE_DELETE(m_RGP);
if(m_DevConfig)
{
SAFE_RELEASE(m_DevConfig->debug);
SAFE_RELEASE(m_DevConfig->devconfig);
SAFE_RELEASE(m_DevConfig->devfactory);
m_DevConfig->sdkconfig->FreeUnusedSDKs();
SAFE_DELETE(m_DevConfig->sdkconfig);
SAFE_DELETE(m_DevConfig);
}
// this destroys the replay object
m_pDevice->Release();
// the this pointer is free'd after this point
@@ -90,9 +102,10 @@ void D3D12Replay::Shutdown()
}
}
void D3D12Replay::Initialise(IDXGIFactory1 *factory)
void D3D12Replay::Initialise(IDXGIFactory1 *factory, D3D12DevConfiguration *config)
{
m_pFactory = factory;
m_DevConfig = config;
RDCEraseEl(m_DriverInfo);
@@ -4557,8 +4570,8 @@ RDResult D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, IRepl
if(initParams.MinimumFeatureLevel < D3D_FEATURE_LEVEL_11_0)
initParams.MinimumFeatureLevel = D3D_FEATURE_LEVEL_11_0;
D3D12_PrepareReplaySDKVersion(rdc && rdc->IsUntrusted(), initParams.SDKVersion, D3D12Core,
D3D12SDKLayers, D3D12Lib);
D3D12DevConfiguration *config = D3D12_PrepareReplaySDKVersion(
rdc && rdc->IsUntrusted(), initParams.SDKVersion, D3D12Core, D3D12SDKLayers, D3D12Lib);
const bool isProxy = (rdc == NULL);
@@ -4648,7 +4661,7 @@ RDResult D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, IRepl
if(shouldEnableDebugLayer)
{
debugLayerEnabled = EnableD3D12DebugLayer();
debugLayerEnabled = EnableD3D12DebugLayer(config, NULL);
if(!debugLayerEnabled && !isProxy)
{
@@ -4659,7 +4672,11 @@ RDResult D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, IRepl
}
ID3D12Device *dev = NULL;
hr = createDevice(adapter, initParams.MinimumFeatureLevel, __uuidof(ID3D12Device), (void **)&dev);
if(config)
hr = config->devfactory->CreateDevice(adapter, initParams.MinimumFeatureLevel,
__uuidof(ID3D12Device), (void **)&dev);
else
hr = createDevice(adapter, initParams.MinimumFeatureLevel, __uuidof(ID3D12Device), (void **)&dev);
if((FAILED(hr) || !dev) && adapter)
{
@@ -4668,7 +4685,12 @@ RDResult D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, IRepl
RDCWARN("Couldn't replay on selected adapter, falling back to default adapter");
SAFE_RELEASE(adapter);
hr = createDevice(adapter, initParams.MinimumFeatureLevel, __uuidof(ID3D12Device), (void **)&dev);
if(config)
hr = config->devfactory->CreateDevice(adapter, initParams.MinimumFeatureLevel,
__uuidof(ID3D12Device), (void **)&dev);
else
hr = createDevice(adapter, initParams.MinimumFeatureLevel, __uuidof(ID3D12Device),
(void **)&dev);
}
SAFE_RELEASE(adapter);
@@ -4723,7 +4745,7 @@ RDResult D3D12_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, IRepl
replay->SetProxy(isProxy);
replay->SetRGP(rgp);
replay->Initialise(factory);
replay->Initialise(factory, config);
*driver = (IReplayDriver *)replay;
return ResultCode::Succeeded;
+5 -1
View File
@@ -94,12 +94,14 @@ class D3D12Replay : public IReplayDriver
public:
D3D12Replay(WrappedID3D12Device *d);
D3D12DevConfiguration *GetDevConfiguration() { return m_DevConfig; }
D3D12DebugManager *GetDebugManager() { return m_DebugManager; }
void SetRGP(AMDRGPControl *rgp) { m_RGP = rgp; }
void Set12On7(bool d3d12on7) { m_D3D12On7 = d3d12on7; }
void SetProxy(bool proxy) { m_Proxy = proxy; }
bool IsRemoteProxy() { return m_Proxy; }
void Initialise(IDXGIFactory1 *factory);
void Initialise(IDXGIFactory1 *factory, D3D12DevConfiguration *config);
void Shutdown();
RDResult FatalErrorCheck();
@@ -561,6 +563,8 @@ private:
D3D12DebugManager *m_DebugManager = NULL;
D3D12DevConfiguration *m_DevConfig = NULL;
IDXGIFactory1 *m_pFactory = NULL;
HMODULE m_D3D12Lib = NULL;
+126 -29
View File
@@ -314,11 +314,14 @@ bool IsSignedByMicrosoft(const rdcstr &filename, rdcstr &signer)
return IsSignatureValid;
}
void D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion, bytebuf d3d12core_file,
bytebuf d3d12sdklayers_file, HMODULE d3d12lib)
D3D12DevConfiguration *D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion,
bytebuf d3d12core_file,
bytebuf d3d12sdklayers_file, HMODULE d3d12lib)
{
// D3D12Core shouldn't be loaded at this point, but it might be due to bugs. If it is, we can't do
// anything to change it anymore so we have to just handle what we have
// D3D12Core shouldn't be loaded at this point, but it might be due to bugs. If it is, we don't do
// anything to change it anymore so we have to just handle what we have.
// In theory it might be possible to load multiple d3d12cores using the new dll selection API, but
// that's probably not stable/reliable so we don't use it.
HMODULE D3D12Core = GetModuleHandleA("D3D12Core.dll");
if(D3D12Core != NULL)
{
@@ -326,7 +329,7 @@ void D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion, byteb
// if the core that's loaded is sufficient, don't show any warnings
if(ver_ptr && SDKVersion <= *ver_ptr)
return;
return NULL;
RDCWARN(
"D3D12Core.dll was already loaded before replay started. This may be caused by a D3D12 "
@@ -339,7 +342,7 @@ void D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion, byteb
RDCWARN("The existing D3D12Core.dll had an unknown version, this capture requires version %u",
SDKVersion);
return;
return NULL;
}
static bool core_fetched = false, hooks_applied = false;
@@ -389,7 +392,7 @@ void D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion, byteb
// if the system doesn't have a core DLL we can't intercept and point to our own runtime, so just
// abort here before doing anything potentially dangerous below.
if(SystemCoreVersion == 0)
return;
return NULL;
// similarly, if the system version is enough then the user didn't use a new runtime (or they used
// what was at the time a new runtime but is now available in the system...), so also abort.
@@ -397,31 +400,13 @@ void D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion, byteb
// The only exception is if the user has configured a force override, in which case we always use
// it.
if(SDKVersion <= SystemCoreVersion && D3D12_D3D12CoreDirPath().empty())
return;
// finally we're at a point where we will hook to force the library we want.
if(!hooks_applied)
{
hooks_applied = true;
Win32_RegisterManualModuleHooking();
D3D12GetInterface_Core_hook.Register("d3d12core.dll", "D3D12GetInterface",
Hooked_Core_D3D12GetInterface);
D3D12GetInterface_SDKLayers_hook.Register("d3d12sdklayers.dll", "D3D12GetInterface",
Hooked_SDKLayers_D3D12GetInterface);
Win32_InterceptLibraryLoads(Hooked_D3D12LoadLibrary);
}
// we do this always, even if the hooks are already applied, because this module has possibly been
// reloaded and needs to be re-hooked each time
Win32_ManualHookModule("d3d12.dll", d3d12lib);
return NULL;
// *always* use the user's path if it exists
D3D12Core_Override_Path = D3D12_D3D12CoreDirPath();
DWORD OverrideDllVersion = 0;
if(D3D12Core_Override_Path.empty() || !FileIO::exists(D3D12Core_Override_Path.c_str()))
{
if(d3d12core_file.empty())
@@ -430,7 +415,7 @@ void D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion, byteb
"No D3D12Core.dll embedded in capture but we need a newer one (version %u) to properly "
"replay this capture",
SDKVersion);
return;
return NULL;
}
// find an appropriate spot to write this file. Other instances of RenderDoc might be running so
@@ -557,6 +542,118 @@ void D3D12_PrepareReplaySDKVersion(bool untrustedCapture, UINT SDKVersion, byteb
FreeLibrary(ret);
}
}
if(FileIO::exists(D3D12Core_Override_Path.c_str()))
{
UINT prevErrorMode = GetErrorMode();
SetErrorMode(prevErrorMode | SEM_FAILCRITICALERRORS);
HMODULE ret =
LoadLibraryW(StringFormat::UTF82Wide(D3D12Core_Override_Path + "/d3d12core.dll").c_str());
SetErrorMode(prevErrorMode);
DWORD *ver_ptr = (DWORD *)GetProcAddress(ret, "D3D12SDKVersion");
if(ver_ptr)
OverrideDllVersion = *ver_ptr;
FreeLibrary(ret);
}
RDCLOG("Loading D3D12 runtime from %s which is version %u", D3D12Core_Override_Path.c_str(),
OverrideDllVersion);
// see if we can use the new proper D3D12 dll selection API
{
HMODULE d3d12Lib = GetModuleHandleA("d3d12.dll");
PFN_D3D12_GET_INTERFACE getD3D12Interface = NULL;
if(d3d12Lib)
getD3D12Interface = (PFN_D3D12_GET_INTERFACE)GetProcAddress(d3d12Lib, "D3D12GetInterface");
if(getD3D12Interface)
{
ID3D12SDKConfiguration *config = NULL;
HRESULT hr = getD3D12Interface(CLSID_D3D12SDKConfiguration, __uuidof(ID3D12SDKConfiguration),
(void **)&config);
if(SUCCEEDED(hr) && config)
{
ID3D12SDKConfiguration1 *config1 = NULL;
ID3D12DeviceFactory *devfactory = NULL;
hr = config->QueryInterface(__uuidof(ID3D12SDKConfiguration1), (void **)&config1);
if(SUCCEEDED(hr) && config1)
{
config1->CreateDeviceFactory(OverrideDllVersion, D3D12Core_Override_Path.c_str(),
__uuidof(ID3D12DeviceFactory), (void **)&devfactory);
}
SAFE_RELEASE(config);
if(devfactory)
{
ID3D12Debug *debug = NULL;
hr = devfactory->GetConfigurationInterface(CLSID_D3D12Debug, __uuidof(ID3D12Debug),
(void **)&debug);
if(FAILED(hr))
SAFE_RELEASE(debug);
ID3D12DeviceConfiguration *devConfig = NULL;
hr = devfactory->QueryInterface(__uuidof(ID3D12DeviceConfiguration), (void **)&devConfig);
if(FAILED(hr))
SAFE_RELEASE(devConfig);
// we got what we need, return the interfaces to use
D3D12DevConfiguration *ret = new D3D12DevConfiguration;
ret->devfactory = devfactory;
ret->sdkconfig = config1;
ret->debug = debug;
ret->devconfig = devConfig;
RDCLOG("Accessing D3D12 dll via SDK configuration API");
return ret;
}
else
{
RDCLOG("Couldn't get device factory");
}
SAFE_RELEASE(config1);
}
else
{
RDCLOG("Couldn't get SDK configuration interface");
}
SAFE_RELEASE(config);
}
else
{
RDCLOG("Couldn't get D3D12 interface query");
}
}
RDCLOG("Accessing D3D12 dll via hooks");
// finally we're at a point where we will hook to force the library we want.
if(!hooks_applied)
{
hooks_applied = true;
Win32_RegisterManualModuleHooking();
D3D12GetInterface_Core_hook.Register("d3d12core.dll", "D3D12GetInterface",
Hooked_Core_D3D12GetInterface);
D3D12GetInterface_SDKLayers_hook.Register("d3d12sdklayers.dll", "D3D12GetInterface",
Hooked_SDKLayers_D3D12GetInterface);
Win32_InterceptLibraryLoads(Hooked_D3D12LoadLibrary);
}
// we do this always, even if the hooks are already applied, because this module has possibly been
// reloaded and needs to be re-hooked each time
Win32_ManualHookModule("d3d12.dll", d3d12lib);
return NULL;
}
void D3D12_CleanupReplaySDK()
+18 -4
View File
@@ -767,8 +767,14 @@ D3D12RootSignature D3D12ShaderCache::GetRootSig(const void *data, size_t dataSiz
}
ID3D12VersionedRootSignatureDeserializer *deser = NULL;
HRESULT hr = deserializeRootSig(
data, dataSize, __uuidof(ID3D12VersionedRootSignatureDeserializer), (void **)&deser);
HRESULT hr;
if(m_DevConfig)
hr = m_DevConfig->devconfig->CreateVersionedRootSignatureDeserializer(
data, dataSize, __uuidof(ID3D12VersionedRootSignatureDeserializer), (void **)&deser);
else
hr = deserializeRootSig(data, dataSize, __uuidof(ID3D12VersionedRootSignatureDeserializer),
(void **)&deser);
if(FAILED(hr))
{
@@ -966,7 +972,12 @@ ID3DBlob *D3D12ShaderCache::MakeRootSig(const rdcarray<D3D12_ROOT_PARAMETER1> &p
ID3DBlob *ret = NULL;
ID3DBlob *errBlob = NULL;
HRESULT hr = serializeRootSig(&verdesc, &ret, &errBlob);
HRESULT hr;
if(m_DevConfig && m_DevConfig->devconfig)
hr = m_DevConfig->devconfig->SerializeVersionedRootSignature(&verdesc, &ret, &errBlob);
else
hr = serializeRootSig(&verdesc, &ret, &errBlob);
SAFE_RELEASE(errBlob);
if(SUCCEEDED(hr))
@@ -981,7 +992,10 @@ ID3DBlob *D3D12ShaderCache::MakeRootSig(const rdcarray<D3D12_ROOT_PARAMETER1> &p
oldSamplers[i] = Downconvert(StaticSamplers[i]);
desc11.pStaticSamplers = oldSamplers.data();
hr = serializeRootSig(&verdesc, &ret, &errBlob);
if(m_DevConfig && m_DevConfig->devconfig)
hr = m_DevConfig->devconfig->SerializeVersionedRootSignature(&verdesc, &ret, &errBlob);
else
hr = serializeRootSig(&verdesc, &ret, &errBlob);
if(FAILED(hr))
{
@@ -61,6 +61,7 @@ public:
void LoadDXC();
void SetDevConfiguration(D3D12DevConfiguration *config) { m_DevConfig = config; }
void SetCaching(bool enabled) { m_CacheShaders = enabled; }
private:
static const uint32_t m_ShaderCacheMagic = 0xf000baba;
@@ -71,6 +72,8 @@ private:
bool m_ShaderCacheDirty = false, m_CacheShaders = false;
std::map<uint32_t, ID3DBlob *> m_ShaderCache;
D3D12DevConfiguration *m_DevConfig = NULL;
D3D12_STATIC_SAMPLER_DESC1 Upconvert(const D3D12_STATIC_SAMPLER_DESC &StaticSampler);
D3D12_STATIC_SAMPLER_DESC Downconvert(const D3D12_STATIC_SAMPLER_DESC1 &StaticSampler);
};