diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index 3c3b2c2b2..77801afbb 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -575,6 +576,42 @@ private: QAbstractItemView *m_widget; }; +// helper functions for using a double spinbox for 64-bit integers. We do this because it's +// infeasible in Qt to actually derive and create a real 64-bit integer spinbox because critical +// functionality depends on deriving QAbstractSpinBoxPrivate which is unavailable. So instead we use +// a QDoubleSpinBox and restrict ourselves to the 53 bits of mantissa. This struct only has inline +// helpers so we can cast a QDoubleSpinBox to one of these and use it as-is. +class RDSpinBox64 : public QDoubleSpinBox +{ +private: + static const qlonglong mask = (1ULL << 53U) - 1; + +public: + void configure() { QDoubleSpinBox::setDecimals(0); } + void setSingleStep(qlonglong val) { QDoubleSpinBox::setSingleStep(makeValue(val)); } + void setMinimum(qlonglong min) { QDoubleSpinBox::setMinimum(makeValue(min)); } + void setMaximum(qlonglong max) { QDoubleSpinBox::setMaximum(makeValue(max)); } + void setRange(qlonglong min, qlonglong max) + { + RDSpinBox64::setMinimum(min); + RDSpinBox64::setMaximum(max); + } + + void setSingleStep(qulonglong val) { QDoubleSpinBox::setSingleStep(makeValue(val)); } + void setMinimum(qulonglong min) { QDoubleSpinBox::setMinimum(makeValue(min)); } + void setMaximum(qulonglong max) { QDoubleSpinBox::setMaximum(makeValue(max)); } + void setRange(qulonglong min, qulonglong max) + { + RDSpinBox64::setMinimum(min); + RDSpinBox64::setMaximum(max); + } + + static qlonglong getValue(double d) { return qlonglong(d); } + static qulonglong getUValue(double d) { return qulonglong(d); } + static double makeValue(qlonglong l) { return l < 0 ? -double((-l) & mask) : double(l & mask); } + static double makeValue(qulonglong l) { return double(l & mask); } +}; + class QMenu; // helper for doing a manual blocking invoke of a dialog diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index 45877ccba..212d1a6f3 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -1913,6 +1913,15 @@ BufferViewer::BufferViewer(ICaptureContext &ctx, bool meshview, QWidget *parent) { ui->setupUi(this); + byteRangeStart = (RDSpinBox64 *)ui->byteRangeStart; + byteRangeLength = (RDSpinBox64 *)ui->byteRangeLength; + + byteRangeStart->configure(); + byteRangeLength->configure(); + + byteRangeStart->setMinimum(0ULL); + byteRangeLength->setMinimum(0ULL); + m_ModelVSIn = new BufferItemModel(ui->vsinData, true, meshview, this); m_ModelVSOut = new BufferItemModel(ui->vsoutData, false, meshview, this); m_ModelGSOut = new BufferItemModel(ui->gsoutData, false, meshview, this); @@ -2129,9 +2138,9 @@ void BufferViewer::SetupMeshView() // hide buttons we don't want in the toolbar ui->byteRangeLine->setVisible(false); ui->byteRangeStartLabel->setVisible(false); - ui->byteRangeStart->setVisible(false); + byteRangeStart->setVisible(false); ui->byteRangeLengthLabel->setVisible(false); - ui->byteRangeLength->setVisible(false); + byteRangeLength->setVisible(false); ui->resourceDetails->setVisible(false); ui->formatSpecifier->setVisible(false); @@ -3848,34 +3857,34 @@ void BufferViewer::processFormat(const QString &format) ui->formatSpecifier->setFormat(format); - uint32_t stride = qMax(1U, cols.type.descriptor.arrayByteStride); + qulonglong stride = qMax(1U, cols.type.descriptor.arrayByteStride); - ui->byteRangeStart->setSingleStep((int)stride); - ui->byteRangeLength->setSingleStep((int)stride); + byteRangeStart->setSingleStep(stride); + byteRangeLength->setSingleStep(stride); - ui->byteRangeStart->setMaximum((int)m_ObjectByteSize); - ui->byteRangeLength->setMaximum((int)m_ObjectByteSize); + byteRangeStart->setMaximum(m_ObjectByteSize); + byteRangeLength->setMaximum(m_ObjectByteSize); - ui->byteRangeStart->setValue((int)m_ByteOffset); - ui->byteRangeLength->setValue((int)m_ByteSize); + byteRangeStart->setValue(m_ByteOffset); + byteRangeLength->setValue(m_ByteSize); ui->formatSpecifier->setErrors(errors); OnEventChanged(m_Ctx.CurEvent()); } -void BufferViewer::on_byteRangeStart_valueChanged(int value) +void BufferViewer::on_byteRangeStart_valueChanged(double value) { - m_ByteOffset = value; + m_ByteOffset = RDSpinBox64::getUValue(value); m_PagingByteOffset = 0; processFormat(m_Format); } -void BufferViewer::on_byteRangeLength_valueChanged(int value) +void BufferViewer::on_byteRangeLength_valueChanged(double value) { - m_ByteSize = value; + m_ByteSize = RDSpinBox64::getUValue(value); m_PagingByteOffset = 0; diff --git a/qrenderdoc/Windows/BufferViewer.h b/qrenderdoc/Windows/BufferViewer.h index 7c103166e..e84db8844 100644 --- a/qrenderdoc/Windows/BufferViewer.h +++ b/qrenderdoc/Windows/BufferViewer.h @@ -34,6 +34,7 @@ namespace Ui class BufferViewer; } +class RDSpinBox64; class QItemSelection; class QMenu; class QPushButton; @@ -112,8 +113,8 @@ private slots: void on_instance_valueChanged(int value); void on_viewIndex_valueChanged(int value); void on_rowOffset_valueChanged(int value); - void on_byteRangeStart_valueChanged(int value); - void on_byteRangeLength_valueChanged(int value); + void on_byteRangeStart_valueChanged(double value); + void on_byteRangeLength_valueChanged(double value); // manual slots void render_mouseMove(QMouseEvent *e); @@ -226,6 +227,9 @@ private: QAction *m_ExportBytes = NULL; QAction *m_DebugVert = NULL; + RDSpinBox64 *byteRangeStart = NULL; + RDSpinBox64 *byteRangeLength = NULL; + RDTableView *tableForStage(MeshDataStage stage); BufferItemModel *modelForStage(MeshDataStage stage); diff --git a/qrenderdoc/Windows/BufferViewer.ui b/qrenderdoc/Windows/BufferViewer.ui index de449430b..d8f18d7be 100644 --- a/qrenderdoc/Windows/BufferViewer.ui +++ b/qrenderdoc/Windows/BufferViewer.ui @@ -916,7 +916,7 @@ Enter 0.0 to use automatic/guessed value derived from data. - + 999123456 @@ -930,7 +930,7 @@ Enter 0.0 to use automatic/guessed value derived from data. - + 999123456