Extend info in accessed resources panel in the shader viewer

This commit is contained in:
Steve Karolewics
2020-05-08 20:43:04 +01:00
committed by Baldur Karlsson
parent 8638dddb84
commit ef58d7e1f8
3 changed files with 295 additions and 56 deletions
+194 -55
View File
@@ -60,11 +60,11 @@ struct VariableTag
struct AccessedResourceTag
{
AccessedResourceTag() : type(VarType::Unknown) { bind.bind = -1; }
AccessedResourceTag(BindpointIndex bp, VarType t) : bind(bp), type(t) {}
AccessedResourceTag(ShaderVariable var)
AccessedResourceTag() : type(VarType::Unknown), step(0) { bind.bind = -1; }
AccessedResourceTag(uint32_t s) : type(VarType::Unknown), step(s) { bind.bind = -1; }
AccessedResourceTag(BindpointIndex bp, VarType t) : bind(bp), type(t), step(0) {}
AccessedResourceTag(ShaderVariable var) : step(0), type(var.type)
{
type = var.type;
if(var.type == VarType::ReadOnlyResource || var.type == VarType::ReadWriteResource)
bind = var.GetBinding();
else
@@ -72,6 +72,7 @@ struct AccessedResourceTag
}
BindpointIndex bind;
VarType type;
uint32_t step;
};
};
@@ -523,7 +524,7 @@ void ShaderViewer::debugShader(const ShaderBindpointMapping *bind, const ShaderR
ui->constants->header()->resizeSection(0, 80);
ui->accessedResources->setColumns({tr("Register(s)"), tr("Type"), tr("Resource")});
ui->accessedResources->setColumns({tr("Location"), tr("Type"), tr("Info")});
ui->accessedResources->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
ui->accessedResources->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
ui->accessedResources->header()->setSectionResizeMode(2, QHeaderView::Interactive);
@@ -1215,24 +1216,41 @@ void ShaderViewer::accessedResources_contextMenu(const QPoint &pos)
if(tree->selectedItem() == NULL)
return;
QMenu contextMenu(this);
const AccessedResourceTag &tag = tree->selectedItem()->tag().value<AccessedResourceTag>();
if(tag.type == VarType::Unknown)
{
// Right clicked on an instruction row
QMenu contextMenu(this);
QAction prevAccess(tr("Run To Previous Access"), this);
QAction nextAccess(tr("Run To Next Access"), this);
QAction gotoInstr(tr("Go to Step"), this);
contextMenu.addAction(&prevAccess);
contextMenu.addAction(&nextAccess);
contextMenu.addAction(&gotoInstr);
QObject::connect(&prevAccess, &QAction::triggered, [this, tree] {
const AccessedResourceTag &tag = tree->selectedItem()->tag().value<AccessedResourceTag>();
runToResourceAccess(false, tag.type, tag.bind);
});
QObject::connect(&nextAccess, &QAction::triggered, [this, tree] {
const AccessedResourceTag &tag = tree->selectedItem()->tag().value<AccessedResourceTag>();
runToResourceAccess(true, tag.type, tag.bind);
});
QObject::connect(&gotoInstr, &QAction::triggered, [this, tag] {
bool forward = (tag.step >= m_CurrentStateIdx);
runTo({tag.step}, forward);
});
RDDialog::show(&contextMenu, w->viewport()->mapToGlobal(pos));
RDDialog::show(&contextMenu, w->viewport()->mapToGlobal(pos));
}
else
{
// Right clicked on a resource row
QMenu contextMenu(this);
QAction prevAccess(tr("Run to Previous Access"), this);
QAction nextAccess(tr("Run to Next Access"), this);
contextMenu.addAction(&prevAccess);
contextMenu.addAction(&nextAccess);
QObject::connect(&prevAccess, &QAction::triggered,
[this, tag] { runToResourceAccess(false, tag.type, tag.bind); });
QObject::connect(&nextAccess, &QAction::triggered,
[this, tag] { runToResourceAccess(true, tag.type, tag.bind); });
RDDialog::show(&contextMenu, w->viewport()->mapToGlobal(pos));
}
}
void ShaderViewer::disassembly_buttonReleased(QMouseEvent *event)
@@ -1716,15 +1734,6 @@ void ShaderViewer::applyBackwardsChange()
break;
}
}
for(size_t i = 0; i < m_AccessedResources.size(); i++)
{
if(c.after.name == m_AccessedResources[i].name)
{
m_AccessedResources.erase(i);
break;
}
}
}
else
{
@@ -1758,7 +1767,7 @@ void ShaderViewer::applyForwardsChange()
m_CurrentStateIdx++;
rdcarray<ShaderVariable> newVariables;
rdcarray<ShaderVariable> newAccessedResources;
rdcarray<AccessedResourceData> newAccessedResources;
for(const ShaderVariableChange &c : GetCurrentState().changes)
{
@@ -1797,15 +1806,17 @@ void ShaderViewer::applyForwardsChange()
bool found = false;
for(size_t i = 0; i < m_AccessedResources.size(); i++)
{
if(c.after.GetBinding() == m_AccessedResources[i].GetBinding())
if(c.after.GetBinding() == m_AccessedResources[i].resource.GetBinding())
{
found = true;
if(m_AccessedResources[i].steps.indexOf(m_CurrentStateIdx) < 0)
m_AccessedResources[i].steps.push_back(m_CurrentStateIdx);
break;
}
}
if(!found)
newAccessedResources.push_back(c.after);
newAccessedResources.push_back({c.after, {m_CurrentStateIdx}});
}
}
}
@@ -2245,6 +2256,141 @@ void ShaderViewer::highlightMatchingVars(RDTreeWidgetItem *root, const QString v
}
}
void ShaderViewer::updateAccessedResources()
{
RDTreeViewExpansionState expansion;
ui->accessedResources->saveExpansion(expansion, 0);
ui->accessedResources->beginUpdate();
ui->accessedResources->clear();
switch(m_AccessedResourceView)
{
case AccessedResourceView::SortByResource:
{
for(size_t i = 0; i < m_AccessedResources.size(); ++i)
{
// Check if the resource was accessed prior to this step
bool accessed = false;
for(size_t j = 0; j < m_AccessedResources[i].steps.size(); ++j)
{
if(m_AccessedResources[i].steps[j] <= m_CurrentStateIdx)
{
accessed = true;
break;
}
}
if(!accessed)
continue;
bool modified = false;
for(const ShaderVariableChange &c : GetCurrentState().changes)
{
if(c.before.name == m_AccessedResources[i].resource.name ||
c.after.name == m_AccessedResources[i].resource.name)
{
modified = true;
break;
}
}
RDTreeWidgetItem *resourceNode =
makeAccessedResourceNode(m_AccessedResources[i].resource, modified);
if(resourceNode)
{
// Add a child for each step that it was accessed
for(size_t j = 0; j < m_AccessedResources[i].steps.size(); ++j)
{
accessed = m_AccessedResources[i].steps[j] <= m_CurrentStateIdx;
if(accessed)
{
RDTreeWidgetItem *stepNode = new RDTreeWidgetItem(
{tr("Step %1").arg(m_AccessedResources[i].steps[j]), lit("Access"), lit("")});
stepNode->setTag(QVariant::fromValue(
AccessedResourceTag((uint32_t)m_AccessedResources[i].steps[j])));
if(m_CurrentStateIdx == m_AccessedResources[i].steps[j])
stepNode->setForegroundColor(QColor(Qt::red));
resourceNode->addChild(stepNode);
}
}
ui->accessedResources->addTopLevelItem(resourceNode);
}
}
break;
}
case AccessedResourceView::SortByStep:
{
rdcarray<rdcpair<size_t, RDTreeWidgetItem *>> stepNodes;
for(size_t i = 0; i < m_AccessedResources.size(); ++i)
{
bool modified = false;
for(const ShaderVariableChange &c : GetCurrentState().changes)
{
if(c.before.name == m_AccessedResources[i].resource.name ||
c.after.name == m_AccessedResources[i].resource.name)
{
modified = true;
break;
}
}
// Add a root node for each instruction, and place the resource node as a child
for(size_t j = 0; j < m_AccessedResources[i].steps.size(); ++j)
{
bool accessed = m_AccessedResources[i].steps[j] <= m_CurrentStateIdx;
if(accessed)
{
int32_t nodeIdx = -1;
for(int32_t k = 0; k < stepNodes.count(); ++k)
{
if(stepNodes[k].first == m_AccessedResources[i].steps[j])
{
nodeIdx = k;
break;
}
}
RDTreeWidgetItem *resourceNode =
makeAccessedResourceNode(m_AccessedResources[i].resource, modified);
if(nodeIdx == -1)
{
RDTreeWidgetItem *stepNode = new RDTreeWidgetItem(
{tr("Step %1").arg(m_AccessedResources[i].steps[j]), lit("Access"), lit("")});
stepNode->setTag(QVariant::fromValue(
AccessedResourceTag((uint32_t)m_AccessedResources[i].steps[j])));
if(m_CurrentStateIdx == m_AccessedResources[i].steps[j])
stepNode->setForegroundColor(QColor(Qt::red));
stepNode->addChild(resourceNode);
stepNodes.push_back({m_AccessedResources[i].steps[j], stepNode});
}
else
{
stepNodes[nodeIdx].second->addChild(resourceNode);
}
}
}
}
std::sort(stepNodes.begin(), stepNodes.end(),
[](const rdcpair<size_t, RDTreeWidgetItem *> &a,
const rdcpair<size_t, RDTreeWidgetItem *> &b) { return a.first < b.first; });
for(size_t i = 0; i < stepNodes.size(); ++i)
ui->accessedResources->addTopLevelItem(stepNodes[i].second);
break;
}
}
ui->accessedResources->endUpdate();
ui->accessedResources->applyExpansion(expansion, 0);
}
void ShaderViewer::updateDebugState()
{
if(!m_Trace || m_States.empty())
@@ -2758,30 +2904,7 @@ void ShaderViewer::updateDebugState()
ui->debugVars->applyExpansion(expansion, 0);
}
{
ui->accessedResources->beginUpdate();
ui->accessedResources->clear();
for(int i = 0; i < m_AccessedResources.count(); i++)
{
bool modified = false;
for(const ShaderVariableChange &c : GetCurrentState().changes)
{
if(c.before.name == m_AccessedResources[i].name || c.after.name == m_AccessedResources[i].name)
{
modified = true;
break;
}
}
ui->accessedResources->addTopLevelItem(
makeAccessedResourceNode(m_AccessedResources[i], modified));
}
ui->accessedResources->endUpdate();
}
updateAccessedResources();
updateWatchVariables();
@@ -4565,6 +4688,22 @@ void ShaderViewer::on_debugToggle_clicked()
updateDebugState();
}
void ShaderViewer::on_resources_sortByStep_clicked()
{
m_AccessedResourceView = AccessedResourceView::SortByStep;
ui->resources_sortByStep->setChecked(true);
ui->resources_sortByResource->setChecked(false);
updateAccessedResources();
}
void ShaderViewer::on_resources_sortByResource_clicked()
{
m_AccessedResourceView = AccessedResourceView::SortByResource;
ui->resources_sortByResource->setChecked(true);
ui->resources_sortByStep->setChecked(false);
updateAccessedResources();
}
ScintillaEdit *ShaderViewer::currentScintilla()
{
ScintillaEdit *cur = qobject_cast<ScintillaEdit *>(QApplication::focusWidget());
+20 -1
View File
@@ -56,6 +56,18 @@ enum class VariableCategory
ByString,
};
enum class AccessedResourceView
{
SortByStep,
SortByResource,
};
struct AccessedResourceData
{
ShaderVariable resource;
rdcarray<size_t> steps;
};
class ShaderViewer : public QFrame, public IShaderViewer, public ICaptureViewer
{
Q_OBJECT
@@ -117,6 +129,9 @@ private slots:
void on_floatView_clicked();
void on_debugToggle_clicked();
void on_resources_sortByStep_clicked();
void on_resources_sortByResource_clicked();
void on_watch_itemChanged(QTableWidgetItem *item);
// manual slots
@@ -238,7 +253,10 @@ private:
rdcarray<ShaderDebugState> m_States;
size_t m_CurrentStateIdx = 0;
rdcarray<ShaderVariable> m_Variables;
rdcarray<ShaderVariable> m_AccessedResources;
rdcarray<AccessedResourceData> m_AccessedResources;
AccessedResourceView m_AccessedResourceView = AccessedResourceView::SortByResource;
rdcarray<BoundResourceArray> m_ReadOnlyResources;
rdcarray<BoundResourceArray> m_ReadWriteResources;
QList<int> m_Breakpoints;
@@ -278,6 +296,7 @@ private:
void updateDebugState();
void updateWatchVariables();
void updateAccessedResources();
RDTreeWidgetItem *makeSourceVariableNode(const ShaderVariable &var, const rdcstr &sourcePath,
const rdcstr &debugVarPath, bool modified);
+81
View File
@@ -165,6 +165,87 @@
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="sortGroup">
<property name="contextMenuPolicy">
<enum>Qt::PreventContextMenu</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<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="QToolButton" name="resources_sortByResource">
<property name="text">
<string>Sort By Resource</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Sort accessed resource by shader binding</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="resources_sortByStep">
<property name="text">
<string>Sort By Instruction</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Sort accessed resource by instruction step</string>
</property>
</widget>
</item>
<item>
<spacer name="resources_horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="RDTreeWidget" name="debugVars">