mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Combine together structs/arrays in HLSL locals panel
This commit is contained in:
@@ -79,13 +79,12 @@ public:
|
||||
return createIndex(row, column, par->m_children[row]);
|
||||
}
|
||||
|
||||
void beginAddChild(RDTreeWidgetItem *item)
|
||||
void beginInsertChild(RDTreeWidgetItem *item, int index)
|
||||
{
|
||||
QModelIndex index = indexForItem(item, 0);
|
||||
beginInsertRows(index, item->childCount(), item->childCount());
|
||||
beginInsertRows(indexForItem(item, 0), index, index);
|
||||
}
|
||||
|
||||
void endAddChild(RDTreeWidgetItem *item) { endInsertRows(); }
|
||||
void endInsertChild(RDTreeWidgetItem *item) { endInsertRows(); }
|
||||
void beginRemoveChildren(RDTreeWidgetItem *parent, int first, int last)
|
||||
{
|
||||
beginRemoveRows(indexForItem(parent, 0), first, last);
|
||||
@@ -420,6 +419,11 @@ void RDTreeWidgetItem::setData(int column, int role, const QVariant &value)
|
||||
}
|
||||
|
||||
void RDTreeWidgetItem::addChild(RDTreeWidgetItem *item)
|
||||
{
|
||||
insertChild(m_children.count(), item);
|
||||
}
|
||||
|
||||
void RDTreeWidgetItem::insertChild(int index, RDTreeWidgetItem *item)
|
||||
{
|
||||
int colCount = item->m_text.count();
|
||||
|
||||
@@ -445,13 +449,13 @@ void RDTreeWidgetItem::addChild(RDTreeWidgetItem *item)
|
||||
item->m_data->resize(qMax(item->m_data->count(), colCount));
|
||||
|
||||
if(m_widget)
|
||||
m_widget->beginAddChild(this);
|
||||
m_widget->beginInsertChild(this, index);
|
||||
|
||||
// add to our list of children
|
||||
m_children.push_back(item);
|
||||
m_children.insert(index, item);
|
||||
|
||||
if(m_widget)
|
||||
m_widget->endAddChild(this);
|
||||
m_widget->endInsertChild(this, index);
|
||||
}
|
||||
|
||||
void RDTreeWidgetItem::setWidget(RDTreeWidget *widget)
|
||||
@@ -783,8 +787,8 @@ void RDTreeWidget::endUpdate()
|
||||
|
||||
if(m_queuedChildren)
|
||||
{
|
||||
m_model->beginAddChild(m_queuedItem);
|
||||
m_model->endAddChild(m_queuedItem);
|
||||
m_model->beginInsertChild(m_queuedItem, m_queuedItem->childCount());
|
||||
m_model->endInsertChild(m_queuedItem);
|
||||
}
|
||||
|
||||
if(!roles.isEmpty())
|
||||
@@ -1179,7 +1183,7 @@ void RDTreeWidget::itemDataChanged(RDTreeWidgetItem *item, int column, int role)
|
||||
emit itemChanged(item, column);
|
||||
}
|
||||
|
||||
void RDTreeWidget::beginAddChild(RDTreeWidgetItem *item)
|
||||
void RDTreeWidget::beginInsertChild(RDTreeWidgetItem *item, int index)
|
||||
{
|
||||
if(m_queueUpdates)
|
||||
{
|
||||
@@ -1190,8 +1194,7 @@ void RDTreeWidget::beginAddChild(RDTreeWidgetItem *item)
|
||||
m_queuedItem = item;
|
||||
// make an update of row 0. This will be a bit pessimistic if there are later data changes
|
||||
// in a later row, but we're generally only changing data *or* adding children, not both,
|
||||
// and
|
||||
// in either case this is primarily about batching updates not providing a minimal update
|
||||
// and in either case this is primarily about batching updates not providing a minimal update
|
||||
// set
|
||||
m_lowestIndex = qMakePair<int, int>(0, 0);
|
||||
m_highestIndex = qMakePair<int, int>(0, m_headers.count() - 1);
|
||||
@@ -1211,13 +1214,13 @@ void RDTreeWidget::beginAddChild(RDTreeWidgetItem *item)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model->beginAddChild(item);
|
||||
m_model->beginInsertChild(item, index);
|
||||
}
|
||||
}
|
||||
|
||||
void RDTreeWidget::endAddChild(RDTreeWidgetItem *item)
|
||||
void RDTreeWidget::endInsertChild(RDTreeWidgetItem *item, int index)
|
||||
{
|
||||
// work is all done in beginAddChild
|
||||
// work is all done in beginInsertChild
|
||||
if(!m_queueUpdates)
|
||||
m_model->endAddChild(item);
|
||||
m_model->endInsertChild(item);
|
||||
}
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
void setData(int column, int role, const QVariant &value);
|
||||
|
||||
void addChild(RDTreeWidgetItem *item);
|
||||
void insertChild(int index, RDTreeWidgetItem *child);
|
||||
|
||||
// the data above requires allocating a bunch of vectors since it's stored per-column. Where
|
||||
// possible, just use this single per-item tag
|
||||
@@ -63,6 +64,7 @@ public:
|
||||
RDTreeWidgetItem *takeChild(int index);
|
||||
void removeChild(RDTreeWidgetItem *child);
|
||||
void clear();
|
||||
inline int dataCount() const { return m_text.count(); }
|
||||
inline int childCount() const { return m_children.count(); }
|
||||
inline RDTreeWidgetItem *parent() const { return m_parent; }
|
||||
inline RDTreeWidget *treeWidget() const { return m_widget; }
|
||||
@@ -295,8 +297,8 @@ private:
|
||||
|
||||
void setModel(QAbstractItemModel *model) override {}
|
||||
void itemDataChanged(RDTreeWidgetItem *item, int column, int role);
|
||||
void beginAddChild(RDTreeWidgetItem *item);
|
||||
void endAddChild(RDTreeWidgetItem *item);
|
||||
void beginInsertChild(RDTreeWidgetItem *item, int index);
|
||||
void endInsertChild(RDTreeWidgetItem *item, int index);
|
||||
|
||||
friend class RDTreeWidgetModel;
|
||||
friend class RDTreeWidgetItem;
|
||||
|
||||
@@ -1380,6 +1380,114 @@ void ShaderViewer::addFileList()
|
||||
list, ToolWindowManager::HideCloseButton | ToolWindowManager::DisallowFloatWindow);
|
||||
}
|
||||
|
||||
void ShaderViewer::combineStructures(RDTreeWidgetItem *root)
|
||||
{
|
||||
RDTreeWidgetItem temp;
|
||||
|
||||
// we perform a filter moving from root to temp. At each point we check the node:
|
||||
// * if the node has no struct or array prefix, it gets moved
|
||||
// * if the node does have a prefix, we sweep finding all matching elements with the same prefix,
|
||||
// strip the prefix off them and make a combined node, then recurse to combine anything
|
||||
// underneath. We aren't greedy in picking prefixes so this should generate a struct/array tree.
|
||||
// * in the event that a node has no matching elements we move it across as if it had no prefix.
|
||||
// * we iterate from last to first, because when combining elements that may be spread out in the
|
||||
// list of children, we want to combine up to the position of the last item, not the position of
|
||||
// the first.
|
||||
|
||||
for(int c = root->childCount() - 1; c >= 0;)
|
||||
{
|
||||
RDTreeWidgetItem *child = root->takeChild(c);
|
||||
c--;
|
||||
|
||||
QString name = child->text(0);
|
||||
|
||||
int dotIndex = name.indexOf(QLatin1Char('.'));
|
||||
int arrIndex = name.indexOf(QLatin1Char('['));
|
||||
|
||||
// if this node doesn't have any segments, just move it across.
|
||||
if(dotIndex < 0 && arrIndex < 0)
|
||||
{
|
||||
temp.insertChild(0, child);
|
||||
continue;
|
||||
}
|
||||
|
||||
// store the index of the first separator
|
||||
int sepIndex = dotIndex;
|
||||
bool isArray = false;
|
||||
if(sepIndex == -1 || (arrIndex > 0 && arrIndex < sepIndex))
|
||||
{
|
||||
sepIndex = arrIndex;
|
||||
isArray = true;
|
||||
}
|
||||
|
||||
// we have a valid node to match against, record the prefix (including separator character)
|
||||
QString prefix = name.mid(0, sepIndex + 1);
|
||||
|
||||
QVector<RDTreeWidgetItem *> matches = {child};
|
||||
|
||||
// iterate down from the next item
|
||||
for(int n = c; n >= 0; n--)
|
||||
{
|
||||
RDTreeWidgetItem *testNode = root->child(n);
|
||||
|
||||
QString testName = testNode->text(0);
|
||||
|
||||
QString testprefix = testName.mid(0, sepIndex + 1);
|
||||
|
||||
// no match - continue
|
||||
if(testprefix != prefix)
|
||||
continue;
|
||||
|
||||
// match, take this child
|
||||
matches.push_back(root->takeChild(n));
|
||||
|
||||
// also decrement c since we're taking a child ahead of where that loop will go.
|
||||
c--;
|
||||
}
|
||||
|
||||
// no other matches with the same prefix, just move across
|
||||
if(matches.count() == 1)
|
||||
{
|
||||
temp.insertChild(0, child);
|
||||
continue;
|
||||
}
|
||||
|
||||
// sort the children by name
|
||||
std::sort(matches.begin(), matches.end(),
|
||||
[](const RDTreeWidgetItem *a, const RDTreeWidgetItem *b) {
|
||||
return a->text(0) < b->text(0);
|
||||
});
|
||||
|
||||
// create a new parent with just the prefix
|
||||
QVariantList values = {isArray ? name : name.mid(0, sepIndex)};
|
||||
for(int i = 1; i < child->dataCount(); i++)
|
||||
values.push_back(QVariant());
|
||||
RDTreeWidgetItem *parent = new RDTreeWidgetItem(values);
|
||||
|
||||
// add all the children (stripping the prefix from their name)
|
||||
for(RDTreeWidgetItem *item : matches)
|
||||
{
|
||||
if(!isArray)
|
||||
item->setText(0, item->text(0).mid(sepIndex + 1));
|
||||
parent->addChild(item);
|
||||
}
|
||||
|
||||
// recurse and combine members of this object if a struct
|
||||
if(!isArray)
|
||||
combineStructures(parent);
|
||||
|
||||
// now add to the list
|
||||
temp.insertChild(0, parent);
|
||||
}
|
||||
|
||||
if(root->childCount() > 0)
|
||||
qCritical() << "Some objects left on root!";
|
||||
|
||||
// move all the children back from the temp object into the parameter
|
||||
while(temp.childCount() > 0)
|
||||
root->addChild(temp.takeChild(0));
|
||||
}
|
||||
|
||||
void ShaderViewer::updateDebugging()
|
||||
{
|
||||
if(!m_Trace || m_CurrentStep < 0 || m_CurrentStep >= m_Trace->states.count())
|
||||
@@ -1619,6 +1727,8 @@ void ShaderViewer::updateDebugging()
|
||||
|
||||
const QString xyzw = lit("xyzw");
|
||||
|
||||
RDTreeWidgetItem fakeroot;
|
||||
|
||||
for(size_t lidx = 0; lidx < state.locals.size(); lidx++)
|
||||
{
|
||||
// iterate in reverse order, so newest locals tend to end up on top
|
||||
@@ -1646,7 +1756,7 @@ void ShaderViewer::updateDebugging()
|
||||
else
|
||||
{
|
||||
if(l.rows > 1)
|
||||
typeName += QFormatStr("%1x%1").arg(l.rows).arg(l.columns);
|
||||
typeName += QFormatStr("%1x%2").arg(l.rows).arg(l.columns);
|
||||
else
|
||||
typeName += QString::number(l.columns);
|
||||
|
||||
@@ -1733,8 +1843,14 @@ void ShaderViewer::updateDebugging()
|
||||
}
|
||||
}
|
||||
|
||||
ui->locals->addTopLevelItem(node);
|
||||
fakeroot.addChild(node);
|
||||
}
|
||||
|
||||
// recursively combine nodes with the same prefix together
|
||||
combineStructures(&fakeroot);
|
||||
|
||||
while(fakeroot.childCount() > 0)
|
||||
ui->locals->addTopLevelItem(fakeroot.takeChild(0));
|
||||
}
|
||||
|
||||
if(ui->registers->topLevelItemCount() == 0)
|
||||
|
||||
@@ -251,4 +251,5 @@ private:
|
||||
QString stringRep(const ShaderVariable &var, bool useType);
|
||||
RDTreeWidgetItem *makeResourceRegister(const Bindpoint &bind, uint32_t idx,
|
||||
const BoundResource &ro, const ShaderResource &resources);
|
||||
void combineStructures(RDTreeWidgetItem *root);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user