mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 09:30:44 +00:00
Loads of changes, fix thread & invoke helpers, skeleton of Core working
* GUIInvoke helper changed to use QMetaObject::invokeMethod which works on threads better. * LambdaThread helper class now has a thread member, it doesn't derive from thread (this seems to be recommended practice).
This commit is contained in:
+155
-6
@@ -1,19 +1,168 @@
|
||||
#include "Core.h"
|
||||
#include "Windows/MainWindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include <QMessageBox>
|
||||
#include <QMetaObject>
|
||||
|
||||
Core::Core()
|
||||
Core::Core(QString paramFilename, QString remoteHost, uint32_t remoteIdent, bool temp)
|
||||
{
|
||||
|
||||
m_MainWindow = new MainWindow(this, paramFilename, remoteHost, remoteIdent, temp);
|
||||
m_MainWindow->show();
|
||||
}
|
||||
|
||||
Core::~Core()
|
||||
{
|
||||
|
||||
delete m_MainWindow;
|
||||
}
|
||||
|
||||
|
||||
void QInvoke::call(const std::function<void()> &f)
|
||||
void Core::LoadLogfile(QString logFile, bool temporary)
|
||||
{
|
||||
QTimer::singleShot(0, new QInvoke(f), SLOT(doInvoke()));
|
||||
LoadLogfile(-1, "", logFile, temporary);
|
||||
}
|
||||
|
||||
void Core::LoadLogfile(int proxyRenderer, QString replayHost, QString logFile, bool temporary)
|
||||
{
|
||||
m_LogFile = logFile;
|
||||
|
||||
m_LoadInProgress = true;
|
||||
|
||||
float loadProgress = 0.0f;
|
||||
float postloadProgress = 0.0f;
|
||||
|
||||
// this function call will block until the log is either loaded, or there's some failure
|
||||
m_Renderer.Init(proxyRenderer, replayHost, logFile, &loadProgress);
|
||||
|
||||
// if the renderer isn't running, we hit a failure case so display an error message
|
||||
if (!m_Renderer.IsRunning())
|
||||
{
|
||||
QString errmsg = "Unknown error message";
|
||||
ReplayCreateStatus status = m_Renderer.GetCreateStatus();
|
||||
errmsg = status;
|
||||
|
||||
if(proxyRenderer >= 0)
|
||||
QMessageBox::critical(NULL, "Error opening log",
|
||||
QString("%1\nFailed to transfer and replay on remote host %2: %3.\n\n" \
|
||||
"Check diagnostic log in Help menu for more details.").arg(logFile, replayHost, errmsg));
|
||||
else
|
||||
QMessageBox::critical(NULL, "Error opening log",
|
||||
QString("%1\nFailed to open logfile for replay: %1.\n\n" \
|
||||
"Check diagnostic log in Help menu for more details.").arg(logFile, errmsg));
|
||||
|
||||
m_LoadInProgress = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_FrameID = 0;
|
||||
m_EventID = 0;
|
||||
|
||||
// fetch initial data like drawcalls, textures and buffers
|
||||
m_Renderer.BlockInvoke([this,&postloadProgress](IReplayRenderer *r) {
|
||||
r->GetFrameInfo(&m_FrameInfo);
|
||||
|
||||
m_APIProps = r->GetAPIProperties();
|
||||
|
||||
postloadProgress = 0.2f;
|
||||
|
||||
m_Drawcalls = new rdctype::array<FetchDrawcall>[m_FrameInfo.count];
|
||||
|
||||
postloadProgress = 0.4f;
|
||||
|
||||
for (int i = 0; i < m_FrameInfo.count; i++)
|
||||
r->GetDrawcalls((uint32_t)i, &m_Drawcalls[i]);
|
||||
|
||||
postloadProgress = 0.7f;
|
||||
|
||||
r->GetBuffers(&m_BufferList);
|
||||
for(int i=0; i < m_BufferList.count; i++)
|
||||
m_Buffers[ m_BufferList[i].ID ] = &m_BufferList[i];
|
||||
|
||||
postloadProgress = 0.8f;
|
||||
|
||||
r->GetTextures(&m_TextureList);
|
||||
for(int i=0; i < m_TextureList.count; i++)
|
||||
m_Textures[ m_TextureList[i].ID ] = &m_TextureList[i];
|
||||
|
||||
postloadProgress = 0.9f;
|
||||
|
||||
r->GetD3D11PipelineState(&CurD3D11PipelineState);
|
||||
r->GetGLPipelineState(&CurGLPipelineState);
|
||||
//CurPipelineState.SetStates(m_APIProps, CurD3D11PipelineState, CurGLPipelineState);
|
||||
|
||||
UnreadMessageCount = 0;
|
||||
AddMessages(m_FrameInfo[0].debugMessages);
|
||||
|
||||
postloadProgress = 1.0f;
|
||||
});
|
||||
|
||||
QThread::msleep(20);
|
||||
|
||||
m_LogLoaded = true;
|
||||
|
||||
QList<ILogViewerForm*> logviewers(m_LogViewers);
|
||||
|
||||
GUIInvoke::blockcall([&logviewers]() {
|
||||
// notify all the registers log viewers that a log has been loaded
|
||||
for(ILogViewerForm *logviewer : logviewers)
|
||||
{
|
||||
if(logviewer) logviewer->OnLogfileLoaded();
|
||||
}
|
||||
});
|
||||
|
||||
m_LoadInProgress = false;
|
||||
}
|
||||
|
||||
void Core::SetEventID(ILogViewerForm *exclude, uint32_t frameID, uint32_t eventID)
|
||||
{
|
||||
m_FrameID = frameID;
|
||||
m_EventID = eventID;
|
||||
|
||||
m_Renderer.BlockInvoke([frameID,eventID,this](IReplayRenderer *r) {
|
||||
r->SetFrameEvent(frameID, eventID);
|
||||
r->GetD3D11PipelineState(&CurD3D11PipelineState);
|
||||
r->GetGLPipelineState(&CurGLPipelineState);
|
||||
//CurPipelineState.SetStates(m_APIProps, CurD3D11PipelineState, CurGLPipelineState);
|
||||
});
|
||||
|
||||
for(ILogViewerForm *logviewer : m_LogViewers)
|
||||
{
|
||||
if(logviewer == exclude)
|
||||
continue;
|
||||
|
||||
logviewer->OnEventSelected(frameID, eventID);
|
||||
}
|
||||
}
|
||||
|
||||
void GUIInvoke::call(const std::function<void()> &f)
|
||||
{
|
||||
if(qApp->thread() == QThread::currentThread())
|
||||
{
|
||||
f();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: could maybe do away with string compare here via caching
|
||||
// invoke->metaObject()->indexOfMethod("doInvoke"); ?
|
||||
|
||||
GUIInvoke *invoke = new GUIInvoke(f);
|
||||
invoke->moveToThread(qApp->thread());
|
||||
QMetaObject::invokeMethod(invoke, "doInvoke", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void GUIInvoke::blockcall(const std::function<void()> &f)
|
||||
{
|
||||
if(qApp->thread() == QThread::currentThread())
|
||||
{
|
||||
f();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: could maybe do away with string compare here via caching
|
||||
// invoke->metaObject()->indexOfMethod("doInvoke"); ?
|
||||
|
||||
GUIInvoke *invoke = new GUIInvoke(f);
|
||||
invoke->moveToThread(qApp->thread());
|
||||
QMetaObject::invokeMethod(invoke, "doInvoke", Qt::BlockingQueuedConnection);
|
||||
}
|
||||
|
||||
+187
-7
@@ -3,16 +3,164 @@
|
||||
|
||||
#include "RenderManager.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
|
||||
struct ILogViewerForm
|
||||
{
|
||||
virtual void OnLogfileLoaded() = 0;
|
||||
virtual void OnLogfileClosed() = 0;
|
||||
virtual void OnEventSelected(uint32_t frameID, uint32_t eventID) = 0;
|
||||
};
|
||||
|
||||
struct ILogLoadProgressListener
|
||||
{
|
||||
virtual void LogfileProgressBegin() = 0;
|
||||
virtual void LogfileProgress(float progress) = 0;
|
||||
};
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class Core
|
||||
{
|
||||
public:
|
||||
Core();
|
||||
Core(QString paramFilename, QString remoteHost, uint32_t remoteIdent, bool temp);
|
||||
~Core();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Control functions
|
||||
|
||||
// loading a local log, no remote replay
|
||||
void LoadLogfile(QString logFile, bool temporary);
|
||||
|
||||
// when loading a log while replaying remotely, provide the proxy renderer that will be used
|
||||
// as well as the hostname to replay on.
|
||||
void LoadLogfile(int proxyRenderer, QString replayHost, QString logFile, bool temporary);
|
||||
|
||||
void CloseLogfile();
|
||||
|
||||
QString TempLogFilename(QString appname);
|
||||
|
||||
void SetEventID(ILogViewerForm *exclude, uint32_t frameID, uint32_t eventID);
|
||||
|
||||
void AddLogProgressListener(ILogLoadProgressListener *p);
|
||||
|
||||
void AddLogViewer(ILogViewerForm *f)
|
||||
{
|
||||
m_LogViewers.push_back(f);
|
||||
|
||||
if(LogLoaded())
|
||||
{
|
||||
f->OnLogfileLoaded();
|
||||
f->OnEventSelected(CurFrame(), CurEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveLogViewer(ILogViewerForm *f)
|
||||
{
|
||||
m_LogViewers.removeAll(f);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Singleton windows
|
||||
|
||||
/*
|
||||
private MainWindow m_MainWindow = null;
|
||||
private EventBrowser m_EventBrowser = null;
|
||||
private APIInspector m_APIInspector = null;
|
||||
private DebugMessages m_DebugMessages = null;
|
||||
private TimelineBar m_TimelineBar = null;
|
||||
private TextureViewer m_TextureViewer = null;
|
||||
private PipelineStateViewer m_PipelineStateViewer = null;
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Accessors
|
||||
|
||||
RenderManager *Renderer() { return &m_Renderer; }
|
||||
|
||||
bool LogLoaded() { return m_LogLoaded; }
|
||||
bool LogLoading() { return m_LoadInProgress; }
|
||||
QString LogFilename() { return m_LogFile; }
|
||||
|
||||
const rdctype::array<FetchFrameInfo> &FrameInfo() { return m_FrameInfo; }
|
||||
const APIProperties &APIProps() { return m_APIProps; }
|
||||
|
||||
// TODO: support multiple frames
|
||||
uint32_t CurFrame() { return m_FrameID; }
|
||||
uint32_t CurEvent() { return m_EventID; }
|
||||
|
||||
const FetchDrawcall *CurDrawcall() { return GetDrawcall(CurFrame(), CurEvent()); }
|
||||
const rdctype::array<FetchDrawcall> &CurDrawcalls(uint32_t frame) { return m_Drawcalls[frame]; }
|
||||
|
||||
FetchTexture *GetTexture(ResourceId id) { return m_Textures[id]; }
|
||||
const rdctype::array<FetchTexture> &GetTextures() { return m_TextureList; }
|
||||
|
||||
FetchBuffer *GetBuffer(ResourceId id) { return m_Buffers[id]; }
|
||||
const rdctype::array<FetchBuffer> &GetBuffers() { return m_BufferList; }
|
||||
|
||||
QList<DebugMessage> DebugMessages;
|
||||
int UnreadMessageCount;
|
||||
void AddMessages(rdctype::array<DebugMessage> &msgs)
|
||||
{
|
||||
UnreadMessageCount += msgs.count;
|
||||
for(int i=0; i < msgs.count; i++)
|
||||
DebugMessages.push_back(msgs[i]);
|
||||
}
|
||||
|
||||
D3D11PipelineState CurD3D11PipelineState;
|
||||
GLPipelineState CurGLPipelineState;
|
||||
//CommonPipelineState CurPipelineState;
|
||||
|
||||
private:
|
||||
RenderManager m_Renderer;
|
||||
|
||||
QList<ILogViewerForm*> m_LogViewers;
|
||||
QList<ILogLoadProgressListener*> m_ProgressListeners;
|
||||
|
||||
bool m_LogLoaded, m_LoadInProgress;
|
||||
QString m_LogFile;
|
||||
|
||||
uint32_t m_FrameID, m_EventID;
|
||||
|
||||
const FetchDrawcall *GetDrawcall(const rdctype::array<FetchDrawcall> &draws, uint32_t eventID)
|
||||
{
|
||||
for(int i=0; i < draws.count; i++)
|
||||
{
|
||||
if (draws[i].children.count > 0)
|
||||
{
|
||||
const FetchDrawcall *draw = GetDrawcall(draws[i].children, eventID);
|
||||
if (draw != NULL) return draw;
|
||||
}
|
||||
|
||||
if (draws[i].eventID == eventID)
|
||||
return &draws[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FetchDrawcall *GetDrawcall(uint32_t frameID, uint32_t eventID)
|
||||
{
|
||||
if (m_Drawcalls == NULL || frameID >= (uint32_t)m_FrameInfo.count)
|
||||
return NULL;
|
||||
|
||||
return GetDrawcall(m_Drawcalls[frameID], eventID);
|
||||
}
|
||||
|
||||
rdctype::array<FetchDrawcall> *m_Drawcalls;
|
||||
|
||||
APIProperties m_APIProps;
|
||||
rdctype::array<FetchFrameInfo> m_FrameInfo;
|
||||
|
||||
QMap<ResourceId, FetchTexture*> m_Textures;
|
||||
rdctype::array<FetchTexture> m_TextureList;
|
||||
QMap<ResourceId, FetchBuffer*> m_Buffers;
|
||||
rdctype::array<FetchBuffer> m_BufferList;
|
||||
|
||||
// Windows
|
||||
MainWindow *m_MainWindow;
|
||||
};
|
||||
|
||||
// Utility class for invoking a lambda on the GUI thread.
|
||||
@@ -20,21 +168,53 @@ class Core
|
||||
// wise not to require a higher version that necessary.
|
||||
#include <functional>
|
||||
|
||||
class QInvoke : public QObject
|
||||
class GUIInvoke : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QInvoke(const std::function<void()> &f) : func(f) {}
|
||||
GUIInvoke(const std::function<void()> &f) : func(f) {}
|
||||
std::function<void()> func;
|
||||
public:
|
||||
public:
|
||||
static void call(const std::function<void()> &f);
|
||||
static void blockcall(const std::function<void()> &f);
|
||||
|
||||
protected slots:
|
||||
protected slots:
|
||||
void doInvoke()
|
||||
{
|
||||
func();
|
||||
deleteLater();
|
||||
func();
|
||||
deleteLater();
|
||||
}
|
||||
};
|
||||
|
||||
// Utility class for calling a lambda on a new thread.
|
||||
#include <QThread>
|
||||
|
||||
class LambdaThread : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
std::function<void()> m_func;
|
||||
QThread *m_Thread;
|
||||
|
||||
public slots:
|
||||
void process()
|
||||
{
|
||||
m_func();
|
||||
m_Thread->quit();
|
||||
deleteLater();
|
||||
m_Thread->deleteLater();
|
||||
}
|
||||
|
||||
public:
|
||||
explicit LambdaThread(std::function<void()> f)
|
||||
{
|
||||
m_Thread = new QThread();
|
||||
m_func = f;
|
||||
moveToThread(m_Thread);
|
||||
connect(m_Thread, SIGNAL(started()), this, SLOT(process()));
|
||||
}
|
||||
|
||||
void start(QThread::Priority prio = QThread::InheritPriority) { m_Thread->start(prio); }
|
||||
bool isRunning() { return m_Thread->isRunning(); }
|
||||
};
|
||||
|
||||
#endif // CORE_H
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#include "RenderManager.h"
|
||||
|
||||
#include "Core.h"
|
||||
|
||||
#include <QMutexLocker>
|
||||
|
||||
RenderManager::RenderManager()
|
||||
{
|
||||
m_Running = false;
|
||||
m_Thread = NULL;
|
||||
}
|
||||
|
||||
RenderManager::~RenderManager()
|
||||
@@ -24,9 +27,15 @@ void RenderManager::Init(int proxyRenderer, QString replayHost, QString logfile,
|
||||
|
||||
*progress = 0.0f;
|
||||
|
||||
start(HighestPriority);
|
||||
m_Thread = new LambdaThread([this]() { run(); });
|
||||
m_Thread->start(QThread::HighestPriority);
|
||||
|
||||
while (!isRunning()) {}
|
||||
while (m_Thread->isRunning() && !m_Running) {}
|
||||
}
|
||||
|
||||
bool RenderManager::IsRunning()
|
||||
{
|
||||
return m_Thread->isRunning() && m_Running;
|
||||
}
|
||||
|
||||
void RenderManager::AsyncInvoke(RenderManager::InvokeMethod m)
|
||||
@@ -53,12 +62,14 @@ void RenderManager::CloseThread()
|
||||
m_RenderCondition.wakeAll();
|
||||
|
||||
// wait for the thread to close and clean up
|
||||
while(isRunning()) {}
|
||||
while(m_Thread->isRunning()) {}
|
||||
|
||||
m_Thread->deleteLater();
|
||||
}
|
||||
|
||||
void RenderManager::PushInvoke(RenderManager::InvokeHandle *cmd)
|
||||
{
|
||||
if(!isRunning() || !m_Running)
|
||||
if(m_Thread == NULL || !m_Thread->isRunning() || !m_Running)
|
||||
{
|
||||
cmd->processed = true;
|
||||
if(cmd->selfdelete) delete cmd;
|
||||
|
||||
@@ -12,12 +12,10 @@
|
||||
#include <QWaitCondition>
|
||||
|
||||
struct IReplayRenderer;
|
||||
class LambdaThread;
|
||||
|
||||
class RenderManager : public QThread
|
||||
class RenderManager
|
||||
{
|
||||
Q_OBJECT
|
||||
void run();
|
||||
|
||||
public:
|
||||
typedef std::function<void(IReplayRenderer*)> InvokeMethod;
|
||||
|
||||
@@ -26,7 +24,7 @@ class RenderManager : public QThread
|
||||
|
||||
void Init(int proxyRenderer, QString replayHost, QString logfile, float *progress);
|
||||
|
||||
bool IsRunning() { return isRunning() && m_Running; }
|
||||
bool IsRunning();
|
||||
ReplayCreateStatus GetCreateStatus() { return m_CreateStatus; }
|
||||
|
||||
void AsyncInvoke(InvokeMethod m);
|
||||
@@ -49,6 +47,8 @@ class RenderManager : public QThread
|
||||
bool selfdelete;
|
||||
};
|
||||
|
||||
void run();
|
||||
|
||||
QMutex m_RenderLock;
|
||||
QQueue<InvokeHandle *> m_RenderQueue;
|
||||
QWaitCondition m_RenderCondition;
|
||||
@@ -61,6 +61,7 @@ class RenderManager : public QThread
|
||||
float *m_Progress;
|
||||
|
||||
volatile bool m_Running;
|
||||
LambdaThread *m_Thread;
|
||||
ReplayCreateStatus m_CreateStatus;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,15 +1,65 @@
|
||||
#include "Windows/MainWindow.h"
|
||||
#include <QApplication>
|
||||
#include "Code/Core.h"
|
||||
|
||||
#include "renderdoc_replay.h"
|
||||
#include <QApplication>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatch>
|
||||
#include <QFileInfo>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
RENDERDOC_LogText("QRenderDoc initialising.");
|
||||
|
||||
QString filename = "";
|
||||
bool temp = false;
|
||||
|
||||
for(int i=0; i < argc; i++)
|
||||
{
|
||||
if(!QString::compare(argv[i], "--tempfile", Qt::CaseInsensitive))
|
||||
temp = true;
|
||||
}
|
||||
|
||||
QString remoteHost = "";
|
||||
uint remoteIdent = 0;
|
||||
|
||||
for (int i = 0; i+1 < argc; i++)
|
||||
{
|
||||
if (!QString::compare(argv[i], "--REMOTEACCESS", Qt::CaseInsensitive))
|
||||
{
|
||||
QRegularExpression regexp("^([a-zA-Z0-9_-]+:)?([0-9]+)$");
|
||||
|
||||
QRegularExpressionMatch match = regexp.match(argv[i+1]);
|
||||
|
||||
if (match.hasMatch())
|
||||
{
|
||||
QString host = match.captured(1);
|
||||
|
||||
if (host.length() > 0 && host[host.length() - 1] == ':')
|
||||
host.chop(1);
|
||||
|
||||
bool ok = false;
|
||||
uint32_t ident = match.captured(2).toUInt(&ok);
|
||||
|
||||
if(ok)
|
||||
{
|
||||
remoteHost = host;
|
||||
remoteIdent = ident;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
filename = argv[argc - 1];
|
||||
QFileInfo checkFile(filename);
|
||||
if(!checkFile.exists() || !checkFile.isFile())
|
||||
filename = "";
|
||||
}
|
||||
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
Core core(filename, remoteHost, remoteIdent, temp);
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
|
||||
#include "renderdoc_replay.h"
|
||||
|
||||
extern ReplayOutput *out;
|
||||
|
||||
CustomPaintWidget::CustomPaintWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
m_Output = NULL;
|
||||
setAttribute(Qt::WA_PaintOnScreen);
|
||||
}
|
||||
|
||||
@@ -17,6 +16,6 @@ CustomPaintWidget::~CustomPaintWidget()
|
||||
|
||||
void CustomPaintWidget::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
ReplayOutput_Display(out);
|
||||
if(m_Output) m_Output->Display();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
struct IReplayOutput;
|
||||
|
||||
class CustomPaintWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -10,6 +12,8 @@ class CustomPaintWidget : public QWidget
|
||||
explicit CustomPaintWidget(QWidget *parent = 0);
|
||||
~CustomPaintWidget();
|
||||
|
||||
void SetOutput(IReplayOutput *out) { m_Output = out; }
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
@@ -17,6 +21,8 @@ class CustomPaintWidget : public QWidget
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e);
|
||||
QPaintEngine *paintEngine() const { return NULL; }
|
||||
|
||||
IReplayOutput *m_Output;
|
||||
};
|
||||
|
||||
#endif // CUSTOMPAINTWIDGET_H
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
|
||||
#include "Code/Core.h"
|
||||
|
||||
#include "renderdoc_replay.h"
|
||||
|
||||
extern ReplayOutput *out;
|
||||
extern ReplayRenderer *renderer;
|
||||
extern TextureDisplay d;
|
||||
extern QWidget *texviewer;
|
||||
|
||||
uint AddDrawcalls(QTreeWidgetItem *parent, const rdctype::array<FetchDrawcall> &draws)
|
||||
{
|
||||
uint lastEID = 0;
|
||||
@@ -25,29 +18,14 @@ uint AddDrawcalls(QTreeWidgetItem *parent, const rdctype::array<FetchDrawcall> &
|
||||
return lastEID;
|
||||
}
|
||||
|
||||
EventBrowser::EventBrowser(QWidget *parent) :
|
||||
EventBrowser::EventBrowser(Core *core, QWidget *parent) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::EventBrowser)
|
||||
ui(new Ui::EventBrowser),
|
||||
m_Core(core)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
rdctype::array<FetchDrawcall> draws;
|
||||
ReplayRenderer_GetDrawcalls(renderer, 0, &draws);
|
||||
|
||||
rdctype::array<FetchFrameInfo> frameInfo;
|
||||
ReplayRenderer_GetFrameInfo(renderer, &frameInfo);
|
||||
|
||||
QTreeWidgetItem *frame = new QTreeWidgetItem((QTreeWidget *)NULL, QStringList{QString("Frame #%1").arg(frameInfo[0].frameNumber), "", ""});
|
||||
|
||||
QTreeWidgetItem *framestart = new QTreeWidgetItem(frame, QStringList{"Frame Start", "0", "0.0"});
|
||||
framestart->setData(0, Qt::UserRole, QVariant(0));
|
||||
|
||||
uint lastEID = AddDrawcalls(frame, draws);
|
||||
frame->setData(0, Qt::UserRole, QVariant(lastEID));
|
||||
|
||||
ui->events->insertTopLevelItem(0, frame);
|
||||
|
||||
ui->events->expandItem(frame);
|
||||
m_Core->AddLogViewer(this);
|
||||
|
||||
ui->events->header()->resizeSection(1, 80);
|
||||
|
||||
@@ -66,22 +44,37 @@ EventBrowser::EventBrowser(QWidget *parent) :
|
||||
|
||||
EventBrowser::~EventBrowser()
|
||||
{
|
||||
m_Core->RemoveLogViewer(this);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EventBrowser::OnLogfileLoaded()
|
||||
{
|
||||
QTreeWidgetItem *frame = new QTreeWidgetItem((QTreeWidget *)NULL, QStringList{QString("Frame #%1").arg(m_Core->FrameInfo()[0].frameNumber), "", ""});
|
||||
|
||||
QTreeWidgetItem *framestart = new QTreeWidgetItem(frame, QStringList{"Frame Start", "0", "0.0"});
|
||||
framestart->setData(0, Qt::UserRole, QVariant(0));
|
||||
|
||||
uint lastEID = AddDrawcalls(frame, m_Core->CurDrawcalls(0));
|
||||
frame->setData(0, Qt::UserRole, QVariant(lastEID));
|
||||
|
||||
ui->events->insertTopLevelItem(0, frame);
|
||||
|
||||
ui->events->expandItem(frame);
|
||||
}
|
||||
|
||||
void EventBrowser::OnLogfileClosed()
|
||||
{
|
||||
ui->events->clear();
|
||||
}
|
||||
|
||||
void EventBrowser::OnEventSelected(uint32_t frameID, uint32_t eventID)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EventBrowser::on_find_clicked()
|
||||
{
|
||||
Core c;
|
||||
|
||||
c.Renderer()->AsyncInvoke([this](IReplayRenderer *r) {
|
||||
|
||||
D3D11PipelineState state;
|
||||
r->GetD3D11PipelineState(&state);
|
||||
|
||||
QInvoke::call([this,state]() {
|
||||
ui->label->setText(state.m_PS.ShaderName.elems);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void EventBrowser::on_gotoEID_clicked()
|
||||
@@ -94,13 +87,5 @@ void EventBrowser::on_events_itemSelectionChanged()
|
||||
|
||||
uint EID = ui->events->selectedItems()[0]->data(0, Qt::UserRole).toUInt();
|
||||
|
||||
ReplayRenderer_SetFrameEvent(renderer, 0, EID);
|
||||
|
||||
D3D11PipelineState state;
|
||||
ReplayRenderer_GetD3D11PipelineState(renderer, &state);
|
||||
|
||||
d.texid = state.m_OM.RenderTargets[0].Resource;
|
||||
ReplayOutput_SetTextureDisplay(out, d);
|
||||
|
||||
texviewer->update();
|
||||
m_Core->SetEventID(this, 0, EID);
|
||||
}
|
||||
|
||||
@@ -3,18 +3,24 @@
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
#include "Code/Core.h"
|
||||
|
||||
namespace Ui {
|
||||
class EventBrowser;
|
||||
}
|
||||
|
||||
class EventBrowser : public QFrame
|
||||
class EventBrowser : public QFrame, public ILogViewerForm
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EventBrowser(QWidget *parent = 0);
|
||||
explicit EventBrowser(Core *core, QWidget *parent = 0);
|
||||
~EventBrowser();
|
||||
|
||||
void OnLogfileLoaded();
|
||||
void OnLogfileClosed();
|
||||
void OnEventSelected(uint32_t frameID, uint32_t eventID);
|
||||
|
||||
private slots:
|
||||
void on_find_clicked();
|
||||
|
||||
@@ -24,6 +30,7 @@ class EventBrowser : public QFrame
|
||||
|
||||
private:
|
||||
Ui::EventBrowser *ui;
|
||||
Core *m_Core;
|
||||
};
|
||||
|
||||
#endif // EVENTBROWSER_H
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/Resources/find.png</normaloff>:/Resources/find.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
@@ -95,7 +95,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/Resources/flag_green.png</normaloff>:/Resources/flag_green.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
@@ -109,7 +109,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/Resources/time.png</normaloff>:/Resources/time.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
@@ -201,8 +201,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources.qrc"/>
|
||||
</resources>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -2,27 +2,24 @@
|
||||
#include "EventBrowser.h"
|
||||
#include "TextureViewer.h"
|
||||
#include "ui_MainWindow.h"
|
||||
#include "renderdoc_replay.h"
|
||||
|
||||
ReplayRenderer *renderer = NULL;
|
||||
QWidget *texviewer = NULL;
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
#include "Code/Core.h"
|
||||
|
||||
MainWindow::MainWindow(Core *core, QString paramFilename, QString remoteHost, uint32_t remoteIdent, bool temp) :
|
||||
QMainWindow(NULL),
|
||||
ui(new Ui::MainWindow),
|
||||
m_Core(core)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
float progress = 0.0f;
|
||||
RENDERDOC_CreateReplayRenderer("T:\\renderdoc\\archive_renderdoc_captures\\deferred_plusplus.rdc", &progress, &renderer);
|
||||
|
||||
EventBrowser *eventbrowser = new EventBrowser();
|
||||
EventBrowser *eventbrowser = new EventBrowser(core);
|
||||
|
||||
ui->toolWindowManager->addToolWindow(eventbrowser, ToolWindowManager::EmptySpace);
|
||||
|
||||
TextureViewer *textureviewer = new TextureViewer();
|
||||
|
||||
texviewer = textureviewer->renderSurf();
|
||||
TextureViewer *textureviewer = new TextureViewer(core);
|
||||
|
||||
ui->toolWindowManager->addToolWindow(textureviewer, ToolWindowManager::AreaReference(ToolWindowManager::RightOf, ui->toolWindowManager->areaOf(eventbrowser)));
|
||||
|
||||
@@ -38,3 +35,20 @@ void MainWindow::on_action_Exit_triggered()
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Open_Log_triggered()
|
||||
{
|
||||
QString filename = QFileDialog::getOpenFileName(this,
|
||||
"Select Logfile to open",
|
||||
"",
|
||||
"Log Files (*.rdc);;Image Files (*.dds *.hdr *.exr *.bmp *.jpg *.jpeg *.png *.tga *.gif *.psd;;All Files (*.*)");
|
||||
|
||||
QFileInfo checkFile(filename);
|
||||
if(filename != "" && checkFile.exists() && checkFile.isFile())
|
||||
{
|
||||
LambdaThread *thread = new LambdaThread([filename,this] () {
|
||||
m_Core->LoadLogfile(filename, false);
|
||||
});
|
||||
thread->start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,30 @@
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class Core;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
explicit MainWindow(Core *core, QString paramFilename, QString remoteHost, uint32_t remoteIdent, bool temp);
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
void on_action_Exit_triggered();
|
||||
|
||||
private:
|
||||
void on_action_Open_Log_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
Core *m_Core;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
@@ -11,7 +11,11 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
<string>QRenderDoc</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/Resources/icon.ico</normaloff>:/Resources/icon.ico</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
@@ -374,6 +378,8 @@
|
||||
<header>ToolWindowManager.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "TextureViewer.h"
|
||||
#include "ui_TextureViewer.h"
|
||||
|
||||
#include "renderdoc_replay.h"
|
||||
#include "Code/Core.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <QX11Info>
|
||||
@@ -9,74 +9,82 @@
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
|
||||
extern ReplayRenderer *renderer;
|
||||
ReplayOutput *out = NULL;
|
||||
TextureDisplay d;
|
||||
|
||||
TextureViewer::TextureViewer(QWidget *parent) :
|
||||
TextureViewer::TextureViewer(Core *core, QWidget *parent) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::TextureViewer)
|
||||
ui(new Ui::TextureViewer),
|
||||
m_Core(core)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
rdctype::array<FetchTexture> texs;
|
||||
ReplayRenderer_GetTextures(renderer, &texs);
|
||||
m_Core->AddLogViewer(this);
|
||||
|
||||
for(int32_t i=0; i < texs.count; i++)
|
||||
{
|
||||
if(texs[i].creationFlags & eTextureCreate_SwapBuffer)
|
||||
{
|
||||
d.texid = texs[i].ID;
|
||||
d.mip = 0;
|
||||
d.sampleIdx = ~0U;
|
||||
d.overlay = eTexOverlay_None;
|
||||
d.CustomShader = ResourceId();
|
||||
d.HDRMul = -1.0f;
|
||||
d.linearDisplayAsGamma = true;
|
||||
d.FlipY = false;
|
||||
d.rangemin = 0.0f;
|
||||
d.rangemax = 1.0f;
|
||||
d.scale = -1.0f;
|
||||
d.offx = 0.0f;
|
||||
d.offy = 0.0f;
|
||||
d.sliceFace = 0;
|
||||
d.rawoutput = false;
|
||||
d.lightBackgroundColour = d.darkBackgroundColour =
|
||||
FloatVector(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
d.Red = d.Green = d.Blue = true;
|
||||
d.Alpha = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ui->framerender->SetOutput(NULL);
|
||||
m_Output = NULL;
|
||||
}
|
||||
|
||||
TextureViewer::~TextureViewer()
|
||||
{
|
||||
m_Core->RemoveLogViewer(this);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TextureViewer::OnLogfileLoaded()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
HWND wnd = (HWND)ui->framerender->winId();
|
||||
out = ReplayRenderer_CreateOutput(renderer, wnd);
|
||||
#elif defined(__linux__)
|
||||
Display *display = QX11Info::display();
|
||||
GLXDrawable drawable = (GLXDrawable)ui->framerender->winId();
|
||||
|
||||
void *displayAndDrawable[2] = { (void *)display, (void *)drawable };
|
||||
|
||||
out = ReplayRenderer_CreateOutput(renderer, (void *)displayAndDrawable);
|
||||
void *wnd = displayAndDrawable;
|
||||
#else
|
||||
#error "Unknown platform"
|
||||
#endif
|
||||
|
||||
OutputConfig c = { eOutputType_TexDisplay };
|
||||
m_Core->Renderer()->BlockInvoke([wnd,this](IReplayRenderer *r) {
|
||||
m_Output = r->CreateOutput(wnd);
|
||||
ui->framerender->SetOutput(m_Output);
|
||||
|
||||
ReplayOutput_SetOutputConfig(out, c);
|
||||
ReplayOutput_SetTextureDisplay(out, d);
|
||||
|
||||
ReplayRenderer_SetFrameEvent(renderer, 0, 10000000+rand()%1000);
|
||||
OutputConfig c = { eOutputType_TexDisplay };
|
||||
m_Output->SetOutputConfig(c);
|
||||
});
|
||||
}
|
||||
|
||||
QWidget *TextureViewer::renderSurf()
|
||||
void TextureViewer::OnLogfileClosed()
|
||||
{
|
||||
return ui->framerender;
|
||||
m_Output = NULL;
|
||||
ui->framerender->SetOutput(NULL);
|
||||
}
|
||||
|
||||
TextureViewer::~TextureViewer()
|
||||
void TextureViewer::OnEventSelected(uint32_t frameID, uint32_t eventID)
|
||||
{
|
||||
delete ui;
|
||||
m_Core->Renderer()->AsyncInvoke([this](IReplayRenderer *) {
|
||||
TextureDisplay d;
|
||||
if(m_Core->APIProps().pipelineType == ePipelineState_D3D11)
|
||||
d.texid = m_Core->CurD3D11PipelineState.m_OM.RenderTargets[0].Resource;
|
||||
else
|
||||
d.texid = m_Core->CurGLPipelineState.m_FB.m_DrawFBO.Color[0];
|
||||
d.mip = 0;
|
||||
d.sampleIdx = ~0U;
|
||||
d.overlay = eTexOverlay_None;
|
||||
d.CustomShader = ResourceId();
|
||||
d.HDRMul = -1.0f;
|
||||
d.linearDisplayAsGamma = true;
|
||||
d.FlipY = false;
|
||||
d.rangemin = 0.0f;
|
||||
d.rangemax = 1.0f;
|
||||
d.scale = -1.0f;
|
||||
d.offx = 0.0f;
|
||||
d.offy = 0.0f;
|
||||
d.sliceFace = 0;
|
||||
d.rawoutput = false;
|
||||
d.lightBackgroundColour = d.darkBackgroundColour =
|
||||
FloatVector(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
d.Red = d.Green = d.Blue = true;
|
||||
d.Alpha = false;
|
||||
m_Output->SetTextureDisplay(d);
|
||||
|
||||
GUIInvoke::call([this]() { ui->framerender->update(); });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,22 +3,28 @@
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
#include "Code/Core.h"
|
||||
|
||||
namespace Ui {
|
||||
class TextureViewer;
|
||||
}
|
||||
|
||||
class TextureViewer : public QFrame
|
||||
class TextureViewer : public QFrame, public ILogViewerForm
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TextureViewer(QWidget *parent = 0);
|
||||
explicit TextureViewer(Core *core, QWidget *parent = 0);
|
||||
~TextureViewer();
|
||||
|
||||
QWidget *renderSurf();
|
||||
void OnLogfileLoaded();
|
||||
void OnLogfileClosed();
|
||||
void OnEventSelected(uint32_t frameID, uint32_t eventID);
|
||||
|
||||
private:
|
||||
Ui::TextureViewer *ui;
|
||||
Core *m_Core;
|
||||
IReplayOutput *m_Output;
|
||||
};
|
||||
|
||||
#endif // TEXTUREVIEWER_H
|
||||
|
||||
Reference in New Issue
Block a user