From 6ce881d5da0156997ccbd86d38f2d1063526aa51 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Thu, 9 Nov 2023 10:37:34 +0000 Subject: [PATCH] UI and Config support for dec/hex display option for Offsets or Sizes Used when fields are marked as being an Offset or Size Include simple latch to trigger a UI refresh when closing the settings dialog. Currently only connected to if the Offset/Size format option is altered --- docs/python_api/qrenderdoc/config.rst | 3 ++ .../Code/Interface/PersistantConfig.cpp | 12 +++++ qrenderdoc/Code/Interface/PersistantConfig.h | 34 ++++++++++++++ qrenderdoc/Code/QRDUtils.cpp | 36 +++++++++++++-- qrenderdoc/Code/QRDUtils.h | 8 +++- qrenderdoc/Windows/Dialogs/SettingsDialog.cpp | 26 +++++++++++ qrenderdoc/Windows/Dialogs/SettingsDialog.h | 2 + qrenderdoc/Windows/Dialogs/SettingsDialog.ui | 45 +++++++++++++------ renderdoc/api/replay/structured_data.h | 6 +++ renderdoc/serialise/serialiser.h | 13 ++++++ 10 files changed, 166 insertions(+), 19 deletions(-) diff --git a/docs/python_api/qrenderdoc/config.rst b/docs/python_api/qrenderdoc/config.rst index f636966c2..2b2e5d025 100644 --- a/docs/python_api/qrenderdoc/config.rst +++ b/docs/python_api/qrenderdoc/config.rst @@ -13,6 +13,9 @@ Config .. autoclass:: qrenderdoc.TimeUnit :members: + +.. autoclass:: qrenderdoc.OffsetSizeDisplayMode + :members: .. autofunction:: qrenderdoc.ConfigFilePath .. autofunction:: qrenderdoc.UnitSuffix diff --git a/qrenderdoc/Code/Interface/PersistantConfig.cpp b/qrenderdoc/Code/Interface/PersistantConfig.cpp index 093bd4895..5e9f6d20b 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.cpp +++ b/qrenderdoc/Code/Interface/PersistantConfig.cpp @@ -44,6 +44,18 @@ rdcstr DoStringise(const TimeUnit &el) END_ENUM_STRINGISE(); } +template <> +rdcstr DoStringise(const OffsetSizeDisplayMode &el) +{ + BEGIN_ENUM_STRINGISE(OffsetSizeDisplayMode) + { + STRINGISE_ENUM_CLASS(Auto); + STRINGISE_ENUM_CLASS(Decimal); + STRINGISE_ENUM_CLASS(Hexadecimal); + } + END_ENUM_STRINGISE(); +} + #define JSON_ID "rdocConfigData" #define JSON_VER 1 diff --git a/qrenderdoc/Code/Interface/PersistantConfig.h b/qrenderdoc/Code/Interface/PersistantConfig.h index 12d77b5ad..1d49db8cd 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.h +++ b/qrenderdoc/Code/Interface/PersistantConfig.h @@ -372,6 +372,16 @@ DECLARE_REFLECTION_STRUCT(BugReport); "Defaults to ``7``."); \ CONFIG_SETTING_VAL(public, int, int, Formatter_PosExp, 7) \ \ + DOCUMENT( \ + "The formatting mode to use for values marked as Offsets or Sizes.\n" \ + "\n" \ + "E.g. Auto: decimal by default and hexadecimal if above a certain threshold, " \ + "Decimal: always use decimal, Hexadecimal: always use hexadecimal." \ + "\n" \ + "Defaults to ``Auto``."); \ + CONFIG_SETTING_VAL(public, int, OffsetSizeDisplayMode, Formatter_OffsetSizeDisplayMode, \ + OffsetSizeDisplayMode::Auto) \ + \ DOCUMENT( \ "The global scale to apply to fonts in the application, expressed as a float.\n" \ "\n" \ @@ -529,6 +539,30 @@ DECLARE_REFLECTION_STRUCT(BugReport); DOCUMENT(""); \ CONFIG_SETTING(private, QVariantList, rdcarray, RemoteHostList) +DOCUMENT(R"(The formatting mode used when displaying fields marked as Offsets or Sizes. + +.. data:: Auto + + The data is displayed as decimal values by default and hexadecimal if above a certain threshold. + +.. data:: Decimal + + The data is displayed as decimal values. + +.. data:: Hexadecimal + + The data is displayed as hexadecimal values. +)"); +enum class OffsetSizeDisplayMode : int +{ + Auto = 0, + Decimal, + Hexadecimal, + Count, +}; + +DECLARE_REFLECTION_ENUM(OffsetSizeDisplayMode); + DOCUMENT(R"(The unit that GPU durations are displayed in. .. data:: Seconds diff --git a/qrenderdoc/Code/QRDUtils.cpp b/qrenderdoc/Code/QRDUtils.cpp index a6a7b2a63..3921e4a06 100644 --- a/qrenderdoc/Code/QRDUtils.cpp +++ b/qrenderdoc/Code/QRDUtils.cpp @@ -1782,6 +1782,11 @@ QVariant SDObject2Variant(const SDObject *obj, bool inlineImportant) } else { + Formatter::FormatterFlags flags = Formatter::NoFlags; + if((obj->type.flags & SDTypeFlags::OffsetOrSize) || + ((obj->GetParent() && obj->GetParent()->type.flags & SDTypeFlags::OffsetOrSize))) + flags = Formatter::OffsetSize; + switch(obj->type.basetype) { case SDBasic::Chunk: @@ -1893,7 +1898,9 @@ QVariant SDObject2Variant(const SDObject *obj, bool inlineImportant) } case SDBasic::Resource: case SDBasic::Enum: - case SDBasic::UnsignedInteger: param = Formatter::HumanFormat(obj->data.basic.u); break; + case SDBasic::UnsignedInteger: + param = Formatter::HumanFormat(obj->data.basic.u, flags); + break; case SDBasic::SignedInteger: param = Formatter::Format(obj->data.basic.i); break; case SDBasic::Float: param = Formatter::Format(obj->data.basic.d); break; case SDBasic::Boolean: param = (obj->data.basic.b ? lit("True") : lit("False")); break; @@ -2477,6 +2484,7 @@ QString Formatter::m_DefaultFontFamily; QString Formatter::m_DefaultMonoFontFamily; float Formatter::m_FixedFontBaseSize = 10.0f; QColor Formatter::m_DarkChecker, Formatter::m_LightChecker; +OffsetSizeDisplayMode Formatter::m_OffsetSizeDisplayMode = OffsetSizeDisplayMode::Auto; void Formatter::setParams(const PersistantConfig &config) { @@ -2488,6 +2496,8 @@ void Formatter::setParams(const PersistantConfig &config) m_expNegValue = qPow(10.0, -config.Formatter_NegExp); m_expPosValue = qPow(10.0, config.Formatter_PosExp); + m_OffsetSizeDisplayMode = config.Formatter_OffsetSizeDisplayMode; + if(!m_Font) { m_Font = new QFont(); @@ -2571,7 +2581,7 @@ QString Formatter::Format(double f, bool) return ret; } -QString Formatter::HumanFormat(uint64_t u) +QString Formatter::HumanFormat(uint64_t u, FormatterFlags flags) { if(u == UINT16_MAX) return lit("UINT16_MAX"); @@ -2581,8 +2591,26 @@ QString Formatter::HumanFormat(uint64_t u) return lit("UINT64_MAX"); // format as hex when over a certain threshold - if(u > 0xffffff) + bool displayHex = (u > 0xffffff); + + if(flags & OffsetSize) + { + switch(m_OffsetSizeDisplayMode) + { + case OffsetSizeDisplayMode::Hexadecimal: displayHex = true; break; + case OffsetSizeDisplayMode::Decimal: displayHex = false; break; + default: break; + } + } + if(displayHex) + { + if(u < UINT32_MAX) + { + uint32_t u32 = u; + return lit("0x") + Format(u32, true); + } return lit("0x") + Format(u, true); + } return Format(u); } @@ -3007,7 +3035,7 @@ void ShowProgressDialog(QWidget *window, const QString &labelText, ProgressFinis // show the dialog RDDialog::show(&dialog); - // signal the thread to exit if somehow we got here without it finishing, then wait for it thread + // signal the thread to exit if somehow we got here without it finishing, then wait for the thread // to clean itself up tickerSemaphore.tryAcquire(); progressTickerThread.wait(); diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index d887e42f7..a7b691663 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -368,13 +368,18 @@ void RegisterMetatypeConversions(); struct Formatter { + enum FormatterFlags + { + NoFlags = 0x0, + OffsetSize = 0x1, + }; static void setParams(const PersistantConfig &config); static void setPalette(QPalette palette); static void shutdown(); static QString Format(double f, bool hex = false); static QString Format(rdhalf f, bool hex = false) { return Format((float)f, hex); } - static QString HumanFormat(uint64_t u); + static QString HumanFormat(uint64_t u, FormatterFlags flags); static QString Format(uint64_t u, bool hex = false) { return QFormatStr("%1").arg(u, hex ? 16 : 0, hex ? 16 : 10, QLatin1Char('0')).toUpper(); @@ -432,6 +437,7 @@ private: static float m_FontBaseSize, m_FixedFontBaseSize; static QString m_DefaultFontFamily, m_DefaultMonoFontFamily; static QColor m_DarkChecker, m_LightChecker; + static OffsetSizeDisplayMode m_OffsetSizeDisplayMode; }; bool SaveToJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, uint32_t magicVersion); diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp index c04710586..ac98312aa 100644 --- a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp +++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp @@ -146,6 +146,11 @@ SettingsDialog::SettingsDialog(ICaptureContext &ctx, QWidget *parent) ui->EventBrowser_TimeUnit->addItem(UnitSuffix((TimeUnit)i)); } + for(int i = 0; i < (int)OffsetSizeDisplayMode::Count; i++) + { + ui->Formatter_OffsetSizeDisplayMode->addItem((ToStr((OffsetSizeDisplayMode)i))); + } + ui->pages->clearSelection(); ui->pages->item(0)->setSelected(true); ui->tabWidget->setCurrentIndex(0); @@ -294,6 +299,8 @@ SettingsDialog::SettingsDialog(ICaptureContext &ctx, QWidget *parent) ui->Formatter_MaxFigures->setValue(m_Ctx.Config().Formatter_MaxFigures); ui->Formatter_NegExp->setValue(m_Ctx.Config().Formatter_NegExp); ui->Formatter_PosExp->setValue(m_Ctx.Config().Formatter_PosExp); + ui->Formatter_OffsetSizeDisplayMode->setCurrentIndex( + (int)m_Ctx.Config().Formatter_OffsetSizeDisplayMode); if(!RENDERDOC_CanGlobalHook()) { @@ -331,6 +338,9 @@ SettingsDialog::~SettingsDialog() m_Ctx.Config().DefaultReplayOptions = m_ReplayOptions->options(); m_Ctx.Config().Save(); + if(m_NeedRefresh) + m_Ctx.RefreshStatus(); + delete ui; } @@ -439,6 +449,22 @@ void SettingsDialog::formatter_valueChanged(int val) m_Ctx.Config().Save(); } +void SettingsDialog::on_Formatter_OffsetSizeDisplayMode_currentIndexChanged(int index) +{ + if(m_Init) + return; + + if(index < 0 || index >= (int)OffsetSizeDisplayMode::Count) + return; + + m_Ctx.Config().Formatter_OffsetSizeDisplayMode = + (OffsetSizeDisplayMode)(ui->Formatter_OffsetSizeDisplayMode->currentIndex()); + + m_Ctx.Config().SetupFormatting(); + m_Ctx.Config().Save(); + m_NeedRefresh = true; +} + void SettingsDialog::on_tempDirectory_textEdited(const QString &dir) { if(QDir(dir).exists()) diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.h b/qrenderdoc/Windows/Dialogs/SettingsDialog.h index 0d87f27f2..e62c3ae3e 100644 --- a/qrenderdoc/Windows/Dialogs/SettingsDialog.h +++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.h @@ -116,6 +116,7 @@ private slots: // manual slots void formatter_valueChanged(int value); + void on_Formatter_OffsetSizeDisplayMode_currentIndexChanged(int index); void on_analyticsDescribeLabel_linkActivated(const QString &link); @@ -128,5 +129,6 @@ private: ReplayOptionsSelector *m_ReplayOptions; ICaptureContext &m_Ctx; + bool m_NeedRefresh = false; bool m_Init = false; }; diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.ui b/qrenderdoc/Windows/Dialogs/SettingsDialog.ui index d6e754be3..463ef954d 100644 --- a/qrenderdoc/Windows/Dialogs/SettingsDialog.ui +++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.ui @@ -287,6 +287,23 @@ e.g. 1000 * 10 = 1e4 + + + Formatting mode to use for fields marked as a byte offset or a byte size + + + Offset or size fields format mode + + + + + + + Auto: decimal by default and hexadecimal if above a certain threshold, Decimal: always use decimal, Hexadecimal: always use hexadecimal. + + + + Changes the directory where capture files are saved after being created, until saved manually or deleted. @@ -298,7 +315,7 @@ Defaults to %TEMP%. - + Changes the directory where capture files are saved after being created, until saved manually or deleted. @@ -307,7 +324,7 @@ Defaults to %TEMP%. - + Changes the directory where capture files are saved after being created, until saved manually or deleted. @@ -319,7 +336,7 @@ Defaults to %TEMP%. - + Changes the default directory for the save dialog when saving capture files. @@ -331,7 +348,7 @@ Defaults to blank, which follows system default behaviour. - + Changes the default directory for the save dialog when saving capture files. @@ -340,7 +357,7 @@ Defaults to blank, which follows system default behaviour. - + Changes the default directory for the save dialog when saving capture files. @@ -352,7 +369,7 @@ Defaults to blank, which follows system default behaviour. - + Enables functionality on the capture application window that will insert RenderDoc automatically @@ -367,7 +384,7 @@ Since this is a global system hook it must be used carefully and only when neces - + Enables functionality on the capture application window that will insert RenderDoc automatically @@ -382,7 +399,7 @@ Since this is a global system hook it must be used carefully and only when neces - + Enables the ability to inject into processes on windows. @@ -396,7 +413,7 @@ program should be launched through RenderDoc via the Launch Process panel. - + Enables the ability to inject into processes on windows. @@ -410,7 +427,7 @@ program should be launched through RenderDoc via the Launch Process panel. - + Allows RenderDoc to phone home to https://renderdoc.org to anonymously check for new versions. @@ -420,7 +437,7 @@ program should be launched through RenderDoc via the Launch Process panel. - + Allows RenderDoc to phone home to https://renderdoc.org to anonymously check for new versions. @@ -430,7 +447,7 @@ program should be launched through RenderDoc via the Launch Process panel. - + If a capture is marked as being created on a significantly different system (different OS or platform) @@ -443,7 +460,7 @@ This option overrides that and will always replay locally if the local context i - + If a capture is marked as being created on a significantly different system (different OS or platform) @@ -456,7 +473,7 @@ This option overrides that and will always replay locally if the local context i - + Qt::Vertical diff --git a/renderdoc/api/replay/structured_data.h b/renderdoc/api/replay/structured_data.h index fa516d6c4..52fc9df5f 100644 --- a/renderdoc/api/replay/structured_data.h +++ b/renderdoc/api/replay/structured_data.h @@ -164,6 +164,11 @@ DOCUMENT(R"(Bitfield flags that could be applied to a type. Indicates that some children are marked as hidden. This can be important for cases where the number of children is important. + +.. data:: OffsetOrSize + + Special flag to indicate that this type will be used as a byte offset or byte size, which is used to + control the formatting mode when the value is displayed in the UI. )"); enum class SDTypeFlags : uint32_t { @@ -177,6 +182,7 @@ enum class SDTypeFlags : uint32_t Important = 0x40, ImportantChildren = 0x80, HiddenChildren = 0x100, + OffsetOrSize = 0x200, }; BITMASK_OPERATORS(SDTypeFlags); diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index 9fb826eb0..6e81f5052 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -1224,6 +1224,19 @@ public: return *this; } + Serialiser &OffsetOrSize() + { + if(ExportStructure() && !m_StructureStack.empty()) + { + SDObject ¤t = *m_StructureStack.back(); + + if(current.NumChildren() > 0) + current.GetChild(current.NumChildren() - 1)->type.flags |= SDTypeFlags::OffsetOrSize; + } + + return *this; + } + // these functions should be used very carefully, they completely disable structured export for // anything serialised while internal is set. void PushInternal() { m_InternalElement++; }