Add ability to debug compute shaders by dispatch thread ID

In some cases it is easier to know the dispatch thread ID you want to
debug rather than the group/thread IDs. This change adds a new window
when the debug button is clicked, to allow you to specify which thread
to debug in the most convenient way.
This commit is contained in:
Steve Karolewics
2021-10-19 18:14:53 +01:00
committed by Baldur Karlsson
parent 0b5e8369d3
commit ec785ba167
16 changed files with 637 additions and 462 deletions
+126
View File
@@ -0,0 +1,126 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2021 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 "ComputeDebugSelector.h"
#include "Code/QRDUtils.h"
#include "ui_ComputeDebugSelector.h"
ComputeDebugSelector::ComputeDebugSelector(QWidget *parent)
: QDialog(parent), ui(new Ui::ComputeDebugSelector)
{
ui->setupUi(this);
m_threadGroupSize[0] = m_threadGroupSize[1] = m_threadGroupSize[2] = 1;
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
ui->groupX->setFont(Formatter::PreferredFont());
ui->groupY->setFont(Formatter::PreferredFont());
ui->groupZ->setFont(Formatter::PreferredFont());
ui->threadX->setFont(Formatter::PreferredFont());
ui->threadY->setFont(Formatter::PreferredFont());
ui->threadZ->setFont(Formatter::PreferredFont());
ui->dispatchX->setFont(Formatter::PreferredFont());
ui->dispatchY->setFont(Formatter::PreferredFont());
ui->dispatchZ->setFont(Formatter::PreferredFont());
// A threadgroup's size in any dimension can be up to 1024, but a dispatch can be 65535
// threadgroups for a dimension. Use that upper bound to fix the min size of all fields.
ui->groupX->setMaximum(65535);
int sizeHint = ui->groupX->minimumSizeHint().width();
ui->groupX->setMinimumWidth(sizeHint);
ui->groupY->setMinimumWidth(sizeHint);
ui->groupZ->setMinimumWidth(sizeHint);
ui->threadX->setMinimumWidth(sizeHint);
ui->threadY->setMinimumWidth(sizeHint);
ui->threadZ->setMinimumWidth(sizeHint);
ui->dispatchX->setMinimumWidth(sizeHint);
ui->dispatchY->setMinimumWidth(sizeHint);
ui->dispatchZ->setMinimumWidth(sizeHint);
}
ComputeDebugSelector::~ComputeDebugSelector()
{
delete ui;
}
void ComputeDebugSelector::SetThreadBounds(const rdcfixedarray<uint32_t, 3> &group,
const rdcfixedarray<uint32_t, 3> &thread)
{
// Set maximums for CS debugging
ui->groupX->setMaximum(group[0] - 1);
ui->groupY->setMaximum(group[1] - 1);
ui->groupZ->setMaximum(group[2] - 1);
ui->threadX->setMaximum(thread[0] - 1);
ui->threadY->setMaximum(thread[1] - 1);
ui->threadZ->setMaximum(thread[2] - 1);
ui->dispatchX->setMaximum(group[0] * thread[0] - 1);
ui->dispatchY->setMaximum(group[1] * thread[1] - 1);
ui->dispatchZ->setMaximum(group[2] * thread[2] - 1);
m_threadGroupSize = thread;
}
void ComputeDebugSelector::SyncGroupThreadValue()
{
ui->dispatchX->setValue(ui->groupX->value() * m_threadGroupSize[0] + ui->threadX->value());
ui->dispatchY->setValue(ui->groupY->value() * m_threadGroupSize[1] + ui->threadY->value());
ui->dispatchZ->setValue(ui->groupZ->value() * m_threadGroupSize[2] + ui->threadZ->value());
}
void ComputeDebugSelector::SyncDispatchThreadValue()
{
uint32_t group[3] = {ui->dispatchX->value() / m_threadGroupSize[0],
ui->dispatchY->value() / m_threadGroupSize[1],
ui->dispatchZ->value() / m_threadGroupSize[2]};
uint32_t thread[3] = {ui->dispatchX->value() % m_threadGroupSize[0],
ui->dispatchY->value() % m_threadGroupSize[1],
ui->dispatchZ->value() % m_threadGroupSize[2]};
ui->groupX->setValue(group[0]);
ui->groupY->setValue(group[1]);
ui->groupZ->setValue(group[2]);
ui->threadX->setValue(thread[0]);
ui->threadY->setValue(thread[1]);
ui->threadZ->setValue(thread[2]);
}
void ComputeDebugSelector::on_beginDebug_clicked()
{
// The dispatch thread IDs and the group/thread IDs are synced on editing either set, so we can
// choose either one to begin debugging.
uint32_t group[3] = {(uint32_t)ui->groupX->value(), (uint32_t)ui->groupY->value(),
(uint32_t)ui->groupZ->value()};
uint32_t thread[3] = {(uint32_t)ui->threadX->value(), (uint32_t)ui->threadY->value(),
(uint32_t)ui->threadZ->value()};
emit beginDebug(group, thread);
close();
}
void ComputeDebugSelector::on_cancelDebug_clicked()
{
close();
}
+71
View File
@@ -0,0 +1,71 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2021 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 ComputeDebugSelector;
}
class ComputeDebugSelector : public QDialog
{
Q_OBJECT
public:
explicit ComputeDebugSelector(QWidget *parent = 0);
~ComputeDebugSelector();
void SetThreadBounds(const rdcfixedarray<uint32_t, 3> &group,
const rdcfixedarray<uint32_t, 3> &thread);
public slots:
signals:
void beginDebug(const rdcfixedarray<uint32_t, 3> &group, const rdcfixedarray<uint32_t, 3> &thread);
private slots:
// automatic slots
void on_groupX_valueChanged(int i) { SyncGroupThreadValue(); }
void on_groupY_valueChanged(int i) { SyncGroupThreadValue(); }
void on_groupZ_valueChanged(int i) { SyncGroupThreadValue(); }
void on_threadX_valueChanged(int i) { SyncGroupThreadValue(); }
void on_threadY_valueChanged(int i) { SyncGroupThreadValue(); }
void on_threadZ_valueChanged(int i) { SyncGroupThreadValue(); }
void on_dispatchX_valueChanged(int i) { SyncDispatchThreadValue(); }
void on_dispatchY_valueChanged(int i) { SyncDispatchThreadValue(); }
void on_dispatchZ_valueChanged(int i) { SyncDispatchThreadValue(); }
void on_beginDebug_clicked();
void on_cancelDebug_clicked();
private:
void SyncGroupThreadValue();
void SyncDispatchThreadValue();
Ui::ComputeDebugSelector *ui;
rdcfixedarray<uint32_t, 3> m_threadGroupSize;
};
+127
View File
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ComputeDebugSelector</class>
<widget class="QDialog" name="ComputeDebugSelector">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>268</width>
<height>237</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Debug Compute Shader</string>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<property name="modal">
<bool>true</bool>
</property>
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Debug Group and Thread ID</string>
</property>
<layout class="QGridLayout" name="gridLayout_groupthread">
<property name="verticalSpacing">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="groupDebugLabel">
<property name="text">
<string>Debug Group:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="groupX"/>
</item>
<item row="0" column="2">
<widget class="QSpinBox" name="groupY"/>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="groupZ"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="threadDebugLabel">
<property name="text">
<string>Thread:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="threadX"/>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="threadY"/>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="threadZ"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox1">
<property name="title">
<string>Dispatch Thread ID</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_dispatchthread">
<item>
<widget class="QSpinBox" name="dispatchX"/>
</item>
<item>
<widget class="QSpinBox" name="dispatchY"/>
</item>
<item>
<widget class="QSpinBox" name="dispatchZ"/>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_buttons">
<property name="alignment">
<set>Qt::AlignRight</set>
</property>
<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>
<resources/>
<connections/>
</ui>
@@ -29,6 +29,7 @@
#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"
@@ -77,6 +78,8 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
{
ui->setupUi(this);
m_ComputeDebugSelector = new ComputeDebugSelector(this);
const QIcon &action = Icons::action();
const QIcon &action_hover = Icons::action_hover();
@@ -148,6 +151,9 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
b->setMinimumSizeHint(QSize(250, 0));
}
QObject::connect(m_ComputeDebugSelector, &ComputeDebugSelector::beginDebug, this,
&D3D11PipelineStateViewer::computeDebugSelector_beginDebug);
for(QToolButton *b : editButtons)
QObject::connect(b, &QToolButton::clicked, &m_Common, &PipelineStateViewer::shaderEdit_clicked);
@@ -413,13 +419,6 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
ui->csUAVs->setFont(Formatter::PreferredFont());
ui->gsStreamOut->setFont(Formatter::PreferredFont());
ui->groupX->setFont(Formatter::PreferredFont());
ui->groupY->setFont(Formatter::PreferredFont());
ui->groupZ->setFont(Formatter::PreferredFont());
ui->threadX->setFont(Formatter::PreferredFont());
ui->threadY->setFont(Formatter::PreferredFont());
ui->threadZ->setFont(Formatter::PreferredFont());
ui->vsShader->setFont(Formatter::PreferredFont());
ui->vsResources->setFont(Formatter::PreferredFont());
ui->vsSamplers->setFont(Formatter::PreferredFont());
@@ -464,6 +463,7 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
D3D11PipelineStateViewer::~D3D11PipelineStateViewer()
{
delete ui;
delete m_ComputeDebugSelector;
}
void D3D11PipelineStateViewer::OnCaptureLoaded()
@@ -982,17 +982,7 @@ void D3D11PipelineStateViewer::clearState()
ui->predicateGroup->setVisible(false);
{
ui->groupX->setEnabled(false);
ui->groupY->setEnabled(false);
ui->groupZ->setEnabled(false);
ui->threadX->setEnabled(false);
ui->threadY->setEnabled(false);
ui->threadZ->setEnabled(false);
ui->debugThread->setEnabled(false);
}
ui->computeDebugSelector->setEnabled(false);
}
void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, RDLabel *shader,
@@ -1939,61 +1929,54 @@ void D3D11PipelineStateViewer::setState()
ui->stencils->endUpdate();
// set up thread debugging inputs
if(m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
state.computeShader.reflection->debugInfo.debuggable && action &&
(action->flags & ActionFlags::Dispatch))
bool enableDebug = m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
state.computeShader.reflection->debugInfo.debuggable && action &&
(action->flags & ActionFlags::Dispatch);
if(enableDebug)
{
ui->groupX->setEnabled(true);
ui->groupY->setEnabled(true);
ui->groupZ->setEnabled(true);
// Validate dispatch/threadgroup dimensions
enableDebug &= action->dispatchDimension[0] > 0;
enableDebug &= action->dispatchDimension[1] > 0;
enableDebug &= action->dispatchDimension[2] > 0;
ui->threadX->setEnabled(true);
ui->threadY->setEnabled(true);
ui->threadZ->setEnabled(true);
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;
}
ui->debugThread->setEnabled(true);
if(enableDebug)
{
ui->computeDebugSelector->setEnabled(true);
// set maximums for CS debugging
ui->groupX->setMaximum((int)action->dispatchDimension[0] - 1);
ui->groupY->setMaximum((int)action->dispatchDimension[1] - 1);
ui->groupZ->setMaximum((int)action->dispatchDimension[2] - 1);
m_ComputeDebugSelector->SetThreadBounds(
action->dispatchDimension, (action->dispatchThreadsDimension[0] == 0)
? state.computeShader.reflection->dispatchThreadsDimension
: action->dispatchThreadsDimension);
if(action->dispatchThreadsDimension[0] == 0)
{
ui->threadX->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[0] - 1);
ui->threadY->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[1] - 1);
ui->threadZ->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[2] - 1);
}
else
{
ui->threadX->setMaximum((int)action->dispatchThreadsDimension[0] - 1);
ui->threadY->setMaximum((int)action->dispatchThreadsDimension[1] - 1);
ui->threadZ->setMaximum((int)action->dispatchThreadsDimension[2] - 1);
}
ui->debugThread->setToolTip(QString());
ui->computeDebugSelector->setToolTip(
tr("Debug this compute shader by specifying group/thread ID or dispatch ID"));
}
else
{
ui->groupX->setEnabled(false);
ui->groupY->setEnabled(false);
ui->groupZ->setEnabled(false);
ui->threadX->setEnabled(false);
ui->threadY->setEnabled(false);
ui->threadZ->setEnabled(false);
ui->debugThread->setEnabled(false);
ui->computeDebugSelector->setEnabled(false);
if(!m_Ctx.APIProps().shaderDebugging)
ui->debugThread->setToolTip(tr("This API does not support shader debugging"));
ui->computeDebugSelector->setToolTip(tr("This API does not support shader debugging"));
else if(!action || !(action->flags & ActionFlags::Dispatch))
ui->debugThread->setToolTip(tr("No dispatch selected"));
ui->computeDebugSelector->setToolTip(tr("No dispatch selected"));
else if(!state.computeShader.reflection)
ui->debugThread->setToolTip(tr("No compute shader bound"));
ui->computeDebugSelector->setToolTip(tr("No compute shader bound"));
else if(!state.computeShader.reflection->debugInfo.debuggable)
ui->debugThread->setToolTip(tr("This shader doesn't support debugging: %1")
.arg(state.computeShader.reflection->debugInfo.debugStatus));
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."));
}
// highlight the appropriate stages in the flowchart
@@ -3200,8 +3183,9 @@ void D3D11PipelineStateViewer::on_meshView_clicked()
ToolWindowManager::raiseToolWindow(m_Ctx.GetMeshPreview()->Widget());
}
void D3D11PipelineStateViewer::on_debugThread_clicked()
void D3D11PipelineStateViewer::on_computeDebugSelector_clicked()
{
// Check whether debugging is valid for this event before showing the dialog
if(!m_Ctx.IsCaptureLoaded())
return;
@@ -3217,37 +3201,40 @@ void D3D11PipelineStateViewer::on_debugThread_clicked()
if(!shaderDetails)
return;
uint32_t groupdim[3] = {};
RDDialog::show(m_ComputeDebugSelector);
}
for(int i = 0; i < 3; i++)
groupdim[i] = action->dispatchDimension[i];
void D3D11PipelineStateViewer::computeDebugSelector_beginDebug(
const rdcfixedarray<uint32_t, 3> &group, const rdcfixedarray<uint32_t, 3> &thread)
{
const ActionDescription *action = m_Ctx.CurAction();
uint32_t threadsdim[3] = {};
for(int i = 0; i < 3; i++)
threadsdim[i] = action->dispatchThreadsDimension[i];
if(!action)
return;
if(threadsdim[0] == 0)
{
for(int i = 0; i < 3; i++)
threadsdim[i] = shaderDetails->dispatchThreadsDimension[i];
}
ShaderReflection *shaderDetails = m_Ctx.CurD3D12PipelineState()->computeShader.reflection;
const ShaderBindpointMapping &bindMapping =
m_Ctx.CurD3D12PipelineState()->computeShader.bindpointMapping;
if(!shaderDetails)
return;
struct threadSelect
{
rdcfixedarray<uint32_t, 3> g;
rdcfixedarray<uint32_t, 3> t;
} thread = {
} debugThread = {
// g[]
{(uint32_t)ui->groupX->value(), (uint32_t)ui->groupY->value(), (uint32_t)ui->groupZ->value()},
{group[0], group[1], group[2]},
// t[]
{(uint32_t)ui->threadX->value(), (uint32_t)ui->threadY->value(), (uint32_t)ui->threadZ->value()},
{thread[0], thread[1], thread[2]},
};
bool done = false;
ShaderDebugTrace *trace = NULL;
m_Ctx.Replay().AsyncInvoke([&trace, &done, thread](IReplayController *r) {
trace = r->DebugThread(thread.g, thread.t);
m_Ctx.Replay().AsyncInvoke([&trace, &done, debugThread](IReplayController *r) {
trace = r->DebugThread(debugThread.g, debugThread.t);
if(trace->debugger == NULL)
{
@@ -3259,12 +3246,12 @@ void D3D11PipelineStateViewer::on_debugThread_clicked()
});
QString debugContext = lit("Group [%1,%2,%3] Thread [%4,%5,%6]")
.arg(thread.g[0])
.arg(thread.g[1])
.arg(thread.g[2])
.arg(thread.t[0])
.arg(thread.t[1])
.arg(thread.t[2]);
.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)
@@ -3283,7 +3270,8 @@ void D3D11PipelineStateViewer::on_debugThread_clicked()
// viewer takes ownership of the trace
IShaderViewer *s =
m_Ctx.DebugShader(&bindMapping, shaderDetails, ResourceId(), trace, debugContext);
m_Ctx.DebugShader(&bindMapping, shaderDetails,
m_Ctx.CurPipelineState().GetComputePipelineObject(), trace, debugContext);
m_Ctx.AddDockWindow(s->Widget(), DockReference::AddTo, this);
}
@@ -33,6 +33,8 @@ class D3D11PipelineStateViewer;
}
class QXmlStreamWriter;
class ComputeDebugSelector;
class RDLabel;
class RDTreeWidget;
class RDTreeWidgetItem;
@@ -77,12 +79,15 @@ private slots:
void cbuffer_itemActivated(RDTreeWidgetItem *item, int column);
void vertex_leave(QEvent *e);
void on_debugThread_clicked();
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, RDTreeWidget *tex,
RDTreeWidget *samp, RDTreeWidget *cbuffer, RDTreeWidget *classes);
@@ -4091,76 +4091,21 @@
</widget>
</item>
<item>
<widget class="QFrame" name="csDebugFrame">
<layout class="QHBoxLayout" name="horizontalLayout_34">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="groupDebugLabel">
<property name="text">
<string>Debug Group:</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="groupX"/>
</item>
<item>
<widget class="QSpinBox" name="groupY"/>
</item>
<item>
<widget class="QSpinBox" name="groupZ"/>
</item>
<item>
<widget class="QLabel" name="threadDebugLabel">
<property name="text">
<string>Thread:</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="threadX"/>
</item>
<item>
<widget class="QSpinBox" name="threadY"/>
</item>
<item>
<widget class="QSpinBox" name="threadZ"/>
</item>
<item>
<widget class="QToolButton" name="debugThread">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<normaloff>:/wrench.png</normaloff>:/wrench.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<widget class="QToolButton" name="computeDebugSelector">
<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>
@@ -29,6 +29,7 @@
#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"
@@ -110,6 +111,8 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(ICaptureContext &ctx,
{
ui->setupUi(this);
m_ComputeDebugSelector = new ComputeDebugSelector(this);
const QIcon &action = Icons::action();
const QIcon &action_hover = Icons::action_hover();
@@ -191,6 +194,9 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(ICaptureContext &ctx,
b->setMinimumSizeHint(QSize(100, 0));
}
QObject::connect(m_ComputeDebugSelector, &ComputeDebugSelector::beginDebug, this,
&D3D12PipelineStateViewer::computeDebugSelector_beginDebug);
for(QToolButton *b : editButtons)
QObject::connect(b, &QToolButton::clicked, &m_Common, &PipelineStateViewer::shaderEdit_clicked);
@@ -448,12 +454,6 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(ICaptureContext &ctx,
ui->iaLayouts->setFont(Formatter::PreferredFont());
ui->iaBuffers->setFont(Formatter::PreferredFont());
ui->gsStreamOut->setFont(Formatter::PreferredFont());
ui->groupX->setFont(Formatter::PreferredFont());
ui->groupY->setFont(Formatter::PreferredFont());
ui->groupZ->setFont(Formatter::PreferredFont());
ui->threadX->setFont(Formatter::PreferredFont());
ui->threadY->setFont(Formatter::PreferredFont());
ui->threadZ->setFont(Formatter::PreferredFont());
ui->vsShader->setFont(Formatter::PreferredFont());
ui->vsResources->setFont(Formatter::PreferredFont());
ui->vsSamplers->setFont(Formatter::PreferredFont());
@@ -496,6 +496,7 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(ICaptureContext &ctx,
D3D12PipelineStateViewer::~D3D12PipelineStateViewer()
{
delete ui;
delete m_ComputeDebugSelector;
}
void D3D12PipelineStateViewer::OnCaptureLoaded()
@@ -1018,17 +1019,7 @@ void D3D12PipelineStateViewer::clearState()
ui->stencils->clear();
{
ui->groupX->setEnabled(false);
ui->groupY->setEnabled(false);
ui->groupZ->setEnabled(false);
ui->threadX->setEnabled(false);
ui->threadY->setEnabled(false);
ui->threadZ->setEnabled(false);
ui->debugThread->setEnabled(false);
}
ui->computeDebugSelector->setEnabled(false);
}
void D3D12PipelineStateViewer::setShaderState(
@@ -2028,61 +2019,54 @@ void D3D12PipelineStateViewer::setState()
ui->stencils->endUpdate();
// set up thread debugging inputs
if(m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
state.computeShader.reflection->debugInfo.debuggable && action &&
(action->flags & ActionFlags::Dispatch))
bool enableDebug = m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
state.computeShader.reflection->debugInfo.debuggable && action &&
(action->flags & ActionFlags::Dispatch);
if(enableDebug)
{
ui->groupX->setEnabled(true);
ui->groupY->setEnabled(true);
ui->groupZ->setEnabled(true);
// Validate dispatch/threadgroup dimensions
enableDebug &= action->dispatchDimension[0] > 0;
enableDebug &= action->dispatchDimension[1] > 0;
enableDebug &= action->dispatchDimension[2] > 0;
ui->threadX->setEnabled(true);
ui->threadY->setEnabled(true);
ui->threadZ->setEnabled(true);
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;
}
ui->debugThread->setEnabled(true);
if(enableDebug)
{
ui->computeDebugSelector->setEnabled(true);
// set maximums for CS debugging
ui->groupX->setMaximum((int)action->dispatchDimension[0] - 1);
ui->groupY->setMaximum((int)action->dispatchDimension[1] - 1);
ui->groupZ->setMaximum((int)action->dispatchDimension[2] - 1);
m_ComputeDebugSelector->SetThreadBounds(
action->dispatchDimension, (action->dispatchThreadsDimension[0] == 0)
? state.computeShader.reflection->dispatchThreadsDimension
: action->dispatchThreadsDimension);
if(action->dispatchThreadsDimension[0] == 0)
{
ui->threadX->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[0] - 1);
ui->threadY->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[1] - 1);
ui->threadZ->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[2] - 1);
}
else
{
ui->threadX->setMaximum((int)action->dispatchThreadsDimension[0] - 1);
ui->threadY->setMaximum((int)action->dispatchThreadsDimension[1] - 1);
ui->threadZ->setMaximum((int)action->dispatchThreadsDimension[2] - 1);
}
ui->debugThread->setToolTip(QString());
ui->computeDebugSelector->setToolTip(
tr("Debug this compute shader by specifying group/thread ID or dispatch ID"));
}
else
{
ui->groupX->setEnabled(false);
ui->groupY->setEnabled(false);
ui->groupZ->setEnabled(false);
ui->threadX->setEnabled(false);
ui->threadY->setEnabled(false);
ui->threadZ->setEnabled(false);
ui->debugThread->setEnabled(false);
ui->computeDebugSelector->setEnabled(false);
if(!m_Ctx.APIProps().shaderDebugging)
ui->debugThread->setToolTip(tr("This API does not support shader debugging"));
ui->computeDebugSelector->setToolTip(tr("This API does not support shader debugging"));
else if(!action || !(action->flags & ActionFlags::Dispatch))
ui->debugThread->setToolTip(tr("No dispatch selected"));
ui->computeDebugSelector->setToolTip(tr("No dispatch selected"));
else if(!state.computeShader.reflection)
ui->debugThread->setToolTip(tr("No compute shader bound"));
ui->computeDebugSelector->setToolTip(tr("No compute shader bound"));
else if(!state.computeShader.reflection->debugInfo.debuggable)
ui->debugThread->setToolTip(tr("This shader doesn't support debugging: %1")
.arg(state.computeShader.reflection->debugInfo.debugStatus));
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."));
}
// highlight the appropriate stages in the flowchart
@@ -3403,8 +3387,9 @@ void D3D12PipelineStateViewer::on_meshView_clicked()
ToolWindowManager::raiseToolWindow(m_Ctx.GetMeshPreview()->Widget());
}
void D3D12PipelineStateViewer::on_debugThread_clicked()
void D3D12PipelineStateViewer::on_computeDebugSelector_clicked()
{
// Check whether debugging is valid for this event before showing the dialog
if(!m_Ctx.APIProps().shaderDebugging)
return;
@@ -3423,37 +3408,40 @@ void D3D12PipelineStateViewer::on_debugThread_clicked()
if(!shaderDetails)
return;
uint32_t groupdim[3] = {};
RDDialog::show(m_ComputeDebugSelector);
}
for(int i = 0; i < 3; i++)
groupdim[i] = action->dispatchDimension[i];
void D3D12PipelineStateViewer::computeDebugSelector_beginDebug(
const rdcfixedarray<uint32_t, 3> &group, const rdcfixedarray<uint32_t, 3> &thread)
{
const ActionDescription *action = m_Ctx.CurAction();
uint32_t threadsdim[3] = {};
for(int i = 0; i < 3; i++)
threadsdim[i] = action->dispatchThreadsDimension[i];
if(!action)
return;
if(threadsdim[0] == 0)
{
for(int i = 0; i < 3; i++)
threadsdim[i] = shaderDetails->dispatchThreadsDimension[i];
}
ShaderReflection *shaderDetails = m_Ctx.CurD3D12PipelineState()->computeShader.reflection;
const ShaderBindpointMapping &bindMapping =
m_Ctx.CurD3D12PipelineState()->computeShader.bindpointMapping;
if(!shaderDetails)
return;
struct threadSelect
{
rdcfixedarray<uint32_t, 3> g;
rdcfixedarray<uint32_t, 3> t;
} thread = {
} debugThread = {
// g[]
{(uint32_t)ui->groupX->value(), (uint32_t)ui->groupY->value(), (uint32_t)ui->groupZ->value()},
{group[0], group[1], group[2]},
// t[]
{(uint32_t)ui->threadX->value(), (uint32_t)ui->threadY->value(), (uint32_t)ui->threadZ->value()},
{thread[0], thread[1], thread[2]},
};
bool done = false;
ShaderDebugTrace *trace = NULL;
m_Ctx.Replay().AsyncInvoke([&trace, &done, thread](IReplayController *r) {
trace = r->DebugThread(thread.g, thread.t);
m_Ctx.Replay().AsyncInvoke([&trace, &done, debugThread](IReplayController *r) {
trace = r->DebugThread(debugThread.g, debugThread.t);
if(trace->debugger == NULL)
{
@@ -3465,12 +3453,12 @@ void D3D12PipelineStateViewer::on_debugThread_clicked()
});
QString debugContext = lit("Group [%1,%2,%3] Thread [%4,%5,%6]")
.arg(thread.g[0])
.arg(thread.g[1])
.arg(thread.g[2])
.arg(thread.t[0])
.arg(thread.t[1])
.arg(thread.t[2]);
.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)
@@ -34,6 +34,7 @@ class D3D12PipelineStateViewer;
class QXmlStreamWriter;
class ComputeDebugSelector;
class RDLabel;
class RDTreeWidget;
class RDTreeWidgetItem;
@@ -77,12 +78,15 @@ private slots:
void cbuffer_itemActivated(RDTreeWidgetItem *item, int column);
void vertex_leave(QEvent *e);
void on_debugThread_clicked();
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 setShaderState(const rdcarray<D3D12Pipe::RootSignatureRange> &rootElements,
const D3D12Pipe::Shader &stage, RDLabel *shader, RDLabel *rootSig,
@@ -3952,76 +3952,21 @@
</widget>
</item>
<item>
<widget class="QFrame" name="csDebugFrame">
<layout class="QHBoxLayout" name="horizontalLayout_34">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="groupDebugLabel">
<property name="text">
<string>Debug Group:</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="groupX"/>
</item>
<item>
<widget class="QSpinBox" name="groupY"/>
</item>
<item>
<widget class="QSpinBox" name="groupZ"/>
</item>
<item>
<widget class="QLabel" name="threadDebugLabel">
<property name="text">
<string>Thread:</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="threadX"/>
</item>
<item>
<widget class="QSpinBox" name="threadY"/>
</item>
<item>
<widget class="QSpinBox" name="threadZ"/>
</item>
<item>
<widget class="QToolButton" name="debugThread">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<normaloff>:/wrench.png</normaloff>:/wrench.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<widget class="QToolButton" name="computeDebugSelector">
<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>
@@ -4339,6 +4284,11 @@
<header>Widgets/CollapseGroupBox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ToolWindowManager</class>
<extends>QWidget</extends>
<header>3rdparty/toolwindowmanager/ToolWindowManager.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../Resources/resources.qrc"/>
@@ -30,6 +30,7 @@
#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"
@@ -123,6 +124,8 @@ VulkanPipelineStateViewer::VulkanPipelineStateViewer(ICaptureContext &ctx,
{
ui->setupUi(this);
m_ComputeDebugSelector = new ComputeDebugSelector(this);
const QIcon &action = Icons::action();
const QIcon &action_hover = Icons::action_hover();
@@ -191,6 +194,9 @@ VulkanPipelineStateViewer::VulkanPipelineStateViewer(ICaptureContext &ctx,
b->setMinimumSizeHint(QSize(250, 0));
}
QObject::connect(m_ComputeDebugSelector, &ComputeDebugSelector::beginDebug, this,
&VulkanPipelineStateViewer::computeDebugSelector_beginDebug);
for(QToolButton *b : editButtons)
QObject::connect(b, &QToolButton::clicked, &m_Common, &PipelineStateViewer::shaderEdit_clicked);
@@ -484,6 +490,7 @@ VulkanPipelineStateViewer::~VulkanPipelineStateViewer()
{
m_CombinedImageSamplers.clear();
delete ui;
delete m_ComputeDebugSelector;
}
void VulkanPipelineStateViewer::OnCaptureLoaded()
@@ -903,17 +910,7 @@ void VulkanPipelineStateViewer::clearState()
ui->stencils->clear();
{
ui->groupX->setEnabled(false);
ui->groupY->setEnabled(false);
ui->groupZ->setEnabled(false);
ui->threadX->setEnabled(false);
ui->threadY->setEnabled(false);
ui->threadZ->setEnabled(false);
ui->debugThread->setEnabled(false);
}
ui->computeDebugSelector->setEnabled(false);
ui->conditionalRenderingGroup->setVisible(false);
ui->csConditionalRenderingGroup->setVisible(false);
@@ -2791,61 +2788,54 @@ void VulkanPipelineStateViewer::setState()
ui->stencils->endUpdate();
// set up thread debugging inputs
if(m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
state.computeShader.reflection->debugInfo.debuggable && action &&
(action->flags & ActionFlags::Dispatch))
bool enableDebug = m_Ctx.APIProps().shaderDebugging && state.computeShader.reflection &&
state.computeShader.reflection->debugInfo.debuggable && action &&
(action->flags & ActionFlags::Dispatch);
if(enableDebug)
{
ui->groupX->setEnabled(true);
ui->groupY->setEnabled(true);
ui->groupZ->setEnabled(true);
// Validate dispatch/threadgroup dimensions
enableDebug &= action->dispatchDimension[0] > 0;
enableDebug &= action->dispatchDimension[1] > 0;
enableDebug &= action->dispatchDimension[2] > 0;
ui->threadX->setEnabled(true);
ui->threadY->setEnabled(true);
ui->threadZ->setEnabled(true);
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;
}
ui->debugThread->setEnabled(true);
if(enableDebug)
{
ui->computeDebugSelector->setEnabled(true);
// set maximums for CS debugging
ui->groupX->setMaximum((int)action->dispatchDimension[0] - 1);
ui->groupY->setMaximum((int)action->dispatchDimension[1] - 1);
ui->groupZ->setMaximum((int)action->dispatchDimension[2] - 1);
m_ComputeDebugSelector->SetThreadBounds(
action->dispatchDimension, (action->dispatchThreadsDimension[0] == 0)
? state.computeShader.reflection->dispatchThreadsDimension
: action->dispatchThreadsDimension);
if(action->dispatchThreadsDimension[0] == 0)
{
ui->threadX->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[0] - 1);
ui->threadY->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[1] - 1);
ui->threadZ->setMaximum((int)state.computeShader.reflection->dispatchThreadsDimension[2] - 1);
}
else
{
ui->threadX->setMaximum((int)action->dispatchThreadsDimension[0] - 1);
ui->threadY->setMaximum((int)action->dispatchThreadsDimension[1] - 1);
ui->threadZ->setMaximum((int)action->dispatchThreadsDimension[2] - 1);
}
ui->debugThread->setToolTip(QString());
ui->computeDebugSelector->setToolTip(
tr("Debug this compute shader by specifying group/thread ID or dispatch ID"));
}
else
{
ui->groupX->setEnabled(false);
ui->groupY->setEnabled(false);
ui->groupZ->setEnabled(false);
ui->threadX->setEnabled(false);
ui->threadY->setEnabled(false);
ui->threadZ->setEnabled(false);
ui->debugThread->setEnabled(false);
ui->computeDebugSelector->setEnabled(false);
if(!m_Ctx.APIProps().shaderDebugging)
ui->debugThread->setToolTip(tr("This API does not support shader debugging"));
ui->computeDebugSelector->setToolTip(tr("This API does not support shader debugging"));
else if(!action || !(action->flags & ActionFlags::Dispatch))
ui->debugThread->setToolTip(tr("No dispatch selected"));
ui->computeDebugSelector->setToolTip(tr("No dispatch selected"));
else if(!state.computeShader.reflection)
ui->debugThread->setToolTip(tr("No compute shader bound"));
ui->computeDebugSelector->setToolTip(tr("No compute shader bound"));
else if(!state.computeShader.reflection->debugInfo.debuggable)
ui->debugThread->setToolTip(tr("This shader doesn't support debugging: %1")
.arg(state.computeShader.reflection->debugInfo.debugStatus));
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."));
}
// highlight the appropriate stages in the flowchart
@@ -4721,8 +4711,9 @@ void VulkanPipelineStateViewer::on_meshView_clicked()
ToolWindowManager::raiseToolWindow(m_Ctx.GetMeshPreview()->Widget());
}
void VulkanPipelineStateViewer::on_debugThread_clicked()
void VulkanPipelineStateViewer::on_computeDebugSelector_clicked()
{
// Check whether debugging is valid for this event before showing the dialog
if(!m_Ctx.APIProps().shaderDebugging)
return;
@@ -4731,47 +4722,50 @@ void VulkanPipelineStateViewer::on_debugThread_clicked()
const ActionDescription *action = m_Ctx.CurAction();
if(!action || !(action->flags & ActionFlags::Dispatch))
if(!action)
return;
ShaderReflection *shaderDetails = m_Ctx.CurVulkanPipelineState()->computeShader.reflection;
ShaderReflection *shaderDetails = m_Ctx.CurD3D12PipelineState()->computeShader.reflection;
const ShaderBindpointMapping &bindMapping =
m_Ctx.CurVulkanPipelineState()->computeShader.bindpointMapping;
m_Ctx.CurD3D12PipelineState()->computeShader.bindpointMapping;
if(!shaderDetails)
return;
uint32_t groupdim[3] = {};
RDDialog::show(m_ComputeDebugSelector);
}
for(int i = 0; i < 3; i++)
groupdim[i] = action->dispatchDimension[i];
void VulkanPipelineStateViewer::computeDebugSelector_beginDebug(
const rdcfixedarray<uint32_t, 3> &group, const rdcfixedarray<uint32_t, 3> &thread)
{
const ActionDescription *action = m_Ctx.CurAction();
uint32_t threadsdim[3] = {};
for(int i = 0; i < 3; i++)
threadsdim[i] = action->dispatchThreadsDimension[i];
if(!action)
return;
if(threadsdim[0] == 0)
{
for(int i = 0; i < 3; i++)
threadsdim[i] = shaderDetails->dispatchThreadsDimension[i];
}
ShaderReflection *shaderDetails = m_Ctx.CurD3D12PipelineState()->computeShader.reflection;
const ShaderBindpointMapping &bindMapping =
m_Ctx.CurD3D12PipelineState()->computeShader.bindpointMapping;
if(!shaderDetails)
return;
struct threadSelect
{
rdcfixedarray<uint32_t, 3> g;
rdcfixedarray<uint32_t, 3> t;
} thread = {
} debugThread = {
// g[]
{(uint32_t)ui->groupX->value(), (uint32_t)ui->groupY->value(), (uint32_t)ui->groupZ->value()},
{group[0], group[1], group[2]},
// t[]
{(uint32_t)ui->threadX->value(), (uint32_t)ui->threadY->value(), (uint32_t)ui->threadZ->value()},
{thread[0], thread[1], thread[2]},
};
bool done = false;
ShaderDebugTrace *trace = NULL;
m_Ctx.Replay().AsyncInvoke([&trace, &done, thread](IReplayController *r) {
trace = r->DebugThread(thread.g, thread.t);
m_Ctx.Replay().AsyncInvoke([&trace, &done, debugThread](IReplayController *r) {
trace = r->DebugThread(debugThread.g, debugThread.t);
if(trace->debugger == NULL)
{
@@ -4783,12 +4777,12 @@ void VulkanPipelineStateViewer::on_debugThread_clicked()
});
QString debugContext = lit("Group [%1,%2,%3] Thread [%4,%5,%6]")
.arg(thread.g[0])
.arg(thread.g[1])
.arg(thread.g[2])
.arg(thread.t[0])
.arg(thread.t[1])
.arg(thread.t[2]);
.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)
@@ -35,6 +35,7 @@ class VulkanPipelineStateViewer;
class QXmlStreamWriter;
class ComputeDebugSelector;
class RDLabel;
class RDTreeWidget;
class RDTreeWidgetItem;
@@ -86,7 +87,9 @@ private slots:
void ubo_itemActivated(RDTreeWidgetItem *item, int column);
void vertex_leave(QEvent *e);
void on_debugThread_clicked();
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();
@@ -95,6 +98,7 @@ private:
Ui::VulkanPipelineStateViewer *ui;
ICaptureContext &m_Ctx;
PipelineStateViewer &m_Common;
ComputeDebugSelector *m_ComputeDebugSelector;
QVariantList makeSampler(const QString &bindset, const QString &slotname,
const VKPipe::BindingElement &descriptor);
@@ -3804,77 +3804,21 @@
</widget>
</item>
<item>
<widget class="QFrame" name="csDebugFrame">
<layout class="QHBoxLayout" name="horizontalLayout_34">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="groupDebugLabel">
<property name="text">
<string>Debug Group:</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="groupX"/>
</item>
<item>
<widget class="QSpinBox" name="groupY"/>
</item>
<item>
<widget class="QSpinBox" name="groupZ"/>
</item>
<item>
<widget class="QLabel" name="threadDebugLabel">
<property name="text">
<string>Thread:</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="threadX"/>
</item>
<item>
<widget class="QSpinBox" name="threadY"/>
</item>
<item>
<widget class="QSpinBox" name="threadZ"/>
</item>
<item>
<widget class="QToolButton" name="debugThread">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<normaloff>:/wrench.png</normaloff>:/wrench.png
</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<widget class="QToolButton" name="computeDebugSelector">
<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>
+3
View File
@@ -198,6 +198,7 @@ SOURCES += Code/qrenderdoc.cpp \
Widgets/Extended/RDToolButton.cpp \
Widgets/Extended/RDDoubleSpinBox.cpp \
Widgets/Extended/RDListView.cpp \
Widgets/ComputeDebugSelector.cpp \
Widgets/CustomPaintWidget.cpp \
Widgets/ResourcePreview.cpp \
Widgets/ThumbnailStrip.cpp \
@@ -282,6 +283,7 @@ HEADERS += Code/CaptureContext.h \
Widgets/Extended/RDToolButton.h \
Widgets/Extended/RDDoubleSpinBox.h \
Widgets/Extended/RDListView.h \
Widgets/ComputeDebugSelector.h \
Widgets/CustomPaintWidget.h \
Widgets/ResourcePreview.h \
Widgets/ThumbnailStrip.h \
@@ -351,6 +353,7 @@ FORMS += Windows/Dialogs/AboutDialog.ui \
Windows/PipelineState/GLPipelineStateViewer.ui \
Windows/ConstantBufferPreviewer.ui \
Widgets/BufferFormatSpecifier.ui \
Widgets/ComputeDebugSelector.ui \
Windows/BufferViewer.ui \
Windows/ShaderViewer.ui \
Windows/ShaderMessageViewer.ui \
+15 -4
View File
@@ -618,6 +618,7 @@
<ClCompile Include="$(IntDir)generated\moc_APIInspector.cpp" />
<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_FindReplace.cpp" />
<ClCompile Include="$(IntDir)generated\moc_BufferViewer.cpp" />
<ClCompile Include="$(IntDir)generated\moc_CaptureDialog.cpp" />
@@ -714,6 +715,7 @@
</ClCompile>
<ClCompile Include="Widgets\BufferFormatSpecifier.cpp" />
<ClCompile Include="Widgets\CollapseGroupBox.cpp" />
<ClCompile Include="Widgets\ComputeDebugSelector.cpp" />
<ClCompile Include="Widgets\FindReplace.cpp" />
<ClCompile Include="Widgets\Extended\RDListWidget.cpp" />
<ClCompile Include="Widgets\Extended\RDTableView.cpp" />
@@ -955,6 +957,7 @@
<ClInclude Include="$(IntDir)generated\ui_APIInspector.h" />
<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_FindReplace.h" />
<ClInclude Include="$(IntDir)generated\ui_BufferViewer.h" />
<ClInclude Include="$(IntDir)generated\ui_CaptureDialog.h" />
@@ -1027,6 +1030,12 @@
<Message>MOC %(Filename).h</Message>
<Outputs>$(IntDir)generated\moc_%(Filename).cpp</Outputs>
</CustomBuild>
<CustomBuild Include="Widgets\ComputeDebugSelector.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>
@@ -1442,6 +1451,12 @@
<Message>UIC %(Filename).ui</Message>
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
</CustomBuild>
<CustomBuild Include="Widgets\ComputeDebugSelector.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>
@@ -1549,7 +1564,6 @@
<Command>"$(QtBinDir)\uic.exe" "%(Fullpath)" -o "$(IntDir)generated\ui_%(Filename).h"</Command>
<Message>UIC %(Filename).ui</Message>
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
<SubType>Designer</SubType>
</CustomBuild>
<CustomBuild Include="Windows\Dialogs\EnvironmentEditor.ui">
<AdditionalInputs>%(Fullpath);$(QtBinDir)\uic.exe;%(AdditionalInputs)</AdditionalInputs>
@@ -1634,7 +1648,6 @@
<Command>"$(QtBinDir)\uic.exe" "%(Fullpath)" -o "$(IntDir)generated\ui_%(Filename).h"</Command>
<Message>UIC %(Filename).ui</Message>
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
<SubType>Designer</SubType>
</CustomBuild>
<CustomBuild Include="Windows\PipelineState\PipelineStateViewer.ui">
<AdditionalInputs>%(Fullpath);$(QtBinDir)\uic.exe;%(AdditionalInputs)</AdditionalInputs>
@@ -1689,7 +1702,6 @@
<Command>"$(QtBinDir)\uic.exe" "%(Fullpath)" -o "$(IntDir)generated\ui_%(Filename).h"</Command>
<Message>UIC %(Filename).ui</Message>
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
<SubType>Designer</SubType>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@@ -1716,7 +1728,6 @@
<Command>"$(QtBinDir)\uic.exe" "%(Fullpath)" -o "$(IntDir)generated\ui_%(Filename).h"</Command>
<Message>UIC %(Filename).ui</Message>
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
<SubType>Designer</SubType>
</CustomBuild>
<None Include="Resources\logo.svg" />
<None Include="Resources\qt.conf" />
@@ -408,6 +408,9 @@
<ClCompile Include="$(IntDir)generated\moc_CaptureDialog.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="$(IntDir)generated\moc_ComputeDebugSelector.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="$(IntDir)generated\moc_ConstantBufferPreviewer.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
@@ -756,6 +759,9 @@
<ClCompile Include="Widgets\MarkerBreadcrumbs.cpp">
<Filter>Widgets</Filter>
</ClCompile>
<ClCompile Include="Widgets\ComputeDebugSelector.cpp">
<Filter>Widgets</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="3rdparty\flowlayout\FlowLayout.h">
@@ -965,6 +971,9 @@
<ClInclude Include="$(IntDir)generated\ui_CaptureDialog.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="$(IntDir)generated\ui_ComputeDebugSelector.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="$(IntDir)generated\ui_ConstantBufferPreviewer.h">
<Filter>Generated Files</Filter>
</ClInclude>
@@ -1535,6 +1544,12 @@
<CustomBuild Include="Widgets\MarkerBreadcrumbs.h">
<Filter>Widgets</Filter>
</CustomBuild>
<CustomBuild Include="Widgets\ComputeDebugSelector.h">
<Filter>Widgets</Filter>
</CustomBuild>
<CustomBuild Include="Widgets\ComputeDebugSelector.ui">
<Filter>Widgets</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<Image Include="Resources\action.png">
+2 -2
View File
@@ -3010,13 +3010,13 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
if(!dxbc)
{
RDCERR("Pixel shader couldn't be reflected");
RDCERR("Compute shader couldn't be reflected");
return new ShaderDebugTrace;
}
if(!refl.debugInfo.debuggable)
{
RDCERR("Pixel shader is not debuggable");
RDCERR("Compute shader is not debuggable");
return new ShaderDebugTrace;
}