mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-18 20:46:31 +00:00
Generate clickable links to resource inspector in RDTreeWidget
This commit is contained in:
@@ -626,7 +626,7 @@ void CaptureContext::AddMessages(const rdcarray<DebugMessage> &msgs)
|
||||
QString CaptureContext::GetResourceName(ResourceId id)
|
||||
{
|
||||
if(id == ResourceId())
|
||||
return tr("{No Resource}");
|
||||
return tr("No Resource");
|
||||
|
||||
if(m_CustomNames.contains(id))
|
||||
return m_CustomNames[id];
|
||||
@@ -672,9 +672,16 @@ void CaptureContext::SetResourceCustomName(ResourceId id, const QString &name)
|
||||
m_CustomNames[id] = name;
|
||||
}
|
||||
|
||||
m_CustomNameCachedID++;
|
||||
|
||||
RefreshUIStatus({}, true, true);
|
||||
}
|
||||
|
||||
int CaptureContext::ResourceNameCacheID()
|
||||
{
|
||||
return m_CustomNameCachedID;
|
||||
}
|
||||
|
||||
void *CaptureContext::FillWindowingData(uintptr_t widget)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
|
||||
@@ -120,6 +120,7 @@ public:
|
||||
bool IsAutogeneratedName(ResourceId id) override;
|
||||
bool HasResourceCustomName(ResourceId id) override;
|
||||
void SetResourceCustomName(ResourceId id, const QString &name) override;
|
||||
int ResourceNameCacheID() override;
|
||||
TextureDescription *GetTexture(ResourceId id) override { return m_Textures[id]; }
|
||||
const rdcarray<TextureDescription> &GetTextures() override { return m_TextureList; }
|
||||
BufferDescription *GetBuffer(ResourceId id) override { return m_Buffers[id]; }
|
||||
@@ -283,6 +284,7 @@ private:
|
||||
rdcarray<ResourceDescription> m_ResourceList;
|
||||
|
||||
QMap<ResourceId, QString> m_CustomNames;
|
||||
int m_CustomNameCachedID = 1;
|
||||
|
||||
const SDFile *m_StructuredFile;
|
||||
SDFile m_DummySDFile;
|
||||
|
||||
@@ -131,3 +131,16 @@ QString ConfigFilePath(const QString &filename)
|
||||
|
||||
return QDir::cleanPath(dir.absoluteFilePath(filename));
|
||||
}
|
||||
|
||||
ICaptureContext *getCaptureContext(QWidget *widget)
|
||||
{
|
||||
void *ctxptr = NULL;
|
||||
|
||||
while(widget && !ctxptr)
|
||||
{
|
||||
ctxptr = widget->property("ICaptureContext").value<void *>();
|
||||
widget = widget->parentWidget();
|
||||
}
|
||||
|
||||
return (ICaptureContext *)ctxptr;
|
||||
}
|
||||
|
||||
@@ -1107,6 +1107,20 @@ name fetched from the capture.
|
||||
)");
|
||||
virtual void SetResourceCustomName(ResourceId id, const QString &name) = 0;
|
||||
|
||||
DOCUMENT(R"(Returns an index that can be used to cache the results of resource naming.
|
||||
|
||||
In some cases (e.g. formatting in widgets) there might be high frequency fetches to names without an
|
||||
easy way to force a refresh on a rename. Instead, the index here can be cached and compared each
|
||||
time to see if any names have changed.
|
||||
|
||||
The index starts at 1, so initialising an internal cache to 0 will cause the first check to be
|
||||
considered out of date
|
||||
|
||||
:return: An incrementing index that can be used as a quick check if any names have changed.
|
||||
:rtype: int
|
||||
)");
|
||||
virtual int ResourceNameCacheID() = 0;
|
||||
|
||||
DOCUMENT(R"(Retrieve the information about a particular texture.
|
||||
|
||||
:param ~renderdoc.ResourceId id: The ID of the texture to query about.
|
||||
@@ -1594,3 +1608,17 @@ protected:
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(ICaptureContext);
|
||||
|
||||
DOCUMENT(R"(Attempt to retrieve the capture context for a particular widget.
|
||||
|
||||
This will search up the widget heirarchy to find if a capture context is associated with this widget
|
||||
or any of its parents. Mostly useful from within widget code where a capture context can't be
|
||||
explicitly passed in.
|
||||
|
||||
This may return ``None`` if no capture context can be found.
|
||||
|
||||
:param QWidget widget: The widget to search from.
|
||||
:return: The capture context associated with this widget, if one unambiguously exists.
|
||||
:rtype: CaptureContext
|
||||
)");
|
||||
ICaptureContext *getCaptureContext(QWidget *widget);
|
||||
@@ -55,7 +55,9 @@ std::string DoStringise(const uint32_t &el)
|
||||
template <>
|
||||
std::string DoStringise(const ResourceId &el)
|
||||
{
|
||||
return QString::number((const uint64_t &)el).toStdString();
|
||||
uint64_t num;
|
||||
memcpy(&num, &el, sizeof(num));
|
||||
return lit("resourceid::%1").arg(num).toStdString();
|
||||
}
|
||||
|
||||
#include "renderdoc_tostr.inl"
|
||||
@@ -359,8 +361,8 @@ void CombineUsageEvents(ICaptureContext &ctx, const rdcarray<EventUsage> &usage,
|
||||
callback(start, end, us);
|
||||
}
|
||||
|
||||
void addStructuredObjects(ICaptureContext &ctx, RDTreeWidgetItem *parent,
|
||||
const StructuredObjectList &objs, bool parentIsArray)
|
||||
void addStructuredObjects(RDTreeWidgetItem *parent, const StructuredObjectList &objs,
|
||||
bool parentIsArray)
|
||||
{
|
||||
for(const SDObject *obj : objs)
|
||||
{
|
||||
@@ -388,7 +390,7 @@ void addStructuredObjects(ICaptureContext &ctx, RDTreeWidgetItem *parent,
|
||||
static_assert(sizeof(id) == sizeof(obj->data.basic.u), "ResourceId is no longer uint64_t!");
|
||||
memcpy(&id, &obj->data.basic.u, sizeof(id));
|
||||
|
||||
param = ctx.GetResourceName(id);
|
||||
param = id;
|
||||
}
|
||||
else if(obj->type.flags & SDTypeFlags::NullString)
|
||||
{
|
||||
@@ -405,11 +407,11 @@ void addStructuredObjects(ICaptureContext &ctx, RDTreeWidgetItem *parent,
|
||||
case SDBasic::Chunk:
|
||||
case SDBasic::Struct:
|
||||
param = QFormatStr("%1()").arg(obj->type.name);
|
||||
addStructuredObjects(ctx, item, obj->data.children, false);
|
||||
addStructuredObjects(item, obj->data.children, false);
|
||||
break;
|
||||
case SDBasic::Array:
|
||||
param = QFormatStr("%1[]").arg(obj->type.name);
|
||||
addStructuredObjects(ctx, item, obj->data.children, true);
|
||||
addStructuredObjects(item, obj->data.children, true);
|
||||
break;
|
||||
case SDBasic::Null: param = lit("NULL"); break;
|
||||
case SDBasic::Buffer: param = lit("(%1 bytes)").arg(obj->type.byteSize); break;
|
||||
|
||||
@@ -104,8 +104,8 @@ void CombineUsageEvents(
|
||||
|
||||
class RDTreeWidgetItem;
|
||||
|
||||
void addStructuredObjects(ICaptureContext &ctx, RDTreeWidgetItem *parent,
|
||||
const StructuredObjectList &objs, bool parentIsArray);
|
||||
void addStructuredObjects(RDTreeWidgetItem *parent, const StructuredObjectList &objs,
|
||||
bool parentIsArray);
|
||||
|
||||
struct Formatter
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "RDTreeWidget.h"
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QColor>
|
||||
@@ -32,8 +33,115 @@
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <QStack>
|
||||
#include <QTextBlock>
|
||||
#include <QTextCursor>
|
||||
#include <QTextDocument>
|
||||
#include <QToolTip>
|
||||
#include "Code/Interface/QRDInterface.h"
|
||||
#include "Code/Resources.h"
|
||||
|
||||
// this is used often, so cache it
|
||||
QRegularExpression &ResourceIdRegexp()
|
||||
{
|
||||
static QRegularExpression re(lit("(resourceid::)([0-9]*)"));
|
||||
return re;
|
||||
}
|
||||
|
||||
struct ResourceIdLinkedText
|
||||
{
|
||||
QVector<QVariant> fragments;
|
||||
|
||||
// cached formatted document. We use cacheId to check if it needs to be updated
|
||||
QTextDocument doc;
|
||||
int cacheId = 0;
|
||||
|
||||
// a plain-text version of the document, suitable for e.g. copy-paste
|
||||
QString text;
|
||||
|
||||
void cacheDocument(QWidget *widget)
|
||||
{
|
||||
ICaptureContext *ctxptr = getCaptureContext(widget);
|
||||
|
||||
if(!ctxptr)
|
||||
return;
|
||||
|
||||
ICaptureContext &ctx = *(ICaptureContext *)ctxptr;
|
||||
|
||||
int refCache = ctx.ResourceNameCacheID();
|
||||
|
||||
if(cacheId == refCache)
|
||||
return;
|
||||
|
||||
cacheId = refCache;
|
||||
|
||||
// use a table to ensure images don't screw up the baseline for text. DON'T JUDGE ME.
|
||||
QString html = lit("<table><tr>");
|
||||
|
||||
int i = 0;
|
||||
|
||||
QVector<int> fragmentIndexFromBlockIndex;
|
||||
|
||||
// there's an empty block at the start.
|
||||
fragmentIndexFromBlockIndex.push_back(-1);
|
||||
|
||||
for(const QVariant &v : fragments)
|
||||
{
|
||||
if(v.userType() == qMetaTypeId<ResourceId>())
|
||||
{
|
||||
html += lit("<td><b>%1</b></td><td><img src=':/link.png'></td>")
|
||||
.arg(ctx.GetResourceName(v.value<ResourceId>()));
|
||||
|
||||
// these generate two blocks (one for each cell)
|
||||
fragmentIndexFromBlockIndex.push_back(i);
|
||||
fragmentIndexFromBlockIndex.push_back(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
html += lit("<td>%1</td>").arg(v.toString());
|
||||
|
||||
// this only generates one block
|
||||
fragmentIndexFromBlockIndex.push_back(i);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// there's another empty block at the end
|
||||
fragmentIndexFromBlockIndex.push_back(-1);
|
||||
|
||||
html += lit("</tr></table>");
|
||||
|
||||
doc.setDocumentMargin(0);
|
||||
doc.setHtml(html);
|
||||
|
||||
if(doc.blockCount() != fragmentIndexFromBlockIndex.count())
|
||||
{
|
||||
qCritical() << "Block count is not what's expected!" << doc.blockCount()
|
||||
<< fragmentIndexFromBlockIndex.count();
|
||||
|
||||
for(i = 0; i < doc.blockCount(); i++)
|
||||
doc.findBlockByNumber(i).setUserState(-1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < doc.blockCount(); i++)
|
||||
doc.findBlockByNumber(i).setUserState(fragmentIndexFromBlockIndex[i]);
|
||||
|
||||
text = doc.toPlainText();
|
||||
// "Embedded objects, such as images, are represented by a Unicode value U+FFFC (OBJECT
|
||||
// REPLACEMENT CHARACTER)."
|
||||
text.remove(QChar(0xfffc));
|
||||
text = text.trimmed();
|
||||
}
|
||||
};
|
||||
|
||||
// using QSharedPointer here since the lifetime management of these objects would get quite
|
||||
// complicated, and there is no obvious QObject parent to assign to. The alternative would be to
|
||||
// have the RDTreeWidgetItem track pointers in and out of the QVariant text
|
||||
typedef QSharedPointer<ResourceIdLinkedText> ResourceIdLinkedTextPtr;
|
||||
|
||||
Q_DECLARE_METATYPE(ResourceIdLinkedTextPtr);
|
||||
|
||||
class RDTreeWidgetModel : public QAbstractItemModel
|
||||
{
|
||||
@@ -165,13 +273,12 @@ public:
|
||||
RDTreeWidgetItem *item = itemForIndex(index);
|
||||
|
||||
// invisible root element has no data
|
||||
if(!item->m_parent)
|
||||
if(!item->m_parent || index.column() >= item->m_text.count())
|
||||
return QVariant();
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
if(index.column() < item->m_text.count())
|
||||
return item->m_text[index.column()];
|
||||
return item->m_text[index.column()];
|
||||
}
|
||||
else if(role == Qt::DecorationRole)
|
||||
{
|
||||
@@ -183,8 +290,7 @@ public:
|
||||
return widget->m_normalHoverIcon;
|
||||
}
|
||||
|
||||
if(index.column() < item->m_icons.count())
|
||||
return item->m_icons[index.column()];
|
||||
return item->m_icons[index.column()];
|
||||
}
|
||||
else if(role == Qt::BackgroundRole)
|
||||
{
|
||||
@@ -311,12 +417,63 @@ RDTreeWidgetItem::RDTreeWidgetItem(const QVariantList &values)
|
||||
for(const QVariant &v : values)
|
||||
m_text.push_back(v);
|
||||
m_icons.resize(m_text.size());
|
||||
|
||||
for(int i = 0; i < m_text.count(); i++)
|
||||
checkForResourceId(i);
|
||||
}
|
||||
|
||||
RDTreeWidgetItem::RDTreeWidgetItem(const std::initializer_list<QVariant> &values)
|
||||
{
|
||||
m_text = values;
|
||||
m_icons.resize(m_text.size());
|
||||
|
||||
for(int i = 0; i < m_text.count(); i++)
|
||||
checkForResourceId(i);
|
||||
}
|
||||
|
||||
void RDTreeWidgetItem::checkForResourceId(int col)
|
||||
{
|
||||
QRegularExpression &re = ResourceIdRegexp();
|
||||
|
||||
QVariant &v = m_text[col];
|
||||
|
||||
if(v.userType() == qMetaTypeId<ResourceId>() || re.match(v.toString()).hasMatch())
|
||||
{
|
||||
QString text;
|
||||
if(v.userType() == qMetaTypeId<ResourceId>())
|
||||
text = ToQStr(v.value<ResourceId>());
|
||||
else
|
||||
text = v.toString();
|
||||
|
||||
ResourceIdLinkedTextPtr linkedText(new ResourceIdLinkedText);
|
||||
|
||||
// use regexp to split up into fragments of text and resourceid. The resourceid is then
|
||||
// formatted on the fly in ResourceIdLinkedText::cacheDocument
|
||||
QRegularExpressionMatch match = re.match(text);
|
||||
while(match.hasMatch())
|
||||
{
|
||||
qulonglong idnum = match.captured(2).toULongLong();
|
||||
ResourceId id;
|
||||
memcpy(&id, &idnum, sizeof(id));
|
||||
|
||||
// push any text that preceeded the ResourceId.
|
||||
if(match.capturedStart(1) > 0)
|
||||
linkedText->fragments.push_back(text.left(match.capturedStart(1)));
|
||||
|
||||
text.remove(0, match.capturedEnd(2));
|
||||
|
||||
linkedText->fragments.push_back(id);
|
||||
|
||||
match = re.match(text);
|
||||
}
|
||||
|
||||
if(!text.isEmpty())
|
||||
linkedText->fragments.push_back(text);
|
||||
|
||||
linkedText->doc.setHtml(text);
|
||||
|
||||
v = QVariant::fromValue(linkedText);
|
||||
}
|
||||
}
|
||||
|
||||
RDTreeWidgetItem::~RDTreeWidgetItem()
|
||||
@@ -424,6 +581,10 @@ void RDTreeWidgetItem::setWidget(RDTreeWidget *widget)
|
||||
if(widget == m_widget)
|
||||
return;
|
||||
|
||||
QWidget *parent = widget;
|
||||
while(parent)
|
||||
parent = parent->parentWidget();
|
||||
|
||||
// if the widget is different, we need to recurse to children
|
||||
m_widget = widget;
|
||||
for(RDTreeWidgetItem *item : m_children)
|
||||
@@ -525,11 +686,236 @@ RDTreeWidgetItemIterator &RDTreeWidgetItemIterator::operator++()
|
||||
return *this;
|
||||
}
|
||||
|
||||
RDTreeWidgetDelegate::RDTreeWidgetDelegate(RDTreeWidget *parent)
|
||||
: m_widget(parent), ForwardingDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
RDTreeWidgetDelegate::~RDTreeWidgetDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void RDTreeWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
RDTreeWidgetModel *model = m_widget->m_model;
|
||||
if(model == index.model())
|
||||
{
|
||||
RDTreeWidgetItem *item = model->itemForIndex(index);
|
||||
|
||||
if(item->m_text[index.column()].userType() == qMetaTypeId<ResourceIdLinkedTextPtr>())
|
||||
{
|
||||
{
|
||||
// draw the item without text, so we get the proper background/selection/etc.
|
||||
QStyleOptionViewItem opt = option;
|
||||
opt.text.clear();
|
||||
|
||||
ForwardingDelegate::paint(painter, opt, index);
|
||||
}
|
||||
|
||||
ResourceIdLinkedTextPtr linkedText =
|
||||
item->m_text[index.column()].value<ResourceIdLinkedTextPtr>();
|
||||
|
||||
painter->save();
|
||||
|
||||
painter->translate(option.rect.left(), option.rect.top());
|
||||
|
||||
linkedText->cacheDocument(m_widget);
|
||||
linkedText->doc.setTextWidth(option.rect.width());
|
||||
linkedText->doc.drawContents(painter);
|
||||
|
||||
if(option.state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->setPen(QPen(option.palette.brush(QPalette::WindowText), 1.0));
|
||||
|
||||
QAbstractTextDocumentLayout *layout = linkedText->doc.documentLayout();
|
||||
|
||||
QPoint p = m_widget->viewport()->mapFromGlobal(QCursor::pos());
|
||||
p -= option.rect.topLeft();
|
||||
|
||||
int pos = layout->hitTest(p, Qt::FuzzyHit);
|
||||
|
||||
if(pos >= 0)
|
||||
{
|
||||
QTextBlock block = linkedText->doc.findBlock(pos);
|
||||
|
||||
int frag = block.userState();
|
||||
if(frag >= 0)
|
||||
{
|
||||
QVariant v = linkedText->fragments[frag];
|
||||
if(v.userType() == qMetaTypeId<ResourceId>() && v.value<ResourceId>() != ResourceId())
|
||||
{
|
||||
layout->blockBoundingRect(block);
|
||||
QRectF rect = layout->blockBoundingRect(block);
|
||||
|
||||
if(block.previous().userState() == frag)
|
||||
{
|
||||
rect = rect.united(layout->blockBoundingRect(block.previous()));
|
||||
}
|
||||
|
||||
if(block.next().userState() == frag)
|
||||
{
|
||||
rect = rect.united(layout->blockBoundingRect(block.next()));
|
||||
}
|
||||
|
||||
rect.translate(0.0, -2.0);
|
||||
|
||||
painter->drawLine(rect.bottomLeft(), rect.bottomRight());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Unexpected model being passed to RDTreeWidgetDelegate!";
|
||||
}
|
||||
|
||||
return ForwardingDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize RDTreeWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if(index.isValid())
|
||||
{
|
||||
RDTreeWidgetModel *model = m_widget->m_model;
|
||||
if(model == index.model())
|
||||
{
|
||||
RDTreeWidgetItem *item = model->itemForIndex(index);
|
||||
|
||||
if(item->m_text[index.column()].userType() == qMetaTypeId<ResourceIdLinkedTextPtr>())
|
||||
{
|
||||
ResourceIdLinkedTextPtr linkedText =
|
||||
item->m_text[index.column()].value<ResourceIdLinkedTextPtr>();
|
||||
|
||||
linkedText->cacheDocument(m_widget);
|
||||
return QSize(linkedText->doc.idealWidth(), option.fontMetrics.height());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Unexpected model being passed to RDTreeWidgetDelegate!";
|
||||
}
|
||||
}
|
||||
|
||||
return ForwardingDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
bool RDTreeWidgetDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index)
|
||||
{
|
||||
if(event->type() == QEvent::MouseButtonRelease && index.isValid())
|
||||
{
|
||||
RDTreeWidgetModel *rdmodel = m_widget->m_model;
|
||||
if(rdmodel == model)
|
||||
{
|
||||
RDTreeWidgetItem *item = rdmodel->itemForIndex(index);
|
||||
|
||||
if(item->m_text[index.column()].userType() == qMetaTypeId<ResourceIdLinkedTextPtr>())
|
||||
{
|
||||
ResourceIdLinkedTextPtr linkedText =
|
||||
item->m_text[index.column()].value<ResourceIdLinkedTextPtr>();
|
||||
|
||||
linkedText->cacheDocument(m_widget);
|
||||
|
||||
QAbstractTextDocumentLayout *layout = linkedText->doc.documentLayout();
|
||||
|
||||
QPoint p = ((QMouseEvent *)event)->pos();
|
||||
p -= option.rect.topLeft();
|
||||
|
||||
int pos = layout->hitTest(p, Qt::FuzzyHit);
|
||||
|
||||
if(pos >= 0)
|
||||
{
|
||||
QTextBlock block = linkedText->doc.findBlock(pos);
|
||||
|
||||
int frag = block.userState();
|
||||
if(frag >= 0)
|
||||
{
|
||||
QVariant v = linkedText->fragments[frag];
|
||||
if(v.userType() == qMetaTypeId<ResourceId>() && v.value<ResourceId>() != ResourceId())
|
||||
{
|
||||
ICaptureContext *ctxptr = getCaptureContext(m_widget);
|
||||
|
||||
if(ctxptr)
|
||||
{
|
||||
ICaptureContext &ctx = *(ICaptureContext *)ctxptr;
|
||||
|
||||
if(!ctx.HasResourceInspector())
|
||||
ctx.ShowResourceInspector();
|
||||
|
||||
ctx.GetResourceInspector()->Inspect(v.value<ResourceId>());
|
||||
|
||||
ctx.RaiseDockWindow(ctx.GetResourceInspector()->Widget());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Unexpected model being passed to RDTreeWidgetDelegate!";
|
||||
}
|
||||
}
|
||||
|
||||
return ForwardingDelegate::editorEvent(event, model, option, index);
|
||||
}
|
||||
|
||||
bool RDTreeWidgetDelegate::linkHover(QMouseEvent *e, const QModelIndex &index)
|
||||
{
|
||||
if(index.isValid())
|
||||
{
|
||||
RDTreeWidgetItem *item = m_widget->m_model->itemForIndex(index);
|
||||
|
||||
if(item->m_text[index.column()].userType() == qMetaTypeId<ResourceIdLinkedTextPtr>())
|
||||
{
|
||||
ResourceIdLinkedTextPtr linkedText =
|
||||
item->m_text[index.column()].value<ResourceIdLinkedTextPtr>();
|
||||
|
||||
linkedText->cacheDocument(m_widget);
|
||||
|
||||
QAbstractTextDocumentLayout *layout = linkedText->doc.documentLayout();
|
||||
|
||||
QPoint p = e->pos();
|
||||
p -= m_widget->visualRect(index).topLeft();
|
||||
|
||||
int pos = layout->hitTest(p, Qt::FuzzyHit);
|
||||
|
||||
if(pos >= 0)
|
||||
{
|
||||
QTextBlock block = linkedText->doc.findBlock(pos);
|
||||
|
||||
int frag = block.userState();
|
||||
if(frag >= 0)
|
||||
{
|
||||
QVariant v = linkedText->fragments[frag];
|
||||
if(v.userType() == qMetaTypeId<ResourceId>() && v.value<ResourceId>() != ResourceId())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RDTreeWidget::RDTreeWidget(QWidget *parent) : RDTreeView(parent)
|
||||
{
|
||||
// we'll call this ourselves in drawBranches()
|
||||
RDTreeView::enableBranchRectFill(false);
|
||||
|
||||
m_delegate = new RDTreeWidgetDelegate(this);
|
||||
RDTreeView::setItemDelegate(m_delegate);
|
||||
|
||||
header()->setSectionsMovable(false);
|
||||
|
||||
m_root = new RDTreeWidgetItem;
|
||||
@@ -610,6 +996,17 @@ void RDTreeWidget::setColumnAlignment(int column, Qt::Alignment align)
|
||||
m_alignments[column] = align;
|
||||
}
|
||||
|
||||
void RDTreeWidget::setItemDelegate(QAbstractItemDelegate *delegate)
|
||||
{
|
||||
m_userDelegate = delegate;
|
||||
m_delegate->setForwardDelegate(m_userDelegate);
|
||||
}
|
||||
|
||||
QAbstractItemDelegate *RDTreeWidget::itemDelegate() const
|
||||
{
|
||||
return m_userDelegate;
|
||||
}
|
||||
|
||||
void RDTreeWidget::setColumns(const QStringList &columns)
|
||||
{
|
||||
m_headers = columns;
|
||||
@@ -710,9 +1107,18 @@ void RDTreeWidget::mouseMoveEvent(QMouseEvent *e)
|
||||
RDTreeWidgetItem *newHover = m_model->itemForIndex(m_currentHoverIndex);
|
||||
|
||||
if(m_currentHoverIndex.column() == m_hoverColumn && m_hoverHandCursor)
|
||||
{
|
||||
setCursor(QCursor(Qt::PointingHandCursor));
|
||||
}
|
||||
else if(m_delegate->linkHover(e, m_currentHoverIndex))
|
||||
{
|
||||
m_model->itemChanged(m_model->itemForIndex(m_currentHoverIndex), {Qt::DecorationRole});
|
||||
setCursor(QCursor(Qt::PointingHandCursor));
|
||||
}
|
||||
else
|
||||
{
|
||||
unsetCursor();
|
||||
}
|
||||
|
||||
if(oldHover == newHover)
|
||||
return;
|
||||
@@ -810,7 +1216,17 @@ void RDTreeWidget::keyPressEvent(QKeyEvent *e)
|
||||
RDTreeWidgetItem *item = m_model->itemForIndex(idx);
|
||||
|
||||
for(int i = 0; i < qMin(colCount, item->m_text.count()); i++)
|
||||
widths[i] = qMax(widths[i], item->m_text[i].toString().count());
|
||||
{
|
||||
QString text = item->m_text[i].toString();
|
||||
if(item->m_text[i].userType() == qMetaTypeId<ResourceIdLinkedTextPtr>())
|
||||
{
|
||||
ResourceIdLinkedTextPtr linkedText = item->m_text[i].value<ResourceIdLinkedTextPtr>();
|
||||
linkedText->cacheDocument(this);
|
||||
text = linkedText->text;
|
||||
}
|
||||
|
||||
widths[i] = qMax(widths[i], text.count());
|
||||
}
|
||||
}
|
||||
|
||||
// only align up to 50 characters so one really long item doesn't mess up the whole thing
|
||||
@@ -825,7 +1241,16 @@ void RDTreeWidget::keyPressEvent(QKeyEvent *e)
|
||||
for(int i = 0; i < qMin(colCount, item->m_text.count()); i++)
|
||||
{
|
||||
QString format = i == 0 ? QFormatStr("%1") : QFormatStr(" %1");
|
||||
clipData += format.arg(item->m_text[i].toString(), -widths[i]);
|
||||
|
||||
QString text = item->m_text[i].toString();
|
||||
if(item->m_text[i].userType() == qMetaTypeId<ResourceIdLinkedTextPtr>())
|
||||
{
|
||||
ResourceIdLinkedTextPtr linkedText = item->m_text[i].value<ResourceIdLinkedTextPtr>();
|
||||
linkedText->cacheDocument(this);
|
||||
text = linkedText->text;
|
||||
}
|
||||
|
||||
clipData += format.arg(text, -widths[i]);
|
||||
}
|
||||
|
||||
clipData += lit("\n");
|
||||
@@ -1003,4 +1428,4 @@ void RDTreeWidget::endAddChild(RDTreeWidgetItem *item)
|
||||
// work is all done in beginAddChild
|
||||
if(!m_queueUpdates)
|
||||
m_model->endAddChild(item);
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
}
|
||||
|
||||
m_text[column] = value;
|
||||
checkForResourceId(column);
|
||||
dataChanged(column, Qt::DisplayRole);
|
||||
}
|
||||
inline void setToolTip(const QString &value)
|
||||
@@ -122,8 +123,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void checkForResourceId(int column);
|
||||
|
||||
friend class RDTreeWidget;
|
||||
friend class RDTreeWidgetModel;
|
||||
friend class RDTreeWidgetDelegate;
|
||||
|
||||
void setWidget(RDTreeWidget *widget);
|
||||
RDTreeWidget *m_widget = NULL;
|
||||
@@ -190,6 +194,26 @@ private:
|
||||
RDTreeWidgetItem *m_Current;
|
||||
};
|
||||
|
||||
class RDTreeWidgetDelegate : public ForwardingDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RDTreeWidgetDelegate(RDTreeWidget *parent);
|
||||
~RDTreeWidgetDelegate();
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) override;
|
||||
|
||||
bool linkHover(QMouseEvent *e, const QModelIndex &index);
|
||||
|
||||
private:
|
||||
RDTreeWidget *m_widget;
|
||||
};
|
||||
|
||||
class RDTreeWidget : public RDTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -225,6 +249,9 @@ public:
|
||||
void endUpdate();
|
||||
void setColumnAlignment(int column, Qt::Alignment align);
|
||||
|
||||
void setItemDelegate(QAbstractItemDelegate *delegate);
|
||||
QAbstractItemDelegate *itemDelegate() const;
|
||||
|
||||
void setColumns(const QStringList &columns);
|
||||
QString headerText(int column) const { return m_headers[column]; }
|
||||
void setHeaderText(int column, const QString &text);
|
||||
@@ -275,12 +302,16 @@ private:
|
||||
|
||||
friend class RDTreeWidgetModel;
|
||||
friend class RDTreeWidgetItem;
|
||||
friend class RDTreeWidgetDelegate;
|
||||
|
||||
// invisible root item, used to simplify recursion by even top-level items having a parent
|
||||
RDTreeWidgetItem *m_root;
|
||||
|
||||
RDTreeWidgetModel *m_model;
|
||||
|
||||
QAbstractItemDelegate *m_userDelegate = NULL;
|
||||
RDTreeWidgetDelegate *m_delegate;
|
||||
|
||||
bool m_clearing = false;
|
||||
|
||||
QStringList m_headers;
|
||||
|
||||
@@ -146,7 +146,7 @@ void APIInspector::fillAPIView()
|
||||
|
||||
root->setText(1, chunk->name);
|
||||
|
||||
addStructuredObjects(m_Ctx, root, chunk->data.children, false);
|
||||
addStructuredObjects(root, chunk->data.children, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -59,6 +59,8 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setProperty("ICaptureContext", QVariant::fromValue((void *)&ctx));
|
||||
|
||||
#if !defined(Q_OS_WIN32)
|
||||
// process injection is not supported on non-Windows, so remove the menu item rather than disable
|
||||
// it without a clear way to communicate that it is never supported
|
||||
|
||||
@@ -606,12 +606,10 @@ void D3D11PipelineStateViewer::addResourceRow(const D3D11ViewTag &view,
|
||||
uint32_t w = 1, h = 1, d = 1;
|
||||
uint32_t a = 1;
|
||||
QString format = tr("Unknown");
|
||||
QString name = m_Ctx.GetResourceName(r.Resource);
|
||||
QString typeName = tr("Unknown");
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
format = lit("-");
|
||||
typeName = lit("-");
|
||||
w = h = d = a = 0;
|
||||
@@ -689,6 +687,11 @@ void D3D11PipelineStateViewer::addResourceRow(const D3D11ViewTag &view,
|
||||
viewDetails = true;
|
||||
}
|
||||
|
||||
QVariant name = r.Resource;
|
||||
|
||||
if(viewDetails)
|
||||
name = tr("%1 viewed by %2").arg(ToQStr(r.Resource)).arg(ToQStr(r.Object));
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({slotname, name, typeName, w, h, d, a, format, QString()});
|
||||
|
||||
@@ -924,8 +927,6 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
if(shaderInput && !shaderInput->name.empty())
|
||||
slotname += lit(": ") + shaderInput->name;
|
||||
|
||||
QString sampName = m_Ctx.GetResourceName(s.Samp);
|
||||
|
||||
QString borderColor = QFormatStr("%1, %2, %3, %4")
|
||||
.arg(s.BorderColor[0])
|
||||
.arg(s.BorderColor[1])
|
||||
@@ -974,7 +975,7 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
filter = QFormatStr(" (%1)").arg(ToQStr(s.Filter.func));
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{slotname, sampName, addressing, filter,
|
||||
{slotname, s.Samp, addressing, filter,
|
||||
QFormatStr("%1 - %2")
|
||||
.arg(s.MinLOD == -FLT_MAX ? lit("0") : QString::number(s.MinLOD))
|
||||
.arg(s.MaxLOD == FLT_MAX ? lit("FLT_MAX") : QString::number(s.MaxLOD)),
|
||||
@@ -1025,17 +1026,10 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(b.Buffer);
|
||||
ulong length = 1;
|
||||
ulong length = 0;
|
||||
int numvars = shaderCBuf ? shaderCBuf->variables.count() : 0;
|
||||
uint32_t bytesize = shaderCBuf ? shaderCBuf->byteSize : 0;
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
length = 0;
|
||||
}
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(b.Buffer);
|
||||
|
||||
if(buf)
|
||||
@@ -1058,7 +1052,8 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
|
||||
QString vecrange = QFormatStr("%1 - %2").arg(b.VecOffset).arg(b.VecOffset + b.VecCount);
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem({slotname, name, vecrange, sizestr, QString()});
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({slotname, b.Buffer, vecrange, sizestr, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(i));
|
||||
|
||||
@@ -1293,20 +1288,16 @@ void D3D11PipelineStateViewer::setState()
|
||||
{
|
||||
if(ibufferUsed || ui->showDisabled->isChecked())
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(state.m_IA.ibuffer.Buffer);
|
||||
uint64_t length = 1;
|
||||
|
||||
if(!ibufferUsed)
|
||||
length = 0;
|
||||
uint64_t length = 0;
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(state.m_IA.ibuffer.Buffer);
|
||||
|
||||
if(buf)
|
||||
length = buf->length;
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({tr("Index"), name, draw ? draw->indexByteWidth : 0,
|
||||
state.m_IA.ibuffer.Offset, (qulonglong)length, QString()});
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{tr("Index"), state.m_IA.ibuffer.Buffer, draw ? draw->indexByteWidth : 0,
|
||||
state.m_IA.ibuffer.Offset, (qulonglong)length, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(
|
||||
D3D11VBIBTag(state.m_IA.ibuffer.Buffer, draw ? draw->indexOffset : 0)));
|
||||
@@ -1350,14 +1341,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(v.Buffer);
|
||||
qulonglong length = 1;
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
length = 0;
|
||||
}
|
||||
qulonglong length = 0;
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(v.Buffer);
|
||||
if(buf)
|
||||
@@ -1366,7 +1350,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
RDTreeWidgetItem *node = NULL;
|
||||
|
||||
if(filledSlot)
|
||||
node = new RDTreeWidgetItem({i, name, v.Stride, v.Offset, length, QString()});
|
||||
node = new RDTreeWidgetItem({i, v.Buffer, v.Stride, v.Offset, length, QString()});
|
||||
else
|
||||
node =
|
||||
new RDTreeWidgetItem({i, tr("No Buffer Set"), lit("-"), lit("-"), lit("-"), QString()});
|
||||
@@ -1447,20 +1431,13 @@ void D3D11PipelineStateViewer::setState()
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(s.Buffer);
|
||||
qulonglong length = 0;
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
}
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(s.Buffer);
|
||||
|
||||
if(buf && length == 0)
|
||||
if(buf)
|
||||
length = buf->length;
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem({i, name, length, s.Offset, QString()});
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem({i, s.Buffer, length, s.Offset, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(s.Buffer));
|
||||
|
||||
|
||||
@@ -683,12 +683,10 @@ void D3D12PipelineStateViewer::addResourceRow(const D3D12ViewTag &view,
|
||||
uint32_t w = 1, h = 1, d = 1;
|
||||
uint32_t a = 1;
|
||||
QString format = tr("Unknown");
|
||||
QString name = m_Ctx.GetResourceName(r.Resource);
|
||||
QString typeName = tr("Unknown");
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
format = lit("-");
|
||||
typeName = lit("-");
|
||||
w = h = d = a = 0;
|
||||
@@ -760,7 +758,7 @@ void D3D12PipelineStateViewer::addResourceRow(const D3D12ViewTag &view,
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{rootel, view.space, regname, name, typeName, w, h, d, a, format, QString()});
|
||||
{rootel, view.space, regname, r.Resource, typeName, w, h, d, a, format, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(view));
|
||||
|
||||
@@ -1140,7 +1138,6 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(b.Buffer);
|
||||
ulong length = b.ByteSize;
|
||||
uint64_t offset = b.Offset;
|
||||
int numvars = shaderCBuf ? shaderCBuf->variables.count() : 0;
|
||||
@@ -1149,9 +1146,6 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
|
||||
if(b.Immediate && !b.RootValues.empty())
|
||||
bytesize = uint32_t(b.RootValues.count() * 4);
|
||||
|
||||
if(!filledSlot)
|
||||
name = tr("Empty");
|
||||
|
||||
QString regname = QString::number(reg);
|
||||
|
||||
if(shaderCBuf && !shaderCBuf->name.empty())
|
||||
@@ -1168,7 +1162,7 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
|
||||
filledSlot = false;
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{rootel, (qulonglong)space, regname, name, (qulonglong)offset, sizestr, QString()});
|
||||
{rootel, (qulonglong)space, regname, b.Buffer, (qulonglong)offset, sizestr, QString()});
|
||||
|
||||
node->setTag(tag);
|
||||
|
||||
@@ -1292,11 +1286,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
{
|
||||
if(ibufferUsed || ui->showDisabled->isChecked())
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(state.m_IA.ibuffer.Buffer);
|
||||
uint64_t length = 1;
|
||||
|
||||
if(!ibufferUsed)
|
||||
length = 0;
|
||||
uint64_t length = 0;
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(state.m_IA.ibuffer.Buffer);
|
||||
|
||||
@@ -1304,7 +1294,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
length = buf->length;
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{tr("Index"), name, draw ? draw->indexByteWidth : 0,
|
||||
{tr("Index"), state.m_IA.ibuffer.Buffer, draw ? draw->indexByteWidth : 0,
|
||||
(qulonglong)state.m_IA.ibuffer.Offset, (qulonglong)length, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(
|
||||
@@ -1349,14 +1339,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(v.Buffer);
|
||||
qulonglong length = 1;
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
length = 0;
|
||||
}
|
||||
qulonglong length = 0;
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(v.Buffer);
|
||||
if(buf)
|
||||
@@ -1365,7 +1348,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
RDTreeWidgetItem *node = NULL;
|
||||
|
||||
if(filledSlot)
|
||||
node = new RDTreeWidgetItem({i, name, v.Stride, (qulonglong)v.Offset, length, QString()});
|
||||
node = new RDTreeWidgetItem({i, v.Buffer, v.Stride, (qulonglong)v.Offset, length, QString()});
|
||||
else
|
||||
node =
|
||||
new RDTreeWidgetItem({i, tr("No Buffer Set"), lit("-"), lit("-"), lit("-"), QString()});
|
||||
@@ -1413,21 +1396,15 @@ void D3D12PipelineStateViewer::setState()
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(s.Buffer);
|
||||
qulonglong length = 0;
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
}
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(s.Buffer);
|
||||
|
||||
if(buf && length == 0)
|
||||
if(buf)
|
||||
length = buf->length;
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({i, name, length, (qulonglong)s.Offset, QString()});
|
||||
new RDTreeWidgetItem({i, s.Buffer, length, (qulonglong)s.Offset, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(s.Buffer));
|
||||
|
||||
|
||||
@@ -652,12 +652,10 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
uint32_t w = 1, h = 1, d = 1;
|
||||
uint32_t a = 1;
|
||||
QString format = lit("Unknown");
|
||||
QString name = m_Ctx.GetResourceName(r.Resource);
|
||||
QString typeName = lit("Unknown");
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
format = lit("-");
|
||||
typeName = lit("-");
|
||||
w = h = d = a = 0;
|
||||
@@ -695,7 +693,7 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({slotname, name, typeName, w, h, d, a, format, QString()});
|
||||
new RDTreeWidgetItem({slotname, r.Resource, typeName, w, h, d, a, format, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(r.Resource));
|
||||
|
||||
@@ -829,7 +827,6 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
if(b)
|
||||
{
|
||||
slotname = QFormatStr("%1: %2").arg(bindPoint).arg(shaderCBuf.name);
|
||||
name = m_Ctx.GetResourceName(b->Resource);
|
||||
offset = b->Offset;
|
||||
length = b->Size;
|
||||
|
||||
@@ -852,7 +849,8 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
byterange = QFormatStr("%1 - %2").arg(offset).arg(offset + length);
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem({slotname, name, byterange, sizestr, QString()});
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({slotname, b->Resource, byterange, sizestr, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(i));
|
||||
|
||||
@@ -927,7 +925,6 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
: readWriteType == GLReadWriteType::SSBO ? tr("SSBO") : tr("Unknown");
|
||||
|
||||
QString slotname = QFormatStr("%1: %2").arg(bindPoint).arg(res.name);
|
||||
QString name = m_Ctx.GetResourceName(id);
|
||||
QString dimensions;
|
||||
QString format = lit("-");
|
||||
QString access = tr("Read/Write");
|
||||
@@ -990,13 +987,12 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
dimensions = lit("-");
|
||||
access = lit("-");
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({binding, slotname, name, dimensions, format, access, QString()});
|
||||
new RDTreeWidgetItem({binding, slotname, id, dimensions, format, access, QString()});
|
||||
|
||||
node->setTag(tag);
|
||||
|
||||
@@ -1192,7 +1188,6 @@ void GLPipelineStateViewer::setState()
|
||||
{
|
||||
if(ibufferUsed || showDisabled)
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(state.m_VtxIn.ibuffer);
|
||||
uint64_t length = 1;
|
||||
|
||||
if(!ibufferUsed)
|
||||
@@ -1201,13 +1196,11 @@ void GLPipelineStateViewer::setState()
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(state.m_VtxIn.ibuffer);
|
||||
|
||||
if(buf)
|
||||
{
|
||||
length = buf->length;
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({tr("Element"), name, draw ? draw->indexByteWidth : 0, 0, 0,
|
||||
(qulonglong)length, QString()});
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem({tr("Element"), state.m_VtxIn.ibuffer,
|
||||
draw ? draw->indexByteWidth : 0, 0, 0,
|
||||
(qulonglong)length, QString()});
|
||||
|
||||
node->setTag(
|
||||
QVariant::fromValue(GLVBIBTag(state.m_VtxIn.ibuffer, draw ? draw->indexOffset : 0)));
|
||||
@@ -1251,22 +1244,15 @@ void GLPipelineStateViewer::setState()
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(v.Buffer);
|
||||
uint64_t length = 1;
|
||||
uint64_t length = 0;
|
||||
uint64_t offset = v.Offset;
|
||||
|
||||
if(!filledSlot)
|
||||
{
|
||||
name = tr("Empty");
|
||||
length = 0;
|
||||
}
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(v.Buffer);
|
||||
if(buf)
|
||||
length = buf->length;
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{i, name, v.Stride, (qulonglong)offset, v.Divisor, (qulonglong)length, QString()});
|
||||
{i, v.Buffer, v.Stride, (qulonglong)offset, v.Divisor, (qulonglong)length, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(GLVBIBTag(v.Buffer, v.Offset)));
|
||||
|
||||
@@ -1311,19 +1297,16 @@ void GLPipelineStateViewer::setState()
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(state.m_Feedback.BufferBinding[i]);
|
||||
qulonglong length = state.m_Feedback.Size[i];
|
||||
|
||||
if(!filledSlot)
|
||||
name = tr("Empty");
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(state.m_Feedback.BufferBinding[i]);
|
||||
|
||||
if(buf && length == 0)
|
||||
if(buf)
|
||||
length = buf->length;
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{i, name, length, (qulonglong)state.m_Feedback.Offset[i], QString()});
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({i, state.m_Feedback.BufferBinding[i], length,
|
||||
(qulonglong)state.m_Feedback.Offset[i], QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(state.m_Feedback.BufferBinding[i]));
|
||||
|
||||
@@ -1616,12 +1599,10 @@ void GLPipelineStateViewer::setState()
|
||||
uint32_t w = 1, h = 1, d = 1;
|
||||
uint32_t a = 1;
|
||||
QString format = tr("Unknown");
|
||||
QString name = m_Ctx.GetResourceName(p);
|
||||
QString typeName = tr("Unknown");
|
||||
|
||||
if(p == ResourceId())
|
||||
{
|
||||
name = tr("Empty");
|
||||
format = lit("-");
|
||||
typeName = lit("-");
|
||||
w = h = d = a = 0;
|
||||
@@ -1637,19 +1618,6 @@ void GLPipelineStateViewer::setState()
|
||||
format = tex->format.Name();
|
||||
typeName = ToQStr(tex->resType);
|
||||
|
||||
if(m_Ctx.IsAutogeneratedName(p) && state.m_FS.ShaderDetails)
|
||||
{
|
||||
for(int s = 0; s < state.m_FS.ShaderDetails->OutputSig.count(); s++)
|
||||
{
|
||||
if(state.m_FS.ShaderDetails->OutputSig[s].regIndex == (uint32_t)db &&
|
||||
(state.m_FS.ShaderDetails->OutputSig[s].systemValue == ShaderBuiltin::Undefined ||
|
||||
state.m_FS.ShaderDetails->OutputSig[s].systemValue == ShaderBuiltin::ColorOutput))
|
||||
{
|
||||
name = QFormatStr("<%1>").arg(state.m_FS.ShaderDetails->OutputSig[s].varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(tex->format.srgbCorrected && !state.m_FB.FramebufferSRGB)
|
||||
format += lit(" (GL_FRAMEBUFFER_SRGB = 0)");
|
||||
}
|
||||
@@ -1664,8 +1632,23 @@ void GLPipelineStateViewer::setState()
|
||||
.arg(ToQStr(r->Swizzle[3]));
|
||||
}
|
||||
|
||||
QString slotname = QString::number(i);
|
||||
|
||||
if(state.m_FS.ShaderDetails)
|
||||
{
|
||||
for(int s = 0; s < state.m_FS.ShaderDetails->OutputSig.count(); s++)
|
||||
{
|
||||
if(state.m_FS.ShaderDetails->OutputSig[s].regIndex == (uint32_t)db &&
|
||||
(state.m_FS.ShaderDetails->OutputSig[s].systemValue == ShaderBuiltin::Undefined ||
|
||||
state.m_FS.ShaderDetails->OutputSig[s].systemValue == ShaderBuiltin::ColorOutput))
|
||||
{
|
||||
slotname += QFormatStr(": %1").arg(state.m_FS.ShaderDetails->OutputSig[s].varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({i, name, typeName, w, h, d, a, format, QString()});
|
||||
new RDTreeWidgetItem({i, p, typeName, w, h, d, a, format, QString()});
|
||||
|
||||
if(tex)
|
||||
node->setTag(QVariant::fromValue(p));
|
||||
@@ -1700,12 +1683,10 @@ void GLPipelineStateViewer::setState()
|
||||
uint32_t w = 1, h = 1, d = 1;
|
||||
uint32_t a = 1;
|
||||
QString format = tr("Unknown");
|
||||
QString name = m_Ctx.GetResourceName(ds);
|
||||
QString typeName = tr("Unknown");
|
||||
|
||||
if(ds == ResourceId())
|
||||
{
|
||||
name = tr("Empty");
|
||||
format = lit("-");
|
||||
typeName = lit("-");
|
||||
w = h = d = a = 0;
|
||||
@@ -1736,7 +1717,7 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({slot, name, typeName, w, h, d, a, format, QString()});
|
||||
new RDTreeWidgetItem({slot, ds, typeName, w, h, d, a, format, QString()});
|
||||
|
||||
if(tex)
|
||||
node->setTag(QVariant::fromValue(ds));
|
||||
|
||||
@@ -653,7 +653,7 @@ QVariantList VulkanPipelineStateViewer::makeSampler(const QString &bindset, cons
|
||||
bindset,
|
||||
slotname,
|
||||
descriptor.immutableSampler ? tr("Immutable Sampler") : tr("Sampler"),
|
||||
m_Ctx.GetResourceName(descriptor.res),
|
||||
descriptor.res,
|
||||
addressing,
|
||||
filter + lit(", ") + lod};
|
||||
}
|
||||
@@ -857,7 +857,6 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
uint32_t samples = 1;
|
||||
uint64_t len = 0;
|
||||
QString format = tr("Unknown");
|
||||
QString name = m_Ctx.GetResourceName(descriptorBind->res);
|
||||
TextureDim restype = TextureDim::Unknown;
|
||||
QVariant tag;
|
||||
|
||||
@@ -906,7 +905,6 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
}
|
||||
else
|
||||
{
|
||||
name = tr("Empty");
|
||||
format = lit("-");
|
||||
w = h = d = a = 0;
|
||||
}
|
||||
@@ -932,7 +930,8 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
range = QFormatStr("%1 - %2").arg(descriptorBind->offset).arg(descriptorLen);
|
||||
|
||||
node = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, ToQStr(bindType), name, tr("%1 bytes").arg(len), range,
|
||||
QString(), bindset, slotname, ToQStr(bindType), descriptorBind->res,
|
||||
tr("%1 bytes").arg(len), range,
|
||||
});
|
||||
|
||||
node->setTag(tag);
|
||||
@@ -1018,7 +1017,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
dim += QFormatStr(", %1x MSAA").arg(samples);
|
||||
|
||||
node = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, typeName, name, dim, format,
|
||||
QString(), bindset, slotname, typeName, descriptorBind->res, dim, format,
|
||||
});
|
||||
|
||||
node->setTag(tag);
|
||||
@@ -1185,7 +1184,6 @@ void VulkanPipelineStateViewer::addConstantBlockRow(ShaderReflection *shaderDeta
|
||||
slotname = QFormatStr("%1[%2]").arg(bind).arg(idx);
|
||||
}
|
||||
|
||||
QString name = m_Ctx.GetResourceName(descriptorBind->res);
|
||||
uint64_t length = 0;
|
||||
int numvars = cblock != NULL ? cblock->variables.count() : 0;
|
||||
uint64_t byteSize = cblock != NULL ? cblock->byteSize : 0;
|
||||
@@ -1206,6 +1204,8 @@ void VulkanPipelineStateViewer::addConstantBlockRow(ShaderReflection *shaderDeta
|
||||
|
||||
QString sizestr;
|
||||
|
||||
QVariant name = descriptorBind->res;
|
||||
|
||||
// push constants or specialization constants
|
||||
if(cblock != NULL && !cblock->bufferBacked)
|
||||
{
|
||||
@@ -1531,7 +1531,6 @@ void VulkanPipelineStateViewer::setState()
|
||||
{
|
||||
if(ibufferUsed || showDisabled)
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(state.IA.ibuffer.buf);
|
||||
uint64_t length = 1;
|
||||
|
||||
if(!ibufferUsed)
|
||||
@@ -1543,7 +1542,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
length = buf->length;
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{tr("Index"), name, tr("Index"), (qulonglong)state.IA.ibuffer.offs,
|
||||
{tr("Index"), state.IA.ibuffer.buf, tr("Index"), (qulonglong)state.IA.ibuffer.offs,
|
||||
draw != NULL ? draw->indexByteWidth : 0, (qulonglong)length, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(
|
||||
@@ -1597,7 +1596,6 @@ void VulkanPipelineStateViewer::setState()
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString name = tr("No Buffer");
|
||||
QString rate = lit("-");
|
||||
uint64_t length = 1;
|
||||
uint64_t offset = 0;
|
||||
@@ -1605,7 +1603,6 @@ void VulkanPipelineStateViewer::setState()
|
||||
|
||||
if(vbuff != NULL)
|
||||
{
|
||||
name = m_Ctx.GetResourceName(vbuff->buffer);
|
||||
offset = vbuff->offset;
|
||||
|
||||
BufferDescription *buf = m_Ctx.GetBuffer(vbuff->buffer);
|
||||
@@ -1620,14 +1617,14 @@ void VulkanPipelineStateViewer::setState()
|
||||
}
|
||||
else
|
||||
{
|
||||
name += tr(", No Binding");
|
||||
rate += tr("No Binding");
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node = NULL;
|
||||
|
||||
if(filledSlot)
|
||||
node = new RDTreeWidgetItem(
|
||||
{i, name, rate, (qulonglong)offset, stride, (qulonglong)length, QString()});
|
||||
{i, vbuff->buffer, rate, (qulonglong)offset, stride, (qulonglong)length, QString()});
|
||||
else
|
||||
node = new RDTreeWidgetItem(
|
||||
{i, tr("No Binding"), lit("-"), lit("-"), lit("-"), lit("-"), QString()});
|
||||
@@ -1783,12 +1780,10 @@ void VulkanPipelineStateViewer::setState()
|
||||
uint32_t w = 1, h = 1, d = 1;
|
||||
uint32_t a = 1;
|
||||
QString format = p.viewfmt.Name();
|
||||
QString name = m_Ctx.GetResourceName(p.img);
|
||||
QString typeName = tr("Unknown");
|
||||
|
||||
if(p.img == ResourceId())
|
||||
{
|
||||
name = tr("Empty");
|
||||
format = lit("-");
|
||||
typeName = lit("-");
|
||||
w = h = d = a = 0;
|
||||
@@ -1802,19 +1797,6 @@ void VulkanPipelineStateViewer::setState()
|
||||
d = tex->depth;
|
||||
a = tex->arraysize;
|
||||
typeName = ToQStr(tex->resType);
|
||||
|
||||
if(m_Ctx.IsAutogeneratedName(p.img) && state.m_FS.ShaderDetails != NULL)
|
||||
{
|
||||
for(int s = 0; s < state.m_FS.ShaderDetails->OutputSig.count(); s++)
|
||||
{
|
||||
if(state.m_FS.ShaderDetails->OutputSig[s].regIndex == (uint32_t)colIdx &&
|
||||
(state.m_FS.ShaderDetails->OutputSig[s].systemValue == ShaderBuiltin::Undefined ||
|
||||
state.m_FS.ShaderDetails->OutputSig[s].systemValue == ShaderBuiltin::ColorOutput))
|
||||
{
|
||||
name = QFormatStr("<%1>").arg(state.m_FS.ShaderDetails->OutputSig[s].varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(p.swizzle[0] != TextureSwizzle::Red || p.swizzle[1] != TextureSwizzle::Green ||
|
||||
@@ -1836,8 +1818,21 @@ void VulkanPipelineStateViewer::setState()
|
||||
else
|
||||
slotname = lit("Depth");
|
||||
|
||||
if(state.m_FS.ShaderDetails != NULL)
|
||||
{
|
||||
for(int s = 0; s < state.m_FS.ShaderDetails->OutputSig.count(); s++)
|
||||
{
|
||||
if(state.m_FS.ShaderDetails->OutputSig[s].regIndex == (uint32_t)colIdx &&
|
||||
(state.m_FS.ShaderDetails->OutputSig[s].systemValue == ShaderBuiltin::Undefined ||
|
||||
state.m_FS.ShaderDetails->OutputSig[s].systemValue == ShaderBuiltin::ColorOutput))
|
||||
{
|
||||
slotname += QFormatStr(": %1").arg(state.m_FS.ShaderDetails->OutputSig[s].varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node =
|
||||
new RDTreeWidgetItem({slotname, name, typeName, w, h, d, a, format, QString()});
|
||||
new RDTreeWidgetItem({slotname, p.img, typeName, w, h, d, a, format, QString()});
|
||||
|
||||
if(tex)
|
||||
node->setTag(QVariant::fromValue(p.img));
|
||||
@@ -2486,7 +2481,6 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe::
|
||||
int i = 0;
|
||||
for(const VKPipe::VB &vb : vi.vbuffers)
|
||||
{
|
||||
QString name = m_Ctx.GetResourceName(vb.buffer);
|
||||
uint64_t length = 0;
|
||||
|
||||
if(vb.buffer == ResourceId())
|
||||
@@ -2500,7 +2494,7 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe::
|
||||
length = buf->length;
|
||||
}
|
||||
|
||||
rows.push_back({i, name, (qulonglong)vb.offset, (qulonglong)length});
|
||||
rows.push_back({i, vb.buffer, (qulonglong)vb.offset, (qulonglong)length});
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ struct CaptureContextInvoker : ICaptureContext
|
||||
{
|
||||
return m_Ctx.HasResourceCustomName(id);
|
||||
}
|
||||
virtual int ResourceNameCacheID() override { return m_Ctx.ResourceNameCacheID(); }
|
||||
virtual TextureDescription *GetTexture(ResourceId id) override { return m_Ctx.GetTexture(id); }
|
||||
virtual const rdcarray<TextureDescription> &GetTextures() override { return m_Ctx.GetTextures(); }
|
||||
virtual BufferDescription *GetBuffer(ResourceId id) override { return m_Ctx.GetBuffer(id); }
|
||||
|
||||
@@ -207,7 +207,7 @@ void ResourceInspector::Inspect(ResourceId id)
|
||||
|
||||
for(ResourceId parent : desc->parentResources)
|
||||
{
|
||||
RDTreeWidgetItem *item = new RDTreeWidgetItem({tr("Parent"), m_Ctx.GetResourceName(parent)});
|
||||
RDTreeWidgetItem *item = new RDTreeWidgetItem({tr("Parent"), parent});
|
||||
item->setData(0, ResourceIdRole, QVariant::fromValue(parent));
|
||||
item->setData(1, ResourceIdRole, QVariant::fromValue(parent));
|
||||
ui->relatedResources->addTopLevelItem(item);
|
||||
@@ -215,7 +215,7 @@ void ResourceInspector::Inspect(ResourceId id)
|
||||
|
||||
for(ResourceId derived : desc->derivedResources)
|
||||
{
|
||||
RDTreeWidgetItem *item = new RDTreeWidgetItem({tr("Derived"), m_Ctx.GetResourceName(derived)});
|
||||
RDTreeWidgetItem *item = new RDTreeWidgetItem({tr("Derived"), derived});
|
||||
item->setData(0, ResourceIdRole, QVariant::fromValue(derived));
|
||||
item->setData(1, ResourceIdRole, QVariant::fromValue(derived));
|
||||
ui->relatedResources->addTopLevelItem(item);
|
||||
@@ -231,7 +231,7 @@ void ResourceInspector::Inspect(ResourceId id)
|
||||
|
||||
root->setText(0, chunkObj->name);
|
||||
|
||||
addStructuredObjects(m_Ctx, root, chunkObj->data.children, false);
|
||||
addStructuredObjects(root, chunkObj->data.children, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user