diff --git a/qrenderdoc/Code/Interface/PersistantConfig.cpp b/qrenderdoc/Code/Interface/PersistantConfig.cpp index 850ed3f45..75043648a 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.cpp +++ b/qrenderdoc/Code/Interface/PersistantConfig.cpp @@ -303,18 +303,6 @@ void PersistantConfig::applyValues(const QVariantMap &values) debug->AddAndOwnChild(makeSDString("$el"_lit, searchPaths[i])); } - if(settings.contains(lit("d3d12ShaderDebugging"))) - { - RENDERDOC_SetConfigSetting("D3D12_ShaderDebugging")->data.basic.b = - settings[lit("d3d12ShaderDebugging")].toBool(); - } - - if(settings.contains(lit("vulkanShaderDebugging"))) - { - RENDERDOC_SetConfigSetting("Vulkan_ShaderDebugging")->data.basic.b = - settings[lit("vulkanShaderDebugging")].toBool(); - } - saveConfig = true; } diff --git a/qrenderdoc/Widgets/OrderedListEditor.cpp b/qrenderdoc/Widgets/OrderedListEditor.cpp index d524df0b9..5dd83fa7f 100644 --- a/qrenderdoc/Widgets/OrderedListEditor.cpp +++ b/qrenderdoc/Widgets/OrderedListEditor.cpp @@ -23,18 +23,20 @@ ******************************************************************************/ #include "OrderedListEditor.h" +#include #include #include #include #include "Code/QRDUtils.h" #include "Code/Resources.h" -OrderedListEditor::OrderedListEditor(const QString &itemName, ItemButton mode, QWidget *parent) +OrderedListEditor::OrderedListEditor(const QString &itemName, OrderedItemExtras extras, + const CustomProp &prop, QWidget *parent) : RDTableWidget(parent) { setFont(Formatter::PreferredFont()); - m_ButtonMode = mode; + m_Prop = prop; setDragEnabled(true); setDragDropOverwriteMode(false); @@ -49,30 +51,45 @@ OrderedListEditor::OrderedListEditor(const QString &itemName, ItemButton mode, Q horizontalHeader()->setMinimumSectionSize(50); verticalHeader()->setHighlightSections(false); - if(m_ButtonMode == ItemButton::None) - { - setColumnCount(1); - setHorizontalHeaderLabels({itemName}); - horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - } - else - { - QStringList labels; - labels << itemName; - switch(m_ButtonMode) - { - case ItemButton::None: labels << lit("????"); break; - case ItemButton::BrowseFile: - case ItemButton::BrowseFolder: labels << tr("Browse"); break; - case ItemButton::Delete: labels << tr("Delete"); break; - } - setColumnCount(2); - setHorizontalHeaderLabels(labels); + QStringList labels; + int columnCount = 1; + labels << itemName; - horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + if(!prop.name.isEmpty()) + { + columnCount++; + labels << prop.name; } + if(extras & OrderedItemExtras::BrowseFile) + { + columnCount++; + labels << tr("Browse"); + m_Extras.push_back(OrderedItemExtras::BrowseFile); + } + else if(extras & OrderedItemExtras::BrowseFolder) + { + columnCount++; + labels << tr("Browse"); + m_Extras.push_back(OrderedItemExtras::BrowseFolder); + } + if(extras & OrderedItemExtras::Delete) + { + columnCount++; + labels << tr("Delete"); + m_Extras.push_back(OrderedItemExtras::Delete); + } + + setColumnCount(columnCount); + setHorizontalHeaderLabels(labels); + + horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + for(int i = 1; i < columnCount; i++) + horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents); + + if(!prop.name.isEmpty()) + horizontalHeaderItem(1)->setToolTip(prop.tooltip); + QObject::connect(this, &RDTableWidget::cellChanged, this, &OrderedListEditor::cellChanged); } @@ -80,22 +97,40 @@ OrderedListEditor::~OrderedListEditor() { } -QToolButton *OrderedListEditor::makeButton() +QWidget *OrderedListEditor::makeCellWidget(int row, OrderedItemExtras extra) { - QToolButton *ret = new QToolButton(this); - - if(m_ButtonMode == ItemButton::Delete) + if(extra == OrderedItemExtras::Delete) + { + QToolButton *ret = new QToolButton(this); + ret->setAutoRaise(true); ret->setIcon(Icons::del()); - else + QObject::connect(ret, &QToolButton::clicked, [this, row, extra]() { extraClicked(row, extra); }); + + return ret; + } + else if(extra == OrderedItemExtras::BrowseFile || extra == OrderedItemExtras::BrowseFolder) + { + QToolButton *ret = new QToolButton(this); + ret->setAutoRaise(true); ret->setIcon(Icons::folder_page_white()); - ret->setAutoRaise(true); + QObject::connect(ret, &QToolButton::clicked, [this, row, extra]() { extraClicked(row, extra); }); - QObject::connect(ret, &QToolButton::clicked, this, &OrderedListEditor::buttonActivate); - - return ret; + return ret; + } + else if(extra == OrderedItemExtras::CustomProp) + { + QCheckBox *ret = new QCheckBox(this); + if(m_Prop.defaultValue) + ret->setChecked(true); + return ret; + } + else + { + return NULL; + } } -void OrderedListEditor::setItems(const QStringList &strings) +void OrderedListEditor::setItemsAndProp(const QStringList &strings, const QList &prop) { setUpdatesEnabled(false); clearContents(); @@ -106,8 +141,28 @@ void OrderedListEditor::setItems(const QStringList &strings) { setItem(i, 0, new QTableWidgetItem(strings[i])); - if(m_ButtonMode != ItemButton::None) - setCellWidget(i, 1, makeButton()); + if(m_Prop.valid()) + { + QWidget *w = makeCellWidget(i, OrderedItemExtras::CustomProp); + if(i < prop.count()) + { + QCheckBox *c = qobject_cast(w); + if(c) + c->setChecked(prop[i]); + } + w->setToolTip(m_Prop.tooltip); + + QWidget *wrapperWidget = new QWidget(); + QHBoxLayout *l = new QHBoxLayout(); + l->setAlignment(Qt::AlignCenter); + l->addWidget(w); + l->setContentsMargins(QMargins(0, 0, 0, 0)); + wrapperWidget->setLayout(l); + setCellWidget(i, 1, wrapperWidget); + } + + for(int c = 0; c < m_Extras.size(); c++) + setCellWidget(i, c + firstExtraColumn(), makeCellWidget(i, m_Extras[c])); } // if we added any strings above the new item row was automatically @@ -116,8 +171,8 @@ void OrderedListEditor::setItems(const QStringList &strings) addNewItemRow(); resizeColumnToContents(0); - if(m_ButtonMode != ItemButton::None) - resizeColumnToContents(1); + for(int c = 0; c < m_Extras.size(); c++) + resizeColumnToContents(c + firstExtraColumn()); setUpdatesEnabled(true); } @@ -133,13 +188,30 @@ void OrderedListEditor::addNewItemRow() item->setFlags(item->flags() & ~(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled)); setItem(rowCount() - 1, 0, item); - if(m_ButtonMode != ItemButton::None) + { + QWidget *w = makeCellWidget(rowCount() - 1, OrderedItemExtras::CustomProp); + QCheckBox *c = qobject_cast(w); + if(c) + c->setChecked(m_Prop.defaultValue); + w->setToolTip(m_Prop.tooltip); + + QWidget *wrapperWidget = new QWidget(); + QHBoxLayout *l = new QHBoxLayout(); + l->setAlignment(Qt::AlignCenter); + l->addWidget(w); + l->setContentsMargins(QMargins(0, 0, 0, 0)); + wrapperWidget->setLayout(l); + setCellWidget(rowCount() - 1, 1, wrapperWidget); + } + + for(int c = 0; c < m_Extras.size(); c++) { item = new QTableWidgetItem(QString()); item->setFlags(item->flags() & ~(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled)); - setItem(rowCount() - 1, 1, item); + setItem(rowCount() - 1, c + firstExtraColumn(), item); - setCellWidget(rowCount() - 1, 1, makeButton()); + setCellWidget(rowCount() - 1, c + firstExtraColumn(), + makeCellWidget(rowCount() - 1, m_Extras[c])); } } @@ -157,6 +229,23 @@ QStringList OrderedListEditor::getItems() return ret; } +QList OrderedListEditor::getItemProps() +{ + QList ret; + + int count = rowCount(); + // don't include the last 'new item' entry + if(allowAddition()) + count--; + for(int i = 0; i < count; i++) + { + QCheckBox *c = cellWidget(i, 1)->findChild(); + ret << (c && c->isChecked()); + } + + return ret; +} + void OrderedListEditor::cellChanged(int row, int column) { // hack :(. Assume this will only be hit on single UI thread. @@ -174,8 +263,8 @@ void OrderedListEditor::cellChanged(int row, int column) { // enable dragging item(row, 0)->setFlags(item(row, 0)->flags() | (Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled)); - if(m_ButtonMode != ItemButton::None) - delete takeItem(row, 1); + for(int c = 0; c < m_Extras.size(); c++) + delete takeItem(row, c + firstExtraColumn()); addNewItemRow(); } @@ -189,34 +278,24 @@ void OrderedListEditor::cellChanged(int row, int column) recurse = false; } -void OrderedListEditor::buttonActivate() +void OrderedListEditor::extraClicked(int row, OrderedItemExtras extra) { - QWidget *tool = qobject_cast(QObject::sender()); - - if(tool) + if(extra == OrderedItemExtras::Delete) { - for(int i = 0; i < rowCount(); i++) - { - QWidget *rowButton = cellWidget(i, 1); - if(rowButton == tool) - { - if(m_ButtonMode == ItemButton::Delete) - { - this->removeRow(i); - return; - } - - QString sel; - if(m_ButtonMode == ItemButton::BrowseFolder) - sel = RDDialog::getExistingDirectory(this, tr("Browse for a folder")); - else if(m_ButtonMode == ItemButton::BrowseFile) - sel = RDDialog::getOpenFileName(this, tr("Browse for a file")); - - if(!sel.isEmpty()) - item(i, 0)->setText(sel); - } - } + // don't delete the last 'new item' entry + if(!allowAddition() || row != rowCount() - 1) + removeRow(row); + return; } + + QString sel; + if(extra == OrderedItemExtras::BrowseFolder) + sel = RDDialog::getExistingDirectory(this, tr("Browse for a folder")); + else if(extra == OrderedItemExtras::BrowseFile) + sel = RDDialog::getOpenFileName(this, tr("Browse for a file")); + + if(!sel.isEmpty()) + item(row, 0)->setText(sel); } void OrderedListEditor::keyPressEvent(QKeyEvent *event) @@ -228,7 +307,11 @@ void OrderedListEditor::keyPressEvent(QKeyEvent *event) row = selectionModel()->selectedIndexes()[0].row(); if(row >= 0) - removeRow(row); + { + // don't delete the last 'new item' entry + if(!allowAddition() || row != rowCount() - 1) + removeRow(row); + } } RDTableWidget::keyPress(event); diff --git a/qrenderdoc/Widgets/OrderedListEditor.h b/qrenderdoc/Widgets/OrderedListEditor.h index 9abe18224..7b4ebc7df 100644 --- a/qrenderdoc/Widgets/OrderedListEditor.h +++ b/qrenderdoc/Widgets/OrderedListEditor.h @@ -28,24 +28,46 @@ class QToolButton; -enum class ItemButton +enum class OrderedItemExtras { - None, - BrowseFolder, - BrowseFile, - Delete, + None = 0x0, + BrowseFolder = 0x1, + BrowseFile = 0x2, + Delete = 0x4, + CustomProp = 0x8, }; +constexpr inline OrderedItemExtras operator|(OrderedItemExtras a, OrderedItemExtras b) +{ + return OrderedItemExtras(int(a) | int(b)); +} + +constexpr inline bool operator&(OrderedItemExtras a, OrderedItemExtras b) +{ + return int(a) & int(b); +} + class OrderedListEditor : public RDTableWidget { Q_OBJECT public: - explicit OrderedListEditor(const QString &itemName, ItemButton button, QWidget *parent = 0); + struct CustomProp + { + QString name, tooltip; + bool defaultValue; + + bool valid() const { return !name.isEmpty(); } + }; + + explicit OrderedListEditor(const QString &itemName, OrderedItemExtras extras, + const CustomProp &prop = {}, QWidget *parent = 0); ~OrderedListEditor(); - void setItems(const QStringList &strings); + void setItemsAndProp(const QStringList &strings, const QList &props); + void setItems(const QStringList &strings) { setItemsAndProp(strings, {}); } QStringList getItems(); + QList getItemProps(); bool allowAddition() { return m_allowAddition; } void setAllowAddition(bool allow) { m_allowAddition = allow; } @@ -53,15 +75,18 @@ public: private slots: // manual slots void cellChanged(int row, int column); - void buttonActivate(); + void extraClicked(int row, OrderedItemExtras extra); private: void keyPressEvent(QKeyEvent *e) override; - ItemButton m_ButtonMode; + int firstExtraColumn() { return m_Prop.valid() ? 2 : 1; } + + QList m_Extras; + CustomProp m_Prop; bool m_allowAddition = true; void addNewItemRow(); - QToolButton *makeButton(); + QWidget *makeCellWidget(int row, OrderedItemExtras extra); }; diff --git a/qrenderdoc/Windows/Dialogs/ConfigEditor.cpp b/qrenderdoc/Windows/Dialogs/ConfigEditor.cpp index ec9e008bd..f077b5648 100644 --- a/qrenderdoc/Windows/Dialogs/ConfigEditor.cpp +++ b/qrenderdoc/Windows/Dialogs/ConfigEditor.cpp @@ -565,12 +565,12 @@ QWidget *SettingDelegate::createEditor(QWidget *parent, const QStyleOptionViewIt listEditor.setWindowTitle(tr("Edit values of %1").arg(QString(settingName))); listEditor.setWindowFlags(listEditor.windowFlags() & ~Qt::WindowContextHelpButtonHint); - ItemButton mode = ItemButton::None; + OrderedItemExtras mode = OrderedItemExtras::None; if(QString(o->name).contains(lit("DirPath"), Qt::CaseSensitive)) - mode = ItemButton::BrowseFolder; + mode = OrderedItemExtras::BrowseFolder; else if(QString(o->name).contains(lit("Path"), Qt::CaseSensitive)) - mode = ItemButton::BrowseFile; + mode = OrderedItemExtras::BrowseFile; OrderedListEditor list(tr("Entry"), mode); diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp index 88d7862bb..ebc016517 100644 --- a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp +++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp @@ -618,7 +618,15 @@ void SettingsDialog::on_chooseSearchPaths_clicked() listEditor.setWindowTitle(tr("Shader debug info search paths")); listEditor.setWindowFlags(listEditor.windowFlags() & ~Qt::WindowContextHelpButtonHint); - OrderedListEditor list(tr("Search Path"), ItemButton::BrowseFolder); + OrderedListEditor::CustomProp customProp = { + tr("Recursive"), + tr("Recursively search through all subdirectories" + "under this path to find matching debug files"), + true, + }; + + OrderedListEditor list(tr("Search Path"), + OrderedItemExtras::BrowseFolder | OrderedItemExtras::Delete, customProp); QVBoxLayout layout; QDialogButtonBox okCancel; @@ -630,21 +638,37 @@ void SettingsDialog::on_chooseSearchPaths_clicked() QObject::connect(&okCancel, &QDialogButtonBox::rejected, &listEditor, &QDialog::reject); listEditor.setLayout(&layout); + listEditor.resize(750, 500); const SDObject *getPaths = RENDERDOC_GetConfigSetting("DXBC.Debug.SearchDirPaths"); QStringList items; + QList recursive; for(const SDObject *c : *getPaths) + { items << c->data.str; + recursive << true; + } - list.setItems(items); + const SDObject *getLimitedPaths = + RENDERDOC_GetConfigSetting("Replay.Shader.LimitedSearchDirPaths"); + + for(const SDObject *c : *getLimitedPaths) + { + int idx = items.indexOf(c->data.str); + if(idx >= 0) + recursive[idx] = false; + } + + list.setItemsAndProp(items, recursive); int res = RDDialog::show(&listEditor); if(res) { items = list.getItems(); + recursive = list.getItemProps(); SDObject *setPaths = RENDERDOC_SetConfigSetting("DXBC.Debug.SearchDirPaths"); @@ -654,6 +678,20 @@ void SettingsDialog::on_chooseSearchPaths_clicked() for(int i = 0; i < items.size(); i++) setPaths->AddAndOwnChild(makeSDString("$el"_lit, items[i])); + SDObject *setLimitedPaths = RENDERDOC_SetConfigSetting("Replay.Shader.LimitedSearchDirPaths"); + + QStringList limited; + + for(int i = 0; i < recursive.count() && i < items.count(); i++) + if(recursive[i] == false) + limited << items[i]; + + setLimitedPaths->DeleteChildren(); + setLimitedPaths->ReserveChildren(limited.size()); + + for(int i = 0; i < limited.size(); i++) + setLimitedPaths->AddAndOwnChild(makeSDString("$el"_lit, limited[i])); + RENDERDOC_SaveConfigSettings(); } } @@ -665,7 +703,7 @@ void SettingsDialog::on_chooseIgnores_clicked() listEditor.setWindowTitle(tr("Ignored DLLs for callstack symbol resolution")); listEditor.setWindowFlags(listEditor.windowFlags() & ~Qt::WindowContextHelpButtonHint); - OrderedListEditor list(tr("Ignored DLL"), ItemButton::Delete); + OrderedListEditor list(tr("Ignored DLL"), OrderedItemExtras::Delete); list.setAllowAddition(false); @@ -761,7 +799,7 @@ void SettingsDialog::on_TextureViewer_ChooseShaderDirectories_clicked() listEditor.setWindowTitle(tr("Custom shaders search directories")); listEditor.setWindowFlags(listEditor.windowFlags() & ~Qt::WindowContextHelpButtonHint); - OrderedListEditor list(tr("Shaders Directory"), ItemButton::BrowseFolder); + OrderedListEditor list(tr("Shaders Directory"), OrderedItemExtras::BrowseFolder); QVBoxLayout layout; QDialogButtonBox okCancel; diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index a831494ff..c010bea88 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -63,7 +63,10 @@ RDOC_CONFIG(bool, Replay_Debug_SingleThreadedCompilation, false, // this is declared centrally so it can be shared with any backend - the name is a misnomer but kept // for backwards compatibility reasons. RDOC_CONFIG(rdcarray, DXBC_Debug_SearchDirPaths, {}, - "Paths to search for separated shader debug PDBs."); + "Paths to search for separated shader debug PDBs, including all types of paths."); +RDOC_CONFIG(rdcarray, Replay_Shader_LimitedSearchDirPaths, {}, + "Companion array to DXBC.Debug.SearchDirPaths - listing paths which should not be " + "searched exhaustively but only used for simple lookups."); void LogReplayOptions(const ReplayOptions &opts) { diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp index 3e5b46cf5..963b1f4f8 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp @@ -41,6 +41,7 @@ // this is extern so that it can be shared with vulkan RDOC_EXTERN_CONFIG(rdcarray, DXBC_Debug_SearchDirPaths); +RDOC_EXTERN_CONFIG(rdcarray, Replay_Shader_LimitedSearchDirPaths); namespace { @@ -93,9 +94,16 @@ void CacheSearchDirDebugPaths() return; rdcarray searchPaths = DXBC_Debug_SearchDirPaths(); + rdcarray limitedSearchPaths = Replay_Shader_LimitedSearchDirPaths(); for(const rdcstr &base : searchPaths) { + if(limitedSearchPaths.contains(base)) + { + RDCLOG("Not recursing to enumerate files under %s", base.c_str()); + continue; + } + size_t sz = cachedDebugFilesLookup.size(); CacheSearchDirDebugPaths(base); RDCLOG("Recursively enumerated all files under %s, found %zu files", base.c_str(),