diff --git a/qrenderdoc/Code/Core.cpp b/qrenderdoc/Code/Core.cpp index 5da363fd3..cdc0cda96 100644 --- a/qrenderdoc/Code/Core.cpp +++ b/qrenderdoc/Code/Core.cpp @@ -1,19 +1,168 @@ #include "Core.h" +#include "Windows/MainWindow.h" +#include #include +#include +#include -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 &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[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 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 &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 &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); } diff --git a/qrenderdoc/Code/Core.h b/qrenderdoc/Code/Core.h index fbac7468a..7682bd5ac 100644 --- a/qrenderdoc/Code/Core.h +++ b/qrenderdoc/Code/Core.h @@ -3,16 +3,164 @@ #include "RenderManager.h" +#include +#include +#include + +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 &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 &CurDrawcalls(uint32_t frame) { return m_Drawcalls[frame]; } + + FetchTexture *GetTexture(ResourceId id) { return m_Textures[id]; } + const rdctype::array &GetTextures() { return m_TextureList; } + + FetchBuffer *GetBuffer(ResourceId id) { return m_Buffers[id]; } + const rdctype::array &GetBuffers() { return m_BufferList; } + + QList DebugMessages; + int UnreadMessageCount; + void AddMessages(rdctype::array &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 m_LogViewers; + QList m_ProgressListeners; + + bool m_LogLoaded, m_LoadInProgress; + QString m_LogFile; + + uint32_t m_FrameID, m_EventID; + + const FetchDrawcall *GetDrawcall(const rdctype::array &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 *m_Drawcalls; + + APIProperties m_APIProps; + rdctype::array m_FrameInfo; + + QMap m_Textures; + rdctype::array m_TextureList; + QMap m_Buffers; + rdctype::array 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 -class QInvoke : public QObject +class GUIInvoke : public QObject { Q_OBJECT - QInvoke(const std::function &f) : func(f) {} + GUIInvoke(const std::function &f) : func(f) {} std::function func; -public: + public: static void call(const std::function &f); + static void blockcall(const std::function &f); -protected slots: + protected slots: void doInvoke() { - func(); - deleteLater(); + func(); + deleteLater(); } }; +// Utility class for calling a lambda on a new thread. +#include + +class LambdaThread : public QObject +{ + Q_OBJECT + + std::function m_func; + QThread *m_Thread; + + public slots: + void process() + { + m_func(); + m_Thread->quit(); + deleteLater(); + m_Thread->deleteLater(); + } + + public: + explicit LambdaThread(std::function 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 diff --git a/qrenderdoc/Code/RenderManager.cpp b/qrenderdoc/Code/RenderManager.cpp index a4da9f8e0..04bc03836 100644 --- a/qrenderdoc/Code/RenderManager.cpp +++ b/qrenderdoc/Code/RenderManager.cpp @@ -1,10 +1,13 @@ #include "RenderManager.h" +#include "Core.h" + #include 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; diff --git a/qrenderdoc/Code/RenderManager.h b/qrenderdoc/Code/RenderManager.h index 69078671d..15e9201f7 100644 --- a/qrenderdoc/Code/RenderManager.h +++ b/qrenderdoc/Code/RenderManager.h @@ -12,12 +12,10 @@ #include struct IReplayRenderer; +class LambdaThread; -class RenderManager : public QThread +class RenderManager { - Q_OBJECT - void run(); - public: typedef std::function 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 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; }; diff --git a/qrenderdoc/Code/main.cpp b/qrenderdoc/Code/main.cpp index d68742f71..d195fa82f 100644 --- a/qrenderdoc/Code/main.cpp +++ b/qrenderdoc/Code/main.cpp @@ -1,15 +1,65 @@ #include "Windows/MainWindow.h" -#include +#include "Code/Core.h" -#include "renderdoc_replay.h" +#include +#include +#include +#include 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(); } diff --git a/qrenderdoc/Widgets/CustomPaintWidget.cpp b/qrenderdoc/Widgets/CustomPaintWidget.cpp index 398133fc8..e32156f5d 100644 --- a/qrenderdoc/Widgets/CustomPaintWidget.cpp +++ b/qrenderdoc/Widgets/CustomPaintWidget.cpp @@ -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(); } diff --git a/qrenderdoc/Widgets/CustomPaintWidget.h b/qrenderdoc/Widgets/CustomPaintWidget.h index 9926fb602..5304c2074 100644 --- a/qrenderdoc/Widgets/CustomPaintWidget.h +++ b/qrenderdoc/Widgets/CustomPaintWidget.h @@ -3,6 +3,8 @@ #include +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 diff --git a/qrenderdoc/Windows/EventBrowser.cpp b/qrenderdoc/Windows/EventBrowser.cpp index 8c86f7392..294ff078d 100644 --- a/qrenderdoc/Windows/EventBrowser.cpp +++ b/qrenderdoc/Windows/EventBrowser.cpp @@ -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 &draws) { uint lastEID = 0; @@ -25,29 +18,14 @@ uint AddDrawcalls(QTreeWidgetItem *parent, const rdctype::array & 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 draws; - ReplayRenderer_GetDrawcalls(renderer, 0, &draws); - - rdctype::array 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); } diff --git a/qrenderdoc/Windows/EventBrowser.h b/qrenderdoc/Windows/EventBrowser.h index 898b2a17c..fc631e316 100644 --- a/qrenderdoc/Windows/EventBrowser.h +++ b/qrenderdoc/Windows/EventBrowser.h @@ -3,18 +3,24 @@ #include +#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 diff --git a/qrenderdoc/Windows/EventBrowser.ui b/qrenderdoc/Windows/EventBrowser.ui index 07f5a788b..80d80211b 100644 --- a/qrenderdoc/Windows/EventBrowser.ui +++ b/qrenderdoc/Windows/EventBrowser.ui @@ -72,7 +72,7 @@ - + :/Resources/find.png:/Resources/find.png @@ -95,7 +95,7 @@ - + :/Resources/flag_green.png:/Resources/flag_green.png @@ -109,7 +109,7 @@ - + :/Resources/time.png:/Resources/time.png @@ -201,8 +201,6 @@ - - - + diff --git a/qrenderdoc/Windows/MainWindow.cpp b/qrenderdoc/Windows/MainWindow.cpp index 86bd56bdf..ee2e4f866 100644 --- a/qrenderdoc/Windows/MainWindow.cpp +++ b/qrenderdoc/Windows/MainWindow.cpp @@ -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 +#include -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(); + } +} diff --git a/qrenderdoc/Windows/MainWindow.h b/qrenderdoc/Windows/MainWindow.h index edde1d67e..32dc12505 100644 --- a/qrenderdoc/Windows/MainWindow.h +++ b/qrenderdoc/Windows/MainWindow.h @@ -2,24 +2,30 @@ #define MAINWINDOW_H #include +#include 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 diff --git a/qrenderdoc/Windows/MainWindow.ui b/qrenderdoc/Windows/MainWindow.ui index cf2d96bde..dde22ff4b 100644 --- a/qrenderdoc/Windows/MainWindow.ui +++ b/qrenderdoc/Windows/MainWindow.ui @@ -11,7 +11,11 @@ - MainWindow + QRenderDoc + + + + :/Resources/icon.ico:/Resources/icon.ico @@ -374,6 +378,8 @@
ToolWindowManager.h
- + + + diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 9d6827295..688955f64 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -1,7 +1,7 @@ #include "TextureViewer.h" #include "ui_TextureViewer.h" -#include "renderdoc_replay.h" +#include "Code/Core.h" #if defined(__linux__) #include @@ -9,74 +9,82 @@ #include #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 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(); }); + }); } diff --git a/qrenderdoc/Windows/TextureViewer.h b/qrenderdoc/Windows/TextureViewer.h index 04abb50a1..06c958465 100644 --- a/qrenderdoc/Windows/TextureViewer.h +++ b/qrenderdoc/Windows/TextureViewer.h @@ -3,22 +3,28 @@ #include +#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