mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
Expand IStackResolver into ICaptureAccess to allow section read/write
This commit is contained in:
@@ -668,7 +668,7 @@ struct IReplayManager
|
||||
:return: The file handle active, or ``None`` if no capture is open.
|
||||
:rtype: StackResolver
|
||||
)");
|
||||
virtual IStackResolver *GetResolver() = 0;
|
||||
virtual ICaptureAccess *GetCaptureAccess() = 0;
|
||||
|
||||
DOCUMENT(R"(Launch an application and inject into it to allow capturing.
|
||||
|
||||
|
||||
@@ -75,12 +75,12 @@ public:
|
||||
void ShutdownServer();
|
||||
void PingRemote();
|
||||
|
||||
IStackResolver *GetResolver()
|
||||
ICaptureAccess *GetCaptureAccess()
|
||||
{
|
||||
if(m_CaptureFile)
|
||||
return m_CaptureFile;
|
||||
if(m_Remote)
|
||||
return m_Remote;
|
||||
if(m_CaptureFile)
|
||||
return m_CaptureFile;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,10 +101,10 @@ void APIInspector::on_apiEvents_itemSelectionChanged()
|
||||
|
||||
if(!ev.callstack.isEmpty())
|
||||
{
|
||||
if(m_Ctx.Replay().GetResolver())
|
||||
if(m_Ctx.Replay().GetCaptureAccess())
|
||||
{
|
||||
m_Ctx.Replay().AsyncInvoke([this, ev](IReplayController *) {
|
||||
rdcarray<rdcstr> stack = m_Ctx.Replay().GetResolver()->GetResolve(ev.callstack);
|
||||
rdcarray<rdcstr> stack = m_Ctx.Replay().GetCaptureAccess()->GetResolve(ev.callstack);
|
||||
|
||||
GUIInvoke::call([this, stack]() { addCallstack(stack); });
|
||||
});
|
||||
|
||||
@@ -1241,7 +1241,7 @@ void MainWindow::OnCaptureLoaded()
|
||||
ui->action_Resolve_Symbols->setEnabled(false);
|
||||
|
||||
m_Ctx.Replay().AsyncInvoke([this](IReplayController *) {
|
||||
bool hasResolver = m_Ctx.Replay().GetResolver()->HasCallstacks();
|
||||
bool hasResolver = m_Ctx.Replay().GetCaptureAccess()->HasCallstacks();
|
||||
|
||||
GUIInvoke::call([this, hasResolver]() {
|
||||
ui->action_Resolve_Symbols->setEnabled(hasResolver);
|
||||
@@ -1505,7 +1505,7 @@ void MainWindow::on_action_Python_Shell_triggered()
|
||||
|
||||
void MainWindow::on_action_Resolve_Symbols_triggered()
|
||||
{
|
||||
if(!m_Ctx.Replay().GetResolver())
|
||||
if(!m_Ctx.Replay().GetCaptureAccess())
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("Not Available"),
|
||||
@@ -1517,7 +1517,7 @@ void MainWindow::on_action_Resolve_Symbols_triggered()
|
||||
bool finished = false;
|
||||
|
||||
m_Ctx.Replay().AsyncInvoke([this, &progress, &finished](IReplayController *) {
|
||||
bool success = m_Ctx.Replay().GetResolver()->InitResolver(&progress, NULL);
|
||||
bool success = m_Ctx.Replay().GetCaptureAccess()->InitResolver(&progress, NULL);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
|
||||
@@ -1074,11 +1074,57 @@ protected:
|
||||
~ITargetControl() = default;
|
||||
};
|
||||
|
||||
DOCUMENT(R"(An interface for resolving callstacks. This is separate since it can be either
|
||||
implemented locally by a file handle, or remotely to an open capture.
|
||||
DOCUMENT(R"(An interface for accessing a capture, possibly over a network connection. This is a
|
||||
subset of the functionality provided in :class:`CaptureFile` which only supports import/export
|
||||
and construction of files.
|
||||
)");
|
||||
struct IStackResolver
|
||||
struct ICaptureAccess
|
||||
{
|
||||
DOCUMENT(R"(Locate the index of a section by its name. Returns ``-1`` if the section is not found.
|
||||
|
||||
This index should not be cached, as writing sections could re-order the indices.
|
||||
|
||||
:param str name: The name of the section to search for.
|
||||
:return: The index of the section, or ``-1`` if not found.
|
||||
:rtype: ``int``.
|
||||
)");
|
||||
virtual int FindSectionByName(const char *name) = 0;
|
||||
|
||||
DOCUMENT(R"(Locate the index of a section by its type. Returns ``-1`` if the section is not found.
|
||||
|
||||
This index should not be cached, as writing sections could re-order the indices.
|
||||
|
||||
:param SectionType type: The type of the section to search for.
|
||||
:return: The index of the section, or ``-1`` if not found.
|
||||
:rtype: ``int``.
|
||||
)");
|
||||
virtual int FindSectionByType(SectionType type) = 0;
|
||||
|
||||
DOCUMENT(R"(Get the describing properties of the specified section.
|
||||
|
||||
:param int index: The index of the section.
|
||||
:return: The properties of the section, if the index is valid.
|
||||
:rtype: SectionProperties.
|
||||
)");
|
||||
virtual SectionProperties GetSectionProperties(int index) = 0;
|
||||
|
||||
DOCUMENT(R"(Get the raw byte contents of the specified section.
|
||||
|
||||
:param int index: The index of the section.
|
||||
:return: The raw contents of the section, if the index is valid.
|
||||
:rtype: ``bytes``.
|
||||
)");
|
||||
virtual bytebuf GetSectionContents(int index) = 0;
|
||||
|
||||
DOCUMENT(R"(Writes a new section with specified properties and contents. If an existing section
|
||||
already has the same type or name, it will be overwritten (two sections cannot share the same type
|
||||
or name).
|
||||
|
||||
:param SectionProperties props: The properties of the section to be written.
|
||||
:param byte contents: The raw contents of the section.
|
||||
)");
|
||||
virtual void WriteSection(const SectionProperties &props, const bytebuf &contents) = 0;
|
||||
|
||||
DOCUMENT(R"(Query if callstacks are available.
|
||||
|
||||
:return: ``True`` if any callstacks are available, ``False`` otherwise.
|
||||
@@ -1112,8 +1158,8 @@ Must only be called after :meth:`InitResolver` has returned ``True``.
|
||||
virtual rdcarray<rdcstr> GetResolve(const rdcarray<uint64_t> &callstack) = 0;
|
||||
|
||||
protected:
|
||||
IStackResolver() = default;
|
||||
~IStackResolver() = default;
|
||||
ICaptureAccess() = default;
|
||||
~ICaptureAccess() = default;
|
||||
};
|
||||
|
||||
DOCUMENT(R"(A connection to a running remote RenderDoc server on another machine. This allows the
|
||||
@@ -1125,7 +1171,7 @@ much work as possible happening on the local machine.
|
||||
|
||||
No preference for a particular value, see :meth:`DebugPixel`.
|
||||
)");
|
||||
struct IRemoteServer : public IStackResolver
|
||||
struct IRemoteServer : public ICaptureAccess
|
||||
{
|
||||
DOCUMENT("Closes the connection without affecting the running server.");
|
||||
virtual void ShutdownConnection() = 0;
|
||||
@@ -1276,7 +1322,7 @@ protected:
|
||||
DOCUMENT(R"(A handle to a capture file. Used for simple cheap processing and meta-data fetching
|
||||
without opening the capture for analysis.
|
||||
)")
|
||||
struct ICaptureFile : public IStackResolver
|
||||
struct ICaptureFile : public ICaptureAccess
|
||||
{
|
||||
DOCUMENT("Closes the file handle.");
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
@@ -61,6 +61,11 @@ enum RemoteServerPacket
|
||||
eRemoteServer_ListDir,
|
||||
eRemoteServer_ExecuteAndInject,
|
||||
eRemoteServer_ShutdownServer,
|
||||
eRemoteServer_FindSectionByName,
|
||||
eRemoteServer_FindSectionByType,
|
||||
eRemoteServer_GetSectionProperties,
|
||||
eRemoteServer_GetSectionContents,
|
||||
eRemoteServer_WriteSection,
|
||||
eRemoteServer_RemoteServerCount,
|
||||
};
|
||||
|
||||
@@ -547,6 +552,121 @@ static void ActiveRemoteClientThread(ClientThread *threadData)
|
||||
SERIALISE_ELEMENT(StackFrames);
|
||||
}
|
||||
}
|
||||
else if(type == eRemoteServer_FindSectionByName)
|
||||
{
|
||||
std::string name;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
SERIALISE_ELEMENT(name);
|
||||
}
|
||||
|
||||
reader.EndChunk();
|
||||
|
||||
int index = rdc ? rdc->SectionIndex(name.c_str()) : -1;
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_FindSectionByName);
|
||||
SERIALISE_ELEMENT(index);
|
||||
}
|
||||
}
|
||||
else if(type == eRemoteServer_FindSectionByType)
|
||||
{
|
||||
SectionType sectionType;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
SERIALISE_ELEMENT(sectionType);
|
||||
}
|
||||
|
||||
reader.EndChunk();
|
||||
|
||||
int index = rdc ? rdc->SectionIndex(sectionType) : -1;
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_FindSectionByType);
|
||||
SERIALISE_ELEMENT(index);
|
||||
}
|
||||
}
|
||||
else if(type == eRemoteServer_GetSectionProperties)
|
||||
{
|
||||
int index = -1;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
SERIALISE_ELEMENT(index);
|
||||
}
|
||||
|
||||
reader.EndChunk();
|
||||
|
||||
SectionProperties props;
|
||||
if(rdc && index >= 0 && index < rdc->NumSections())
|
||||
props = rdc->GetSectionProperties(index);
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_GetSectionProperties);
|
||||
SERIALISE_ELEMENT(props);
|
||||
}
|
||||
}
|
||||
else if(type == eRemoteServer_GetSectionContents)
|
||||
{
|
||||
int index = -1;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
SERIALISE_ELEMENT(index);
|
||||
}
|
||||
|
||||
reader.EndChunk();
|
||||
|
||||
bytebuf contents;
|
||||
|
||||
if(rdc && index >= 0 && index < rdc->NumSections())
|
||||
{
|
||||
StreamReader *sectionReader = rdc->ReadSection(index);
|
||||
|
||||
contents.resize((size_t)sectionReader->GetSize());
|
||||
bool success = sectionReader->Read(contents.data(), sectionReader->GetSize());
|
||||
|
||||
if(!success)
|
||||
contents.clear();
|
||||
|
||||
delete sectionReader;
|
||||
}
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_GetSectionContents);
|
||||
SERIALISE_ELEMENT(contents);
|
||||
}
|
||||
}
|
||||
else if(type == eRemoteServer_WriteSection)
|
||||
{
|
||||
SectionProperties props;
|
||||
bytebuf contents;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
SERIALISE_ELEMENT(props);
|
||||
SERIALISE_ELEMENT(contents);
|
||||
}
|
||||
|
||||
reader.EndChunk();
|
||||
|
||||
if(rdc)
|
||||
{
|
||||
StreamWriter *sectionWriter = rdc->WriteSection(props);
|
||||
|
||||
if(sectionWriter)
|
||||
{
|
||||
sectionWriter->Write(contents.data(), contents.size());
|
||||
delete sectionWriter;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(type == eRemoteServer_CloseLog)
|
||||
{
|
||||
reader.EndChunk();
|
||||
@@ -1268,6 +1388,157 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CloseCapture(IReplayController *rend)
|
||||
{
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_CloseLog);
|
||||
}
|
||||
|
||||
rend->Shutdown();
|
||||
}
|
||||
|
||||
int FindSectionByName(const char *name)
|
||||
{
|
||||
if(!Connected())
|
||||
return -1;
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_FindSectionByName);
|
||||
SERIALISE_ELEMENT(name);
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
RemoteServerPacket type = ser.ReadChunk<RemoteServerPacket>();
|
||||
|
||||
if(type == eRemoteServer_FindSectionByName)
|
||||
{
|
||||
SERIALISE_ELEMENT(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected response to FindSectionByName");
|
||||
}
|
||||
|
||||
ser.EndChunk();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int FindSectionByType(SectionType sectionType)
|
||||
{
|
||||
if(!Connected())
|
||||
return -1;
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_FindSectionByType);
|
||||
SERIALISE_ELEMENT(sectionType);
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
RemoteServerPacket type = ser.ReadChunk<RemoteServerPacket>();
|
||||
|
||||
if(type == eRemoteServer_FindSectionByType)
|
||||
{
|
||||
SERIALISE_ELEMENT(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected response to FindSectionByType");
|
||||
}
|
||||
|
||||
ser.EndChunk();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
SectionProperties GetSectionProperties(int index)
|
||||
{
|
||||
if(!Connected())
|
||||
return SectionProperties();
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_GetSectionProperties);
|
||||
SERIALISE_ELEMENT(index);
|
||||
}
|
||||
|
||||
SectionProperties props;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
RemoteServerPacket type = ser.ReadChunk<RemoteServerPacket>();
|
||||
|
||||
if(type == eRemoteServer_GetSectionProperties)
|
||||
{
|
||||
SERIALISE_ELEMENT(props);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected response to GetSectionProperties");
|
||||
}
|
||||
|
||||
ser.EndChunk();
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
bytebuf GetSectionContents(int index) override
|
||||
{
|
||||
if(!Connected())
|
||||
return bytebuf();
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_GetSectionContents);
|
||||
SERIALISE_ELEMENT(index);
|
||||
}
|
||||
|
||||
bytebuf contents;
|
||||
|
||||
{
|
||||
READ_DATA_SCOPE();
|
||||
RemoteServerPacket type = ser.ReadChunk<RemoteServerPacket>();
|
||||
|
||||
if(type == eRemoteServer_GetSectionContents)
|
||||
{
|
||||
SERIALISE_ELEMENT(contents);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected response to GetSectionContents");
|
||||
}
|
||||
|
||||
ser.EndChunk();
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
void WriteSection(const SectionProperties &props, const bytebuf &contents)
|
||||
{
|
||||
if(!Connected())
|
||||
return;
|
||||
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_WriteSection);
|
||||
SERIALISE_ELEMENT(props);
|
||||
SERIALISE_ELEMENT(contents);
|
||||
}
|
||||
}
|
||||
|
||||
bool HasCallstacks()
|
||||
{
|
||||
if(!Connected())
|
||||
@@ -1377,16 +1648,6 @@ public:
|
||||
return StackFrames;
|
||||
}
|
||||
|
||||
void CloseCapture(IReplayController *rend)
|
||||
{
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(eRemoteServer_CloseLog);
|
||||
}
|
||||
|
||||
rend->Shutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
Network::Socket *m_Socket;
|
||||
WriteSerialiser writer;
|
||||
|
||||
@@ -162,6 +162,15 @@ public:
|
||||
}
|
||||
|
||||
bytebuf GetThumbnail(FileType type, uint32_t maxsize);
|
||||
|
||||
// ICaptureAccess
|
||||
|
||||
int FindSectionByName(const char *name);
|
||||
int FindSectionByType(SectionType type);
|
||||
SectionProperties GetSectionProperties(int index);
|
||||
bytebuf GetSectionContents(int index);
|
||||
void WriteSection(const SectionProperties &props, const bytebuf &contents);
|
||||
|
||||
bool HasCallstacks();
|
||||
bool InitResolver(float *progress, volatile bool *killSignal);
|
||||
rdcarray<rdcstr> GetResolve(const rdcarray<uint64_t> &callstack);
|
||||
@@ -213,6 +222,7 @@ ReplayStatus CaptureFile::OpenFile(const char *filename, const char *filetype)
|
||||
if(filetype != NULL && strcmp(filetype, "") && strcmp(filetype, "rdc"))
|
||||
RDCWARN("Opening file with unrecognised filetype '%s' - treating as 'rdc'", filetype);
|
||||
|
||||
delete m_RDC;
|
||||
m_RDC = new RDCFile;
|
||||
m_RDC->Open(filename);
|
||||
}
|
||||
@@ -582,6 +592,61 @@ bytebuf CaptureFile::GetThumbnail(FileType type, uint32_t maxsize)
|
||||
return buf;
|
||||
}
|
||||
|
||||
int CaptureFile::FindSectionByName(const char *name)
|
||||
{
|
||||
if(!m_RDC)
|
||||
return -1;
|
||||
|
||||
return m_RDC->SectionIndex(name);
|
||||
}
|
||||
|
||||
int CaptureFile::FindSectionByType(SectionType type)
|
||||
{
|
||||
if(!m_RDC)
|
||||
return -1;
|
||||
|
||||
return m_RDC->SectionIndex(type);
|
||||
}
|
||||
|
||||
SectionProperties CaptureFile::GetSectionProperties(int index)
|
||||
{
|
||||
if(!m_RDC || index < 0 || index >= m_RDC->NumSections())
|
||||
return SectionProperties();
|
||||
|
||||
return m_RDC->GetSectionProperties(index);
|
||||
}
|
||||
|
||||
bytebuf CaptureFile::GetSectionContents(int index)
|
||||
{
|
||||
bytebuf ret;
|
||||
|
||||
if(!m_RDC || index < 0 || index >= m_RDC->NumSections())
|
||||
return ret;
|
||||
|
||||
StreamReader *reader = m_RDC->ReadSection(index);
|
||||
|
||||
ret.resize((size_t)reader->GetSize());
|
||||
bool success = reader->Read(ret.data(), reader->GetSize());
|
||||
|
||||
delete reader;
|
||||
|
||||
if(!success)
|
||||
ret.clear();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CaptureFile::WriteSection(const SectionProperties &props, const bytebuf &contents)
|
||||
{
|
||||
StreamWriter *writer = m_RDC->WriteSection(props);
|
||||
if(!writer)
|
||||
return;
|
||||
|
||||
writer->Write(contents.data(), contents.size());
|
||||
|
||||
delete writer;
|
||||
}
|
||||
|
||||
bool CaptureFile::HasCallstacks()
|
||||
{
|
||||
return m_RDC && m_RDC->SectionIndex(SectionType::ResolveDatabase) >= 0;
|
||||
|
||||
Reference in New Issue
Block a user