diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index 4eac92bee..8da8f9ce1 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -453,6 +453,37 @@ ResourceRange::ResourceRange(ID3D11Resource *res, UINT mip, UINT slice) stencilReadOnly = false; } +D3D11InitParams::D3D11InitParams() +{ + DriverType = D3D_DRIVER_TYPE_UNKNOWN; + Flags = 0; + SDKVersion = D3D11_SDK_VERSION; + NumFeatureLevels = 0; + RDCEraseEl(FeatureLevels); +} + +bool D3D11InitParams::IsSupportedVersion(uint64_t ver) +{ + if(ver == CurrentVersion) + return true; + + // we can check other older versions we support here. + + return false; +} + +template +void DoSerialise(SerialiserType &ser, D3D11InitParams &el) +{ + SERIALISE_MEMBER(DriverType); + SERIALISE_MEMBER(Flags); + SERIALISE_MEMBER(SDKVersion); + SERIALISE_MEMBER(NumFeatureLevels); + SERIALISE_MEMBER(FeatureLevels); +} + +INSTANTIATE_SERIALISE_TYPE(D3D11InitParams); + TextureDim MakeTextureDim(D3D11_SRV_DIMENSION dim) { switch(dim) diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 1ee0c7b2d..24db2eb55 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -37,85 +37,6 @@ WRAPPED_POOL_INST(WrappedID3D11Device); WrappedID3D11Device *WrappedID3D11Device::m_pCurrentWrappedDevice = NULL; -D3D11InitParams::D3D11InitParams() -{ - SerialiseVersion = D3D11_SERIALISE_VERSION; - DriverType = D3D_DRIVER_TYPE_UNKNOWN; - Flags = 0; - SDKVersion = D3D11_SDK_VERSION; - NumFeatureLevels = 0; - RDCEraseEl(FeatureLevels); -} - -// handling for these versions is scattered throughout the code (as relevant to enable/disable bits -// of serialisation -// and set some defaults if necessary). -// Here we list which non-current versions we support, and what changed -const uint32_t D3D11InitParams::D3D11_OLD_VERSIONS[D3D11InitParams::D3D11_NUM_SUPPORTED_OLD_VERSIONS] = { - // from 0x4 to 0x5, we added the stream-out hidden counters in the context's - // Serialise_BeginCaptureFrame - 0x000004, - // from 0x5 to 0x6, several new calls were made 'drawcalls', like Copy & - // GenerateMips, with serialised debug messages - 0x000005, - // from 0x6 to 0x7, we added some more padding in some buffer & texture chunks to - // get larger alignment than 16-byte - 0x000006, - // from 0x7 to 0x8, we changed the UAV arrays in the render state to be D3D11.1 - // sized and separate CS array. - 0x000007, - // from 0x8 to 0x9, we added the view creation details to clear calls in the device - // record so that we can still perform the clear even if the view wasn't referenced. - 0x000008, - // from 0x9 to 0xA, we refactored deferred context handling - it's flattened on - // capture now. So on replay if deferred contexts are present, we go through a - // flattening stpe. - 0x000009, - // from 0xA to 0xB, we added the SwapDeviceContextState from ID3D11DeviceContext1 - 0x00000A, -}; - -ReplayStatus D3D11InitParams::Serialise() -{ - SERIALISE_ELEMENT(uint32_t, ver, D3D11_SERIALISE_VERSION); - SerialiseVersion = ver; - - if(ver != D3D11_SERIALISE_VERSION) - { - bool oldsupported = false; - for(uint32_t i = 0; i < D3D11_NUM_SUPPORTED_OLD_VERSIONS; i++) - { - if(ver == D3D11_OLD_VERSIONS[i]) - { - oldsupported = true; - RDCWARN( - "Old D3D11 serialise version %d, latest is %d. Loading with possibly degraded " - "features/support.", - ver, D3D11_SERIALISE_VERSION); - } - } - - if(!oldsupported) - { - RDCERR("Incompatible D3D11 serialise version, expected %d got %d", D3D11_SERIALISE_VERSION, - ver); - return ReplayStatus::APIIncompatibleVersion; - } - } - - SERIALISE_ELEMENT(D3D_DRIVER_TYPE, driverType, DriverType); - DriverType = driverType; - SERIALISE_ELEMENT(uint32_t, flags, Flags); - Flags = flags; - SERIALISE_ELEMENT(uint32_t, sdk, SDKVersion); - SDKVersion = sdk; - SERIALISE_ELEMENT(uint32_t, numlevels, NumFeatureLevels); - NumFeatureLevels = numlevels; - m_pSerialiser->SerialisePODArray("FeatureLevels", FeatureLevels); - - return ReplayStatus::Succeeded; -} - void WrappedID3D11Device::NewSwapchainBuffer(IUnknown *backbuffer) { WrappedID3D11Texture2D1 *wrapped = (WrappedID3D11Texture2D1 *)backbuffer; @@ -150,6 +71,8 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara if(RenderDoc::Inst().GetCrashHandler()) RenderDoc::Inst().GetCrashHandler()->RegisterMemoryRegion(this, sizeof(WrappedID3D11Device)); + m_SectionVersion = D3D11InitParams::CurrentVersion; + m_pDevice1 = NULL; m_pDevice->QueryInterface(__uuidof(ID3D11Device1), (void **)&m_pDevice1); @@ -955,12 +878,10 @@ void WrappedID3D11Device::Serialise_CaptureScope(uint64_t offset) } } -void WrappedID3D11Device::ReadLogInitialisation() +void WrappedID3D11Device::ReadLogInitialisation(RDCFile *rdc) { uint64_t frameOffset = 0; - LazyInit(); - m_pSerialiser->SetDebugText(true); m_pSerialiser->Rewind(); diff --git a/renderdoc/driver/d3d11/d3d11_device.h b/renderdoc/driver/d3d11/d3d11_device.h index 6d20fb745..2cb93a691 100644 --- a/renderdoc/driver/d3d11/d3d11_device.h +++ b/renderdoc/driver/d3d11/d3d11_device.h @@ -51,10 +51,9 @@ enum TextureDisplayType TEXDISPLAY_INDIRECT_VIEW, }; -struct D3D11InitParams : public RDCInitParams +struct D3D11InitParams { D3D11InitParams(); - ReplayStatus Serialise(); D3D_DRIVER_TYPE DriverType; UINT Flags; @@ -62,16 +61,13 @@ struct D3D11InitParams : public RDCInitParams UINT NumFeatureLevels; D3D_FEATURE_LEVEL FeatureLevels[16]; - static const uint32_t D3D11_SERIALISE_VERSION = 0x000000B; - - // backwards compatibility for old logs described at the declaration of this array - static const uint32_t D3D11_NUM_SUPPORTED_OLD_VERSIONS = 7; - static const uint32_t D3D11_OLD_VERSIONS[D3D11_NUM_SUPPORTED_OLD_VERSIONS]; - - // version number internal to d3d11 stream - uint32_t SerialiseVersion; + // check if a frame capture section version is supported + static const uint64_t CurrentVersion = 0xC; + static bool IsSupportedVersion(uint64_t ver); }; +DECLARE_REFLECTION_STRUCT(D3D11InitParams); + class WrappedID3D11Device; class WrappedShader; @@ -342,6 +338,7 @@ private: vector m_ShaderSearchPaths; D3D11InitParams m_InitParams; + uint64_t m_SectionVersion; ResourceId m_BBID; @@ -405,13 +402,13 @@ public: ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D11Device, AllocPoolCount); WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitParams *params); - void SetLogFile(const char *logfile); - void SetLogVersion(uint32_t fileversion) + void SetInitParams(const D3D11InitParams ¶ms, uint64_t sectionVersion) { LazyInit(); - m_InitParams.SerialiseVersion = fileversion; + m_InitParams = params; + m_SectionVersion = sectionVersion; } - uint32_t GetLogVersion() { return m_InitParams.SerialiseVersion; } + uint64_t GetLogVersion() { return m_SectionVersion; } virtual ~WrappedID3D11Device(); //////////////////////////////////////////////////////////////// @@ -496,7 +493,7 @@ public: void Create_InitialState(ResourceId id, ID3D11DeviceChild *live, bool hasData); void Apply_InitialState(ID3D11DeviceChild *live, D3D11ResourceManager::InitialContentData initial); - void ReadLogInitialisation(); + void ReadLogInitialisation(RDCFile *rdc); void ProcessChunk(uint64_t offset, D3D11Chunk context); void ReplayLog(uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType); diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 482e599ad..3cc84fe88 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -27,6 +27,7 @@ #include "driver/dx/official/d3dcompiler.h" #include "driver/ihv/amd/amd_isa.h" #include "driver/shaders/dxbc/dxbc_debug.h" +#include "serialise/rdcfile.h" #include "strings/string_utils.h" #include "d3d11_context.h" #include "d3d11_debug.h" @@ -1289,9 +1290,9 @@ void D3D11Replay::SavePipelineState() } } -void D3D11Replay::ReadLogInitialisation() +void D3D11Replay::ReadLogInitialisation(RDCFile *rdc) { - m_pDevice->ReadLogInitialisation(); + m_pDevice->ReadLogInitialisation(rdc); } void D3D11Replay::ReplayLog(uint32_t endEventID, ReplayLogType replayType) @@ -1907,12 +1908,16 @@ void D3D11Replay::SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSi ID3DDevice *GetD3D11DeviceIfAlloc(IUnknown *dev); -ReplayStatus D3D11_CreateReplayDevice(const char *logfile, IReplayDriver **driver) +extern "C" HRESULT RENDERDOC_CreateWrappedD3D11DeviceAndSwapChain( + __in_opt IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, + __in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL *, UINT FeatureLevels, UINT, + __in_opt CONST DXGI_SWAP_CHAIN_DESC *, __out_opt IDXGISwapChain **, __out_opt ID3D11Device **, + __out_opt D3D_FEATURE_LEVEL *, __out_opt ID3D11DeviceContext **); + +ReplayStatus D3D11_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) { RDCDEBUG("Creating a D3D11 replay device"); - WrappedIDXGISwapChain4::RegisterD3DDeviceCallback(GetD3D11DeviceIfAlloc); - HMODULE lib = NULL; lib = LoadLibraryA("d3d11.dll"); if(lib == NULL) @@ -1941,35 +1946,51 @@ ReplayStatus D3D11_CreateReplayDevice(const char *logfile, IReplayDriver **drive return ReplayStatus::APIInitFailed; } - typedef HRESULT(__cdecl * PFN_RENDERDOC_CREATE_DEVICE_AND_SWAP_CHAIN)( - __in_opt IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, - __in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL *, UINT FeatureLevels, UINT, - __in_opt CONST DXGI_SWAP_CHAIN_DESC *, __out_opt IDXGISwapChain **, __out_opt ID3D11Device **, - __out_opt D3D_FEATURE_LEVEL *, __out_opt ID3D11DeviceContext **); - - PFN_RENDERDOC_CREATE_DEVICE_AND_SWAP_CHAIN createDevice = - (PFN_RENDERDOC_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress( - GetModuleHandleA("renderdoc.dll"), "RENDERDOC_CreateWrappedD3D11DeviceAndSwapChain"); - - RDCASSERT(createDevice); - - ID3D11Device *device = NULL; - D3D11InitParams initParams; - RDCDriver driverFileType = RDC_D3D11; - string driverName = "D3D11"; - uint64_t machineIdent = 0; - if(logfile) + + uint64_t ver = D3D11InitParams::CurrentVersion; + + WrappedIDXGISwapChain4::RegisterD3DDeviceCallback(GetD3D11DeviceIfAlloc); + + // if we have an RDCFile, open the frame capture section and serialise the init params. + // if not, we're creating a proxy-capable device so use default-initialised init params. + if(rdc) { - auto status = RenderDoc::Inst().FillInitParams(logfile, driverFileType, driverName, - machineIdent, (RDCInitParams *)&initParams); - if(status != ReplayStatus::Succeeded) - return status; + int sectionIdx = rdc->SectionIndex(SectionType::FrameCapture); + + if(sectionIdx < 0) + return ReplayStatus::InternalError; + + ver = rdc->GetSectionProperties(sectionIdx).version; + + if(!D3D11InitParams::IsSupportedVersion(ver)) + { + RDCERR("Incompatible D3D11 serialise version %llu", ver); + return ReplayStatus::APIUnsupported; + } + + StreamReader *reader = rdc->ReadSection(sectionIdx); + + ReadSerialiser ser(reader, Ownership::Stream); + + SystemChunk chunk = ser.ReadChunk(); + + if(chunk != SystemChunk::DriverInit) + { + RDCERR("Expected to get a DriverInit chunk, instead got %u", chunk); + return ReplayStatus::FileCorrupted; + } + + SERIALISE_ELEMENT(initParams); + + if(ser.IsErrored()) + { + RDCERR("Failed reading driver init params."); + return ReplayStatus::FileIOFailed; + } } - // initParams.SerialiseVersion is guaranteed to be valid/supported since otherwise the - // FillInitParams (which calls D3D11InitParams::Serialise) would have failed above, so no need to - // check it here. + ID3D11Device *device = NULL; if(initParams.SDKVersion != D3D11_SDK_VERSION) { @@ -2006,8 +2027,9 @@ ReplayStatus D3D11_CreateReplayDevice(const char *logfile, IReplayDriver **drive // check for feature level 11 support - passing NULL feature level array implicitly checks for // 11_0 before others - hr = createDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, - NULL, &maxFeatureLevel, NULL); + hr = RENDERDOC_CreateWrappedD3D11DeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, + 0, D3D11_SDK_VERSION, NULL, NULL, NULL, + &maxFeatureLevel, NULL); bool warpFallback = false; @@ -2025,7 +2047,7 @@ ReplayStatus D3D11_CreateReplayDevice(const char *logfile, IReplayDriver **drive hr = E_FAIL; for(;;) { - hr = createDevice( + hr = RENDERDOC_CreateWrappedD3D11DeviceAndSwapChain( /*pAdapter=*/NULL, driverType, /*Software=*/NULL, flags, /*pFeatureLevels=*/featureLevelArray, /*nFeatureLevels=*/numFeatureLevels, D3D11_SDK_VERSION, /*pSwapChainDesc=*/NULL, (IDXGISwapChain **)NULL, (ID3D11Device **)&device, @@ -2034,20 +2056,12 @@ ReplayStatus D3D11_CreateReplayDevice(const char *logfile, IReplayDriver **drive if(SUCCEEDED(hr)) { WrappedID3D11Device *wrappedDev = (WrappedID3D11Device *)device; - if(logfile) - wrappedDev->SetLogFile(logfile); - wrappedDev->SetLogVersion(initParams.SerialiseVersion); - - if(logfile && wrappedDev->GetSerialiser()->HasError()) - { - SAFE_RELEASE(wrappedDev); - return ReplayStatus::FileIOFailed; - } + wrappedDev->SetInitParams(initParams, ver); RDCLOG("Created device."); D3D11Replay *replay = wrappedDev->GetReplay(); - replay->SetProxy(logfile == NULL, warpFallback); + replay->SetProxy(rdc == NULL, warpFallback); if(warpFallback) { wrappedDev->AddDebugMessage( diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index 3576fddfd..183a5b86b 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -73,7 +73,7 @@ public: void FreeTargetResource(ResourceId id); void FreeCustomShader(ResourceId id); - void ReadLogInitialisation(); + void ReadLogInitialisation(RDCFile *rdc); void ReplayLog(uint32_t endEventID, ReplayLogType replayType); vector GetPassEvents(uint32_t eventID);