Refactor texture viewer thumbnails to not use swapchains

* There seems to be a significant slowdown when using real swapchains, both for
  creation and display. Since thumbnails don't update often (only on event
  change, or if the panel is resized which is not a regular occurence)
  counterintuitively it's better to render and readback the image offscreen and
  re-upload it on the CPU.
This commit is contained in:
baldurk committed 2022-11-09 14:14:24 +00:00
1 parent 2e276a7f84
commit d11da2f3a1
7 files changed
+269 -22

No files matched your search

+62 -4
View File
@@ -35,6 +35,29 @@ ResourcePreview::ResourcePreview(ICaptureContext &c, IReplayOutput *output, QWid
ui->thumbnail->SetContext(c);
ui->thumbnail->SetOutput(output);
Initialise();
}
ResourcePreview::ResourcePreview(bool, QWidget *parent)
: QFrame(parent), ui(new Ui::ResourcePreview)
{
ui->setupUi(this);
delete ui->thumbnail;
ui->thumbnail = NULL;
m_ManualThumbnail = new RDLabel();
m_ManualThumbnail->setGeometry(QRect(0, 0, 16, 16));
m_ManualThumbnail->setScaledContents(true);
m_ManualThumbnail->setSizePolicy(
QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
ui->gridLayout->addWidget(m_ManualThumbnail, 0, 0, 1, 2);
Initialise();
}
void ResourcePreview::Initialise()
{
setBackgroundRole(QPalette::Background);
setForegroundRole(QPalette::Foreground);
@@ -57,12 +80,19 @@ ResourcePreview::ResourcePreview(ICaptureContext &c, IReplayOutput *output, QWid
ui->descriptionLabel->setForegroundRole(QPalette::Foreground);
ui->descriptionLabel->setFont(Formatter::PreferredFont());
QObject::connect(ui->thumbnail, &CustomPaintWidget::clicked, this, &ResourcePreview::clickEvent);
if(ui->thumbnail)
QObject::connect(ui->thumbnail, &CustomPaintWidget::clicked, this, &ResourcePreview::clickEvent);
else if(m_ManualThumbnail)
QObject::connect(m_ManualThumbnail, &RDLabel::clicked, this, &ResourcePreview::clickEvent);
QObject::connect(ui->slotLabel, &RDLabel::clicked, this, &ResourcePreview::clickEvent);
QObject::connect(ui->descriptionLabel, &RDLabel::clicked, this, &ResourcePreview::clickEvent);
QObject::connect(ui->thumbnail, &CustomPaintWidget::doubleClicked, this,
&ResourcePreview::doubleClickEvent);
if(ui->thumbnail)
QObject::connect(ui->thumbnail, &CustomPaintWidget::doubleClicked, this,
&ResourcePreview::doubleClickEvent);
else if(m_ManualThumbnail)
QObject::connect(m_ManualThumbnail, &RDLabel::doubleClicked, this,
&ResourcePreview::doubleClickEvent);
QObject::connect(ui->slotLabel, &RDLabel::doubleClicked, this, &ResourcePreview::doubleClickEvent);
QObject::connect(ui->descriptionLabel, &RDLabel::doubleClicked, this,
&ResourcePreview::doubleClickEvent);
@@ -110,5 +140,33 @@ void ResourcePreview::setSelected(bool sel)
WindowingData ResourcePreview::GetWidgetWindowingData()
{
return ui->thumbnail->GetWidgetWindowingData();
if(ui->thumbnail)
return ui->thumbnail->GetWidgetWindowingData();
return {};
}
QSize ResourcePreview::GetThumbSize()
{
if(ui->thumbnail)
return ui->thumbnail->size();
if(m_ManualThumbnail)
return m_ManualThumbnail->size();
return {};
}
void ResourcePreview::UpdateThumb(QSize s, const bytebuf &imgData)
{
if(!m_ManualThumbnail)
return;
QImage thumb(imgData.data(), s.width(), s.height(), s.width() * 3, QImage::Format_RGB888);
m_ManualThumbnail->setPixmap(QPixmap::fromImage(thumb));
}
void ResourcePreview::resizeEvent(QResizeEvent *e)
{
emit resized(this);
QFrame::resizeEvent(e);
}
+13
View File
@@ -34,6 +34,7 @@ class ResourcePreview;
struct IReplayOutput;
struct ICaptureContext;
class RDLabel;
class ResourcePreview : public QFrame
{
@@ -41,11 +42,17 @@ class ResourcePreview : public QFrame
public:
explicit ResourcePreview(ICaptureContext &c, IReplayOutput *output, QWidget *parent = 0);
// create a manually rendered preview
explicit ResourcePreview(bool, QWidget *parent = 0);
void Initialise();
~ResourcePreview();
signals:
void clicked(QMouseEvent *e);
void doubleClicked(QMouseEvent *e);
void resized(ResourcePreview *prev);
public:
void setSlotName(const QString &n);
@@ -55,6 +62,8 @@ public:
void doubleClickEvent(QMouseEvent *e);
WindowingData GetWidgetWindowingData();
QSize GetThumbSize();
void UpdateThumb(QSize s, const bytebuf &imgData);
void setActive(bool b)
{
@@ -68,8 +77,12 @@ public:
void setSelected(bool sel);
private:
virtual void resizeEvent(QResizeEvent *event);
Ui::ResourcePreview *ui;
RDLabel *m_ManualThumbnail = NULL;
bool m_Active;
bool m_Selected = false;
};
+44 -18
View File
@@ -1981,10 +1981,11 @@ void TextureViewer::textureTab_Closing(int index)
ResourcePreview *TextureViewer::UI_CreateThumbnail(ThumbnailStrip *strip)
{
ResourcePreview *prev = new ResourcePreview(m_Ctx, m_Output);
ResourcePreview *prev = new ResourcePreview(true);
QObject::connect(prev, &ResourcePreview::clicked, this, &TextureViewer::thumb_clicked);
QObject::connect(prev, &ResourcePreview::doubleClicked, this, &TextureViewer::thumb_doubleClicked);
QObject::connect(prev, &ResourcePreview::resized, this, &TextureViewer::UI_PreviewResized);
prev->setActive(false);
strip->addThumb(prev);
@@ -2366,6 +2367,7 @@ void TextureViewer::InitResourcePreview(ResourcePreview *prev, BoundResource res
Following &follow, const QString &bindName,
const QString &slotName)
{
Subresource sub = {0, 0, ~0U};
if(res.resourceId != ResourceId() || force)
{
QString fullname = bindName;
@@ -2380,8 +2382,6 @@ void TextureViewer::InitResourcePreview(ResourcePreview *prev, BoundResource res
prev->setResourceName(fullname);
WindowingData winData = prev->GetWidgetWindowingData();
prev->setProperty("f", QVariant::fromValue(follow));
prev->setSlotName(slotName);
prev->setActive(true);
@@ -2389,20 +2389,15 @@ void TextureViewer::InitResourcePreview(ResourcePreview *prev, BoundResource res
if(m_Ctx.GetTexture(res.resourceId))
{
m_Ctx.Replay().AsyncInvoke([this, winData, res](IReplayController *) {
Subresource sub = {0, 0, ~0U};
if(res.firstMip >= 0)
sub.mip = res.firstMip;
if(res.firstSlice >= 0)
sub.slice = res.firstSlice;
m_Output->AddThumbnail(winData, res.resourceId, sub, res.typeCast);
});
if(res.firstMip >= 0)
sub.mip = res.firstMip;
if(res.firstSlice >= 0)
sub.slice = res.firstSlice;
}
else
{
m_Ctx.Replay().AsyncInvoke([this, winData](IReplayController *) {
m_Output->AddThumbnail(winData, ResourceId(), {0, 0, ~0U}, CompType::Typeless);
});
res.resourceId = ResourceId();
res.typeCast = CompType::Typeless;
}
}
else if(m_Following == follow)
@@ -2411,17 +2406,48 @@ void TextureViewer::InitResourcePreview(ResourcePreview *prev, BoundResource res
prev->setActive(true);
prev->setSelected(true);
WindowingData winData = prev->GetWidgetWindowingData();
m_Ctx.Replay().AsyncInvoke([this, winData](IReplayController *) {
m_Output->AddThumbnail(winData, ResourceId(), {0, 0, ~0U}, CompType::Typeless);
});
res.resourceId = ResourceId();
res.typeCast = CompType::Typeless;
}
else
{
prev->setResourceName(QString());
prev->setActive(false);
prev->setSelected(false);
return;
}
prev->setProperty("id", QVariant::fromValue(res.resourceId));
prev->setProperty("mip", sub.mip);
prev->setProperty("slice", sub.slice);
prev->setProperty("cast", uint32_t(res.typeCast));
GUIInvoke::call(this, [this, prev] { UI_PreviewResized(prev); });
}
void TextureViewer::UI_PreviewResized(ResourcePreview *prev)
{
QSize s = prev->GetThumbSize();
ResourceId id = prev->property("id").value<ResourceId>();
Subresource sub = {0, 0, ~0U};
sub.mip = prev->property("mip").toUInt();
sub.slice = prev->property("slice").toUInt();
CompType typeCast = (CompType)prev->property("cast").toUInt();
m_Ctx.Replay().AsyncInvoke(lit("preview%1").arg((qulonglong)(void *)prev),
[this, prev, s, sub, id, typeCast](IReplayController *) {
bytebuf data =
m_Output->DrawThumbnail(s.width(), s.height(), id, sub, typeCast);
// new and swap to move the data into the lambda
bytebuf *copy = new bytebuf;
copy->swap(data);
GUIInvoke::call(this, [prev, s, copy]() {
prev->UpdateThumb(s, *copy);
delete copy;
});
});
}
void TextureViewer::InitStageResourcePreviews(ShaderStage stage,
+2
View File
@@ -275,6 +275,8 @@ private:
rdcarray<BoundResourceArray> &ResList, ThumbnailStrip *prevs,
int &prevIndex, bool copy, bool rw);
void UI_PreviewResized(ResourcePreview *prev);
void AddResourceUsageEntry(QMenu &menu, uint32_t start, uint32_t end, ResourceUsage usage);
void OpenResourceContextMenu(ResourceId id, bool input, const rdcarray<EventUsage> &usage);