mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-11-13 09:20:13 +00:00
Add a dialog for directly-launching pixel shader debug. Closes #3422
This commit is contained in:
26 files changed
+802
-614
No files matched your search
@@ -0,0 +1,105 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021-2026 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 "PixelDebugSelector.h"
|
||||
#include "Code/QRDUtils.h"
|
||||
#include "ui_PixelDebugSelector.h"
|
||||
|
||||
PixelDebugSelector::PixelDebugSelector(ICaptureContext &ctx, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::PixelDebugSelector), m_Ctx(ctx)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
ui->x->setFont(Formatter::PreferredFont());
|
||||
ui->y->setFont(Formatter::PreferredFont());
|
||||
ui->primitive->setFont(Formatter::PreferredFont());
|
||||
ui->sample->setFont(Formatter::PreferredFont());
|
||||
ui->view->setFont(Formatter::PreferredFont());
|
||||
}
|
||||
|
||||
PixelDebugSelector::~PixelDebugSelector()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void PixelDebugSelector::UpdateTarget()
|
||||
{
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const PipeState &pipe = m_Ctx.CurPipelineState();
|
||||
|
||||
ui->view->setMaximum(pipe.MultiviewBroadcastCount() - 1);
|
||||
ui->viewLabel->setVisible(ui->view->maximum() > 1);
|
||||
ui->view->setVisible(ui->view->maximum() > 1);
|
||||
|
||||
uint32_t sampleCount = pipe.GetOverrideSampleCount();
|
||||
|
||||
if(sampleCount == 0)
|
||||
{
|
||||
for(const Descriptor &d : pipe.GetOutputTargets())
|
||||
{
|
||||
const TextureDescription *tex = m_Ctx.GetTexture(d.resource);
|
||||
if(tex)
|
||||
sampleCount = qMax(sampleCount, tex->msSamp);
|
||||
}
|
||||
}
|
||||
|
||||
ui->sample->setMaximum(pipe.GetOverrideSampleCount() - 1);
|
||||
ui->sampleLabel->setVisible(ui->sample->maximum() > 1);
|
||||
ui->sample->setVisible(ui->sample->maximum() > 1);
|
||||
}
|
||||
|
||||
void PixelDebugSelector::on_selectedPixel_clicked()
|
||||
{
|
||||
rdcpair<int32_t, int32_t> sel = m_Ctx.GetTextureViewer()->GetPickedLocation();
|
||||
|
||||
ui->x->setValue(sel.first);
|
||||
ui->y->setValue(sel.second);
|
||||
}
|
||||
|
||||
void PixelDebugSelector::on_beginDebug_clicked()
|
||||
{
|
||||
DebugPixelInputs inputs;
|
||||
|
||||
bool ok = false;
|
||||
inputs.primitive = ui->primitive->text().toUInt(&ok);
|
||||
if(!ok)
|
||||
inputs.primitive = ~0U;
|
||||
|
||||
inputs.sample = ui->sample->value();
|
||||
inputs.view = ui->view->value();
|
||||
|
||||
emit beginDebug(ui->x->value(), ui->y->value(), inputs);
|
||||
close();
|
||||
}
|
||||
|
||||
void PixelDebugSelector::on_cancelDebug_clicked()
|
||||
{
|
||||
close();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021-2026 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 <QDialog>
|
||||
#include "Code/Interface/QRDInterface.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class PixelDebugSelector;
|
||||
}
|
||||
|
||||
class PixelDebugSelector : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PixelDebugSelector(ICaptureContext &ctx, QWidget *parent = 0);
|
||||
~PixelDebugSelector();
|
||||
|
||||
void UpdateTarget();
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
void beginDebug(uint32_t x, uint32_t y, const DebugPixelInputs &inputs);
|
||||
|
||||
private slots:
|
||||
// automatic slots
|
||||
void on_selectedPixel_clicked();
|
||||
void on_beginDebug_clicked();
|
||||
void on_cancelDebug_clicked();
|
||||
|
||||
private:
|
||||
void SyncGroupThreadValue();
|
||||
void SyncDispatchThreadValue();
|
||||
|
||||
Ui::PixelDebugSelector *ui;
|
||||
|
||||
ICaptureContext &m_Ctx;
|
||||
};
|
||||
@@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PixelDebugSelector</class>
|
||||
<widget class="QDialog" name="PixelDebugSelector">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>176</width>
|
||||
<height>274</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Debug Pixel Shader</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetFixedSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Pixel co-ordinate</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_groupthread">
|
||||
<property name="verticalSpacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="xLabel">
|
||||
<property name="text">
|
||||
<string>X:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="y">
|
||||
<property name="maximum">
|
||||
<number>16384</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="yLabel">
|
||||
<property name="text">
|
||||
<string>Y:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="x">
|
||||
<property name="maximum">
|
||||
<number>16384</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="selectedPixel">
|
||||
<property name="text">
|
||||
<string>Use Selected Pixel</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/wand.png</normaloff>:/wand.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox1">
|
||||
<property name="title">
|
||||
<string>Disambiguation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="primLabel">
|
||||
<property name="text">
|
||||
<string>Primitive:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="sample"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="view"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="sampleLabel">
|
||||
<property name="text">
|
||||
<string>Sample:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="viewLabel">
|
||||
<property name="text">
|
||||
<string>Multiview:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="RDLineEdit" name="primitive">
|
||||
<property name="placeholderText">
|
||||
<string>Any</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_buttons">
|
||||
<item>
|
||||
<widget class="QPushButton" name="beginDebug">
|
||||
<property name="text">
|
||||
<string>Debug</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/wrench.png</normaloff>:/wrench.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancelDebug">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RDLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>Widgets/Extended/RDLineEdit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../Resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <QScrollBar>
|
||||
#include <QXmlStreamWriter>
|
||||
#include "Code/Resources.h"
|
||||
#include "Widgets/ComputeDebugSelector.h"
|
||||
#include "Widgets/Extended/RDHeaderView.h"
|
||||
#include "flowlayout/FlowLayout.h"
|
||||
#include "toolwindowmanager/ToolWindowManager.h"
|
||||
@@ -78,8 +77,6 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_ComputeDebugSelector = new ComputeDebugSelector(this);
|
||||
|
||||
const QIcon &action = Icons::action();
|
||||
const QIcon &action_hover = Icons::action_hover();
|
||||
|
||||
@@ -163,8 +160,10 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
|
||||
b->setMinimumSizeHint(QSize(250, 0));
|
||||
}
|
||||
|
||||
QObject::connect(m_ComputeDebugSelector, &ComputeDebugSelector::beginDebug, this,
|
||||
&D3D11PipelineStateViewer::computeDebugSelector_beginDebug);
|
||||
QObject::connect(ui->computeDebugSelector, &QToolButton::clicked, &m_Common,
|
||||
&PipelineStateViewer::computeDebugSelector_clicked);
|
||||
QObject::connect(ui->pixelDebugSelector, &QToolButton::clicked, &m_Common,
|
||||
&PipelineStateViewer::pixelDebugSelector_clicked);
|
||||
|
||||
for(QToolButton *b : editButtons)
|
||||
QObject::connect(b, &QToolButton::clicked, &m_Common, &PipelineStateViewer::shaderEdit_clicked);
|
||||
@@ -486,7 +485,6 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
|
||||
D3D11PipelineStateViewer::~D3D11PipelineStateViewer()
|
||||
{
|
||||
delete ui;
|
||||
delete m_ComputeDebugSelector;
|
||||
}
|
||||
|
||||
void D3D11PipelineStateViewer::OnCaptureLoaded()
|
||||
@@ -1195,6 +1193,7 @@ void D3D11PipelineStateViewer::clearState()
|
||||
ui->predicateGroup->setVisible(false);
|
||||
|
||||
ui->computeDebugSelector->setEnabled(false);
|
||||
ui->pixelDebugSelector->setEnabled(false);
|
||||
}
|
||||
|
||||
void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, RDLabel *shader,
|
||||
@@ -2099,56 +2098,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
ui->stencils->clearSelection();
|
||||
ui->stencils->endUpdate();
|
||||
|
||||
// set up thread debugging inputs
|
||||
bool enableDebug = m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
|
||||
state.computeShader.reflection->debugInfo.debuggable && action &&
|
||||
(action->flags & ActionFlags::Dispatch);
|
||||
if(enableDebug)
|
||||
{
|
||||
// Validate dispatch/threadgroup dimensions
|
||||
enableDebug &= action->dispatchDimension[0] > 0;
|
||||
enableDebug &= action->dispatchDimension[1] > 0;
|
||||
enableDebug &= action->dispatchDimension[2] > 0;
|
||||
|
||||
const rdcfixedarray<uint32_t, 3> &threadDims =
|
||||
(action->dispatchThreadsDimension[0] == 0)
|
||||
? state.computeShader.reflection->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension;
|
||||
enableDebug &= threadDims[0] > 0;
|
||||
enableDebug &= threadDims[1] > 0;
|
||||
enableDebug &= threadDims[2] > 0;
|
||||
}
|
||||
|
||||
if(enableDebug)
|
||||
{
|
||||
ui->computeDebugSelector->setEnabled(true);
|
||||
|
||||
// set maximums for CS debugging
|
||||
m_ComputeDebugSelector->SetThreadBounds(
|
||||
action->dispatchDimension, (action->dispatchThreadsDimension[0] == 0)
|
||||
? state.computeShader.reflection->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension);
|
||||
|
||||
ui->computeDebugSelector->setToolTip(
|
||||
tr("Debug this compute shader by specifying group/thread ID or dispatch ID"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->computeDebugSelector->setEnabled(false);
|
||||
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
ui->computeDebugSelector->setToolTip(tr("This API does not support shader debugging"));
|
||||
else if(!action || !(action->flags & ActionFlags::Dispatch))
|
||||
ui->computeDebugSelector->setToolTip(tr("No dispatch selected"));
|
||||
else if(!state.computeShader.reflection)
|
||||
ui->computeDebugSelector->setToolTip(tr("No compute shader bound"));
|
||||
else if(!state.computeShader.reflection->debugInfo.debuggable)
|
||||
ui->computeDebugSelector->setToolTip(
|
||||
tr("This shader doesn't support debugging: %1")
|
||||
.arg(state.computeShader.reflection->debugInfo.debugStatus));
|
||||
else
|
||||
ui->computeDebugSelector->setToolTip(tr("Invalid dispatch/threadgroup dimensions."));
|
||||
}
|
||||
m_Common.SetupDebugSelectors(ui->computeDebugSelector, ui->pixelDebugSelector);
|
||||
|
||||
// highlight the appropriate stages in the flowchart
|
||||
if(action == NULL)
|
||||
@@ -3437,93 +3387,3 @@ void D3D11PipelineStateViewer::on_meshView_clicked()
|
||||
m_Ctx.ShowMeshPreview();
|
||||
ToolWindowManager::raiseToolWindow(m_Ctx.GetMeshPreview()->Widget());
|
||||
}
|
||||
|
||||
void D3D11PipelineStateViewer::on_computeDebugSelector_clicked()
|
||||
{
|
||||
// Check whether debugging is valid for this event before showing the dialog
|
||||
if(!m_Ctx.IsCaptureLoaded())
|
||||
return;
|
||||
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
RDDialog::show(m_ComputeDebugSelector);
|
||||
}
|
||||
|
||||
void D3D11PipelineStateViewer::computeDebugSelector_beginDebug(
|
||||
const rdcfixedarray<uint32_t, 3> &group, const rdcfixedarray<uint32_t, 3> &thread)
|
||||
{
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
struct threadSelect
|
||||
{
|
||||
rdcfixedarray<uint32_t, 3> g;
|
||||
rdcfixedarray<uint32_t, 3> t;
|
||||
} debugThread = {
|
||||
// g[]
|
||||
{group[0], group[1], group[2]},
|
||||
// t[]
|
||||
{thread[0], thread[1], thread[2]},
|
||||
};
|
||||
|
||||
bool done = false;
|
||||
ShaderDebugTrace *trace = NULL;
|
||||
|
||||
m_Ctx.Replay().AsyncInvoke([&trace, &done, debugThread](IReplayController *r) {
|
||||
trace = r->DebugThread(debugThread.g, debugThread.t);
|
||||
|
||||
if(trace->debugger == NULL)
|
||||
{
|
||||
r->FreeTrace(trace);
|
||||
trace = NULL;
|
||||
}
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
QString debugContext = lit("Group [%1,%2,%3] Thread [%4,%5,%6]")
|
||||
.arg(group[0])
|
||||
.arg(group[1])
|
||||
.arg(group[2])
|
||||
.arg(thread[0])
|
||||
.arg(thread[1])
|
||||
.arg(thread[2]);
|
||||
|
||||
// wait a short while before displaying the progress dialog (which won't show if we're already
|
||||
// done by the time we reach it)
|
||||
for(int i = 0; !done && i < 100; i++)
|
||||
QThread::msleep(5);
|
||||
|
||||
ShowProgressDialog(this, tr("Debugging %1").arg(debugContext), [&done]() { return done; });
|
||||
|
||||
if(!trace)
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("Error debugging"),
|
||||
tr("Error debugging thread - make sure a valid group and thread is selected"));
|
||||
return;
|
||||
}
|
||||
|
||||
// viewer takes ownership of the trace
|
||||
IShaderViewer *s = m_Ctx.DebugShader(
|
||||
shaderDetails, m_Ctx.CurPipelineState().GetComputePipelineObject(), trace, debugContext);
|
||||
|
||||
m_Ctx.AddDockWindow(s->Widget(), DockReference::AddTo, this);
|
||||
}
|
||||
@@ -34,7 +34,6 @@ class D3D11PipelineStateViewer;
|
||||
|
||||
class QXmlStreamWriter;
|
||||
|
||||
class ComputeDebugSelector;
|
||||
class RDLabel;
|
||||
class RDTreeWidget;
|
||||
class RDTreeWidgetItem;
|
||||
@@ -79,15 +78,10 @@ private slots:
|
||||
void cbuffer_itemActivated(RDTreeWidgetItem *item, int column);
|
||||
void vertex_leave(QEvent *e);
|
||||
|
||||
void on_computeDebugSelector_clicked();
|
||||
void computeDebugSelector_beginDebug(const rdcfixedarray<uint32_t, 3> &group,
|
||||
const rdcfixedarray<uint32_t, 3> &thread);
|
||||
|
||||
private:
|
||||
Ui::D3D11PipelineStateViewer *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
PipelineStateViewer &m_Common;
|
||||
ComputeDebugSelector *m_ComputeDebugSelector;
|
||||
|
||||
void setShaderState(const D3D11Pipe::Shader &stage, RDLabel *shader, RDLabel *shaderDebug,
|
||||
RDTreeWidget *tex, RDTreeWidget *samp, RDTreeWidget *cbuffer,
|
||||
|
||||
@@ -3010,6 +3010,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="pixelDebugSelector">
|
||||
<property name="text">
|
||||
<string>Debug</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/wrench.png</normaloff>:/wrench.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="psShaderSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <QScrollBar>
|
||||
#include <QXmlStreamWriter>
|
||||
#include "Code/Resources.h"
|
||||
#include "Widgets/ComputeDebugSelector.h"
|
||||
#include "Widgets/Extended/RDHeaderView.h"
|
||||
#include "Windows/DescriptorViewer.h"
|
||||
#include "flowlayout/FlowLayout.h"
|
||||
@@ -100,8 +99,6 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(ICaptureContext &ctx,
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_ComputeDebugSelector = new ComputeDebugSelector(this);
|
||||
|
||||
const QIcon &action = Icons::action();
|
||||
const QIcon &action_hover = Icons::action_hover();
|
||||
|
||||
@@ -217,8 +214,10 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(ICaptureContext &ctx,
|
||||
ui->predicate->setMinimumSizeHint(QSize(250, 0));
|
||||
}
|
||||
|
||||
QObject::connect(m_ComputeDebugSelector, &ComputeDebugSelector::beginDebug, this,
|
||||
&D3D12PipelineStateViewer::computeDebugSelector_beginDebug);
|
||||
QObject::connect(ui->computeDebugSelector, &QToolButton::clicked, &m_Common,
|
||||
&PipelineStateViewer::computeDebugSelector_clicked);
|
||||
QObject::connect(ui->pixelDebugSelector, &QToolButton::clicked, &m_Common,
|
||||
&PipelineStateViewer::pixelDebugSelector_clicked);
|
||||
|
||||
for(QToolButton *b : editButtons)
|
||||
QObject::connect(b, &QToolButton::clicked, &m_Common, &PipelineStateViewer::shaderEdit_clicked);
|
||||
@@ -510,7 +509,6 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(ICaptureContext &ctx,
|
||||
D3D12PipelineStateViewer::~D3D12PipelineStateViewer()
|
||||
{
|
||||
delete ui;
|
||||
delete m_ComputeDebugSelector;
|
||||
}
|
||||
|
||||
void D3D12PipelineStateViewer::OnCaptureLoaded()
|
||||
@@ -1196,6 +1194,7 @@ void D3D12PipelineStateViewer::clearState()
|
||||
ui->predicateGroup->setVisible(false);
|
||||
|
||||
ui->computeDebugSelector->setEnabled(false);
|
||||
ui->pixelDebugSelector->setEnabled(false);
|
||||
}
|
||||
|
||||
void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, RDLabel *pipeline,
|
||||
@@ -2307,56 +2306,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
ui->stencils->clearSelection();
|
||||
ui->stencils->endUpdate();
|
||||
|
||||
// set up thread debugging inputs
|
||||
bool enableDebug = m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
|
||||
state.computeShader.reflection->debugInfo.debuggable && action &&
|
||||
(action->flags & ActionFlags::Dispatch);
|
||||
if(enableDebug)
|
||||
{
|
||||
// Validate dispatch/threadgroup dimensions
|
||||
enableDebug &= action->dispatchDimension[0] > 0;
|
||||
enableDebug &= action->dispatchDimension[1] > 0;
|
||||
enableDebug &= action->dispatchDimension[2] > 0;
|
||||
|
||||
const rdcfixedarray<uint32_t, 3> &threadDims =
|
||||
(action->dispatchThreadsDimension[0] == 0)
|
||||
? state.computeShader.reflection->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension;
|
||||
enableDebug &= threadDims[0] > 0;
|
||||
enableDebug &= threadDims[1] > 0;
|
||||
enableDebug &= threadDims[2] > 0;
|
||||
}
|
||||
|
||||
if(enableDebug)
|
||||
{
|
||||
ui->computeDebugSelector->setEnabled(true);
|
||||
|
||||
// set maximums for CS debugging
|
||||
m_ComputeDebugSelector->SetThreadBounds(
|
||||
action->dispatchDimension, (action->dispatchThreadsDimension[0] == 0)
|
||||
? state.computeShader.reflection->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension);
|
||||
|
||||
ui->computeDebugSelector->setToolTip(
|
||||
tr("Debug this compute shader by specifying group/thread ID or dispatch ID"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->computeDebugSelector->setEnabled(false);
|
||||
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
ui->computeDebugSelector->setToolTip(tr("This API does not support shader debugging"));
|
||||
else if(!action || !(action->flags & ActionFlags::Dispatch))
|
||||
ui->computeDebugSelector->setToolTip(tr("No dispatch selected"));
|
||||
else if(!state.computeShader.reflection)
|
||||
ui->computeDebugSelector->setToolTip(tr("No compute shader bound"));
|
||||
else if(!state.computeShader.reflection->debugInfo.debuggable)
|
||||
ui->computeDebugSelector->setToolTip(
|
||||
tr("This shader doesn't support debugging: %1")
|
||||
.arg(state.computeShader.reflection->debugInfo.debugStatus));
|
||||
else
|
||||
ui->computeDebugSelector->setToolTip(tr("Invalid dispatch/threadgroup dimensions."));
|
||||
}
|
||||
m_Common.SetupDebugSelectors(ui->computeDebugSelector, ui->pixelDebugSelector);
|
||||
}
|
||||
|
||||
void D3D12PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int column)
|
||||
@@ -3701,96 +3651,3 @@ void D3D12PipelineStateViewer::on_meshView_clicked()
|
||||
m_Ctx.ShowMeshPreview();
|
||||
ToolWindowManager::raiseToolWindow(m_Ctx.GetMeshPreview()->Widget());
|
||||
}
|
||||
|
||||
void D3D12PipelineStateViewer::on_computeDebugSelector_clicked()
|
||||
{
|
||||
// Check whether debugging is valid for this event before showing the dialog
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
return;
|
||||
|
||||
if(!m_Ctx.IsCaptureLoaded())
|
||||
return;
|
||||
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
RDDialog::show(m_ComputeDebugSelector);
|
||||
}
|
||||
|
||||
void D3D12PipelineStateViewer::computeDebugSelector_beginDebug(
|
||||
const rdcfixedarray<uint32_t, 3> &group, const rdcfixedarray<uint32_t, 3> &thread)
|
||||
{
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
struct threadSelect
|
||||
{
|
||||
rdcfixedarray<uint32_t, 3> g;
|
||||
rdcfixedarray<uint32_t, 3> t;
|
||||
} debugThread = {
|
||||
// g[]
|
||||
{group[0], group[1], group[2]},
|
||||
// t[]
|
||||
{thread[0], thread[1], thread[2]},
|
||||
};
|
||||
|
||||
bool done = false;
|
||||
ShaderDebugTrace *trace = NULL;
|
||||
|
||||
m_Ctx.Replay().AsyncInvoke([&trace, &done, debugThread](IReplayController *r) {
|
||||
trace = r->DebugThread(debugThread.g, debugThread.t);
|
||||
|
||||
if(trace->debugger == NULL)
|
||||
{
|
||||
r->FreeTrace(trace);
|
||||
trace = NULL;
|
||||
}
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
QString debugContext = lit("Group [%1,%2,%3] Thread [%4,%5,%6]")
|
||||
.arg(group[0])
|
||||
.arg(group[1])
|
||||
.arg(group[2])
|
||||
.arg(thread[0])
|
||||
.arg(thread[1])
|
||||
.arg(thread[2]);
|
||||
|
||||
// wait a short while before displaying the progress dialog (which won't show if we're already
|
||||
// done by the time we reach it)
|
||||
for(int i = 0; !done && i < 100; i++)
|
||||
QThread::msleep(5);
|
||||
|
||||
ShowProgressDialog(this, tr("Debugging %1").arg(debugContext), [&done]() { return done; });
|
||||
|
||||
if(!trace)
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("Error debugging"),
|
||||
tr("Error debugging thread - make sure a valid group and thread is selected"));
|
||||
return;
|
||||
}
|
||||
|
||||
// viewer takes ownership of the trace
|
||||
IShaderViewer *s = m_Ctx.DebugShader(
|
||||
shaderDetails, m_Ctx.CurPipelineState().GetComputePipelineObject(), trace, debugContext);
|
||||
|
||||
m_Ctx.AddDockWindow(s->Widget(), DockReference::AddTo, this);
|
||||
}
|
||||
@@ -34,7 +34,6 @@ class D3D12PipelineStateViewer;
|
||||
|
||||
class QXmlStreamWriter;
|
||||
|
||||
class ComputeDebugSelector;
|
||||
class RDLabel;
|
||||
class RDTreeWidget;
|
||||
class RDTreeWidgetItem;
|
||||
@@ -81,15 +80,10 @@ private slots:
|
||||
void cbuffer_itemActivated(RDTreeWidgetItem *item, int column);
|
||||
void vertex_leave(QEvent *e);
|
||||
|
||||
void on_computeDebugSelector_clicked();
|
||||
void computeDebugSelector_beginDebug(const rdcfixedarray<uint32_t, 3> &group,
|
||||
const rdcfixedarray<uint32_t, 3> &thread);
|
||||
|
||||
private:
|
||||
Ui::D3D12PipelineStateViewer *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
PipelineStateViewer &m_Common;
|
||||
ComputeDebugSelector *m_ComputeDebugSelector;
|
||||
|
||||
void setOldMeshPipeFlow();
|
||||
void setNewMeshPipeFlow();
|
||||
|
||||
@@ -3126,6 +3126,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="pixelDebugSelector">
|
||||
<property name="text">
|
||||
<string>Debug</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/wrench.png</normaloff>:/wrench.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="psShaderSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <QScrollBar>
|
||||
#include <QXmlStreamWriter>
|
||||
#include "Code/Resources.h"
|
||||
#include "Widgets/ComputeDebugSelector.h"
|
||||
#include "Widgets/Extended/RDHeaderView.h"
|
||||
#include "flowlayout/FlowLayout.h"
|
||||
#include "toolwindowmanager/ToolWindowManager.h"
|
||||
@@ -87,8 +86,6 @@ GLPipelineStateViewer::GLPipelineStateViewer(ICaptureContext &ctx, PipelineState
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_ComputeDebugSelector = new ComputeDebugSelector(this);
|
||||
|
||||
const QIcon &action = Icons::action();
|
||||
const QIcon &action_hover = Icons::action_hover();
|
||||
|
||||
@@ -210,8 +207,10 @@ GLPipelineStateViewer::GLPipelineStateViewer(ICaptureContext &ctx, PipelineState
|
||||
QObject::connect(res, &RDTreeWidget::itemActivated, this,
|
||||
&GLPipelineStateViewer::resource_itemActivated);
|
||||
|
||||
QObject::connect(m_ComputeDebugSelector, &ComputeDebugSelector::beginDebug, this,
|
||||
&GLPipelineStateViewer::computeDebugSelector_beginDebug);
|
||||
QObject::connect(ui->computeDebugSelector, &QToolButton::clicked, &m_Common,
|
||||
&PipelineStateViewer::computeDebugSelector_clicked);
|
||||
QObject::connect(ui->pixelDebugSelector, &QToolButton::clicked, &m_Common,
|
||||
&PipelineStateViewer::pixelDebugSelector_clicked);
|
||||
|
||||
{
|
||||
QMenu *extensionsMenu = new QMenu(this);
|
||||
@@ -1281,6 +1280,7 @@ void GLPipelineStateViewer::clearState()
|
||||
ui->stencils->clear();
|
||||
|
||||
ui->computeDebugSelector->setEnabled(false);
|
||||
ui->pixelDebugSelector->setEnabled(false);
|
||||
}
|
||||
|
||||
void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, RDLabel *pipeline,
|
||||
@@ -2599,56 +2599,7 @@ void GLPipelineStateViewer::setState()
|
||||
ui->stencils->clearSelection();
|
||||
ui->stencils->endUpdate();
|
||||
|
||||
// set up thread debugging inputs
|
||||
bool enableDebug = m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
|
||||
state.computeShader.reflection->debugInfo.debuggable && action &&
|
||||
(action->flags & ActionFlags::Dispatch);
|
||||
if(enableDebug)
|
||||
{
|
||||
// Validate dispatch/threadgroup dimensions
|
||||
enableDebug &= action->dispatchDimension[0] > 0;
|
||||
enableDebug &= action->dispatchDimension[1] > 0;
|
||||
enableDebug &= action->dispatchDimension[2] > 0;
|
||||
|
||||
const rdcfixedarray<uint32_t, 3> &threadDims =
|
||||
(action->dispatchThreadsDimension[0] == 0)
|
||||
? state.computeShader.reflection->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension;
|
||||
enableDebug &= threadDims[0] > 0;
|
||||
enableDebug &= threadDims[1] > 0;
|
||||
enableDebug &= threadDims[2] > 0;
|
||||
}
|
||||
|
||||
if(enableDebug)
|
||||
{
|
||||
ui->computeDebugSelector->setEnabled(true);
|
||||
|
||||
// set maximums for CS debugging
|
||||
m_ComputeDebugSelector->SetThreadBounds(
|
||||
action->dispatchDimension, (action->dispatchThreadsDimension[0] == 0)
|
||||
? state.computeShader.reflection->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension);
|
||||
|
||||
ui->computeDebugSelector->setToolTip(
|
||||
tr("Debug this compute shader by specifying group/thread ID or dispatch ID"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->computeDebugSelector->setEnabled(false);
|
||||
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
ui->computeDebugSelector->setToolTip(tr("This API does not support shader debugging"));
|
||||
else if(!action || !(action->flags & ActionFlags::Dispatch))
|
||||
ui->computeDebugSelector->setToolTip(tr("No dispatch selected"));
|
||||
else if(!state.computeShader.reflection)
|
||||
ui->computeDebugSelector->setToolTip(tr("No compute shader bound"));
|
||||
else if(!state.computeShader.reflection->debugInfo.debuggable)
|
||||
ui->computeDebugSelector->setToolTip(
|
||||
tr("This shader doesn't support debugging: %1")
|
||||
.arg(state.computeShader.reflection->debugInfo.debugStatus));
|
||||
else
|
||||
ui->computeDebugSelector->setToolTip(tr("Invalid dispatch/threadgroup dimensions."));
|
||||
}
|
||||
m_Common.SetupDebugSelectors(ui->computeDebugSelector, ui->pixelDebugSelector);
|
||||
|
||||
// highlight the appropriate stages in the flowchart
|
||||
if(action == NULL)
|
||||
@@ -4001,93 +3952,3 @@ void GLPipelineStateViewer::on_meshView_clicked()
|
||||
m_Ctx.ShowMeshPreview();
|
||||
ToolWindowManager::raiseToolWindow(m_Ctx.GetMeshPreview()->Widget());
|
||||
}
|
||||
|
||||
void GLPipelineStateViewer::on_computeDebugSelector_clicked()
|
||||
{
|
||||
// Check whether debugging is valid for this event before showing the dialog
|
||||
if(!m_Ctx.IsCaptureLoaded())
|
||||
return;
|
||||
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
RDDialog::show(m_ComputeDebugSelector);
|
||||
}
|
||||
|
||||
void GLPipelineStateViewer::computeDebugSelector_beginDebug(const rdcfixedarray<uint32_t, 3> &group,
|
||||
const rdcfixedarray<uint32_t, 3> &thread)
|
||||
{
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
struct threadSelect
|
||||
{
|
||||
rdcfixedarray<uint32_t, 3> g;
|
||||
rdcfixedarray<uint32_t, 3> t;
|
||||
} debugThread = {
|
||||
// g[]
|
||||
{group[0], group[1], group[2]},
|
||||
// t[]
|
||||
{thread[0], thread[1], thread[2]},
|
||||
};
|
||||
|
||||
bool done = false;
|
||||
ShaderDebugTrace *trace = NULL;
|
||||
|
||||
m_Ctx.Replay().AsyncInvoke([&trace, &done, debugThread](IReplayController *r) {
|
||||
trace = r->DebugThread(debugThread.g, debugThread.t);
|
||||
|
||||
if(trace->debugger == NULL)
|
||||
{
|
||||
r->FreeTrace(trace);
|
||||
trace = NULL;
|
||||
}
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
QString debugContext = lit("Group [%1,%2,%3] Thread [%4,%5,%6]")
|
||||
.arg(group[0])
|
||||
.arg(group[1])
|
||||
.arg(group[2])
|
||||
.arg(thread[0])
|
||||
.arg(thread[1])
|
||||
.arg(thread[2]);
|
||||
|
||||
// wait a short while before displaying the progress dialog (which won't show if we're already
|
||||
// done by the time we reach it)
|
||||
for(int i = 0; !done && i < 100; i++)
|
||||
QThread::msleep(5);
|
||||
|
||||
ShowProgressDialog(this, tr("Debugging %1").arg(debugContext), [&done]() { return done; });
|
||||
|
||||
if(!trace)
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("Error debugging"),
|
||||
tr("Error debugging thread - make sure a valid group and thread is selected"));
|
||||
return;
|
||||
}
|
||||
|
||||
// viewer takes ownership of the trace
|
||||
IShaderViewer *s = m_Ctx.DebugShader(
|
||||
shaderDetails, m_Ctx.CurPipelineState().GetComputePipelineObject(), trace, debugContext);
|
||||
|
||||
m_Ctx.AddDockWindow(s->Widget(), DockReference::AddTo, this);
|
||||
}
|
||||
@@ -34,7 +34,6 @@ class GLPipelineStateViewer;
|
||||
|
||||
class QXmlStreamWriter;
|
||||
|
||||
class ComputeDebugSelector;
|
||||
class RDLabel;
|
||||
class RDTreeWidget;
|
||||
class RDTreeWidgetItem;
|
||||
@@ -84,15 +83,10 @@ private slots:
|
||||
void ubo_itemActivated(RDTreeWidgetItem *item, int column);
|
||||
void vertex_leave(QEvent *e);
|
||||
|
||||
void on_computeDebugSelector_clicked();
|
||||
void computeDebugSelector_beginDebug(const rdcfixedarray<uint32_t, 3> &group,
|
||||
const rdcfixedarray<uint32_t, 3> &thread);
|
||||
|
||||
private:
|
||||
Ui::GLPipelineStateViewer *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
PipelineStateViewer &m_Common;
|
||||
ComputeDebugSelector *m_ComputeDebugSelector;
|
||||
|
||||
QString MakeGenericValueString(uint32_t compCount, CompType compType,
|
||||
const GLPipe::VertexAttribute &val);
|
||||
|
||||
@@ -3720,6 +3720,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="pixelDebugSelector">
|
||||
<property name="text">
|
||||
<string>Debug</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/wrench.png</normaloff>:/wrench.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="fsShaderSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -33,8 +33,10 @@
|
||||
#include <QXmlStreamWriter>
|
||||
#include "Code/QRDUtils.h"
|
||||
#include "Code/Resources.h"
|
||||
#include "Widgets/ComputeDebugSelector.h"
|
||||
#include "Widgets/Extended/RDLabel.h"
|
||||
#include "Widgets/Extended/RDTreeWidget.h"
|
||||
#include "Widgets/PixelDebugSelector.h"
|
||||
#include "toolwindowmanager/ToolWindowManager.h"
|
||||
#include "D3D11PipelineStateViewer.h"
|
||||
#include "D3D12PipelineStateViewer.h"
|
||||
@@ -185,6 +187,15 @@ PipelineStateViewer::PipelineStateViewer(ICaptureContext &ctx, QWidget *parent)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_ComputeDebugSelector = new ComputeDebugSelector(this);
|
||||
m_PixelDebugSelector = new PixelDebugSelector(m_Ctx, this);
|
||||
|
||||
QObject::connect(m_ComputeDebugSelector, &ComputeDebugSelector::beginDebug, this,
|
||||
&PipelineStateViewer::computeDebugSelector_beginDebug);
|
||||
|
||||
QObject::connect(m_PixelDebugSelector, &PixelDebugSelector::beginDebug, this,
|
||||
&PipelineStateViewer::pixelDebugSelector_beginDebug);
|
||||
|
||||
ui->thumbnail->SetContext(m_Ctx);
|
||||
ui->layout->removeWidget(ui->thumbnail);
|
||||
|
||||
@@ -218,6 +229,9 @@ PipelineStateViewer::~PipelineStateViewer()
|
||||
m_Ctx.BuiltinWindowClosed(this);
|
||||
m_Ctx.RemoveCaptureViewer(this);
|
||||
|
||||
delete m_ComputeDebugSelector;
|
||||
delete m_PixelDebugSelector;
|
||||
|
||||
delete m_Tooltip;
|
||||
|
||||
delete ui;
|
||||
@@ -948,6 +962,259 @@ void PipelineStateViewer::shaderEdit_clicked()
|
||||
menu->actions()[0]->trigger();
|
||||
}
|
||||
|
||||
void PipelineStateViewer::SetupDebugSelectors(QToolButton *computeDebugSelector,
|
||||
QToolButton *pixelDebugSelector)
|
||||
{
|
||||
const ShaderReflection *csRefl = m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
const ShaderReflection *psRefl = m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Pixel);
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
// set up thread debugging inputs
|
||||
bool enableComputeDebug = m_Ctx.APIProps().shaderDebugging && csRefl &&
|
||||
csRefl->debugInfo.debuggable && action &&
|
||||
(action->flags & ActionFlags::Dispatch);
|
||||
if(enableComputeDebug)
|
||||
{
|
||||
// Validate dispatch/threadgroup dimensions
|
||||
enableComputeDebug &= action->dispatchDimension[0] > 0;
|
||||
enableComputeDebug &= action->dispatchDimension[1] > 0;
|
||||
enableComputeDebug &= action->dispatchDimension[2] > 0;
|
||||
|
||||
const rdcfixedarray<uint32_t, 3> &threadDims = (action->dispatchThreadsDimension[0] == 0)
|
||||
? csRefl->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension;
|
||||
enableComputeDebug &= threadDims[0] > 0;
|
||||
enableComputeDebug &= threadDims[1] > 0;
|
||||
enableComputeDebug &= threadDims[2] > 0;
|
||||
}
|
||||
|
||||
if(enableComputeDebug)
|
||||
{
|
||||
computeDebugSelector->setEnabled(true);
|
||||
|
||||
// set maximums for CS debugging
|
||||
m_ComputeDebugSelector->SetThreadBounds(action->dispatchDimension,
|
||||
(action->dispatchThreadsDimension[0] == 0)
|
||||
? csRefl->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension);
|
||||
|
||||
computeDebugSelector->setToolTip(
|
||||
tr("Debug this compute shader by specifying group/thread ID or dispatch ID"));
|
||||
}
|
||||
else
|
||||
{
|
||||
computeDebugSelector->setEnabled(false);
|
||||
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
computeDebugSelector->setToolTip(tr("This API does not support shader debugging"));
|
||||
else if(!action || !(action->flags & ActionFlags::Dispatch))
|
||||
computeDebugSelector->setToolTip(tr("No dispatch selected"));
|
||||
else if(!csRefl)
|
||||
computeDebugSelector->setToolTip(tr("No compute shader bound"));
|
||||
else if(!csRefl->debugInfo.debuggable)
|
||||
computeDebugSelector->setToolTip(
|
||||
tr("This shader doesn't support debugging: %1").arg(csRefl->debugInfo.debugStatus));
|
||||
else
|
||||
computeDebugSelector->setToolTip(tr("Invalid dispatch/threadgroup dimensions."));
|
||||
}
|
||||
|
||||
// set up thread debugging inputs
|
||||
bool enablePixelDebug = m_Ctx.APIProps().shaderDebugging && psRefl &&
|
||||
psRefl->debugInfo.debuggable && action &&
|
||||
(action->flags & ActionFlags::Drawcall);
|
||||
if(enablePixelDebug)
|
||||
{
|
||||
pixelDebugSelector->setEnabled(true);
|
||||
|
||||
pixelDebugSelector->setToolTip(
|
||||
tr("Debug this pixel shader by manually selecting a co-ordinate"));
|
||||
}
|
||||
else
|
||||
{
|
||||
pixelDebugSelector->setEnabled(false);
|
||||
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
pixelDebugSelector->setToolTip(tr("This API does not support shader debugging"));
|
||||
else if(!action || !(action->flags & ActionFlags::Drawcall))
|
||||
pixelDebugSelector->setToolTip(tr("No draw selected"));
|
||||
else if(!psRefl)
|
||||
pixelDebugSelector->setToolTip(tr("No pixel shader bound"));
|
||||
else if(!psRefl->debugInfo.debuggable)
|
||||
pixelDebugSelector->setToolTip(
|
||||
tr("This shader doesn't support debugging: %1").arg(psRefl->debugInfo.debugStatus));
|
||||
}
|
||||
}
|
||||
|
||||
void PipelineStateViewer::computeDebugSelector_clicked()
|
||||
{
|
||||
// Check whether debugging is valid for this event before showing the dialog
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
return;
|
||||
|
||||
if(!m_Ctx.IsCaptureLoaded())
|
||||
return;
|
||||
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
RDDialog::show(m_ComputeDebugSelector);
|
||||
}
|
||||
|
||||
void PipelineStateViewer::computeDebugSelector_beginDebug(const rdcfixedarray<uint32_t, 3> &group,
|
||||
const rdcfixedarray<uint32_t, 3> &thread)
|
||||
{
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
struct threadSelect
|
||||
{
|
||||
rdcfixedarray<uint32_t, 3> g;
|
||||
rdcfixedarray<uint32_t, 3> t;
|
||||
} debugThread = {
|
||||
// g[]
|
||||
{group[0], group[1], group[2]},
|
||||
// t[]
|
||||
{thread[0], thread[1], thread[2]},
|
||||
};
|
||||
|
||||
bool done = false;
|
||||
ShaderDebugTrace *trace = NULL;
|
||||
|
||||
m_Ctx.Replay().AsyncInvoke([&trace, &done, debugThread](IReplayController *r) {
|
||||
trace = r->DebugThread(debugThread.g, debugThread.t);
|
||||
|
||||
if(trace->debugger == NULL)
|
||||
{
|
||||
r->FreeTrace(trace);
|
||||
trace = NULL;
|
||||
}
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
QString debugContext = lit("Group [%1,%2,%3] Thread [%4,%5,%6]")
|
||||
.arg(group[0])
|
||||
.arg(group[1])
|
||||
.arg(group[2])
|
||||
.arg(thread[0])
|
||||
.arg(thread[1])
|
||||
.arg(thread[2]);
|
||||
|
||||
// wait a short while before displaying the progress dialog (which won't show if we're already
|
||||
// done by the time we reach it)
|
||||
for(int i = 0; !done && i < 100; i++)
|
||||
QThread::msleep(5);
|
||||
|
||||
ShowProgressDialog(this, tr("Debugging %1").arg(debugContext), [&done]() { return done; });
|
||||
|
||||
if(!trace)
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("Error debugging"),
|
||||
tr("Error debugging thread - make sure a valid group and thread is selected"));
|
||||
return;
|
||||
}
|
||||
|
||||
// viewer takes ownership of the trace
|
||||
IShaderViewer *s = m_Ctx.DebugShader(
|
||||
shaderDetails, m_Ctx.CurPipelineState().GetComputePipelineObject(), trace, debugContext);
|
||||
|
||||
m_Ctx.AddDockWindow(s->Widget(), DockReference::AddTo, this);
|
||||
}
|
||||
|
||||
void PipelineStateViewer::pixelDebugSelector_clicked()
|
||||
{
|
||||
// Check whether debugging is valid for this event before showing the dialog
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
return;
|
||||
|
||||
if(!m_Ctx.IsCaptureLoaded())
|
||||
return;
|
||||
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Pixel);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
m_PixelDebugSelector->UpdateTarget();
|
||||
|
||||
RDDialog::show(m_PixelDebugSelector);
|
||||
}
|
||||
|
||||
void PipelineStateViewer::pixelDebugSelector_beginDebug(uint32_t x, uint32_t y,
|
||||
const DebugPixelInputs &inputs)
|
||||
{
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Pixel);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
bool done = false;
|
||||
ShaderDebugTrace *trace = NULL;
|
||||
|
||||
m_Ctx.Replay().AsyncInvoke([&trace, &done, x, y, &inputs](IReplayController *r) {
|
||||
trace = r->DebugPixel(x, y, inputs);
|
||||
|
||||
if(trace->debugger == NULL)
|
||||
{
|
||||
r->FreeTrace(trace);
|
||||
trace = NULL;
|
||||
}
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
QString debugContext = QFormatStr("Pixel %1,%2 @ %3").arg(x).arg(y).arg(action->eventId);
|
||||
|
||||
// wait a short while before displaying the progress dialog (which won't show if we're already
|
||||
// done by the time we reach it)
|
||||
for(int i = 0; !done && i < 100; i++)
|
||||
QThread::msleep(5);
|
||||
|
||||
ShowProgressDialog(this, tr("Debugging %1").arg(debugContext), [&done]() { return done; });
|
||||
|
||||
if(!trace)
|
||||
{
|
||||
RDDialog::critical(this, tr("Error debugging"),
|
||||
tr("Error debugging pixel - make sure a valid co-ordinate is selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
// viewer takes ownership of the trace
|
||||
IShaderViewer *s = m_Ctx.DebugShader(
|
||||
shaderDetails, m_Ctx.CurPipelineState().GetGraphicsPipelineObject(), trace, debugContext);
|
||||
|
||||
m_Ctx.AddDockWindow(s->Widget(), DockReference::AddTo, this);
|
||||
}
|
||||
|
||||
IShaderViewer *PipelineStateViewer::EditShader(ResourceId id, ShaderStage shaderType,
|
||||
const rdcstr &entry, ShaderCompileFlags compileFlags,
|
||||
KnownShaderTool knownTool,
|
||||
|
||||
@@ -36,6 +36,9 @@ class PipelineStateViewer;
|
||||
|
||||
class QXmlStreamWriter;
|
||||
|
||||
class ComputeDebugSelector;
|
||||
class PixelDebugSelector;
|
||||
|
||||
class QToolButton;
|
||||
class QMenu;
|
||||
class RDLabel;
|
||||
@@ -115,6 +118,8 @@ public:
|
||||
|
||||
void SetupResourceView(RDTreeWidget *view);
|
||||
|
||||
void SetupDebugSelectors(QToolButton *computeSelector, QToolButton *pixelSelector);
|
||||
|
||||
QString GetVBufferFormatString(uint32_t slot);
|
||||
|
||||
QColor GetViewDetailsColor();
|
||||
@@ -134,12 +139,23 @@ public:
|
||||
public slots:
|
||||
void shaderEdit_clicked();
|
||||
|
||||
void computeDebugSelector_clicked();
|
||||
void computeDebugSelector_beginDebug(const rdcfixedarray<uint32_t, 3> &group,
|
||||
const rdcfixedarray<uint32_t, 3> &thread);
|
||||
|
||||
void pixelDebugSelector_clicked();
|
||||
void pixelDebugSelector_beginDebug(uint32_t x, uint32_t y, const DebugPixelInputs &inputs);
|
||||
|
||||
|
||||
private:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
Ui::PipelineStateViewer *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
|
||||
ComputeDebugSelector *m_ComputeDebugSelector;
|
||||
PixelDebugSelector *m_PixelDebugSelector;
|
||||
|
||||
QMenu *editMenus[NumShaderStages] = {};
|
||||
|
||||
RDPreviewTooltip *m_Tooltip = NULL;
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <QScrollBar>
|
||||
#include <QXmlStreamWriter>
|
||||
#include "Code/Resources.h"
|
||||
#include "Widgets/ComputeDebugSelector.h"
|
||||
#include "Widgets/Extended/RDHeaderView.h"
|
||||
#include "flowlayout/FlowLayout.h"
|
||||
#include "toolwindowmanager/ToolWindowManager.h"
|
||||
@@ -142,8 +141,6 @@ VulkanPipelineStateViewer::VulkanPipelineStateViewer(ICaptureContext &ctx,
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_ComputeDebugSelector = new ComputeDebugSelector(this);
|
||||
|
||||
const QIcon &action = Icons::action();
|
||||
const QIcon &action_hover = Icons::action_hover();
|
||||
|
||||
@@ -262,8 +259,10 @@ VulkanPipelineStateViewer::VulkanPipelineStateViewer(ICaptureContext &ctx,
|
||||
ui->tsDescGroup->setCollapsed(true);
|
||||
ui->msDescGroup->setCollapsed(true);
|
||||
|
||||
QObject::connect(m_ComputeDebugSelector, &ComputeDebugSelector::beginDebug, this,
|
||||
&VulkanPipelineStateViewer::computeDebugSelector_beginDebug);
|
||||
QObject::connect(ui->computeDebugSelector, &QToolButton::clicked, &m_Common,
|
||||
&PipelineStateViewer::computeDebugSelector_clicked);
|
||||
QObject::connect(ui->pixelDebugSelector, &QToolButton::clicked, &m_Common,
|
||||
&PipelineStateViewer::pixelDebugSelector_clicked);
|
||||
|
||||
for(QToolButton *b : editButtons)
|
||||
QObject::connect(b, &QToolButton::clicked, &m_Common, &PipelineStateViewer::shaderEdit_clicked);
|
||||
@@ -566,7 +565,6 @@ VulkanPipelineStateViewer::~VulkanPipelineStateViewer()
|
||||
{
|
||||
m_CombinedImageSamplers.clear();
|
||||
delete ui;
|
||||
delete m_ComputeDebugSelector;
|
||||
}
|
||||
|
||||
void VulkanPipelineStateViewer::OnCaptureLoaded()
|
||||
@@ -1115,6 +1113,7 @@ void VulkanPipelineStateViewer::clearState()
|
||||
ui->stencils->clear();
|
||||
|
||||
ui->computeDebugSelector->setEnabled(false);
|
||||
ui->pixelDebugSelector->setEnabled(false);
|
||||
|
||||
ui->conditionalRenderingGroup->setVisible(false);
|
||||
ui->csConditionalRenderingGroup->setVisible(false);
|
||||
@@ -3176,56 +3175,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
ui->stencils->clearSelection();
|
||||
ui->stencils->endUpdate();
|
||||
|
||||
// set up thread debugging inputs
|
||||
bool enableDebug = m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
|
||||
state.computeShader.reflection->debugInfo.debuggable && action &&
|
||||
(action->flags & ActionFlags::Dispatch);
|
||||
if(enableDebug)
|
||||
{
|
||||
// Validate dispatch/threadgroup dimensions
|
||||
enableDebug &= action->dispatchDimension[0] > 0;
|
||||
enableDebug &= action->dispatchDimension[1] > 0;
|
||||
enableDebug &= action->dispatchDimension[2] > 0;
|
||||
|
||||
const rdcfixedarray<uint32_t, 3> &threadDims =
|
||||
(action->dispatchThreadsDimension[0] == 0)
|
||||
? state.computeShader.reflection->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension;
|
||||
enableDebug &= threadDims[0] > 0;
|
||||
enableDebug &= threadDims[1] > 0;
|
||||
enableDebug &= threadDims[2] > 0;
|
||||
}
|
||||
|
||||
if(enableDebug)
|
||||
{
|
||||
ui->computeDebugSelector->setEnabled(true);
|
||||
|
||||
// set maximums for CS debugging
|
||||
m_ComputeDebugSelector->SetThreadBounds(
|
||||
action->dispatchDimension, (action->dispatchThreadsDimension[0] == 0)
|
||||
? state.computeShader.reflection->dispatchThreadsDimension
|
||||
: action->dispatchThreadsDimension);
|
||||
|
||||
ui->computeDebugSelector->setToolTip(
|
||||
tr("Debug this compute shader by specifying group/thread ID or dispatch ID"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->computeDebugSelector->setEnabled(false);
|
||||
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
ui->computeDebugSelector->setToolTip(tr("This API does not support shader debugging"));
|
||||
else if(!action || !(action->flags & ActionFlags::Dispatch))
|
||||
ui->computeDebugSelector->setToolTip(tr("No dispatch selected"));
|
||||
else if(!state.computeShader.reflection)
|
||||
ui->computeDebugSelector->setToolTip(tr("No compute shader bound"));
|
||||
else if(!state.computeShader.reflection->debugInfo.debuggable)
|
||||
ui->computeDebugSelector->setToolTip(
|
||||
tr("This shader doesn't support debugging: %1")
|
||||
.arg(state.computeShader.reflection->debugInfo.debugStatus));
|
||||
else
|
||||
ui->computeDebugSelector->setToolTip(tr("Invalid dispatch/threadgroup dimensions."));
|
||||
}
|
||||
m_Common.SetupDebugSelectors(ui->computeDebugSelector, ui->pixelDebugSelector);
|
||||
}
|
||||
|
||||
void VulkanPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int column)
|
||||
@@ -5555,96 +5505,3 @@ void VulkanPipelineStateViewer::on_meshView_clicked()
|
||||
m_Ctx.ShowMeshPreview();
|
||||
ToolWindowManager::raiseToolWindow(m_Ctx.GetMeshPreview()->Widget());
|
||||
}
|
||||
|
||||
void VulkanPipelineStateViewer::on_computeDebugSelector_clicked()
|
||||
{
|
||||
// Check whether debugging is valid for this event before showing the dialog
|
||||
if(!m_Ctx.APIProps().shaderDebugging)
|
||||
return;
|
||||
|
||||
if(!m_Ctx.IsCaptureLoaded())
|
||||
return;
|
||||
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
RDDialog::show(m_ComputeDebugSelector);
|
||||
}
|
||||
|
||||
void VulkanPipelineStateViewer::computeDebugSelector_beginDebug(
|
||||
const rdcfixedarray<uint32_t, 3> &group, const rdcfixedarray<uint32_t, 3> &thread)
|
||||
{
|
||||
const ActionDescription *action = m_Ctx.CurAction();
|
||||
|
||||
if(!action)
|
||||
return;
|
||||
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Compute);
|
||||
|
||||
if(!shaderDetails)
|
||||
return;
|
||||
|
||||
struct threadSelect
|
||||
{
|
||||
rdcfixedarray<uint32_t, 3> g;
|
||||
rdcfixedarray<uint32_t, 3> t;
|
||||
} debugThread = {
|
||||
// g[]
|
||||
{group[0], group[1], group[2]},
|
||||
// t[]
|
||||
{thread[0], thread[1], thread[2]},
|
||||
};
|
||||
|
||||
bool done = false;
|
||||
ShaderDebugTrace *trace = NULL;
|
||||
|
||||
m_Ctx.Replay().AsyncInvoke([&trace, &done, debugThread](IReplayController *r) {
|
||||
trace = r->DebugThread(debugThread.g, debugThread.t);
|
||||
|
||||
if(trace->debugger == NULL)
|
||||
{
|
||||
r->FreeTrace(trace);
|
||||
trace = NULL;
|
||||
}
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
QString debugContext = lit("Group [%1,%2,%3] Thread [%4,%5,%6]")
|
||||
.arg(group[0])
|
||||
.arg(group[1])
|
||||
.arg(group[2])
|
||||
.arg(thread[0])
|
||||
.arg(thread[1])
|
||||
.arg(thread[2]);
|
||||
|
||||
// wait a short while before displaying the progress dialog (which won't show if we're already
|
||||
// done by the time we reach it)
|
||||
for(int i = 0; !done && i < 100; i++)
|
||||
QThread::msleep(5);
|
||||
|
||||
ShowProgressDialog(this, tr("Debugging %1").arg(debugContext), [&done]() { return done; });
|
||||
|
||||
if(!trace)
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("Error debugging"),
|
||||
tr("Error debugging thread - make sure a valid group and thread is selected"));
|
||||
return;
|
||||
}
|
||||
|
||||
// viewer takes ownership of the trace
|
||||
IShaderViewer *s = m_Ctx.DebugShader(
|
||||
shaderDetails, m_Ctx.CurPipelineState().GetComputePipelineObject(), trace, debugContext);
|
||||
|
||||
m_Ctx.AddDockWindow(s->Widget(), DockReference::AddTo, this);
|
||||
}
|
||||
@@ -35,7 +35,6 @@ class VulkanPipelineStateViewer;
|
||||
|
||||
class QXmlStreamWriter;
|
||||
|
||||
class ComputeDebugSelector;
|
||||
class RDLabel;
|
||||
class RDTreeWidget;
|
||||
class RDTreeWidgetItem;
|
||||
@@ -89,10 +88,6 @@ private slots:
|
||||
void descSet_itemActivated(RDTreeWidgetItem *item, int column);
|
||||
void vertex_leave(QEvent *e);
|
||||
|
||||
void on_computeDebugSelector_clicked();
|
||||
void computeDebugSelector_beginDebug(const rdcfixedarray<uint32_t, 3> &group,
|
||||
const rdcfixedarray<uint32_t, 3> &thread);
|
||||
|
||||
void exportHTML_clicked();
|
||||
void exportFOZ_clicked();
|
||||
|
||||
@@ -100,7 +95,6 @@ private:
|
||||
Ui::VulkanPipelineStateViewer *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
PipelineStateViewer &m_Common;
|
||||
ComputeDebugSelector *m_ComputeDebugSelector;
|
||||
|
||||
void setOldMeshPipeFlow();
|
||||
void setNewMeshPipeFlow();
|
||||
|
||||
@@ -3486,6 +3486,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="pixelDebugSelector">
|
||||
<property name="text">
|
||||
<string>Debug</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/wrench.png</normaloff>:/wrench.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="fsShaderSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -402,18 +402,33 @@ void TextureViewer::UI_UpdateCachedTexture()
|
||||
return;
|
||||
}
|
||||
|
||||
bool debugOutput = false;
|
||||
|
||||
ResourceId id = m_LockedId;
|
||||
if(id == ResourceId())
|
||||
{
|
||||
debugOutput = m_Following.Type == FollowType::OutputColor ||
|
||||
m_Following.Type == FollowType::OutputDepth ||
|
||||
m_Following.Type == FollowType::OutputDepthResolve;
|
||||
id = m_Following.GetResourceId(m_Ctx);
|
||||
}
|
||||
|
||||
if(id == ResourceId())
|
||||
{
|
||||
debugOutput = false;
|
||||
id = m_TexDisplay.resourceId;
|
||||
}
|
||||
|
||||
m_CachedTexture = m_Ctx.GetTexture(id);
|
||||
|
||||
if(m_CachedTexture != NULL)
|
||||
{
|
||||
if(m_Ctx.APIProps().shaderDebugging)
|
||||
if(!debugOutput)
|
||||
{
|
||||
ui->debugPixelContext->setEnabled(false);
|
||||
ui->debugPixelContext->setToolTip(tr("No output texture selected"));
|
||||
}
|
||||
else if(m_Ctx.APIProps().shaderDebugging)
|
||||
{
|
||||
const ShaderReflection *shaderDetails =
|
||||
m_Ctx.CurPipelineState().GetShaderReflection(ShaderStage::Pixel);
|
||||
|
||||
@@ -205,6 +205,7 @@ SOURCES += Code/qrenderdoc.cpp \
|
||||
Widgets/Extended/RDDoubleSpinBox.cpp \
|
||||
Widgets/Extended/RDListView.cpp \
|
||||
Widgets/ComputeDebugSelector.cpp \
|
||||
Widgets/PixelDebugSelector.cpp \
|
||||
Widgets/CustomPaintWidget.cpp \
|
||||
Widgets/ResourcePreview.cpp \
|
||||
Widgets/ThumbnailStrip.cpp \
|
||||
@@ -296,6 +297,7 @@ HEADERS += Code/CaptureContext.h \
|
||||
Widgets/Extended/RDDoubleSpinBox.h \
|
||||
Widgets/Extended/RDListView.h \
|
||||
Widgets/ComputeDebugSelector.h \
|
||||
Widgets/PixelDebugSelector.h \
|
||||
Widgets/CustomPaintWidget.h \
|
||||
Widgets/ResourcePreview.h \
|
||||
Widgets/ThumbnailStrip.h \
|
||||
@@ -369,6 +371,7 @@ FORMS += Windows/Dialogs/AboutDialog.ui \
|
||||
Windows/PipelineState/GLPipelineStateViewer.ui \
|
||||
Widgets/BufferFormatSpecifier.ui \
|
||||
Widgets/ComputeDebugSelector.ui \
|
||||
Widgets/PixelDebugSelector.ui \
|
||||
Windows/BufferViewer.ui \
|
||||
Windows/ShaderViewer.ui \
|
||||
Windows/ShaderMessageViewer.ui \
|
||||
|
||||
@@ -610,6 +610,7 @@
|
||||
<ClCompile Include="$(IntDir)generated\moc_ResourceInspector.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_BufferFormatSpecifier.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_ComputeDebugSelector.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_PixelDebugSelector.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_FindReplace.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_BufferViewer.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_CaptureDialog.cpp" />
|
||||
@@ -709,6 +710,7 @@
|
||||
<ClCompile Include="Widgets\BufferFormatSpecifier.cpp" />
|
||||
<ClCompile Include="Widgets\CollapseGroupBox.cpp" />
|
||||
<ClCompile Include="Widgets\ComputeDebugSelector.cpp" />
|
||||
<ClCompile Include="Widgets\PixelDebugSelector.cpp" />
|
||||
<ClCompile Include="Widgets\FindReplace.cpp" />
|
||||
<ClCompile Include="Widgets\Extended\RDListWidget.cpp" />
|
||||
<ClCompile Include="Widgets\Extended\RDTableView.cpp" />
|
||||
@@ -962,6 +964,7 @@
|
||||
<ClInclude Include="$(IntDir)generated\ui_ResourceInspector.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_BufferFormatSpecifier.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_ComputeDebugSelector.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_PixelDebugSelector.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_FindReplace.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_BufferViewer.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_CaptureDialog.h" />
|
||||
@@ -1040,6 +1043,12 @@
|
||||
<Message>MOC %(Filename).h</Message>
|
||||
<Outputs>$(IntDir)generated\moc_%(Filename).cpp</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Widgets\PixelDebugSelector.h">
|
||||
<AdditionalInputs>%(Fullpath);$(QtBinDir)\moc.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>"$(QtBinDir)\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"$(QtIncludeDir)" -I"$(QtIncludeDir)\QtWidgets" -I"$(QtIncludeDir)\QtGui" -I"$(QtIncludeDir)\QtCore" "%(Fullpath)" -o "$(IntDir)generated\moc_%(Filename).cpp"</Command>
|
||||
<Message>MOC %(Filename).h</Message>
|
||||
<Outputs>$(IntDir)generated\moc_%(Filename).cpp</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Widgets\FindReplace.h">
|
||||
<AdditionalInputs>%(Fullpath);$(QtBinDir)\moc.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>"$(QtBinDir)\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"$(QtIncludeDir)" -I"$(QtIncludeDir)\QtWidgets" -I"$(QtIncludeDir)\QtGui" -I"$(QtIncludeDir)\QtCore" "%(Fullpath)" -o "$(IntDir)generated\moc_%(Filename).cpp"</Command>
|
||||
@@ -1491,6 +1500,12 @@
|
||||
<Message>UIC %(Filename).ui</Message>
|
||||
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Widgets\PixelDebugSelector.ui">
|
||||
<AdditionalInputs>%(Fullpath);$(QtBinDir)\uic.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>"$(QtBinDir)\uic.exe" "%(Fullpath)" -o "$(IntDir)generated\ui_%(Filename).h"</Command>
|
||||
<Message>UIC %(Filename).ui</Message>
|
||||
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Widgets\FindReplace.ui">
|
||||
<AdditionalInputs>%(Fullpath);$(QtBinDir)\uic.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>"$(QtBinDir)\uic.exe" "%(Fullpath)" -o "$(IntDir)generated\ui_%(Filename).h"</Command>
|
||||
|
||||
@@ -801,6 +801,12 @@
|
||||
<ClCompile Include="Code\Interface\Helpers.cpp">
|
||||
<Filter>Code\Interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)generated\moc_PixelDebugSelector.cpp">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Widgets\PixelDebugSelector.cpp">
|
||||
<Filter>Widgets</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="3rdparty\flowlayout\FlowLayout.h">
|
||||
@@ -1190,6 +1196,9 @@
|
||||
<ClInclude Include="Code\Interface\Helpers.h">
|
||||
<Filter>Code\Interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(IntDir)generated\ui_PixelDebugSelector.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Code\pyrenderdoc\pyconversion.h">
|
||||
@@ -1634,6 +1643,12 @@
|
||||
<CustomBuild Include="Widgets\Extended\RDToolTip.h">
|
||||
<Filter>Widgets\Extended</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Widgets\PixelDebugSelector.ui">
|
||||
<Filter>Widgets</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Widgets\PixelDebugSelector.h">
|
||||
<Filter>Widgets</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Resources\action.png">
|
||||
|
||||
@@ -723,6 +723,12 @@ struct FBO
|
||||
:type: int
|
||||
)");
|
||||
int32_t readBuffer = 0;
|
||||
|
||||
DOCUMENT(R"(The default sample count to use if the framebuffer has no attachments
|
||||
|
||||
:type: int
|
||||
)");
|
||||
uint32_t defaultSampleCount = 0;
|
||||
};
|
||||
|
||||
DOCUMENT(R"(
|
||||
|
||||
@@ -176,6 +176,12 @@ public:
|
||||
)");
|
||||
uint32_t MultiviewBroadcastCount() const;
|
||||
|
||||
DOCUMENT(R"(
|
||||
:return: The number of multisample samples to use when not implicit from output targets.
|
||||
:rtype: int
|
||||
)");
|
||||
uint32_t GetOverrideSampleCount() const;
|
||||
|
||||
DOCUMENT(R"(Determines whether or not the current capture supports binding arrays of resources.
|
||||
|
||||
:return: A boolean indicating if binding arrays of resources is supported.
|
||||
|
||||
@@ -397,6 +397,31 @@ uint32_t PipeState::MultiviewBroadcastCount() const
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t PipeState::GetOverrideSampleCount() const
|
||||
{
|
||||
if(IsCaptureLoaded())
|
||||
{
|
||||
if(IsCaptureD3D11())
|
||||
{
|
||||
return m_D3D11->rasterizer.state.forcedSampleCount;
|
||||
}
|
||||
else if(IsCaptureD3D12())
|
||||
{
|
||||
return m_D3D11->rasterizer.state.forcedSampleCount;
|
||||
}
|
||||
else if(IsCaptureGL())
|
||||
{
|
||||
return m_GL->framebuffer.drawFBO.defaultSampleCount;
|
||||
}
|
||||
else if(IsCaptureVK())
|
||||
{
|
||||
return m_Vulkan->multisample.rasterSamples;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdcstr PipeState::GetShaderEntryPoint(ShaderStage stage) const
|
||||
{
|
||||
if(IsCaptureLoaded() && IsCaptureVK())
|
||||
|
||||
@@ -769,6 +769,7 @@ extern bool IsGLES;
|
||||
EXT_TO_CHECK(43, 31, ARB_program_interface_query) \
|
||||
EXT_TO_CHECK(43, 31, ARB_shader_storage_buffer_object) \
|
||||
EXT_TO_CHECK(43, 31, ARB_stencil_texturing) \
|
||||
EXT_TO_CHECK(43, 31, ARB_framebuffer_no_attachments) \
|
||||
/* See above with ARB_texture_multisample_no_array */ \
|
||||
EXT_TO_CHECK(43, 32, ARB_texture_storage_multisample_no_array) \
|
||||
EXT_TO_CHECK(43, 99, ARB_texture_storage_multisample) \
|
||||
|
||||
@@ -1884,6 +1884,14 @@ void GLReplay::SavePipelineState(uint32_t eventId)
|
||||
pipe.framebuffer.drawFBO.readBuffer = b - eGL_COLOR_ATTACHMENT0;
|
||||
else
|
||||
pipe.framebuffer.drawFBO.readBuffer = -1;
|
||||
|
||||
if(HasExt[ARB_framebuffer_no_attachments])
|
||||
{
|
||||
drv.glGetFramebufferParameteriv(eGL_READ_FRAMEBUFFER, eGL_FRAMEBUFFER_DEFAULT_SAMPLES,
|
||||
(GLint *)&pipe.framebuffer.readFBO.defaultSampleCount);
|
||||
drv.glGetFramebufferParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_FRAMEBUFFER_DEFAULT_SAMPLES,
|
||||
(GLint *)&pipe.framebuffer.drawFBO.defaultSampleCount);
|
||||
}
|
||||
}
|
||||
|
||||
pipe.framebuffer.blendState.blendFactor = rs.BlendColor;
|
||||
|
||||
Reference in new issue
Block a user