mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-23 23:16:31 +00:00
Extend info in accessed resources panel in the shader viewer
This commit is contained in:
committed by
Baldur Karlsson
parent
8638dddb84
commit
ef58d7e1f8
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user