Add pagination for very large range buffer viewers

This commit is contained in:
baldurk
2020-02-25 18:19:52 +00:00
parent a2b437b903
commit 4703012a87
2 changed files with 142 additions and 32 deletions
+135 -32
View File
@@ -30,6 +30,7 @@
#include <QMenu>
#include <QMouseEvent>
#include <QMutexLocker>
#include <QPushButton>
#include <QScrollBar>
#include <QTimer>
#include <QtMath>
@@ -37,6 +38,8 @@
#include "Code/Resources.h"
#include "ui_BufferViewer.h"
static const uint32_t MaxVisibleRows = 10000;
namespace NativeScanCode
{
enum
@@ -459,6 +462,7 @@ struct BufferConfiguration
{
uint32_t curInstance = 0, curView = 0;
uint32_t numRows = 0, unclampedNumRows = 0;
uint32_t pagingOffset = 0;
// we can have two index buffers for VSOut data:
// the original index buffer is used for the displayed value (in displayIndices), and the actual
@@ -486,6 +490,7 @@ struct BufferConfiguration
curInstance = o.curInstance;
numRows = o.numRows;
unclampedNumRows = o.unclampedNumRows;
pagingOffset = o.pagingOffset;
displayIndices = o.displayIndices;
if(displayIndices)
@@ -714,7 +719,13 @@ public:
}
QModelIndex parent(const QModelIndex &index) const override { return QModelIndex(); }
int rowCount(const QModelIndex &parent = QModelIndex()) const override { return config.numRows; }
int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
int ret = config.numRows;
if(config.pagingOffset > 0)
ret++;
return ret;
}
int columnCount(const QModelIndex &parent = QModelIndex()) const override
{
return totalColumnCount;
@@ -785,6 +796,17 @@ public:
uint32_t row = index.row();
int col = index.column();
if(config.pagingOffset > 0)
{
if(row == 0)
{
if(role == Qt::DisplayRole)
return lit("...");
return QVariant();
}
row--;
}
if(role == columnGroupRole)
{
if(col < reservedColumnCount())
@@ -911,8 +933,16 @@ public:
{
if(config.unclampedNumRows > 0 && row >= config.numRows - 2)
{
if(col < 2 && row == config.numRows - 1)
return QString::number(config.unclampedNumRows - config.numRows);
if(meshView)
{
if(col < 2 && row == config.numRows - 1)
return QString::number(config.unclampedNumRows - 1);
}
else
{
if(col == 0 && row == config.numRows - 1)
return QString::number(config.pagingOffset + config.unclampedNumRows - 1);
}
return lit("...");
}
@@ -920,7 +950,7 @@ public:
if(col >= 0 && col < totalColumnCount && row < config.numRows)
{
if(col == 0)
return row;
return row + config.pagingOffset;
uint32_t idx = row;
@@ -1526,7 +1556,7 @@ static void ConfigureMeshColumns(ICaptureContext &ctx, PopulateBufferData *bufda
}
// if we have significantly clamped, then set the unclamped number of rows and clamp.
if(numRowsUpperBound + 100 < bufdata->vsinConfig.numRows)
if(numRowsUpperBound != ~0U && numRowsUpperBound + 100 < bufdata->vsinConfig.numRows)
{
bufdata->vsinConfig.unclampedNumRows = bufdata->vsinConfig.numRows;
bufdata->vsinConfig.numRows = numRowsUpperBound + 100;
@@ -2030,8 +2060,11 @@ void BufferViewer::SetupRawView()
ui->dockarea->areaOf(ui->vsinData), 0.5f));
ui->dockarea->setToolWindowProperties(ui->formatSpecifier, ToolWindowManager::HideCloseButton);
QObject::connect(ui->formatSpecifier, &BufferFormatSpecifier::processFormat, this,
&BufferViewer::processFormat);
QObject::connect(ui->formatSpecifier, &BufferFormatSpecifier::processFormat,
[this](const QString &format) {
m_PagingByteOffset = 0;
processFormat(format);
});
QVBoxLayout *vertical = new QVBoxLayout(this);
@@ -2406,19 +2439,47 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
else
{
buf = new BufferData;
// calculate tight stride
buf->stride = 0;
for(int i = 0; i < bufdata->vsinConfig.props.count(); i++)
buf->stride += bufdata->vsinConfig.props[i].format.ElementSize() *
bufdata->vsinConfig.columns[i].type.descriptor.rows;
buf->stride = qMax((size_t)1, buf->stride);
uint64_t unclampedLen = m_ByteSize;
if(unclampedLen == UINT64_MAX)
unclampedLen = 0;
if(unclampedLen == 0)
unclampedLen = m_IsBuffer ? m_Ctx.GetBuffer(m_BufferID)->length : 0;
uint64_t clampedLen =
qMin(unclampedLen - CurrentByteOffset(), buf->stride * (MaxVisibleRows + 2));
if(m_IsBuffer)
{
uint64_t len = m_ByteSize;
if(len == UINT64_MAX)
len = 0;
buf->storage = r->GetBufferData(m_BufferID, m_ByteOffset, len);
buf->storage = r->GetBufferData(m_BufferID, CurrentByteOffset(), clampedLen);
}
else
{
buf->storage = r->GetTextureData(m_BufferID, m_TexSub);
}
uint32_t bufCount = uint32_t(buf->size());
bufdata->vsinConfig.pagingOffset = uint32_t(m_PagingByteOffset / buf->stride);
bufdata->vsinConfig.numRows = uint32_t((bufCount + buf->stride - 1) / buf->stride);
bufdata->vsinConfig.unclampedNumRows = 0;
if(unclampedLen > CurrentByteOffset() + clampedLen)
bufdata->vsinConfig.unclampedNumRows =
bufdata->vsinConfig.numRows +
uint32_t((unclampedLen - (CurrentByteOffset() + clampedLen) + buf->stride - 1) /
buf->stride);
// ownership passes to model
bufdata->vsinConfig.buffers.push_back(buf);
if(!me)
{
delete buf;
@@ -2427,26 +2488,6 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
}
GUIInvoke::call(this, [this, buf, bufdata]() {
if(buf)
{
// calculate tight stride
buf->stride = 0;
for(int i = 0; i < bufdata->vsinConfig.props.count(); i++)
buf->stride += bufdata->vsinConfig.props[i].format.ElementSize() *
bufdata->vsinConfig.columns[i].type.descriptor.rows;
buf->stride = qMax((size_t)1, buf->stride);
uint32_t bufCount = uint32_t(buf->size());
bufdata->vsinConfig.numRows = uint32_t((bufCount + buf->stride - 1) / buf->stride);
bufdata->vsinConfig.unclampedNumRows = 0;
// ownership passes to model
bufdata->vsinConfig.buffers.push_back(buf);
}
m_ModelVSIn->endReset(bufdata->vsinConfig);
m_ModelVSOut->endReset(bufdata->vsoutConfig);
m_ModelGSOut->endReset(bufdata->gsoutConfig);
@@ -2504,6 +2545,31 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
ui->vsoutData->horizontalScrollBar()->setValue(bufdata->vsoutHoriz);
ui->gsoutData->horizontalScrollBar()->setValue(bufdata->gsoutHoriz);
if(!m_MeshView)
{
const bool prev = (bufdata->vsinConfig.pagingOffset > 0);
const bool next = (bufdata->vsinConfig.numRows >= MaxVisibleRows);
if(prev && next)
{
ui->vsinData->setIndexWidget(m_ModelVSIn->index(0, 1), MakePreviousPageButton());
ui->vsinData->setIndexWidget(m_ModelVSIn->index(0, 2), MakeNextPageButton());
ui->vsinData->setIndexWidget(m_ModelVSIn->index(MaxVisibleRows + 1, 1),
MakePreviousPageButton());
ui->vsinData->setIndexWidget(m_ModelVSIn->index(MaxVisibleRows + 1, 2),
MakeNextPageButton());
}
else if(prev)
{
ui->vsinData->setIndexWidget(m_ModelVSIn->index(0, 1), MakePreviousPageButton());
}
else if(next)
{
ui->vsinData->setIndexWidget(m_ModelVSIn->index(MaxVisibleRows, 1), MakeNextPageButton());
}
}
// we're done with it, the buffer configurations are individually copied/refcounted
delete bufdata;
@@ -2781,6 +2847,11 @@ void BufferViewer::UI_ResetArcball()
INVOKE_MEMFN(RT_UpdateAndDisplay);
}
uint64_t BufferViewer::CurrentByteOffset()
{
return m_ByteOffset + m_PagingByteOffset;
}
void BufferViewer::UI_CalculateMeshFormats()
{
if(!m_MeshView)
@@ -3168,6 +3239,8 @@ void BufferViewer::ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId
if(buf)
m_ObjectByteSize = buf->length;
m_PagingByteOffset = 0;
processFormat(format);
}
@@ -3186,6 +3259,8 @@ void BufferViewer::ViewTexture(ResourceId id, const Subresource &sub, const rdcs
if(tex)
m_ObjectByteSize = tex->byteSize;
m_PagingByteOffset = 0;
processFormat(format);
}
@@ -3260,6 +3335,30 @@ void BufferViewer::RT_UpdateAndDisplay(IReplayController *)
GUIInvoke::call(this, [this]() { ui->render->update(); });
}
QPushButton *BufferViewer::MakePreviousPageButton()
{
QPushButton *b = new QPushButton(tr("Previous Page"), this);
QObject::connect(b, &QPushButton::clicked, [this] {
uint64_t step = MaxVisibleRows * m_ModelVSIn->getConfig().buffers[0]->stride;
if(m_PagingByteOffset > step)
m_PagingByteOffset -= step;
else
m_PagingByteOffset = 0;
processFormat(m_Format);
});
return b;
}
QPushButton *BufferViewer::MakeNextPageButton()
{
QPushButton *b = new QPushButton(tr("Next Page"), this);
QObject::connect(b, &QPushButton::clicked, [this] {
m_PagingByteOffset += MaxVisibleRows * m_ModelVSIn->getConfig().buffers[0]->stride;
processFormat(m_Format);
});
return b;
}
RDTableView *BufferViewer::tableForStage(MeshDataStage stage)
{
if(stage == MeshDataStage::VSIn)
@@ -3612,6 +3711,8 @@ void BufferViewer::on_byteRangeStart_valueChanged(int value)
{
m_ByteOffset = value;
m_PagingByteOffset = 0;
processFormat(m_Format);
}
@@ -3619,6 +3720,8 @@ void BufferViewer::on_byteRangeLength_valueChanged(int value)
{
m_ByteSize = value;
m_PagingByteOffset = 0;
processFormat(m_Format);
}
+7
View File
@@ -36,6 +36,7 @@ class BufferViewer;
class QItemSelection;
class QMenu;
class QPushButton;
class RDTableView;
class BufferItemModel;
class CameraWrapper;
@@ -150,6 +151,9 @@ private:
void RT_UpdateAndDisplay(IReplayController *r);
QPushButton *MakePreviousPageButton();
QPushButton *MakeNextPageButton();
MeshDisplay m_Config;
MeshDataStage m_CurStage;
@@ -172,11 +176,14 @@ private:
void UI_ResetArcball();
uint64_t CurrentByteOffset();
// data from raw buffer view
bool m_IsBuffer = true;
QString m_Format;
Subresource m_TexSub = {0, 0, 0};
uint64_t m_ByteOffset = 0;
uint64_t m_PagingByteOffset = 0;
uint64_t m_ObjectByteSize = UINT64_MAX;
uint64_t m_ByteSize = UINT64_MAX;
ResourceId m_BufferID;