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:
baldurk
2015-04-06 01:31:14 +01:00
parent f6400f383e
commit a405ee13ca
15 changed files with 576 additions and 150 deletions
+155 -6
View File
@@ -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
View File
@@ -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
+15 -4
View File
@@ -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;
+6 -5
View File
@@ -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;
};
+54 -4
View File
@@ -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();
}
+2 -3
View File
@@ -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();
}
+6
View File
@@ -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
+31 -46
View File
@@ -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);
}
+9 -2
View File
@@ -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
+4 -6
View File
@@ -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>
+27 -13
View File
@@ -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();
}
}
+8 -2
View File
@@ -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
+8 -2
View File
@@ -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>
+55 -47
View File
@@ -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(); });
});
}
+9 -3
View File
@@ -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