mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
Add ability to convert a capture to structured data without replaying
This commit is contained in:
@@ -784,6 +784,13 @@ void RenderDoc::RegisterRemoteProvider(RDCDriver driver, const char *name,
|
||||
m_RemoteDriverProviders[driver] = provider;
|
||||
}
|
||||
|
||||
void RenderDoc::RegisterStructuredProcessor(RDCDriver driver, StructuredProcessor provider)
|
||||
{
|
||||
RDCASSERT(m_StructProcesssors.find(driver) == m_StructProcesssors.end());
|
||||
|
||||
m_StructProcesssors[driver] = provider;
|
||||
}
|
||||
|
||||
void RenderDoc::RegisterCaptureExporter(const char *filetype, const char *description,
|
||||
CaptureExporter exporter)
|
||||
{
|
||||
@@ -805,6 +812,16 @@ void RenderDoc::RegisterCaptureImportExporter(const char *filetype, const char *
|
||||
m_Exporters[filetype] = exporter;
|
||||
}
|
||||
|
||||
StructuredProcessor RenderDoc::GetStructuredProcessor(RDCDriver driver)
|
||||
{
|
||||
auto it = m_StructProcesssors.find(driver);
|
||||
|
||||
if(it == m_StructProcesssors.end())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
CaptureExporter RenderDoc::GetCaptureExporter(const char *filetype)
|
||||
{
|
||||
auto it = m_Exporters.find(filetype);
|
||||
|
||||
@@ -142,6 +142,11 @@ constexpr inline bool IsActiveCapturing(CaptureState state)
|
||||
return state == CaptureState::ActiveCapturing;
|
||||
}
|
||||
|
||||
constexpr inline bool IsStructuredExporting(CaptureState state)
|
||||
{
|
||||
return state == CaptureState::StructuredExport;
|
||||
}
|
||||
|
||||
enum class SystemChunk : uint32_t
|
||||
{
|
||||
// 0 is reserved as a 'null' chunk that is only for debug
|
||||
@@ -232,6 +237,8 @@ class RDCFile;
|
||||
typedef ReplayStatus (*RemoteDriverProvider)(RDCFile *rdc, IRemoteDriver **driver);
|
||||
typedef ReplayStatus (*ReplayDriverProvider)(RDCFile *rdc, IReplayDriver **driver);
|
||||
|
||||
typedef void (*StructuredProcessor)(RDCFile *rdc, SDFile &structData);
|
||||
|
||||
typedef ReplayStatus (*CaptureImporter)(const char *filename, StreamReader &reader, RDCFile *rdc,
|
||||
SDFile &structData);
|
||||
typedef ReplayStatus (*CaptureExporter)(const char *filename, const RDCFile &rdc,
|
||||
@@ -311,11 +318,15 @@ public:
|
||||
void RegisterReplayProvider(RDCDriver driver, const char *name, ReplayDriverProvider provider);
|
||||
void RegisterRemoteProvider(RDCDriver driver, const char *name, RemoteDriverProvider provider);
|
||||
|
||||
void RegisterStructuredProcessor(RDCDriver driver, StructuredProcessor provider);
|
||||
|
||||
void RegisterCaptureExporter(const char *filetype, const char *description,
|
||||
CaptureExporter exporter);
|
||||
void RegisterCaptureImportExporter(const char *filetype, const char *description,
|
||||
CaptureImporter importer, CaptureExporter exporter);
|
||||
|
||||
StructuredProcessor GetStructuredProcessor(RDCDriver driver);
|
||||
|
||||
CaptureExporter GetCaptureExporter(const char *filetype);
|
||||
CaptureImporter GetCaptureImporter(const char *filetype);
|
||||
|
||||
@@ -462,6 +473,8 @@ private:
|
||||
map<RDCDriver, ReplayDriverProvider> m_ReplayDriverProviders;
|
||||
map<RDCDriver, RemoteDriverProvider> m_RemoteDriverProviders;
|
||||
|
||||
std::map<RDCDriver, StructuredProcessor> m_StructProcesssors;
|
||||
|
||||
std::map<std::string, std::string> m_ImportExportFormats;
|
||||
std::map<std::string, CaptureImporter> m_Importers;
|
||||
std::map<std::string, CaptureExporter> m_Exporters;
|
||||
@@ -542,6 +555,14 @@ struct DriverRegistration
|
||||
}
|
||||
};
|
||||
|
||||
struct StructuredProcessRegistration
|
||||
{
|
||||
StructuredProcessRegistration(RDCDriver driver, StructuredProcessor provider)
|
||||
{
|
||||
RenderDoc::Inst().RegisterStructuredProcessor(driver, provider);
|
||||
}
|
||||
};
|
||||
|
||||
struct ConversionRegistration
|
||||
{
|
||||
ConversionRegistration(const char *filetype, const char *description, CaptureImporter importer,
|
||||
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
FrameRecord GetFrameRecord() { return m_FrameRecord; }
|
||||
const D3D11Pipe::State &GetD3D11PipelineState() { return m_PipelineState; }
|
||||
// other operations are dropped/ignored, to avoid confusion
|
||||
void ReadLogInitialisation(RDCFile *rdc) {}
|
||||
void ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers) {}
|
||||
void RenderMesh(uint32_t eventID, const vector<MeshFormat> &secondaryDraws, const MeshDisplay &cfg)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ static void ActiveRemoteClientThread(ClientThread *threadData)
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->ReadLogInitialisation(rdc);
|
||||
driver->ReadLogInitialisation(rdc, false);
|
||||
|
||||
RenderDoc::Inst().SetProgressPtr(NULL);
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
|
||||
bool IsRemoteProxy() { return !m_RemoteServer; }
|
||||
void Shutdown() { delete this; }
|
||||
void ReadLogInitialisation(RDCFile *rdc) {}
|
||||
void ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers) {}
|
||||
vector<WindowingSystem> GetSupportedWindowSystems()
|
||||
{
|
||||
if(m_Proxy)
|
||||
|
||||
@@ -97,23 +97,27 @@ WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device *real
|
||||
|
||||
D3D11_FEATURE_DATA_D3D11_OPTIONS features;
|
||||
RDCEraseEl(features);
|
||||
HRESULT hr =
|
||||
m_pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features, sizeof(features));
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if(m_pRealContext)
|
||||
hr = m_pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features, sizeof(features));
|
||||
|
||||
m_SetCBuffer1 = false;
|
||||
if(SUCCEEDED(hr))
|
||||
m_SetCBuffer1 = features.ConstantBufferOffsetting == TRUE;
|
||||
|
||||
m_pRealContext1 = NULL;
|
||||
m_pRealContext->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&m_pRealContext1);
|
||||
|
||||
m_pRealContext2 = NULL;
|
||||
m_pRealContext->QueryInterface(__uuidof(ID3D11DeviceContext2), (void **)&m_pRealContext2);
|
||||
|
||||
m_pRealContext3 = NULL;
|
||||
m_pRealContext->QueryInterface(__uuidof(ID3D11DeviceContext3), (void **)&m_pRealContext3);
|
||||
if(m_pRealContext)
|
||||
{
|
||||
m_pRealContext->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&m_pRealContext1);
|
||||
m_pRealContext->QueryInterface(__uuidof(ID3D11DeviceContext2), (void **)&m_pRealContext2);
|
||||
m_pRealContext->QueryInterface(__uuidof(ID3D11DeviceContext3), (void **)&m_pRealContext3);
|
||||
}
|
||||
|
||||
m_NeedUpdateSubWorkaround = false;
|
||||
if(m_pRealContext)
|
||||
{
|
||||
D3D11_FEATURE_DATA_THREADING caps = {FALSE, FALSE};
|
||||
|
||||
@@ -167,7 +171,7 @@ WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device *real
|
||||
m_DeferredSavedState = NULL;
|
||||
m_DoStateVerify = IsCaptureMode(m_State);
|
||||
|
||||
if(context->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE)
|
||||
if(!context || context->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE)
|
||||
{
|
||||
m_CurrentPipelineState->SetImmediatePipeline(m_pDevice);
|
||||
}
|
||||
@@ -188,7 +192,7 @@ WrappedID3D11DeviceContext::~WrappedID3D11DeviceContext()
|
||||
if(m_ContextRecord)
|
||||
m_ContextRecord->Delete(m_pDevice->GetResourceManager());
|
||||
|
||||
if(m_pRealContext->GetType() != D3D11_DEVICE_CONTEXT_IMMEDIATE)
|
||||
if(m_pRealContext && m_pRealContext->GetType() != D3D11_DEVICE_CONTEXT_IMMEDIATE)
|
||||
m_pDevice->RemoveDeferredContext(this);
|
||||
|
||||
for(auto it = m_StreamOutCounters.begin(); it != m_StreamOutCounters.end(); ++it)
|
||||
@@ -1049,8 +1053,12 @@ void WrappedID3D11DeviceContext::ReplayLog(CaptureState readType, uint32_t start
|
||||
ser.SetStringDatabase(&m_StringDB);
|
||||
ser.SetUserData(GetResourceManager());
|
||||
|
||||
if(IsLoading(m_State))
|
||||
ser.ConfigureStructuredExport(&GetChunkName, false);
|
||||
if(IsLoading(m_State) || IsStructuredExporting(m_State))
|
||||
{
|
||||
ser.ConfigureStructuredExport(&GetChunkName, IsStructuredExporting(m_State));
|
||||
|
||||
ser.GetStructuredFile().swap(m_pDevice->GetStructuredFile());
|
||||
}
|
||||
|
||||
m_DoStateVerify = true;
|
||||
|
||||
@@ -1196,6 +1204,10 @@ void WrappedID3D11DeviceContext::ReplayLog(CaptureState readType, uint32_t start
|
||||
// RDCDEBUG("Can skip %d initial states.", initialSkips);
|
||||
}
|
||||
|
||||
// swap the structure back now that we've accumulated the frame as well.
|
||||
if(IsLoading(m_State) || IsStructuredExporting(m_State))
|
||||
ser.GetStructuredFile().swap(m_pDevice->GetStructuredFile());
|
||||
|
||||
m_pDevice->GetResourceManager()->MarkInFrame(false);
|
||||
|
||||
m_DoStateVerify = false;
|
||||
|
||||
@@ -68,17 +68,19 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
|
||||
|
||||
m_ScratchSerialiser.SetChunkMetadataRecording(flags);
|
||||
|
||||
m_StructuredFile = &m_StoredStructuredData;
|
||||
|
||||
m_pDevice1 = NULL;
|
||||
m_pDevice->QueryInterface(__uuidof(ID3D11Device1), (void **)&m_pDevice1);
|
||||
|
||||
m_pDevice2 = NULL;
|
||||
m_pDevice->QueryInterface(__uuidof(ID3D11Device2), (void **)&m_pDevice2);
|
||||
|
||||
m_pDevice3 = NULL;
|
||||
m_pDevice->QueryInterface(__uuidof(ID3D11Device3), (void **)&m_pDevice3);
|
||||
|
||||
m_pDevice4 = NULL;
|
||||
m_pDevice->QueryInterface(__uuidof(ID3D11Device4), (void **)&m_pDevice4);
|
||||
if(m_pDevice)
|
||||
{
|
||||
m_pDevice->QueryInterface(__uuidof(ID3D11Device1), (void **)&m_pDevice1);
|
||||
m_pDevice->QueryInterface(__uuidof(ID3D11Device2), (void **)&m_pDevice2);
|
||||
m_pDevice->QueryInterface(__uuidof(ID3D11Device3), (void **)&m_pDevice3);
|
||||
m_pDevice->QueryInterface(__uuidof(ID3D11Device4), (void **)&m_pDevice4);
|
||||
}
|
||||
|
||||
m_Replay.SetDevice(this);
|
||||
|
||||
@@ -104,12 +106,6 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
|
||||
#if ENABLED(RDOC_RELEASE)
|
||||
const bool debugSerialiser = false;
|
||||
#else
|
||||
const bool debugSerialiser = true;
|
||||
#endif
|
||||
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
m_State = CaptureState::LoadingReplaying;
|
||||
@@ -148,17 +144,22 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
|
||||
}
|
||||
|
||||
ID3D11DeviceContext *context = NULL;
|
||||
realDevice->GetImmediateContext(&context);
|
||||
if(realDevice)
|
||||
realDevice->GetImmediateContext(&context);
|
||||
|
||||
m_pImmediateContext = new WrappedID3D11DeviceContext(this, context);
|
||||
|
||||
realDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&m_pInfoQueue);
|
||||
realDevice->QueryInterface(__uuidof(ID3D11Debug), (void **)&m_WrappedDebug.m_pDebug);
|
||||
m_pInfoQueue = NULL;
|
||||
if(realDevice)
|
||||
{
|
||||
realDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&m_pInfoQueue);
|
||||
realDevice->QueryInterface(__uuidof(ID3D11Debug), (void **)&m_WrappedDebug.m_pDebug);
|
||||
}
|
||||
|
||||
// useful for marking regions during replay for self-captures
|
||||
m_RealAnnotations = NULL;
|
||||
m_pImmediateContext->GetReal()->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
|
||||
(void **)&m_RealAnnotations);
|
||||
if(context)
|
||||
context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation), (void **)&m_RealAnnotations);
|
||||
|
||||
if(m_pInfoQueue)
|
||||
{
|
||||
@@ -186,12 +187,13 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
m_pInfoQueue->SetMuteDebugOutput(false);
|
||||
}
|
||||
else
|
||||
else if(m_pDevice)
|
||||
{
|
||||
RDCDEBUG("Couldn't get ID3D11InfoQueue.");
|
||||
}
|
||||
|
||||
m_InitParams = *params;
|
||||
if(params)
|
||||
m_InitParams = *params;
|
||||
|
||||
// ATI workaround - these dlls can get unloaded and cause a crash.
|
||||
|
||||
@@ -752,8 +754,11 @@ void WrappedID3D11Device::ProcessChunk(ReadSerialiser &ser, D3D11Chunk context)
|
||||
// add a reference for the resource manager - normally it takes ownership of the resource on
|
||||
// creation and releases it
|
||||
// to destruction, but we want to control our immediate context ourselves.
|
||||
m_pImmediateContext->AddRef();
|
||||
m_ResourceManager->AddLiveResource(ImmediateContext, m_pImmediateContext);
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
m_pImmediateContext->AddRef();
|
||||
m_ResourceManager->AddLiveResource(ImmediateContext, m_pImmediateContext);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case D3D11Chunk::SetResourceName: Serialise_SetResourceName(ser, 0x0, ""); break;
|
||||
@@ -901,7 +906,7 @@ void WrappedID3D11Device::Serialise_CaptureScope(SerialiserType &ser)
|
||||
}
|
||||
}
|
||||
|
||||
void WrappedID3D11Device::ReadLogInitialisation(RDCFile *rdc)
|
||||
void WrappedID3D11Device::ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers)
|
||||
{
|
||||
int sectionIdx = rdc->SectionIndex(SectionType::FrameCapture);
|
||||
|
||||
@@ -918,8 +923,11 @@ void WrappedID3D11Device::ReadLogInitialisation(RDCFile *rdc)
|
||||
ser.SetStringDatabase(&m_StringDB);
|
||||
ser.SetUserData(GetResourceManager());
|
||||
|
||||
// TODO make this an option passed in
|
||||
ser.ConfigureStructuredExport(&GetChunkName, false);
|
||||
ser.ConfigureStructuredExport(&GetChunkName, storeStructuredBuffers);
|
||||
|
||||
m_StructuredFile = &ser.GetStructuredFile();
|
||||
|
||||
m_StoredStructuredData.version = m_StructuredFile->version = m_SectionVersion;
|
||||
|
||||
int chunkIdx = 0;
|
||||
|
||||
@@ -964,7 +972,8 @@ void WrappedID3D11Device::ReadLogInitialisation(RDCFile *rdc)
|
||||
|
||||
m_pImmediateContext->SetFrameReader(new StreamReader(reader, frameDataSize));
|
||||
|
||||
GetResourceManager()->ApplyInitialContents();
|
||||
if(!IsStructuredExporting(m_State))
|
||||
GetResourceManager()->ApplyInitialContents();
|
||||
|
||||
m_pImmediateContext->ReplayLog(m_State, 0, 0, false);
|
||||
}
|
||||
@@ -977,8 +986,17 @@ void WrappedID3D11Device::ReadLogInitialisation(RDCFile *rdc)
|
||||
break;
|
||||
}
|
||||
|
||||
DrawcallDescription *previous = NULL;
|
||||
SetupDrawcallPointers(&m_Drawcalls, GetFrameRecord().drawcallList, NULL, previous);
|
||||
// steal the structured data for ourselves
|
||||
m_StructuredFile->swap(m_StoredStructuredData);
|
||||
|
||||
// and in future use this file.
|
||||
m_StructuredFile = &m_StoredStructuredData;
|
||||
|
||||
if(!IsStructuredExporting(m_State))
|
||||
{
|
||||
DrawcallDescription *previous = NULL;
|
||||
SetupDrawcallPointers(&m_Drawcalls, GetFrameRecord().drawcallList, NULL, previous);
|
||||
}
|
||||
|
||||
#if ENABLED(RDOC_DEVEL)
|
||||
for(auto it = chunkInfos.begin(); it != chunkInfos.end(); ++it)
|
||||
|
||||
@@ -393,6 +393,9 @@ private:
|
||||
CaptureFailReason m_FailedReason;
|
||||
uint32_t m_Failures;
|
||||
|
||||
SDFile *m_StructuredFile = NULL;
|
||||
SDFile m_StoredStructuredData;
|
||||
|
||||
vector<DebugMessage> m_DebugMessages;
|
||||
|
||||
vector<FrameDescription> m_CapturedFrames;
|
||||
@@ -440,6 +443,7 @@ public:
|
||||
void LockForChunkRemoval();
|
||||
void UnlockForChunkRemoval();
|
||||
|
||||
SDFile &GetStructuredFile() { return *m_StructuredFile; }
|
||||
void FirstFrame(WrappedIDXGISwapChain4 *swapChain);
|
||||
|
||||
std::vector<DebugMessage> GetDebugMessages();
|
||||
@@ -500,7 +504,12 @@ public:
|
||||
void Create_InitialState(ResourceId id, ID3D11DeviceChild *live, bool hasData);
|
||||
void Apply_InitialState(ID3D11DeviceChild *live, D3D11ResourceManager::InitialContentData initial);
|
||||
|
||||
void ReadLogInitialisation(RDCFile *rdc);
|
||||
void SetStructuredExport(uint64_t sectionVersion)
|
||||
{
|
||||
m_SectionVersion = sectionVersion;
|
||||
m_State = CaptureState::StructuredExport;
|
||||
}
|
||||
void ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
|
||||
void ProcessChunk(ReadSerialiser &ser, D3D11Chunk context);
|
||||
void ReplayLog(uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType);
|
||||
|
||||
|
||||
@@ -934,6 +934,9 @@ bool WrappedID3D11Device::Serialise_InitialState(SerialiserType &ser, ResourceId
|
||||
|
||||
void WrappedID3D11Device::Create_InitialState(ResourceId id, ID3D11DeviceChild *live, bool hasData)
|
||||
{
|
||||
if(IsStructuredExporting(m_State))
|
||||
return;
|
||||
|
||||
ResourceType type = IdentifyTypeByPtr(live);
|
||||
|
||||
{
|
||||
|
||||
@@ -1290,9 +1290,9 @@ void D3D11Replay::SavePipelineState()
|
||||
}
|
||||
}
|
||||
|
||||
void D3D11Replay::ReadLogInitialisation(RDCFile *rdc)
|
||||
void D3D11Replay::ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers)
|
||||
{
|
||||
m_pDevice->ReadLogInitialisation(rdc);
|
||||
m_pDevice->ReadLogInitialisation(rdc, storeStructuredBuffers);
|
||||
}
|
||||
|
||||
void D3D11Replay::ReplayLog(uint32_t endEventID, ReplayLogType replayType)
|
||||
@@ -2110,3 +2110,16 @@ ReplayStatus D3D11_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
|
||||
}
|
||||
|
||||
static DriverRegistration D3D11DriverRegistration(RDC_D3D11, "D3D11", &D3D11_CreateReplayDevice);
|
||||
|
||||
void D3D11_ProcessStructured(RDCFile *rdc, SDFile &output)
|
||||
{
|
||||
WrappedID3D11Device device(NULL, NULL);
|
||||
|
||||
device.SetStructuredExport(
|
||||
rdc->GetSectionProperties(rdc->SectionIndex(SectionType::FrameCapture)).version);
|
||||
device.ReadLogInitialisation(rdc, true);
|
||||
|
||||
device.GetStructuredFile().swap(output);
|
||||
}
|
||||
|
||||
static StructuredProcessRegistration D3D11ProcessRegistration(RDC_D3D11, &D3D11_ProcessStructured);
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
void FreeTargetResource(ResourceId id);
|
||||
void FreeCustomShader(ResourceId id);
|
||||
|
||||
void ReadLogInitialisation(RDCFile *rdc);
|
||||
void ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
|
||||
void ReplayLog(uint32_t endEventID, ReplayLogType replayType);
|
||||
|
||||
vector<uint32_t> GetPassEvents(uint32_t eventID);
|
||||
|
||||
@@ -99,6 +99,8 @@ WrappedVulkan::WrappedVulkan() : m_RenderState(this, &m_CreationInfo)
|
||||
m_State = CaptureState::BackgroundCapturing;
|
||||
}
|
||||
|
||||
m_StructuredFile = &m_StoredStructuredData;
|
||||
|
||||
m_SectionVersion = VkInitParams::CurrentVersion;
|
||||
|
||||
InitSPIRVCompiler();
|
||||
@@ -1383,7 +1385,7 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
|
||||
return true;
|
||||
}
|
||||
|
||||
void WrappedVulkan::ReadLogInitialisation(RDCFile *rdc)
|
||||
void WrappedVulkan::ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers)
|
||||
{
|
||||
int sectionIdx = rdc->SectionIndex(SectionType::FrameCapture);
|
||||
|
||||
@@ -1400,9 +1402,11 @@ void WrappedVulkan::ReadLogInitialisation(RDCFile *rdc)
|
||||
ser.SetStringDatabase(&m_StringDB);
|
||||
ser.SetUserData(GetResourceManager());
|
||||
|
||||
// TODO make this an option passed in
|
||||
ser.ConfigureStructuredExport(&GetChunkName, false);
|
||||
ser.ConfigureStructuredExport(&GetChunkName, storeStructuredBuffers);
|
||||
|
||||
m_StructuredFile = &ser.GetStructuredFile();
|
||||
|
||||
m_StoredStructuredData.version = m_StructuredFile->version = m_SectionVersion;
|
||||
|
||||
int chunkIdx = 0;
|
||||
|
||||
@@ -1472,6 +1476,12 @@ void WrappedVulkan::ReadLogInitialisation(RDCFile *rdc)
|
||||
}
|
||||
#endif
|
||||
|
||||
// steal the structured data for ourselves
|
||||
m_StructuredFile->swap(m_StoredStructuredData);
|
||||
|
||||
// and in future use this file.
|
||||
m_StructuredFile = &m_StoredStructuredData;
|
||||
|
||||
m_FrameRecord.frameInfo.uncompressedFileSize =
|
||||
rdc->GetSectionProperties(sectionIdx).uncompressedSize;
|
||||
m_FrameRecord.frameInfo.compressedFileSize = rdc->GetSectionProperties(sectionIdx).compressedSize;
|
||||
@@ -1483,8 +1493,11 @@ void WrappedVulkan::ReadLogInitialisation(RDCFile *rdc)
|
||||
m_FrameRecord.frameInfo.persistentSize);
|
||||
|
||||
// ensure the capture at least created a device and fetched a queue.
|
||||
RDCASSERT(m_Device != VK_NULL_HANDLE && m_Queue != VK_NULL_HANDLE &&
|
||||
m_InternalCmds.cmdpool != VK_NULL_HANDLE);
|
||||
if(!IsStructuredExporting(m_State))
|
||||
{
|
||||
RDCASSERT(m_Device != VK_NULL_HANDLE && m_Queue != VK_NULL_HANDLE &&
|
||||
m_InternalCmds.cmdpool != VK_NULL_HANDLE);
|
||||
}
|
||||
}
|
||||
|
||||
void WrappedVulkan::ContextReplayLog(CaptureState readType, uint32_t startEventID,
|
||||
@@ -1497,9 +1510,17 @@ void WrappedVulkan::ContextReplayLog(CaptureState readType, uint32_t startEventI
|
||||
ser.SetStringDatabase(&m_StringDB);
|
||||
ser.SetUserData(GetResourceManager());
|
||||
|
||||
if(IsLoading(m_State))
|
||||
SDFile *prevFile = m_StructuredFile;
|
||||
|
||||
if(IsLoading(m_State) || IsStructuredExporting(m_State))
|
||||
{
|
||||
ser.ConfigureStructuredExport(&GetChunkName, false);
|
||||
|
||||
ser.GetStructuredFile().swap(*m_StructuredFile);
|
||||
|
||||
m_StructuredFile = &ser.GetStructuredFile();
|
||||
}
|
||||
|
||||
VulkanChunk header = ser.ReadChunk<VulkanChunk>();
|
||||
RDCASSERTEQUAL(header, VulkanChunk::CaptureBegin);
|
||||
|
||||
@@ -1510,7 +1531,8 @@ void WrappedVulkan::ContextReplayLog(CaptureState readType, uint32_t startEventI
|
||||
|
||||
ser.EndChunk();
|
||||
|
||||
ObjDisp(GetDev())->DeviceWaitIdle(Unwrap(GetDev()));
|
||||
if(!IsStructuredExporting(m_State))
|
||||
ObjDisp(GetDev())->DeviceWaitIdle(Unwrap(GetDev()));
|
||||
|
||||
// apply initial contents here so that images are in the right layout
|
||||
// (not undefined)
|
||||
@@ -1606,6 +1628,12 @@ void WrappedVulkan::ContextReplayLog(CaptureState readType, uint32_t startEventI
|
||||
}
|
||||
}
|
||||
|
||||
// swap the structure back now that we've accumulated the frame as well.
|
||||
if(IsLoading(m_State) || IsStructuredExporting(m_State))
|
||||
ser.GetStructuredFile().swap(*prevFile);
|
||||
|
||||
m_StructuredFile = prevFile;
|
||||
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
GetFrameRecord().drawcallList = m_ParentDrawcall.Bake();
|
||||
@@ -1622,11 +1650,14 @@ void WrappedVulkan::ContextReplayLog(CaptureState readType, uint32_t startEventI
|
||||
m_ParentDrawcall.children.clear();
|
||||
}
|
||||
|
||||
ObjDisp(GetDev())->DeviceWaitIdle(Unwrap(GetDev()));
|
||||
if(!IsStructuredExporting(m_State))
|
||||
{
|
||||
ObjDisp(GetDev())->DeviceWaitIdle(Unwrap(GetDev()));
|
||||
|
||||
// destroy any events we created for waiting on
|
||||
for(size_t i = 0; i < m_CleanupEvents.size(); i++)
|
||||
ObjDisp(GetDev())->DestroyEvent(Unwrap(GetDev()), m_CleanupEvents[i], NULL);
|
||||
// destroy any events we created for waiting on
|
||||
for(size_t i = 0; i < m_CleanupEvents.size(); i++)
|
||||
ObjDisp(GetDev())->DestroyEvent(Unwrap(GetDev()), m_CleanupEvents[i], NULL);
|
||||
}
|
||||
|
||||
m_CleanupEvents.clear();
|
||||
|
||||
|
||||
@@ -259,6 +259,9 @@ private:
|
||||
|
||||
VulkanDrawcallCallback *m_DrawcallCallback;
|
||||
|
||||
SDFile *m_StructuredFile;
|
||||
SDFile m_StoredStructuredData;
|
||||
|
||||
// util function to handle fetching the right eventID, calling any
|
||||
// aliases then calling PreDraw/PreDispatch.
|
||||
uint32_t HandlePreCallback(VkCommandBuffer commandBuffer, DrawFlags type = DrawFlags::Drawcall,
|
||||
@@ -742,10 +745,16 @@ public:
|
||||
|
||||
ReplayStatus Initialise(VkInitParams ¶ms, uint64_t sectionVersion);
|
||||
uint64_t GetLogVersion() { return m_SectionVersion; }
|
||||
void SetStructuredExport(uint64_t sectionVersion)
|
||||
{
|
||||
m_SectionVersion = sectionVersion;
|
||||
m_State = CaptureState::StructuredExport;
|
||||
}
|
||||
void Shutdown();
|
||||
void ReplayLog(uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType);
|
||||
void ReadLogInitialisation(RDCFile *rdc);
|
||||
void ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
|
||||
|
||||
SDFile &GetStructuredFile() { return *m_StructuredFile; }
|
||||
FrameRecord &GetFrameRecord() { return m_FrameRecord; }
|
||||
const APIEvent &GetEvent(uint32_t eventID);
|
||||
uint32_t GetMaxEID() { return m_Events.back().eventID; }
|
||||
|
||||
@@ -712,7 +712,7 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, W
|
||||
}
|
||||
else if(type == eResDeviceMemory || type == eResImage)
|
||||
{
|
||||
VkDevice d = GetDev();
|
||||
VkDevice d = !IsStructuredExporting(m_State) ? GetDev() : VK_NULL_HANDLE;
|
||||
VulkanResourceManager::InitialContentData initContents =
|
||||
GetResourceManager()->GetInitialContents(id);
|
||||
|
||||
@@ -797,7 +797,8 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, W
|
||||
ser.Serialise("Contents", Contents, ContentsSize, SerialiserFlags::NoFlags);
|
||||
|
||||
// unmap the resource we mapped before - we need to do this on read and on write.
|
||||
ObjDisp(d)->UnmapMemory(Unwrap(d), Unwrap(mappedMem));
|
||||
if(!IsStructuredExporting(m_State))
|
||||
ObjDisp(d)->UnmapMemory(Unwrap(d), Unwrap(mappedMem));
|
||||
|
||||
// if we're handling a device memory object, we're done - we note the memory object to delete at
|
||||
// the end of the program, and store the buffer to copy off in Apply
|
||||
@@ -1023,6 +1024,9 @@ template bool WrappedVulkan::Serialise_InitialState(WriteSerialiser &ser, Resour
|
||||
|
||||
void WrappedVulkan::Create_InitialState(ResourceId id, WrappedVkRes *live, bool hasData)
|
||||
{
|
||||
if(IsStructuredExporting(m_State))
|
||||
return;
|
||||
|
||||
VkResourceType type = IdentifyTypeByPtr(live);
|
||||
|
||||
if(type == eResDescriptorSet)
|
||||
|
||||
@@ -659,9 +659,9 @@ APIProperties VulkanReplay::GetAPIProperties()
|
||||
return ret;
|
||||
}
|
||||
|
||||
void VulkanReplay::ReadLogInitialisation(RDCFile *rdc)
|
||||
void VulkanReplay::ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers)
|
||||
{
|
||||
m_pDriver->ReadLogInitialisation(rdc);
|
||||
m_pDriver->ReadLogInitialisation(rdc, storeStructuredBuffers);
|
||||
}
|
||||
|
||||
void VulkanReplay::ReplayLog(uint32_t endEventID, ReplayLogType replayType)
|
||||
@@ -5429,3 +5429,15 @@ struct VulkanDriverRegistration
|
||||
};
|
||||
|
||||
static VulkanDriverRegistration VkDriverRegistration;
|
||||
|
||||
void Vulkan_ProcessStructured(RDCFile *rdc, SDFile &output)
|
||||
{
|
||||
WrappedVulkan vulkan;
|
||||
vulkan.SetStructuredExport(
|
||||
rdc->GetSectionProperties(rdc->SectionIndex(SectionType::FrameCapture)).version);
|
||||
vulkan.ReadLogInitialisation(rdc, true);
|
||||
|
||||
vulkan.GetStructuredFile().swap(output);
|
||||
}
|
||||
|
||||
static StructuredProcessRegistration VulkanProcessRegistration(RDC_Vulkan, &Vulkan_ProcessStructured);
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
const VKPipe::State &GetVulkanPipelineState() { return m_VulkanPipelineState; }
|
||||
void FreeTargetResource(ResourceId id);
|
||||
|
||||
void ReadLogInitialisation(RDCFile *rdc);
|
||||
void ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
|
||||
void ReplayLog(uint32_t endEventID, ReplayLogType replayType);
|
||||
|
||||
vector<uint32_t> GetPassEvents(uint32_t eventID);
|
||||
|
||||
@@ -478,7 +478,7 @@ template <typename SerialiserType>
|
||||
bool WrappedVulkan::Serialise_SparseBufferInitialState(
|
||||
SerialiserType &ser, ResourceId id, VulkanResourceManager::InitialContentData contents)
|
||||
{
|
||||
VkDevice d = GetDev();
|
||||
VkDevice d = !IsStructuredExporting(m_State) ? GetDev() : VK_NULL_HANDLE;
|
||||
VkResult vkr = VK_SUCCESS;
|
||||
|
||||
SparseBufferInitState *info = (SparseBufferInitState *)contents.blob;
|
||||
@@ -580,7 +580,7 @@ template <typename SerialiserType>
|
||||
bool WrappedVulkan::Serialise_SparseImageInitialState(SerialiserType &ser, ResourceId id,
|
||||
VulkanResourceManager::InitialContentData contents)
|
||||
{
|
||||
VkDevice d = GetDev();
|
||||
VkDevice d = !IsStructuredExporting(m_State) ? GetDev() : VK_NULL_HANDLE;
|
||||
VkResult vkr = VK_SUCCESS;
|
||||
|
||||
SparseImageInitState *info = (SparseImageInitState *)contents.blob;
|
||||
|
||||
@@ -131,7 +131,17 @@ public:
|
||||
|
||||
const SDFile &GetStructuredData()
|
||||
{
|
||||
// TODO - fetch structured data from capture on demand?
|
||||
if(m_StructuredData.chunks.empty() && m_RDC && m_RDC->SectionIndex(SectionType::FrameCapture) >= 0)
|
||||
{
|
||||
// decompile to structured data on demand.
|
||||
StructuredProcessor proc = RenderDoc::Inst().GetStructuredProcessor(m_RDC->GetDriver());
|
||||
|
||||
if(proc)
|
||||
proc(m_RDC, m_StructuredData);
|
||||
else
|
||||
RDCERR("Can't get structured data for driver %s", m_RDC->GetDriverName().c_str());
|
||||
}
|
||||
|
||||
return m_StructuredData;
|
||||
}
|
||||
|
||||
|
||||
@@ -1545,7 +1545,7 @@ ReplayStatus ReplayController::PostCreateInit(IReplayDriver *device, RDCFile *rd
|
||||
{
|
||||
m_pDevice = device;
|
||||
|
||||
m_pDevice->ReadLogInitialisation(rdc);
|
||||
m_pDevice->ReadLogInitialisation(rdc, false);
|
||||
|
||||
FetchPipelineState();
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
|
||||
virtual FrameRecord GetFrameRecord() = 0;
|
||||
|
||||
virtual void ReadLogInitialisation(RDCFile *rdc) = 0;
|
||||
virtual void ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers) = 0;
|
||||
virtual void ReplayLog(uint32_t endEventID, ReplayLogType replayType) = 0;
|
||||
|
||||
virtual vector<uint32_t> GetPassEvents(uint32_t eventID) = 0;
|
||||
|
||||
@@ -618,6 +618,125 @@ struct ReplayCommand : public Command
|
||||
}
|
||||
};
|
||||
|
||||
struct ConvertCommand : public Command
|
||||
{
|
||||
rdcarray<CaptureFileFormat> m_Formats;
|
||||
|
||||
ConvertCommand(const GlobalEnvironment &env) : Command(env)
|
||||
{
|
||||
ICaptureFile *tmp = RENDERDOC_OpenCaptureFile();
|
||||
|
||||
m_Formats = tmp->GetCaptureFileFormats();
|
||||
|
||||
tmp->Shutdown();
|
||||
}
|
||||
|
||||
virtual void AddOptions(cmdline::parser &parser)
|
||||
{
|
||||
cmdline::oneof_reader<string> formatOptions;
|
||||
for(CaptureFileFormat f : m_Formats)
|
||||
formatOptions.add(f.name);
|
||||
|
||||
parser.add<string>("filename", 'f', "The file to convert from.", false);
|
||||
parser.add<string>("output", 'o', "The file to convert from.", false);
|
||||
parser.add<string>("input-format", 'i', "The format of the input file.", false, "",
|
||||
formatOptions);
|
||||
parser.add<string>("convert-format", 'c', "The format of the output file.", false, "",
|
||||
formatOptions);
|
||||
parser.add("list-formats", '\0', "print a list of target formats");
|
||||
parser.stop_at_rest(true);
|
||||
}
|
||||
virtual const char *Description() { return "Run internal tests such as unit tests."; }
|
||||
virtual bool IsInternalOnly() { return false; }
|
||||
virtual bool IsCaptureCommand() { return false; }
|
||||
virtual int Execute(cmdline::parser &parser, const CaptureOptions &)
|
||||
{
|
||||
if(parser.exist("list-formats"))
|
||||
{
|
||||
std::cerr << "Available formats:" << std::endl;
|
||||
for(CaptureFileFormat f : m_Formats)
|
||||
std::cerr << "'" << (std::string)f.name << "': " << (std::string)f.description << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string infile = parser.get<string>("filename");
|
||||
std::string outfile = parser.get<string>("output");
|
||||
|
||||
if(infile.empty())
|
||||
{
|
||||
std::cerr << "Need an input filename." << std::endl;
|
||||
std::cerr << parser.usage() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(outfile.empty())
|
||||
{
|
||||
std::cerr << "Need an output filename." << std::endl;
|
||||
std::cerr << parser.usage() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string infmt = parser.get<string>("input-format");
|
||||
std::string outfmt = parser.get<string>("convert-format");
|
||||
|
||||
if(infmt.empty())
|
||||
{
|
||||
// try to guess the format by looking for the extension in the filename
|
||||
for(CaptureFileFormat f : m_Formats)
|
||||
{
|
||||
string extension = ".";
|
||||
extension += f.name;
|
||||
|
||||
if(infile.find(extension.c_str()) != string::npos)
|
||||
{
|
||||
infmt = f.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(outfmt.empty())
|
||||
{
|
||||
// try to guess the format by looking for the extension in the filename
|
||||
for(CaptureFileFormat f : m_Formats)
|
||||
{
|
||||
string extension = ".";
|
||||
extension += f.name;
|
||||
|
||||
if(outfile.find(extension.c_str()) != string::npos)
|
||||
{
|
||||
outfmt = f.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ICaptureFile *file = RENDERDOC_OpenCaptureFile();
|
||||
|
||||
ReplayStatus st = file->OpenFile(infile.c_str(), infmt.c_str());
|
||||
|
||||
if(st != ReplayStatus::Succeeded)
|
||||
{
|
||||
std::cerr << "Couldn't load '" << infile << "' as '" << infmt << "': " << ToStr(st)
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
st = file->Convert(outfile.c_str(), outfmt.c_str());
|
||||
|
||||
if(st != ReplayStatus::Succeeded)
|
||||
{
|
||||
std::cerr << "Couldn't convert '" << infile << "' to '" << outfile << "' as '" << outfmt
|
||||
<< "': " << ToStr(st) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Converted '" << infile << "' to '" << outfile << "'" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct TestCommand : public Command
|
||||
{
|
||||
TestCommand(const GlobalEnvironment &env) : Command(env) {}
|
||||
@@ -783,6 +902,7 @@ int renderdoccmd(const GlobalEnvironment &env, std::vector<std::string> &argv)
|
||||
add_command("replay", new ReplayCommand(env));
|
||||
add_command("capaltbit", new CapAltBitCommand(env));
|
||||
add_command("test", new TestCommand(env));
|
||||
add_command("convert", new ConvertCommand(env));
|
||||
|
||||
if(argv.size() <= 1)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user