Add support for raw buffer views (not mesh output)

This commit is contained in:
baldurk
2017-01-26 23:27:08 +00:00
parent bac0c011cd
commit 9690db525b
9 changed files with 561 additions and 331 deletions
+1 -1
View File
@@ -472,7 +472,7 @@ BufferViewer *CaptureContext::meshPreview()
if(m_MeshPreview)
return m_MeshPreview;
m_MeshPreview = new BufferViewer(this, m_MainWindow);
m_MeshPreview = new BufferViewer(this, true, m_MainWindow);
m_MeshPreview->setObjectName("meshPreview");
setupDockWindow(m_MeshPreview);
+1 -1
View File
@@ -759,7 +759,7 @@ ShaderVariable FormatElement::GetShaderVar(const byte *&data, const byte *end) c
return ret;
}
uint32_t FormatElement::byteSize()
uint32_t FormatElement::byteSize() const
{
uint32_t vecSize = format.compByteWidth * format.compCount;
+1 -1
View File
@@ -373,7 +373,7 @@ struct FormatElement
QString ElementString(const QVariant &var);
uint32_t byteSize();
uint32_t byteSize() const;
QString name;
int buffer;
+470 -301
View File
@@ -325,6 +325,7 @@ public:
void endReset()
{
cacheColumns();
m_ColumnCount = columnLookup.count() + reservedColumnCount();
emit endResetModel();
}
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
@@ -339,7 +340,7 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const override { return numRows; }
int columnCount(const QModelIndex &parent = QModelIndex()) const override
{
return columnLookup.count() + 2;
return m_ColumnCount;
}
Qt::ItemFlags flags(const QModelIndex &index) const override
{
@@ -351,13 +352,13 @@ public:
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
{
if(section < columnCount() && orientation == Qt::Horizontal && role == Qt::DisplayRole)
if(section < m_ColumnCount && orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
if(section == 0)
if(section == 0 && meshView)
{
return "VTX";
}
else if(section == 1)
else if(section == 1 && meshView)
{
return "IDX";
}
@@ -387,7 +388,7 @@ public:
opt.features |= QStyleOptionViewItem::HasDisplay;
// pad these columns to allow for sufficiently wide data
if(index.column() < 2)
if(index.column() < 2 && meshView)
opt.text = "999999";
else
opt.text = data(index).toString();
@@ -402,9 +403,9 @@ public:
uint32_t row = index.row();
int col = index.column();
if(col >= 0 && col < columnCount() && row < numRows)
if(col >= 0 && col < m_ColumnCount && row < numRows)
{
if(col == 0)
if(col == 0 && meshView)
return row;
uint32_t idx = row;
@@ -418,7 +419,7 @@ public:
idx = *(uint32_t *)idxData;
}
if(col == 1)
if(col == 1 && meshView)
return idx;
const FormatElement &el = columnForIndex(col);
@@ -510,6 +511,7 @@ public:
uint32_t curInstance = 0;
uint32_t numRows = 0;
bool meshView = true;
BufferData indices;
QList<FormatElement> columns;
QList<BufferData> buffers;
@@ -523,9 +525,14 @@ private:
// { 0, 1, 2, 3, 0, 1, 2, 0 };
QVector<int> columnLookup;
QVector<int> componentLookup;
int m_ColumnCount;
const FormatElement &columnForIndex(int col) const { return columns[columnLookup[col - 2]]; }
int componentForIndex(int col) const { return componentLookup[col - 2]; }
int reservedColumnCount() const { return (meshView ? 2 : 0); }
const FormatElement &columnForIndex(int col) const
{
return columns[columnLookup[col - reservedColumnCount()]];
}
int componentForIndex(int col) const { return componentLookup[col - reservedColumnCount()]; }
void cacheColumns()
{
columnLookup.clear();
@@ -575,7 +582,7 @@ private:
}
};
BufferViewer::BufferViewer(CaptureContext *ctx, QWidget *parent)
BufferViewer::BufferViewer(CaptureContext *ctx, bool meshview, QWidget *parent)
: QFrame(parent), ui(new Ui::BufferViewer), m_Ctx(ctx)
{
ui->setupUi(this);
@@ -588,17 +595,11 @@ BufferViewer::BufferViewer(CaptureContext *ctx, QWidget *parent)
m_Arcball = new ArcballWrapper();
m_CurrentCamera = m_Arcball;
m_Output = NULL;
memset(&m_Config, 0, sizeof(m_Config));
m_Config.type = eMeshDataStage_VSIn;
m_Config.ortho = false;
m_Config.showPrevInstances = false;
m_Config.showAllInstances = false;
m_Config.showWholePass = false;
m_Config.curInstance = 0;
m_Config.showBBox = false;
m_Config.solidShadeMode = eShade_None;
m_Config.wireframeDraw = true;
memset(&m_Config.position, 0, sizeof(m_Config.position));
memset(&m_Config.second, 0, sizeof(m_Config.second));
ui->outputTabs->setCurrentIndex(0);
m_CurStage = eMeshDataStage_VSIn;
@@ -607,46 +608,16 @@ BufferViewer::BufferViewer(CaptureContext *ctx, QWidget *parent)
ui->vsoutData->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
ui->gsoutData->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
setWindowTitle(tr("Mesh Output"));
m_ModelVSIn->meshView = m_ModelVSOut->meshView = m_ModelGSOut->meshView = m_MeshView = meshview;
ui->formatSpecifier->setVisible(false);
ui->cameraControlsGroup->setVisible(false);
ui->outputTabs->setWindowTitle(tr("Preview"));
ui->dockarea->addToolWindow(ui->outputTabs, ToolWindowManager::EmptySpace);
ui->dockarea->setToolWindowProperties(ui->outputTabs, ToolWindowManager::HideCloseButton);
ui->vsinData->setWindowTitle(tr("VS Input"));
ui->dockarea->addToolWindow(
ui->vsinData, ToolWindowManager::AreaReference(ToolWindowManager::TopOf,
ui->dockarea->areaOf(ui->outputTabs), 0.5f));
ui->dockarea->setToolWindowProperties(ui->vsinData, ToolWindowManager::HideCloseButton);
ui->vsoutData->setWindowTitle(tr("VS Output"));
ui->dockarea->addToolWindow(
ui->vsoutData, ToolWindowManager::AreaReference(ToolWindowManager::RightOf,
ui->dockarea->areaOf(ui->vsinData), 0.5f));
ui->dockarea->setToolWindowProperties(ui->vsoutData, ToolWindowManager::HideCloseButton);
ui->gsoutData->setWindowTitle(tr("GS/DS Output"));
ui->dockarea->addToolWindow(
ui->gsoutData, ToolWindowManager::AreaReference(ToolWindowManager::AddTo,
ui->dockarea->areaOf(ui->vsoutData), 0.5f));
ui->dockarea->setToolWindowProperties(ui->gsoutData, ToolWindowManager::HideCloseButton);
ToolWindowManager::raiseToolWindow(ui->vsoutData);
if(meshview)
SetupMeshView();
else
SetupRawView();
ui->dockarea->setAllowFloatingWindow(false);
ui->dockarea->setRubberBandLineWidth(50);
QVBoxLayout *vertical = new QVBoxLayout(this);
vertical->setSpacing(3);
vertical->setContentsMargins(0, 0, 0, 0);
vertical->addWidget(ui->meshToolbar);
vertical->addWidget(ui->dockarea);
ui->controlType->addItems({tr("Arcball"), tr("WASD")});
ui->controlType->adjustSize();
@@ -691,15 +662,92 @@ BufferViewer::BufferViewer(CaptureContext *ctx, QWidget *parent)
QObject::connect(ui->matrixType, OverloadedSlot<int>::of(&QComboBox::currentIndexChanged),
[this](int) { camGuess_changed(0.0); });
Reset();
m_Ctx->AddLogViewer(this);
}
void BufferViewer::SetupRawView()
{
ui->formatSpecifier->setVisible(true);
ui->outputTabs->setVisible(false);
ui->vsoutData->setVisible(false);
ui->gsoutData->setVisible(false);
// hide buttons we don't want in the toolbar
ui->syncViews->setVisible(false);
ui->offsetLine->setVisible(false);
ui->instanceLabel->setVisible(false);
ui->instance->setVisible(false);
ui->rowOffsetLabel->setVisible(false);
ui->rowOffset->setVisible(false);
ui->vsinData->setWindowTitle(tr("Buffer Contents"));
ui->dockarea->addToolWindow(ui->vsinData, ToolWindowManager::EmptySpace);
ui->dockarea->setToolWindowProperties(ui->vsinData, ToolWindowManager::HideCloseButton);
ui->formatSpecifier->setWindowTitle(tr("Buffer Format"));
ui->dockarea->addToolWindow(ui->formatSpecifier, ToolWindowManager::AreaReference(
ToolWindowManager::BottomOf,
ui->dockarea->areaOf(ui->vsinData), 0.5f));
ui->dockarea->setToolWindowProperties(ui->formatSpecifier, ToolWindowManager::HideCloseButton);
QObject::connect(ui->formatSpecifier, &BufferFormatSpecifier::processFormat, this,
&BufferViewer::processFormat);
QVBoxLayout *vertical = new QVBoxLayout(this);
vertical->setSpacing(3);
vertical->setContentsMargins(0, 0, 0, 0);
vertical->addWidget(ui->meshToolbar);
vertical->addWidget(ui->dockarea);
}
void BufferViewer::SetupMeshView()
{
setWindowTitle(tr("Mesh Output"));
ui->formatSpecifier->setVisible(false);
ui->cameraControlsGroup->setVisible(false);
ui->outputTabs->setWindowTitle(tr("Preview"));
ui->dockarea->addToolWindow(ui->outputTabs, ToolWindowManager::EmptySpace);
ui->dockarea->setToolWindowProperties(ui->outputTabs, ToolWindowManager::HideCloseButton);
ui->vsinData->setWindowTitle(tr("VS Input"));
ui->dockarea->addToolWindow(
ui->vsinData, ToolWindowManager::AreaReference(ToolWindowManager::TopOf,
ui->dockarea->areaOf(ui->outputTabs), 0.5f));
ui->dockarea->setToolWindowProperties(ui->vsinData, ToolWindowManager::HideCloseButton);
ui->vsoutData->setWindowTitle(tr("VS Output"));
ui->dockarea->addToolWindow(
ui->vsoutData, ToolWindowManager::AreaReference(ToolWindowManager::RightOf,
ui->dockarea->areaOf(ui->vsinData), 0.5f));
ui->dockarea->setToolWindowProperties(ui->vsoutData, ToolWindowManager::HideCloseButton);
ui->gsoutData->setWindowTitle(tr("GS/DS Output"));
ui->dockarea->addToolWindow(
ui->gsoutData, ToolWindowManager::AreaReference(ToolWindowManager::AddTo,
ui->dockarea->areaOf(ui->vsoutData), 0.5f));
ui->dockarea->setToolWindowProperties(ui->gsoutData, ToolWindowManager::HideCloseButton);
ToolWindowManager::raiseToolWindow(ui->vsoutData);
QVBoxLayout *vertical = new QVBoxLayout(this);
vertical->setSpacing(3);
vertical->setContentsMargins(0, 0, 0, 0);
vertical->addWidget(ui->meshToolbar);
vertical->addWidget(ui->dockarea);
QTimer *renderTimer = new QTimer(this);
QObject::connect(renderTimer, &QTimer::timeout, this, &BufferViewer::render_timer);
renderTimer->setSingleShot(false);
renderTimer->setInterval(10);
renderTimer->start();
Reset();
m_Ctx->AddLogViewer(this);
}
BufferViewer::~BufferViewer()
@@ -717,7 +765,9 @@ BufferViewer::~BufferViewer()
delete m_Arcball;
delete m_Flycam;
m_Ctx->windowClosed(this);
if(m_MeshView)
m_Ctx->windowClosed(this);
m_Ctx->RemoveLogViewer(this);
delete ui;
}
@@ -726,6 +776,9 @@ void BufferViewer::OnLogfileLoaded()
{
Reset();
if(!m_MeshView)
return;
WId renderID = ui->render->winId();
m_Ctx->Renderer()->BlockInvoke([renderID, this](IReplayRenderer *r) {
@@ -752,15 +805,18 @@ void BufferViewer::OnEventChanged(uint32_t eventID)
int vsoutHoriz = ui->vsoutData->horizontalScrollBar()->value();
int gsoutHoriz = ui->gsoutData->horizontalScrollBar()->value();
ClearModels();
if(m_MeshView)
{
ClearModels();
memset(&m_VSIn, 0, sizeof(m_VSIn));
memset(&m_PostVS, 0, sizeof(m_PostVS));
memset(&m_PostGS, 0, sizeof(m_PostGS));
memset(&m_VSIn, 0, sizeof(m_VSIn));
memset(&m_PostVS, 0, sizeof(m_PostVS));
memset(&m_PostGS, 0, sizeof(m_PostGS));
CalcColumnWidth();
CalcColumnWidth();
ClearModels();
ClearModels();
}
EnableCameraGuessControls();
@@ -774,14 +830,255 @@ void BufferViewer::OnEventChanged(uint32_t eventID)
const FetchDrawcall *draw = m_Ctx->CurDrawcall();
QVector<VertexInputAttribute> vinputs = m_Ctx->CurPipelineState.GetVertexInputs();
ui->instance->setEnabled(draw && draw->numInstances > 1);
if(!ui->instance->isEnabled())
ui->instance->setValue(0);
ui->instance->setMaximum(qMax(0, int(draw->numInstances) - 1));
if(m_MeshView)
ConfigureMeshColumns();
m_Ctx->Renderer()->AsyncInvoke([this, vsinHoriz, vsoutHoriz, gsoutHoriz](IReplayRenderer *r) {
if(m_MeshView)
{
RT_FetchMeshData(r);
}
else
{
BufferData buf = {};
rdctype::array<byte> data;
if(m_IsBuffer)
{
uint64_t len = m_ByteSize;
if(len == UINT64_MAX)
len = 0;
r->GetBufferData(m_BufferID, m_ByteOffset, len, &data);
}
else
{
r->GetTextureData(m_BufferID, m_TexArrayIdx, m_TexMip, &data);
}
buf.data = new byte[data.count];
memcpy(buf.data, data.elems, data.count);
buf.end = buf.data + data.count;
// calculate tight stride
buf.stride = 0;
for(const FormatElement &el : m_ModelVSIn->columns)
buf.stride += el.byteSize();
buf.stride = qMax((size_t)1, buf.stride);
m_ModelVSIn->numRows = uint32_t((data.count + buf.stride - 1) / buf.stride);
m_ModelVSIn->buffers.push_back(buf);
}
UpdateMeshConfig();
RT_UpdateAndDisplay(r);
GUIInvoke::call([this, vsinHoriz, vsoutHoriz, gsoutHoriz] {
m_ModelVSIn->endReset();
m_ModelVSOut->endReset();
m_ModelGSOut->endReset();
ApplyColumnWidths(m_ModelVSIn->columnCount(), ui->vsinData);
ApplyColumnWidths(m_ModelVSOut->columnCount(), ui->vsoutData);
ApplyColumnWidths(m_ModelGSOut->columnCount(), ui->gsoutData);
int numRows = qMax(qMax(m_ModelVSIn->numRows, m_ModelVSOut->numRows), m_ModelGSOut->numRows);
ui->rowOffset->setMaximum(qMax(0, numRows - 1));
ScrollToRow(m_ModelVSIn, ui->rowOffset->value());
ScrollToRow(m_ModelVSOut, ui->rowOffset->value());
ScrollToRow(m_ModelGSOut, ui->rowOffset->value());
ui->vsinData->horizontalScrollBar()->setValue(vsinHoriz);
ui->vsoutData->horizontalScrollBar()->setValue(vsoutHoriz);
ui->gsoutData->horizontalScrollBar()->setValue(gsoutHoriz);
});
});
}
void BufferViewer::RT_FetchMeshData(IReplayRenderer *r)
{
const FetchDrawcall *draw = m_Ctx->CurDrawcall();
ResourceId ib;
uint64_t ioffset = 0;
m_Ctx->CurPipelineState.GetIBuffer(ib, ioffset);
QVector<BoundVBuffer> vbs = m_Ctx->CurPipelineState.GetVBuffers();
rdctype::array<byte> idata;
if(ib != ResourceId() && draw)
r->GetBufferData(ib, ioffset + draw->indexOffset * draw->indexByteWidth,
draw->numIndices * draw->indexByteWidth, &idata);
uint32_t *indices = NULL;
m_ModelVSIn->indices = BufferData();
if(draw && draw->indexByteWidth != 0 && idata.count != 0)
{
indices = new uint32_t[draw->numIndices];
m_ModelVSIn->indices.data = (byte *)indices;
m_ModelVSIn->indices.end = (byte *)(indices + draw->numIndices);
}
uint32_t maxIndex = qMax(1U, draw->numIndices) - 1;
if(idata.count > 0)
{
maxIndex = 0;
if(draw->indexByteWidth == 1)
{
for(size_t i = 0; i < (size_t)idata.count && (uint32_t)i < draw->numIndices; i++)
{
indices[i] = (uint32_t)idata.elems[i];
maxIndex = qMax(maxIndex, indices[i]);
}
}
else if(draw->indexByteWidth == 2)
{
uint16_t *src = (uint16_t *)idata.elems;
for(size_t i = 0;
i < (size_t)idata.count / sizeof(uint16_t) && (uint32_t)i < draw->numIndices; i++)
{
indices[i] = (uint32_t)src[i];
maxIndex = qMax(maxIndex, indices[i]);
}
}
else if(draw->indexByteWidth == 4)
{
memcpy(indices, idata.elems, qMin((size_t)idata.count, draw->numIndices * sizeof(uint32_t)));
for(uint32_t i = 0; i < draw->numIndices; i++)
maxIndex = qMax(maxIndex, indices[i]);
}
}
int vbIdx = 0;
for(BoundVBuffer vb : vbs)
{
bool used = false;
bool pi = false;
bool pv = false;
for(const FormatElement &col : m_ModelVSIn->columns)
{
if(col.buffer == vbIdx)
{
used = true;
if(col.perinstance)
pi = true;
else
pv = true;
}
}
vbIdx++;
uint32_t maxIdx = 0;
uint32_t offset = 0;
if(used && draw)
{
if(pi)
{
maxIdx = qMax(1U, draw->numInstances) - 1;
offset = draw->instanceOffset;
}
if(pv)
{
maxIdx = qMax(maxIndex, maxIdx);
offset = draw->vertexOffset;
if(draw->baseVertex > 0)
maxIdx += (uint32_t)draw->baseVertex;
}
if(pi && pv)
qCritical() << "Buffer used for both instance and vertex rendering!";
}
BufferData buf = {};
if(used)
{
rdctype::array<byte> bufdata;
r->GetBufferData(vb.Buffer, vb.ByteOffset + offset * vb.ByteStride,
(maxIdx + 1) * vb.ByteStride, &bufdata);
buf.data = new byte[bufdata.count];
memcpy(buf.data, bufdata.elems, bufdata.count);
buf.end = buf.data + bufdata.count;
buf.stride = vb.ByteStride;
}
m_ModelVSIn->buffers.push_back(buf);
}
r->GetPostVSData(m_Config.curInstance, eMeshDataStage_VSOut, &m_PostVS);
m_ModelVSOut->numRows = m_PostVS.numVerts;
if(m_PostVS.idxbuf != ResourceId())
r->GetBufferData(m_PostVS.idxbuf, ioffset + draw->indexOffset * draw->indexByteWidth,
draw->numIndices * draw->indexByteWidth, &idata);
indices = NULL;
m_ModelVSOut->indices = BufferData();
if(draw && draw->indexByteWidth != 0 && idata.count != 0)
{
indices = new uint32_t[draw->numIndices];
m_ModelVSOut->indices.data = (byte *)indices;
m_ModelVSOut->indices.end = (byte *)(indices + draw->numIndices);
}
if(idata.count > 0)
{
if(draw->indexByteWidth == 1)
{
for(size_t i = 0; i < (size_t)idata.count && (uint32_t)i < draw->numIndices; i++)
indices[i] = (uint32_t)idata.elems[i];
}
else if(draw->indexByteWidth == 2)
{
uint16_t *src = (uint16_t *)idata.elems;
for(size_t i = 0;
i < (size_t)idata.count / sizeof(uint16_t) && (uint32_t)i < draw->numIndices; i++)
indices[i] = (uint32_t)src[i];
}
else if(draw->indexByteWidth == 4)
{
memcpy(indices, idata.elems, qMin((size_t)idata.count, draw->numIndices * sizeof(uint32_t)));
}
}
if(m_PostVS.buf != ResourceId())
{
BufferData postvs = {};
rdctype::array<byte> bufdata;
r->GetBufferData(m_PostVS.buf, m_PostVS.offset, 0, &bufdata);
postvs.data = new byte[bufdata.count];
memcpy(postvs.data, bufdata.elems, bufdata.count);
postvs.end = postvs.data + bufdata.count;
postvs.stride = m_PostVS.stride;
m_ModelVSOut->buffers.push_back(postvs);
}
}
void BufferViewer::ConfigureMeshColumns()
{
const FetchDrawcall *draw = m_Ctx->CurDrawcall();
QVector<VertexInputAttribute> vinputs = m_Ctx->CurPipelineState.GetVertexInputs();
m_ModelVSIn->columns.reserve(vinputs.count());
for(const VertexInputAttribute &a : vinputs)
@@ -915,199 +1212,20 @@ void BufferViewer::OnEventChanged(uint32_t eventID)
m_ModelVSOut->columns.insert(0, m_ModelVSOut->columns.takeAt(posidx));
}
}
m_Ctx->Renderer()->AsyncInvoke([this, draw, vbs, ib, ioffset, vsinHoriz, vsoutHoriz,
gsoutHoriz](IReplayRenderer *r) {
rdctype::array<byte> idata;
if(ib != ResourceId() && draw)
r->GetBufferData(ib, ioffset + draw->indexOffset * draw->indexByteWidth,
draw->numIndices * draw->indexByteWidth, &idata);
uint32_t *indices = NULL;
m_ModelVSIn->indices = BufferData();
if(draw && draw->indexByteWidth != 0 && idata.count != 0)
{
indices = new uint32_t[draw->numIndices];
m_ModelVSIn->indices.data = (byte *)indices;
m_ModelVSIn->indices.end = (byte *)(indices + draw->numIndices);
}
uint32_t maxIndex = qMax(1U, draw->numIndices) - 1;
if(idata.count > 0)
{
maxIndex = 0;
if(draw->indexByteWidth == 1)
{
for(size_t i = 0; i < (size_t)idata.count && (uint32_t)i < draw->numIndices; i++)
{
indices[i] = (uint32_t)idata.elems[i];
maxIndex = qMax(maxIndex, indices[i]);
}
}
else if(draw->indexByteWidth == 2)
{
uint16_t *src = (uint16_t *)idata.elems;
for(size_t i = 0;
i < (size_t)idata.count / sizeof(uint16_t) && (uint32_t)i < draw->numIndices; i++)
{
indices[i] = (uint32_t)src[i];
maxIndex = qMax(maxIndex, indices[i]);
}
}
else if(draw->indexByteWidth == 4)
{
memcpy(indices, idata.elems, qMin((size_t)idata.count, draw->numIndices * sizeof(uint32_t)));
for(uint32_t i = 0; i < draw->numIndices; i++)
maxIndex = qMax(maxIndex, indices[i]);
}
}
int vbIdx = 0;
for(BoundVBuffer vb : vbs)
{
bool used = false;
bool pi = false;
bool pv = false;
for(const FormatElement &col : m_ModelVSIn->columns)
{
if(col.buffer == vbIdx)
{
used = true;
if(col.perinstance)
pi = true;
else
pv = true;
}
}
vbIdx++;
uint32_t maxIdx = 0;
uint32_t offset = 0;
if(used && draw)
{
if(pi)
{
maxIdx = qMax(1U, draw->numInstances) - 1;
offset = draw->instanceOffset;
}
if(pv)
{
maxIdx = qMax(maxIndex, maxIdx);
offset = draw->vertexOffset;
if(draw->baseVertex > 0)
maxIdx += (uint32_t)draw->baseVertex;
}
if(pi && pv)
qCritical() << "Buffer used for both instance and vertex rendering!";
}
BufferData buf = {};
if(used)
{
rdctype::array<byte> data;
r->GetBufferData(vb.Buffer, vb.ByteOffset + offset * vb.ByteStride,
(maxIdx + 1) * vb.ByteStride, &data);
buf.data = new byte[data.count];
memcpy(buf.data, data.elems, data.count);
buf.end = buf.data + data.count;
buf.stride = vb.ByteStride;
}
m_ModelVSIn->buffers.push_back(buf);
}
r->GetPostVSData(m_Config.curInstance, eMeshDataStage_VSOut, &m_PostVS);
m_ModelVSOut->numRows = m_PostVS.numVerts;
if(m_PostVS.idxbuf != ResourceId())
r->GetBufferData(m_PostVS.idxbuf, ioffset + draw->indexOffset * draw->indexByteWidth,
draw->numIndices * draw->indexByteWidth, &idata);
indices = NULL;
m_ModelVSOut->indices = BufferData();
if(draw && draw->indexByteWidth != 0 && idata.count != 0)
{
indices = new uint32_t[draw->numIndices];
m_ModelVSOut->indices.data = (byte *)indices;
m_ModelVSOut->indices.end = (byte *)(indices + draw->numIndices);
}
if(idata.count > 0)
{
if(draw->indexByteWidth == 1)
{
for(size_t i = 0; i < (size_t)idata.count && (uint32_t)i < draw->numIndices; i++)
indices[i] = (uint32_t)idata.elems[i];
}
else if(draw->indexByteWidth == 2)
{
uint16_t *src = (uint16_t *)idata.elems;
for(size_t i = 0;
i < (size_t)idata.count / sizeof(uint16_t) && (uint32_t)i < draw->numIndices; i++)
indices[i] = (uint32_t)src[i];
}
else if(draw->indexByteWidth == 4)
{
memcpy(indices, idata.elems, qMin((size_t)idata.count, draw->numIndices * sizeof(uint32_t)));
}
}
if(m_PostVS.buf != ResourceId())
{
BufferData postvs = {};
rdctype::array<byte> data;
r->GetBufferData(m_PostVS.buf, m_PostVS.offset, 0, &data);
postvs.data = new byte[data.count];
memcpy(postvs.data, data.elems, data.count);
postvs.end = postvs.data + data.count;
postvs.stride = m_PostVS.stride;
m_ModelVSOut->buffers.push_back(postvs);
}
UpdateMeshConfig();
RT_UpdateAndDisplay(r);
GUIInvoke::call([this, vsinHoriz, vsoutHoriz, gsoutHoriz] {
m_ModelVSIn->endReset();
m_ModelVSOut->endReset();
ApplyColumnWidths(m_ModelVSIn->columnCount(), ui->vsinData);
ApplyColumnWidths(m_ModelVSOut->columnCount(), ui->vsoutData);
ApplyColumnWidths(m_ModelGSOut->columnCount(), ui->gsoutData);
int numRows = qMax(qMax(m_ModelVSIn->numRows, m_ModelVSOut->numRows), m_ModelGSOut->numRows);
ui->rowOffset->setMaximum(qMax(0, numRows - 1));
ScrollToRow(m_ModelVSIn, ui->rowOffset->value());
ScrollToRow(m_ModelVSOut, ui->rowOffset->value());
ScrollToRow(m_ModelGSOut, ui->rowOffset->value());
ui->vsinData->horizontalScrollBar()->setValue(vsinHoriz);
ui->vsoutData->horizontalScrollBar()->setValue(vsoutHoriz);
ui->gsoutData->horizontalScrollBar()->setValue(gsoutHoriz);
});
});
}
void BufferViewer::ApplyColumnWidths(int numColumns, RDTableView *view)
{
view->setColumnWidth(0, m_IdxColWidth);
view->setColumnWidth(1, m_IdxColWidth);
int start = 0;
for(int i = 2; i < numColumns; i++)
if(m_MeshView)
{
view->setColumnWidth(0, m_IdxColWidth);
view->setColumnWidth(1, m_IdxColWidth);
start = 2;
}
for(int i = start; i < numColumns; i++)
view->setColumnWidth(i, m_DataColWidth);
}
@@ -1185,6 +1303,41 @@ void BufferViewer::ScrollToRow(BufferItemModel *model, int row)
model->view->selectRow(row);
}
void BufferViewer::ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id,
const QString &format)
{
if(!m_Ctx->LogLoaded())
return;
m_IsBuffer = true;
m_ByteOffset = byteOffset;
m_ByteSize = byteSize;
m_BufferID = id;
FetchBuffer *buf = m_Ctx->GetBuffer(id);
if(buf)
setWindowTitle(ToQStr(buf->name) + " - Contents");
processFormat(format);
}
void BufferViewer::ViewTexture(uint32_t arrayIdx, uint32_t mip, ResourceId id, const QString &format)
{
if(!m_Ctx->LogLoaded())
return;
m_IsBuffer = false;
m_TexArrayIdx = arrayIdx;
m_TexMip = mip;
m_BufferID = id;
FetchTexture *tex = m_Ctx->GetTexture(id);
if(tex)
setWindowTitle(ToQStr(tex->name) + " - Contents");
processFormat(format);
}
void BufferViewer::render_mouseWheel(QWheelEvent *e)
{
if(m_CurrentCamera)
@@ -1337,62 +1490,54 @@ void BufferViewer::CalcColumnWidth()
floatFmt.compType = eCompType_UInt;
floatFmt.compCount = 1;
FormatElement floatEl("ColumnSizeTest", 0, 0, false, 1, false, 1, floatFmt, false);
FormatElement xintEl("ColumnSizeTest", 1, 0, false, 1, false, 1, intFmt, true);
FormatElement uintEl("ColumnSizeTest", 2, 0, false, 1, false, 1, intFmt, false);
FormatElement("ColumnSizeTest", 0, 0, false, 1, false, 1, floatFmt, false);
FormatElement("ColumnSizeTest", 0, 0, false, 1, false, 1, intFmt, true);
FormatElement("ColumnSizeTest", 0, 0, false, 1, false, 1, intFmt, false);
m_ModelVSIn->columns.clear();
m_ModelVSIn->columns.push_back(floatEl);
m_ModelVSIn->columns.push_back(xintEl);
m_ModelVSIn->columns.push_back(uintEl);
m_ModelVSIn->columns.push_back(
FormatElement("ColumnSizeTest", 0, 0, false, 1, false, 1, floatFmt, false));
m_ModelVSIn->columns.push_back(
FormatElement("ColumnSizeTest", 0, 4, false, 1, false, 1, floatFmt, false));
m_ModelVSIn->columns.push_back(
FormatElement("ColumnSizeTest", 0, 8, false, 1, false, 1, floatFmt, false));
m_ModelVSIn->columns.push_back(
FormatElement("ColumnSizeTest", 0, 12, false, 1, false, 1, intFmt, true));
m_ModelVSIn->columns.push_back(
FormatElement("ColumnSizeTest", 0, 16, false, 1, false, 1, intFmt, false));
m_ModelVSIn->numRows = 4;
m_ModelVSIn->numRows = 2;
m_ModelVSIn->indices.stride = sizeof(uint32_t);
m_ModelVSIn->indices.data = new byte[sizeof(uint32_t) * 4];
m_ModelVSIn->indices.end = m_ModelVSIn->indices.data + sizeof(uint32_t) * 4;
m_ModelVSIn->indices.data = new byte[sizeof(uint32_t) * 2];
m_ModelVSIn->indices.end = m_ModelVSIn->indices.data + sizeof(uint32_t) * 2;
uint32_t *indices = (uint32_t *)m_ModelVSIn->indices.data;
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 1000000;
indices[1] = 1000000;
m_ModelVSIn->buffers.clear();
struct TestData
{
float f[3];
uint32_t ui[3];
};
BufferData bufdata;
bufdata.stride = sizeof(float);
bufdata.data = new byte[sizeof(float) * 3];
bufdata.end = m_ModelVSIn->indices.data + sizeof(float) * 3;
bufdata.stride = sizeof(TestData);
bufdata.data = new byte[sizeof(TestData)];
bufdata.end = m_ModelVSIn->indices.data + sizeof(TestData);
m_ModelVSIn->buffers.push_back(bufdata);
float *floats = (float *)bufdata.data;
TestData *test = (TestData *)bufdata.data;
floats[0] = 1.0f;
floats[1] = 1.2345e-20f;
floats[2] = 123456.7890123456789f;
test->f[0] = 1.0f;
test->f[1] = 1.2345e-20f;
test->f[2] = 123456.7890123456789f;
bufdata.stride = sizeof(uint32_t);
bufdata.data = new byte[sizeof(uint32_t) * 3];
bufdata.end = m_ModelVSIn->indices.data + sizeof(uint32_t) * 3;
m_ModelVSIn->buffers.push_back(bufdata);
uint32_t *xints = (uint32_t *)bufdata.data;
xints[0] = 0;
xints[1] = 0x12345678;
xints[2] = 0xffffffff;
bufdata.stride = sizeof(uint32_t);
bufdata.data = new byte[sizeof(uint32_t) * 3];
bufdata.end = m_ModelVSIn->indices.data + sizeof(uint32_t) * 3;
m_ModelVSIn->buffers.push_back(bufdata);
uint32_t *uints = (uint32_t *)bufdata.data;
uints[0] = 0;
uints[1] = 0x12345678;
uints[2] = 0xffffffff;
test->ui[1] = 0x12345678;
test->ui[2] = 0xffffffff;
m_ModelVSIn->endReset();
@@ -1400,12 +1545,19 @@ void BufferViewer::CalcColumnWidth()
ui->vsinData->resizeColumnsToContents();
// index column
m_IdxColWidth = ui->vsinData->columnWidth(1);
int col = 0;
if(m_MeshView)
{
m_IdxColWidth = ui->vsinData->columnWidth(1);
col = 2;
}
int floatColWidth = ui->vsinData->columnWidth(2);
int xintColWidth = ui->vsinData->columnWidth(2);
int uintColWidth = ui->vsinData->columnWidth(3);
m_DataColWidth = qMax(floatColWidth, qMax(xintColWidth, uintColWidth));
m_DataColWidth = 10;
for(int c = 0; c < 5; c++)
{
int colWidth = ui->vsinData->columnWidth(col + c);
m_DataColWidth = qMax(m_DataColWidth, colWidth);
}
}
void BufferViewer::data_selected(const QItemSelection &selected, const QItemSelection &deselected)
@@ -1468,6 +1620,23 @@ void BufferViewer::camGuess_changed(double value)
INVOKE_MEMFN(RT_UpdateAndDisplay);
}
void BufferViewer::processFormat(const QString &format)
{
QString errors;
Reset();
CalcColumnWidth();
ClearModels();
m_ModelVSIn->columns = FormatElement::ParseFormatString(format, 0, true, errors);
ui->formatSpecifier->setErrors(errors);
OnEventChanged(m_Ctx->CurEvent());
}
void BufferViewer::SyncViews(RDTableView *primary, bool selection, bool scroll)
{
if(!ui->syncViews->isChecked())
+25 -1
View File
@@ -43,14 +43,19 @@ class BufferViewer : public QFrame, public ILogViewerForm
Q_OBJECT
public:
explicit BufferViewer(CaptureContext *ctx, QWidget *parent = 0);
explicit BufferViewer(CaptureContext *ctx, bool meshview, QWidget *parent = 0);
~BufferViewer();
void ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id, const QString &format = "");
void ViewTexture(uint32_t arrayIdx, uint32_t mip, ResourceId id, const QString &format = "");
void OnLogfileLoaded();
void OnLogfileClosed();
void OnSelectedEventChanged(uint32_t eventID) {}
void OnEventChanged(uint32_t eventID);
void RT_FetchMeshData(IReplayRenderer *r);
private slots:
// automatic slots
void on_outputTabs_currentChanged(int index);
@@ -80,6 +85,8 @@ private slots:
void data_scrolled(int scroll);
void camGuess_changed(double value);
void processFormat(const QString &format);
private:
Ui::BufferViewer *ui;
CaptureContext *m_Ctx;
@@ -91,14 +98,26 @@ private:
MeshDisplay m_Config;
MeshDataStage m_CurStage;
// data from mesh pipeline
MeshFormat m_VSIn;
MeshFormat m_PostVS;
MeshFormat m_PostGS;
// data from raw buffer view
bool m_IsBuffer = true;
uint32_t m_TexArrayIdx = 0;
uint32_t m_TexMip = 0;
uint64_t m_ByteOffset = 0;
uint64_t m_ByteSize = UINT64_MAX;
ResourceId m_BufferID;
CameraWrapper *m_CurrentCamera = NULL;
ArcballWrapper *m_Arcball = NULL;
FlycamWrapper *m_Flycam = NULL;
bool m_MeshView;
BufferItemModel *m_ModelVSIn;
BufferItemModel *m_ModelVSOut;
BufferItemModel *m_ModelGSOut;
@@ -110,9 +129,14 @@ private:
BufferItemModel *currentBufferModel();
bool isCurrentRasterOut();
void SetupMeshView();
void SetupRawView();
void Reset();
void ClearModels();
void ConfigureMeshColumns();
void UpdateMeshConfig();
void EnableCameraGuessControls();
+2 -9
View File
@@ -610,7 +610,7 @@
</widget>
</item>
<item>
<widget class="Line" name="line">
<widget class="Line" name="controlsLine">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@@ -666,7 +666,7 @@
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<widget class="Line" name="offsetLine">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@@ -689,13 +689,6 @@
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="instanceLabel">
<property name="text">
@@ -1747,10 +1747,16 @@ void D3D11PipelineStateViewer::resource_itemActivated(QTreeWidgetItem *item, int
{
if(tex->resType == eResType_Buffer)
{
// TODO Buffer viewer
// var viewer = new BufferViewer(m_Core, false);
// viewer.ViewRawBuffer(false, 0, ulong.MaxValue, tex.ID);
// viewer.Show(m_DockContent.DockPanel);
BufferViewer *viewer = new BufferViewer(m_Ctx, false, m_Ctx->mainWindow());
viewer->ViewTexture(0, 0, tex->ID);
m_Ctx->setupDockWindow(viewer);
ToolWindowManager *manager = ToolWindowManager::managerOf(this);
ToolWindowManager::AreaReference ref(ToolWindowManager::AddTo, manager->areaOf(this));
manager->addToolWindow(viewer, ref);
}
else
{
@@ -1822,7 +1828,7 @@ void D3D11PipelineStateViewer::resource_itemActivated(QTreeWidgetItem *item, int
{
format = QString("// struct %1\n{\n%2}")
.arg(ToQStr(res.variableType.descriptor.name))
.arg(formatMembers(1, "", res.variableType.members.back().type.members));
.arg(formatMembers(1, "", res.variableType.members));
}
else
{
@@ -1838,7 +1844,7 @@ void D3D11PipelineStateViewer::resource_itemActivated(QTreeWidgetItem *item, int
if(desc.rows > 1 && desc.cols > 1)
format += QString("%1x%2").arg(desc.rows).arg(desc.cols);
else if(desc.cols > 1)
format += desc.cols;
format += QString::number(desc.cols);
if(!desc.name.empty())
format += " " + ToQStr(desc.name);
@@ -1905,17 +1911,23 @@ void D3D11PipelineStateViewer::resource_itemActivated(QTreeWidgetItem *item, int
if(view.res.Flags & RawBuffer)
format = "xint";
format += fmt.compCount;
format += QString::number(fmt.compCount);
}
}
}
}
{
// TODO Buffer viewer
// var viewer = new BufferViewer(m_Core, false);
// viewer.ViewRawBuffer(true, buf.offset, buf.size, buf.ID, format);
// viewer.Show(m_DockContent.DockPanel);
BufferViewer *viewer = new BufferViewer(m_Ctx, false, m_Ctx->mainWindow());
viewer->ViewBuffer(offs, size, view.res.Resource, format);
m_Ctx->setupDockWindow(viewer);
ToolWindowManager *manager = ToolWindowManager::managerOf(this);
ToolWindowManager::AreaReference ref(ToolWindowManager::AddTo, manager->areaOf(this));
manager->addToolWindow(viewer, ref);
}
}
}
@@ -1967,10 +1979,16 @@ void D3D11PipelineStateViewer::on_iaBuffers_itemActivated(QTreeWidgetItem *item,
if(buf.id != ResourceId())
{
// TODO Buffer Viewer
// var viewer = new BufferViewer(m_Core, false);
// viewer.ViewRawBuffer(true, buf.offset, ulong.MaxValue, buf.id);
// viewer.Show(m_DockContent.DockPanel);
BufferViewer *viewer = new BufferViewer(m_Ctx, false, m_Ctx->mainWindow());
viewer->ViewBuffer(buf.offset, UINT64_MAX, buf.id);
m_Ctx->setupDockWindow(viewer);
ToolWindowManager *manager = ToolWindowManager::managerOf(this);
ToolWindowManager::AreaReference ref(ToolWindowManager::AddTo, manager->areaOf(this));
manager->addToolWindow(viewer, ref);
}
}
}
@@ -1810,7 +1810,7 @@ void D3D12PipelineStateViewer::resource_itemActivated(QTreeWidgetItem *item, int
{
format = QString("// struct %1\n{\n%2}")
.arg(ToQStr(res.variableType.descriptor.name))
.arg(formatMembers(1, "", res.variableType.members.back().type.members));
.arg(formatMembers(1, "", res.variableType.members));
}
else
{
+27 -1
View File
@@ -39,7 +39,9 @@
#include "Dialogs/TextureSaveDialog.h"
#include "Widgets/ResourcePreview.h"
#include "Widgets/TextureGoto.h"
#include "BufferViewer.h"
#include "FlowLayout.h"
#include "MainWindow.h"
#include "ui_TextureViewer.h"
float area(const QSizeF &s)
@@ -1704,7 +1706,16 @@ void TextureViewer::ViewTexture(ResourceId ID, bool focus)
FetchBuffer *buf = m_Ctx->GetBuffer(ID);
if(buf)
{
// load in BufferViewer
BufferViewer *viewer = new BufferViewer(m_Ctx, false, m_Ctx->mainWindow());
viewer->ViewTexture(0, 0, ID);
m_Ctx->setupDockWindow(viewer);
ToolWindowManager *manager = ToolWindowManager::managerOf(this);
ToolWindowManager::AreaReference ref(ToolWindowManager::AddTo, manager->areaOf(this));
manager->addToolWindow(viewer, ref);
}
}
@@ -3168,6 +3179,21 @@ void TextureViewer::ShowGotoPopup()
void TextureViewer::on_viewTexBuffer_clicked()
{
FetchTexture *texptr = GetCurrentTexture();
if(texptr)
{
BufferViewer *viewer = new BufferViewer(m_Ctx, false, m_Ctx->mainWindow());
viewer->ViewTexture(m_TexDisplay.sliceFace, m_TexDisplay.mip, texptr->ID);
m_Ctx->setupDockWindow(viewer);
ToolWindowManager *manager = ToolWindowManager::managerOf(this);
ToolWindowManager::AreaReference ref(ToolWindowManager::AddTo, manager->areaOf(this));
manager->addToolWindow(viewer, ref);
}
}
void TextureViewer::on_saveTex_clicked()