Combine together structs/arrays in HLSL locals panel

This commit is contained in:
baldurk
2018-06-08 18:29:02 +01:00
parent 880f529fda
commit cb0df2c844
4 changed files with 142 additions and 20 deletions
+19 -16
View File
@@ -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);
}
+4 -2
View File
@@ -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;
+118 -2
View File
@@ -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)
+1
View File
@@ -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);
};