From 4f39279578a97fd4bb0b7de894c26054bbb02a67 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 13 Mar 2020 18:00:34 +0000 Subject: [PATCH] When opening a texture in raw buffer viewer, scroll to selected point --- qrenderdoc/Code/Interface/QRDInterface.h | 7 ++ qrenderdoc/Widgets/Extended/RDTableView.cpp | 26 +++--- qrenderdoc/Windows/BufferViewer.cpp | 88 +++++++++++++++++++-- qrenderdoc/Windows/BufferViewer.h | 15 +++- qrenderdoc/Windows/TextureViewer.cpp | 3 + 5 files changed, 113 insertions(+), 26 deletions(-) diff --git a/qrenderdoc/Code/Interface/QRDInterface.h b/qrenderdoc/Code/Interface/QRDInterface.h index e748ab0dd..335a12775 100644 --- a/qrenderdoc/Code/Interface/QRDInterface.h +++ b/qrenderdoc/Code/Interface/QRDInterface.h @@ -287,6 +287,13 @@ struct IBufferViewer )"); virtual void ScrollToRow(int row, MeshDataStage stage = MeshDataStage::VSIn) = 0; + DOCUMENT(R"(Scroll to the given column in the given stage's data. + +:param int column: the column to scroll to. +:param ~renderdoc.MeshDataStage stage: The stage of the geometry pipeline to scroll within. +)"); + virtual void ScrollToColumn(int column, MeshDataStage stage = MeshDataStage::VSIn) = 0; + DOCUMENT(R"(In a raw buffer viewer, load the contents from a particular buffer resource. :param int byteOffset: The offset in bytes to the start of the data. diff --git a/qrenderdoc/Widgets/Extended/RDTableView.cpp b/qrenderdoc/Widgets/Extended/RDTableView.cpp index f2f091f75..c31d679b2 100644 --- a/qrenderdoc/Widgets/Extended/RDTableView.cpp +++ b/qrenderdoc/Widgets/Extended/RDTableView.cpp @@ -375,23 +375,7 @@ void RDTableView::scrollTo(const QModelIndex &index, ScrollHint hint) // assume per-item vertical scrolling and per-pixel horizontal scrolling // for any hint except position at center, we just ensure it's visible horizontally - if(hint != QAbstractItemView::PositionAtCenter) - { - // scroll into view from the left - if(dataRect.left() > cellRect.left()) - { - horizontalScrollBar()->setValue(horizontalScrollBar()->value() - - (dataRect.left() - cellRect.left())); - } - - // scroll into view from the right - if(dataRect.right() < cellRect.right()) - { - horizontalScrollBar()->setValue(horizontalScrollBar()->value() + - (cellRect.right() - dataRect.right())); - } - } - else + if(hint == QAbstractItemView::PositionAtCenter) { // center it horizontally from the left QPoint dataCenter = dataRect.center(); @@ -410,6 +394,14 @@ void RDTableView::scrollTo(const QModelIndex &index, ScrollHint hint) (cellCenter.x() - dataCenter.x())); } } + else if(hint == QAbstractItemView::PositionAtTop) + { + horizontalScrollBar()->setValue(cellRect.left() - dataRect.left()); + } + else if(hint == QAbstractItemView::PositionAtBottom) + { + horizontalScrollBar()->setValue(cellRect.right() - dataRect.right()); + } // collapse EnsureVisible to either PositionAtTop or PositionAtBottom depending on which side it's // on, or just return if we only had to make it visible horizontally diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index 5d09b6592..d7631d78a 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -1331,6 +1331,8 @@ struct CachedElData struct PopulateBufferData { + int sequence; + int vsinHoriz; int vsoutHoriz; int gsoutHoriz; @@ -2309,10 +2311,8 @@ void BufferViewer::OnCaptureClosed() ToolWindowManager::closeToolWindow(this); } -void BufferViewer::OnEventChanged(uint32_t eventId) +void BufferViewer::FillScrolls(PopulateBufferData *bufdata) { - PopulateBufferData *bufdata = new PopulateBufferData; - bufdata->vsinHoriz = ui->vsinData->horizontalScrollBar()->value(); bufdata->vsoutHoriz = ui->vsoutData->horizontalScrollBar()->value(); bufdata->gsoutHoriz = ui->gsoutData->horizontalScrollBar()->value(); @@ -2320,6 +2320,39 @@ void BufferViewer::OnEventChanged(uint32_t eventId) bufdata->vsinVert = ui->vsinData->indexAt(QPoint(0, 0)).row(); bufdata->vsoutVert = ui->vsoutData->indexAt(QPoint(0, 0)).row(); bufdata->gsoutVert = ui->gsoutData->indexAt(QPoint(0, 0)).row(); +} + +void BufferViewer::OnEventChanged(uint32_t eventId) +{ + PopulateBufferData *bufdata = new PopulateBufferData; + + m_Sequence++; + bufdata->sequence = m_Sequence; + + if(m_Scrolls) + { + bufdata->vsinHoriz = m_Scrolls->vsinHoriz; + bufdata->vsoutHoriz = m_Scrolls->vsoutHoriz; + bufdata->gsoutHoriz = m_Scrolls->gsoutHoriz; + + bufdata->vsinVert = m_Scrolls->vsinVert; + bufdata->vsoutVert = m_Scrolls->vsoutVert; + bufdata->gsoutVert = m_Scrolls->gsoutVert; + + delete m_Scrolls; + m_Scrolls = NULL; + } + else + { + FillScrolls(bufdata); + } + + // remove any pending scrolls, which have been applied. If nothing changes over the data + // population the above scroll preserving will work. + // however if m_Scroll is set while data is populationg, we'll apply it when it comes to the end + m_Scroll[(int)MeshDataStage::VSIn] = QPoint(-1, -1); + m_Scroll[(int)MeshDataStage::VSOut] = QPoint(-1, -1); + m_Scroll[(int)MeshDataStage::GSOut] = QPoint(-1, -1); bufdata->highlightNames[0] = m_ModelVSIn->posName(); bufdata->highlightNames[1] = m_ModelVSIn->secondaryName(); @@ -2488,6 +2521,9 @@ void BufferViewer::OnEventChanged(uint32_t eventId) } GUIInvoke::call(this, [this, bufdata]() { + if(bufdata->sequence != m_Sequence) + return; + m_ModelVSIn->endReset(bufdata->vsinConfig); m_ModelVSOut->endReset(bufdata->vsoutConfig); m_ModelGSOut->endReset(bufdata->gsoutConfig); @@ -2548,11 +2584,22 @@ void BufferViewer::OnEventChanged(uint32_t eventId) ui->vsoutData->horizontalScrollBar()->setValue(bufdata->vsoutHoriz); ui->gsoutData->horizontalScrollBar()->setValue(bufdata->gsoutHoriz); - if(!m_MeshView) - on_rowOffset_valueChanged(ui->rowOffset->value()); + for(MeshDataStage stage : {MeshDataStage::VSIn, MeshDataStage::VSOut, MeshDataStage::GSOut}) + { + int i = (int)stage; + + if(m_Scroll[i].y() >= 0) + ScrollToRow(tableForStage(stage), m_Scroll[i].y()); + if(m_Scroll[i].x() >= 0) + ScrollToColumn(tableForStage(stage), m_Scroll[i].x()); + + m_Scroll[i] = QPoint(-1, -1); + } if(!m_MeshView) { + on_rowOffset_valueChanged(ui->rowOffset->value()); + const bool prev = (bufdata->vsinConfig.pagingOffset > 0); const bool next = (bufdata->vsinConfig.numRows >= MaxVisibleRows); @@ -3228,6 +3275,15 @@ void BufferViewer::ScrollToRow(RDTableView *view, int row) view->horizontalScrollBar()->setValue(hs); } +void BufferViewer::ScrollToColumn(RDTableView *view, int column) +{ + int vs = view->verticalScrollBar()->value(); + + view->scrollTo(view->model()->index(0, column), QAbstractItemView::PositionAtTop); + + view->verticalScrollBar()->setValue(vs); +} + void BufferViewer::ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id, const rdcstr &format) { @@ -3270,6 +3326,24 @@ void BufferViewer::ViewTexture(ResourceId id, const Subresource &sub, const rdcs processFormat(format); } +void BufferViewer::ScrollToRow(int row, MeshDataStage stage) +{ + ScrollToRow(tableForStage(stage), row); + + if(m_MeshView) + m_Scroll[(int)stage].setY(row); + else + // the row scroll is visible and handles paging in the non-mesh view, so use it + ui->rowOffset->setValue(row); +} + +void BufferViewer::ScrollToColumn(int column, MeshDataStage stage) +{ + ScrollToColumn(tableForStage(stage), column); + + m_Scroll[(int)stage].setX(column); +} + bool BufferViewer::eventFilter(QObject *watched, QEvent *event) { if(!m_MeshView && watched == ui->vsinData->viewport() && event->type() == QEvent::MouseMove) @@ -3678,6 +3752,10 @@ void BufferViewer::processFormat(const QString &format) { QString errors; + // save scroll values now before we reset all the models + m_Scrolls = new PopulateBufferData; + FillScrolls(m_Scrolls); + Reset(); BufferConfiguration bufconfig; diff --git a/qrenderdoc/Windows/BufferViewer.h b/qrenderdoc/Windows/BufferViewer.h index 4bf078061..7c103166e 100644 --- a/qrenderdoc/Windows/BufferViewer.h +++ b/qrenderdoc/Windows/BufferViewer.h @@ -80,10 +80,8 @@ public: // IBufferViewer QWidget *Widget() override { return this; } - void ScrollToRow(int row, MeshDataStage stage = MeshDataStage::VSIn) override - { - ScrollToRow(tableForStage(stage), row); - } + void ScrollToRow(int row, MeshDataStage stage = MeshDataStage::VSIn) override; + void ScrollToColumn(int column, MeshDataStage stage = MeshDataStage::VSIn) override; void ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id, const rdcstr &format = "") override; void ViewTexture(ResourceId id, const Subresource &sub, const rdcstr &format = "") override; @@ -174,6 +172,8 @@ private: void UI_UpdateBoundingBox(const CalcBoundingBoxData &bbox); void UI_UpdateBoundingBoxLabels(int compCount = 0); + void FillScrolls(PopulateBufferData *bufdata); + void UI_ResetArcball(); uint64_t CurrentByteOffset(); @@ -198,6 +198,12 @@ private: BufferItemModel *m_ModelVSOut; BufferItemModel *m_ModelGSOut; + PopulateBufferData *m_Scrolls = NULL; + + QPoint m_Scroll[4]; + + int m_Sequence = 0; + RDTableView *m_CurView = NULL; int m_ContextColumn = -1; @@ -251,4 +257,5 @@ private: void SyncViews(RDTableView *primary, bool selection, bool scroll); void UpdateHighlightVerts(); void ScrollToRow(RDTableView *view, int row); + void ScrollToColumn(RDTableView *view, int column); }; diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 52d6ca342..43d07e0c2 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -3626,6 +3626,9 @@ void TextureViewer::on_viewTexBuffer_clicked() m_Ctx.ViewTextureAsBuffer(texptr->resourceId, m_TexDisplay.subresource, BufferFormatter::GetTextureFormatString(*texptr)); + viewer->ScrollToRow(m_PickedPoint.y()); + viewer->ScrollToColumn(m_PickedPoint.x() * texptr->format.compCount + 1); + m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this); } }