diff --git a/qrenderdoc/Widgets/PipelineFlowChart.cpp b/qrenderdoc/Widgets/PipelineFlowChart.cpp new file mode 100644 index 000000000..d1d3740e1 --- /dev/null +++ b/qrenderdoc/Widgets/PipelineFlowChart.cpp @@ -0,0 +1,304 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "PipelineFlowChart.h" +#include +#include + +PipelineFlowChart::PipelineFlowChart(QWidget *parent) : QFrame(parent) +{ + setMouseTracking(true); +} + +PipelineFlowChart::~PipelineFlowChart() +{ +} + +void PipelineFlowChart::setStages(const QStringList &abbrevs, const QStringList &names) +{ + m_StageNames = names; + m_StageAbbrevs = abbrevs; + m_StageFlows.reserve(m_StageNames.count()); + m_StagesEnabled.reserve(m_StageNames.count()); + for(int i = 0; i < m_StageNames.count(); i++) + { + m_StageFlows.push_back(true); + m_StagesEnabled.push_back(true); + } + + update(); +} + +void PipelineFlowChart::setStageName(int index, const QString &abbrev, const QString &name) +{ + if(index >= 0 && index < m_StageNames.count()) + { + m_StageAbbrevs[index] = abbrev; + m_StageNames[index] = name; + } + + update(); +} + +void PipelineFlowChart::setIsolatedStage(int index) +{ + if(index >= 0 && index < m_StageFlows.count()) + m_StageFlows[index] = false; +} + +void PipelineFlowChart::setSelectedStage(int idx) +{ + if(idx >= 0 && idx < m_StageNames.length()) + { + m_SelectedStage = idx; + update(); + + emit stageSelected(idx); + } +} + +int PipelineFlowChart::selectedStage() +{ + return m_SelectedStage; +} + +void PipelineFlowChart::setStagesEnabled(const QList &enabled) +{ + for(int i = 0; i < enabled.count() && i < m_StagesEnabled.count(); i++) + m_StagesEnabled[i] = enabled[i]; + + update(); +} + +bool PipelineFlowChart::stageEnabled(int index) +{ + return index >= 0 && index < m_StagesEnabled.count() && m_StagesEnabled[index]; +} + +int PipelineFlowChart::numGaps() +{ + if(!m_StageNames.isEmpty()) + return m_StageNames.count() - 1; + + return 1; +} + +int PipelineFlowChart::numItems() +{ + if(!m_StageNames.isEmpty()) + return m_StageNames.count(); + + return 2; +} + +QRectF PipelineFlowChart::totalAreaRect() +{ + QRectF rect = this->rect(); + + qreal m = 6 + BoxBorderWidth; + + return rect.marginsRemoved(QMarginsF(m, m, m, m)); +} + +qreal PipelineFlowChart::boxMargin() +{ + qreal margin = qMax(totalAreaRect().width(), totalAreaRect().height()) * BoxMarginFraction; + + margin = qMax(MinBoxMargin, margin); + + return margin; +} + +QRectF PipelineFlowChart::boxRect(int i) +{ + QRectF totalRect = totalAreaRect(); + + qreal boxeswidth = totalRect.width() - numGaps() * boxMargin(); + + qreal boxdim = qMin(totalRect.height(), boxeswidth / numItems()); + + boxdim = qMax(MinBoxDimension, boxdim); + + qreal oblongwidth = qMax(0.0, (boxeswidth - boxdim * numItems()) / numItems()); + + QSizeF boxSize(boxdim + oblongwidth, boxdim); + + QRectF ret(totalRect.x() + i * (boxSize.width() + boxMargin()), + totalRect.y() + totalRect.height() / 2 - boxSize.height() / 2, boxSize.width(), + boxSize.height()); + + return ret; +} + +void PipelineFlowChart::drawArrow(QPainter &p, const QPen &pen, float headsize, float y, float left, + float right) +{ + p.setPen(pen); + + p.drawPolygon(QPolygonF({QPointF(right, y), QPointF(right - headsize, y - headsize), + QPointF(right - headsize, y + headsize)})); + + QPen linePen(pen); + linePen.setWidthF(BoxBorderWidth); + p.setPen(linePen); + + p.drawLine(QPointF(left, y), QPointF(right, y)); +} + +void PipelineFlowChart::paintEvent(QPaintEvent *e) +{ + if(m_StageNames.empty()) + return; + + QPainter p(this); + + p.fillRect(rect(), Qt::transparent); + + p.setRenderHint(QPainter::Antialiasing, true); + + const QRectF totalRect = totalAreaRect(); + const QRectF box0Rect = boxRect(0); + + const qreal radius = qMin(MaxBoxCornerRadius, box0Rect.height() * BoxCornerRadiusFraction); + + const qreal arrowY = totalRect.y() + totalRect.height() / 2; + + QColor base = palette().color(QPalette::Base); + QColor baseText = palette().color(QPalette::Text); + QColor inactiveWin = palette().color(QPalette::Inactive, QPalette::Dark); + QColor inactiveWinText = palette().color(QPalette::Inactive, QPalette::WindowText); + QColor tooltip = palette().color(QPalette::ToolTipBase); + QColor tooltipText = palette().color(QPalette::ToolTipText); + + QPen pen(baseText); + QPen selectedPen(Qt::red); + + int num = numGaps(); + for(int i = 0; i < num; i++) + { + if(!m_StageFlows[i] || !m_StageFlows[i + 1]) + continue; + + float right = totalRect.x() + (i + 1) * (box0Rect.width() + boxMargin()); + float left = right - boxMargin(); + + p.setBrush(baseText); + drawArrow(p, pen, ArrowHeadSize, arrowY, left, right); + } + + num = numItems(); + for(int i = 0; i < num; i++) + { + QRectF boxrect = boxRect(i); + + QBrush backBrush(base); + QPen textPen(baseText); + QPen outlinePen = pen; + + if(!stageEnabled(i)) + { + backBrush.setColor(inactiveWin); + textPen.setColor(inactiveWinText); + } + + if(i == m_HoverStage) + { + backBrush.setColor(tooltip); + textPen.setColor(tooltipText); + } + + if(i == m_SelectedStage) + { + outlinePen = selectedPen; + } + + outlinePen.setWidthF(BoxBorderWidth); + + p.setPen(outlinePen); + p.setBrush(backBrush); + p.drawRoundedRect(boxrect, radius, radius); + + QTextOption opts(Qt::AlignCenter); + opts.setWrapMode(QTextOption::NoWrap); + + QString s = m_StageNames[i]; + + QRectF reqBox = p.boundingRect(QRectF(0, 0, 1, 1), m_StageNames[i], opts); + + if(reqBox.width() + BoxLabelMargin > (float)boxrect.width()) + s = m_StageAbbrevs[i]; + + p.setPen(textPen); + p.drawText(boxrect, s, opts); + } +} + +void PipelineFlowChart::mouseMoveEvent(QMouseEvent *e) +{ + int old = m_HoverStage; + m_HoverStage = -1; + + const int num = numItems(); + for(int i = 0; i < num; i++) + { + if(boxRect(i).contains(e->pos())) + { + m_HoverStage = i; + break; + } + } + + if(m_HoverStage != old) + update(); +} + +void PipelineFlowChart::mousePressEvent(QMouseEvent *e) +{ + if(e->button() == Qt::LeftButton) + { + const int num = numItems(); + for(int i = 0; i < numItems(); i++) + { + if(boxRect(i).contains(e->pos())) + { + setSelectedStage(i); + break; + } + } + } +} + +void PipelineFlowChart::leaveEvent(QEvent *e) +{ + m_HoverStage = -1; + + update(); +} + +void PipelineFlowChart::focusOutEvent(QFocusEvent *event) +{ + m_HoverStage = -1; + + update(); +} diff --git a/qrenderdoc/Widgets/PipelineFlowChart.h b/qrenderdoc/Widgets/PipelineFlowChart.h new file mode 100644 index 000000000..03dc60e75 --- /dev/null +++ b/qrenderdoc/Widgets/PipelineFlowChart.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +#include + +class PipelineFlowChart : public QFrame +{ + Q_OBJECT + +public: + explicit PipelineFlowChart(QWidget *parent = 0); + ~PipelineFlowChart(); + + void setStages(const QStringList &abbrevs, const QStringList &names); + void setStageName(int index, const QString &abbrev, const QString &name); + void setIsolatedStage(int index); + + void setStagesEnabled(const QList &enabled); + + void setSelectedStage(int idx); + int selectedStage(); + +signals: + void stageSelected(int idx); + +private: + void paintEvent(QPaintEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void leaveEvent(QEvent *e) override; + void focusOutEvent(QFocusEvent *event) override; + + QList m_StagesEnabled; + QList m_StageFlows; + QStringList m_StageAbbrevs; + QStringList m_StageNames; + + int m_HoverStage = -1; + int m_SelectedStage = 0; + + bool stageEnabled(int index); + + const qreal BoxBorderWidth = 2.5; + const qreal MinBoxDimension = 25.0; + const qreal MaxBoxCornerRadius = 20.0; + const qreal BoxCornerRadiusFraction = 1.0 / 6.0; + const qreal ArrowHeadSize = 6.0; + const qreal MinBoxMargin = 4.0; + const qreal BoxLabelMargin = 8.0; + const qreal BoxMarginFraction = 0.02; + + int numGaps(); + int numItems(); + + QRectF totalAreaRect(); + qreal boxMargin(); + QRectF boxRect(int i); + + void drawArrow(QPainter &p, const QPen &pen, float headsize, float y, float left, float right); +}; diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp index e6ab59eeb..c11d0dfe4 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp @@ -318,6 +318,21 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(CaptureContext &ctx, Pipeline // this is often changed just because we're changing some tab in the designer. ui->stagesTabs->setCurrentIndex(0); + ui->stagesTabs->tabBar()->setVisible(false); + + ui->pipeFlow->setStages( + { + "IA", "VS", "HS", "DS", "GS", "RS", "PS", "OM", "CS", + }, + { + "Input Assembler", "Vertex Shader", "Hull Shader", "Domain Shader", "Geometry Shader", + "Rasterizer", "Pixel Shader", "Output Merger", "Compute Shader", + }); + + ui->pipeFlow->setIsolatedStage(8); // compute shader isolated + + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); + // reset everything back to defaults clearState(); } @@ -334,6 +349,8 @@ void D3D11PipelineStateViewer::OnLogfileLoaded() void D3D11PipelineStateViewer::OnLogfileClosed() { + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); + clearState(); } @@ -1628,37 +1645,21 @@ void D3D11PipelineStateViewer::setState() ui->stencils->clearSelection(); ui->stencils->setUpdatesEnabled(true); -// highlight the appropriate stages in the flowchart -#if 0 - if(draw == null) + // highlight the appropriate stages in the flowchart + if(draw == NULL) { - pipeFlow.SetStagesEnabled(new bool[] { true, true, true, true, true, true, true, true, true }); + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); } - else if((draw.flags & DrawcallFlags.Dispatch) != 0) + else if(draw->flags & eDraw_Dispatch) { - pipeFlow.SetStagesEnabled(new bool[] { false, false, false, false, false, false, false, false, true }); + ui->pipeFlow->setStagesEnabled({false, false, false, false, false, false, false, false, true}); } else { - pipeFlow.SetStagesEnabled(new bool[] { - true, - true, - state.HS.Shader != ResourceId(), - state.DS.Shader != ResourceId(), - state.GS.Shader != ResourceId(), - true, - state.PS.Shader != ResourceId(), - true, - false - }); - - // if(streamout only) - //{ - // pipeFlow.Rasterizer = false; - // pipeFlow.OutputMerger = false; - //} + ui->pipeFlow->setStagesEnabled( + {true, true, state.m_HS.Shader != ResourceId(), state.m_DS.Shader != ResourceId(), + state.m_GS.Shader != ResourceId(), true, state.m_PS.Shader != ResourceId(), true, false}); } -#endif } QString D3D11PipelineStateViewer::formatMembers(int indent, const QString &nameprefix, @@ -2088,6 +2089,11 @@ void D3D11PipelineStateViewer::on_iaBuffers_mouseMove(QMouseEvent *e) } } +void D3D11PipelineStateViewer::on_pipeFlow_stageSelected(int index) +{ + ui->stagesTabs->setCurrentIndex(index); +} + void D3D11PipelineStateViewer::vertex_leave(QEvent *e) { ui->iaLayouts->model()->blockSignals(true); diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h index 593508181..8c7cc04f6 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h @@ -61,6 +61,7 @@ private slots: void on_iaBuffers_itemActivated(QTreeWidgetItem *item, int column); void on_iaLayouts_mouseMove(QMouseEvent *event); void on_iaBuffers_mouseMove(QMouseEvent *event); + void on_pipeFlow_stageSelected(int index); // manual slots void shaderView_clicked(); diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.ui b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.ui index a67013663..4ab66f651 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.ui +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.ui @@ -7,7 +7,7 @@ 0 0 996 - 574 + 586 @@ -143,6 +143,33 @@ + + + + + 0 + 0 + + + + + 0 + 60 + + + + + 16777215 + 75 + + + + + 12 + + + + @@ -4977,6 +5004,12 @@ padding: 0px; QLabel
Widgets/Extended/RDLabel.h
+ + PipelineFlowChart + QFrame +
Widgets/PipelineFlowChart.h
+ 1 +
diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp index e850649f1..4c91456f0 100644 --- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp @@ -354,6 +354,21 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(CaptureContext &ctx, Pipeline // this is often changed just because we're changing some tab in the designer. ui->stagesTabs->setCurrentIndex(0); + ui->stagesTabs->tabBar()->setVisible(false); + + ui->pipeFlow->setStages( + { + "IA", "VS", "HS", "DS", "GS", "RS", "PS", "OM", "CS", + }, + { + "Input Assembler", "Vertex Shader", "Hull Shader", "Domain Shader", "Geometry Shader", + "Rasterizer", "Pixel Shader", "Output Merger", "Compute Shader", + }); + + ui->pipeFlow->setIsolatedStage(8); // compute shader isolated + + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); + // reset everything back to defaults clearState(); } @@ -370,6 +385,8 @@ void D3D12PipelineStateViewer::OnLogfileLoaded() void D3D12PipelineStateViewer::OnLogfileClosed() { + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); + clearState(); } @@ -1611,37 +1628,21 @@ void D3D12PipelineStateViewer::setState() ui->stencils->clearSelection(); ui->stencils->setUpdatesEnabled(true); -// highlight the appropriate stages in the flowchart -#if 0 - if(draw == null) + // highlight the appropriate stages in the flowchart + if(draw == NULL) { - pipeFlow.SetStagesEnabled(new bool[] { true, true, true, true, true, true, true, true, true }); + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); } - else if((draw.flags & DrawcallFlags.Dispatch) != 0) + else if(draw->flags & eDraw_Dispatch) { - pipeFlow.SetStagesEnabled(new bool[] { false, false, false, false, false, false, false, false, true }); + ui->pipeFlow->setStagesEnabled({false, false, false, false, false, false, false, false, true}); } else { - pipeFlow.SetStagesEnabled(new bool[] { - true, - true, - state.HS.Shader != ResourceId(), - state.DS.Shader != ResourceId(), - state.GS.Shader != ResourceId(), - true, - state.PS.Shader != ResourceId(), - true, - false - }); - - // if(streamout only) - //{ - // pipeFlow.Rasterizer = false; - // pipeFlow.OutputMerger = false; - //} + ui->pipeFlow->setStagesEnabled( + {true, true, state.m_HS.Shader != ResourceId(), state.m_DS.Shader != ResourceId(), + state.m_GS.Shader != ResourceId(), true, state.m_PS.Shader != ResourceId(), true, false}); } -#endif } QString D3D12PipelineStateViewer::formatMembers(int indent, const QString &nameprefix, @@ -2134,6 +2135,11 @@ void D3D12PipelineStateViewer::vertex_leave(QEvent *e) } } +void D3D12PipelineStateViewer::on_pipeFlow_stageSelected(int index) +{ + ui->stagesTabs->setCurrentIndex(index); +} + void D3D12PipelineStateViewer::shaderView_clicked() { QWidget *sender = qobject_cast(QObject::sender()); diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.h index 745b45ab9..e174d36a6 100644 --- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.h @@ -61,6 +61,7 @@ private slots: void on_iaBuffers_itemActivated(QTreeWidgetItem *item, int column); void on_iaLayouts_mouseMove(QMouseEvent *event); void on_iaBuffers_mouseMove(QMouseEvent *event); + void on_pipeFlow_stageSelected(int index); // manual slots void shaderView_clicked(); diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.ui b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.ui index 12464dad6..27d775d76 100644 --- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.ui +++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.ui @@ -143,6 +143,28 @@
+ + + + + 0 + 0 + + + + + 0 + 60 + + + + + 16777215 + 75 + + + + @@ -5188,6 +5210,12 @@ padding: 0px; QLabel
Widgets/Extended/RDLabel.h
+ + PipelineFlowChart + QFrame +
Widgets/PipelineFlowChart.h
+ 1 +
diff --git a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp index a01b6aca3..d7c9abf93 100644 --- a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp @@ -324,6 +324,22 @@ GLPipelineStateViewer::GLPipelineStateViewer(CaptureContext &ctx, PipelineStateV // this is often changed just because we're changing some tab in the designer. ui->stagesTabs->setCurrentIndex(0); + ui->stagesTabs->tabBar()->setVisible(false); + + ui->pipeFlow->setStages( + { + "VTX", "VS", "TCS", "TES", "GS", "RS", "FS", "FB", "CS", + }, + { + "Vertex Input", "Vertex Shader", "Tess. Control Shader", "Tess. Eval. Shader", + "Geometry Shader", "Rasterizer", "Fragment Shader", "Framebuffer Output", + "Compute Shader", + }); + + ui->pipeFlow->setIsolatedStage(8); // compute shader isolated + + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); + // reset everything back to defaults clearState(); } @@ -340,6 +356,8 @@ void GLPipelineStateViewer::OnLogfileLoaded() void GLPipelineStateViewer::OnLogfileClosed() { + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); + clearState(); } @@ -1864,37 +1882,21 @@ void GLPipelineStateViewer::setState() ui->stencils->clearSelection(); ui->stencils->setUpdatesEnabled(true); -// highlight the appropriate stages in the flowchart -#if 0 - if(draw == null) + // highlight the appropriate stages in the flowchart + if(draw == NULL) { - pipeFlow.SetStagesEnabled(new bool[] { true, true, true, true, true, true, true, true, true }); + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); } - else if((draw.flags & DrawcallFlags.Dispatch) != 0) + else if(draw->flags & eDraw_Dispatch) { - pipeFlow.SetStagesEnabled(new bool[] { false, false, false, false, false, false, false, false, true }); + ui->pipeFlow->setStagesEnabled({false, false, false, false, false, false, false, false, true}); } else { - pipeFlow.SetStagesEnabled(new bool[] { - true, - true, - state.TCS.Shader != ResourceId(), - state.TES.Shader != ResourceId(), - state.GS.Shader != ResourceId(), - true, - state.FS.Shader != ResourceId(), - true, - false - }); - - // if(streamout only) - //{ - // pipeFlow.Rasterizer = false; - // pipeFlow.OutputMerger = false; - //} + ui->pipeFlow->setStagesEnabled( + {true, true, state.m_TCS.Shader != ResourceId(), state.m_TES.Shader != ResourceId(), + state.m_GS.Shader != ResourceId(), true, state.m_FS.Shader != ResourceId(), true, false}); } -#endif } QString GLPipelineStateViewer::formatMembers(int indent, const QString &nameprefix, @@ -2232,6 +2234,11 @@ void GLPipelineStateViewer::vertex_leave(QEvent *e) } } +void GLPipelineStateViewer::on_pipeFlow_stageSelected(int index) +{ + ui->stagesTabs->setCurrentIndex(index); +} + void GLPipelineStateViewer::shaderView_clicked() { const GLPipelineState::ShaderStage *stage = diff --git a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.h index 065b0ecc5..6496b58e3 100644 --- a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.h @@ -60,6 +60,7 @@ private slots: void on_viBuffers_itemActivated(QTreeWidgetItem *item, int column); void on_viAttrs_mouseMove(QMouseEvent *event); void on_viBuffers_mouseMove(QMouseEvent *event); + void on_pipeFlow_stageSelected(int index); // manual slots void shaderView_clicked(); diff --git a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.ui b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.ui index aae8b03b3..bb1ecf5e9 100644 --- a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.ui +++ b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.ui @@ -143,6 +143,28 @@
+ + + + + 0 + 0 + + + + + 0 + 60 + + + + + 16777215 + 75 + + + + @@ -5488,6 +5510,12 @@ padding: 0px; QLabel
Widgets/Extended/RDLabel.h
+ + PipelineFlowChart + QFrame +
Widgets/PipelineFlowChart.h
+ 1 +
diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index df73d6374..cdff45475 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -288,6 +288,22 @@ VulkanPipelineStateViewer::VulkanPipelineStateViewer(CaptureContext &ctx, // this is often changed just because we're changing some tab in the designer. ui->stagesTabs->setCurrentIndex(0); + ui->stagesTabs->tabBar()->setVisible(false); + + ui->pipeFlow->setStages( + { + "VTX", "VS", "TCS", "TES", "GS", "RS", "FS", "FB", "CS", + }, + { + "Vertex Input", "Vertex Shader", "Tess. Control Shader", "Tess. Eval. Shader", + "Geometry Shader", "Rasterizer", "Fragment Shader", "Framebuffer Output", + "Compute Shader", + }); + + ui->pipeFlow->setIsolatedStage(8); // compute shader isolated + + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); + // reset everything back to defaults clearState(); } @@ -304,6 +320,8 @@ void VulkanPipelineStateViewer::OnLogfileLoaded() void VulkanPipelineStateViewer::OnLogfileClosed() { + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); + clearState(); } @@ -1955,37 +1973,21 @@ void VulkanPipelineStateViewer::setState() ui->stencils->clearSelection(); ui->stencils->setUpdatesEnabled(true); -// highlight the appropriate stages in the flowchart -#if 0 - if(draw == null) + // highlight the appropriate stages in the flowchart + if(draw == NULL) { - pipeFlow.SetStagesEnabled(new bool[] { true, true, true, true, true, true, true, true, true }); + ui->pipeFlow->setStagesEnabled({true, true, true, true, true, true, true, true, true}); } - else if((draw.flags & DrawcallFlags.Dispatch) != 0) + else if(draw->flags & eDraw_Dispatch) { - pipeFlow.SetStagesEnabled(new bool[] { false, false, false, false, false, false, false, false, true }); + ui->pipeFlow->setStagesEnabled({false, false, false, false, false, false, false, false, true}); } else { - pipeFlow.SetStagesEnabled(new bool[] { - true, - true, - state.TCS.Shader != ResourceId(), - state.TES.Shader != ResourceId(), - state.GS.Shader != ResourceId(), - true, - state.FS.Shader != ResourceId(), - true, - false - }); - - // if(streamout only) - //{ - // pipeFlow.Rasterizer = false; - // pipeFlow.OutputMerger = false; - //} + ui->pipeFlow->setStagesEnabled( + {true, true, state.m_TCS.Shader != ResourceId(), state.m_TES.Shader != ResourceId(), + state.m_GS.Shader != ResourceId(), true, state.m_FS.Shader != ResourceId(), true, false}); } -#endif } QString VulkanPipelineStateViewer::formatMembers(int indent, const QString &nameprefix, @@ -2334,6 +2336,11 @@ void VulkanPipelineStateViewer::vertex_leave(QEvent *e) } } +void VulkanPipelineStateViewer::on_pipeFlow_stageSelected(int index) +{ + ui->stagesTabs->setCurrentIndex(index); +} + void VulkanPipelineStateViewer::shaderView_clicked() { const VulkanPipelineState::ShaderStage *stage = diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h index a24aef42b..6d1f966e3 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h @@ -67,6 +67,7 @@ private slots: void on_viBuffers_itemActivated(QTreeWidgetItem *item, int column); void on_viAttrs_mouseMove(QMouseEvent *event); void on_viBuffers_mouseMove(QMouseEvent *event); + void on_pipeFlow_stageSelected(int index); // manual slots void shaderView_clicked(); diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.ui b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.ui index eaab4d450..43a62f5eb 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.ui +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.ui @@ -143,6 +143,28 @@
+ + + + + 0 + 0 + + + + + 0 + 60 + + + + + 16777215 + 75 + + + + @@ -3738,6 +3760,12 @@ padding: 0px; QLabel
Widgets/Extended/RDLabel.h
+ + PipelineFlowChart + QFrame +
Widgets/PipelineFlowChart.h
+ 1 +
diff --git a/qrenderdoc/qrenderdoc.pro b/qrenderdoc/qrenderdoc.pro index 4c5b7acb3..63e2f665a 100644 --- a/qrenderdoc/qrenderdoc.pro +++ b/qrenderdoc/qrenderdoc.pro @@ -145,7 +145,8 @@ SOURCES += Code/qrenderdoc.cpp \ Windows/Dialogs/SuggestRemoteDialog.cpp \ Windows/Dialogs/VirtualFileDialog.cpp \ Windows/Dialogs/RemoteManager.cpp \ - Windows/PixelHistoryView.cpp + Windows/PixelHistoryView.cpp \ + Widgets/PipelineFlowChart.cpp HEADERS += Code/CaptureContext.h \ Code/qprocessinfo.h \ @@ -193,7 +194,8 @@ HEADERS += Code/CaptureContext.h \ Windows/Dialogs/SuggestRemoteDialog.h \ Windows/Dialogs/VirtualFileDialog.h \ Windows/Dialogs/RemoteManager.h \ - Windows/PixelHistoryView.h + Windows/PixelHistoryView.h \ + Widgets/PipelineFlowChart.h FORMS += Windows/Dialogs/AboutDialog.ui \ Windows/MainWindow.ui \ diff --git a/qrenderdoc/qrenderdoc_local.vcxproj b/qrenderdoc/qrenderdoc_local.vcxproj index 7b5a9138a..b0ebe0b97 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj +++ b/qrenderdoc/qrenderdoc_local.vcxproj @@ -661,6 +661,7 @@ + @@ -706,6 +707,7 @@ + @@ -966,6 +968,12 @@ MOC %(Filename).h generated\moc_%(Filename).cpp + + %(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe;%(AdditionalInputs) + $(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -D_WIN32 -D_WIN64 -DRENDERDOC_PLATFORM_WIN32 -DSCINTILLA_QT=1 -DSCI_LEXER=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1900 -I$(ProjectDir) -I$(SolutionDir)\renderdoc\api\replay -I$(ProjectDir)3rdparty\qt\$(Platform)\mkspecs/win32-msvc2015 -I$(ProjectDir)3rdparty\qt\$(Platform)\include -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtWidgets -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtGui -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtCore %(Fullpath) -o $(ProjectDir)generated\moc_%(Filename).cpp + MOC %(Filename).h + generated\moc_%(Filename).cpp + %(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe;%(AdditionalInputs) $(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -D_WIN32 -D_WIN64 -DRENDERDOC_PLATFORM_WIN32 -DSCINTILLA_QT=1 -DSCI_LEXER=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1900 -I$(ProjectDir) -I$(SolutionDir)\renderdoc\api\replay -I$(ProjectDir)3rdparty\qt\$(Platform)\mkspecs/win32-msvc2015 -I$(ProjectDir)3rdparty\qt\$(Platform)\include -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtWidgets -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtGui -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtCore %(Fullpath) -o $(ProjectDir)generated\moc_%(Filename).cpp