diff --git a/qrenderdoc/Windows/ShaderViewer.cpp b/qrenderdoc/Windows/ShaderViewer.cpp index 08e04a558..3eac2659c 100644 --- a/qrenderdoc/Windows/ShaderViewer.cpp +++ b/qrenderdoc/Windows/ShaderViewer.cpp @@ -46,6 +46,11 @@ struct VariableTag VariableCategory cat = VariableCategory::Unknown; int idx = 0; int arrayIdx = 0; + + bool operator==(const VariableTag &o) + { + return cat == o.cat && idx == o.idx && arrayIdx == o.arrayIdx; + } }; }; @@ -279,6 +284,10 @@ void ShaderViewer::debugShader(const ShaderBindpointMapping *bind, const ShaderR m_DisassemblyView->setReadOnly(true); } + // we always want to highlight words/registers + QObject::connect(m_DisassemblyView, &ScintillaEdit::buttonReleased, this, + &ShaderViewer::disassembly_buttonReleased); + // suppress the built-in context menu and hook up our own if(trace) { @@ -694,6 +703,80 @@ void ShaderViewer::disassembly_contextMenu(const QPoint &pos) RDDialog::show(&contextMenu, m_DisassemblyView->viewport()->mapToGlobal(pos)); } +void ShaderViewer::disassembly_buttonReleased(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) + { + sptr_t scintillaPos = m_DisassemblyView->positionFromPoint(event->x(), event->y()); + + sptr_t start = m_DisassemblyView->wordStartPosition(scintillaPos, true); + sptr_t end = m_DisassemblyView->wordEndPosition(scintillaPos, true); + + QString text = QString::fromUtf8(m_DisassemblyView->textRange(start, end)); + + if(!text.isEmpty()) + { + qInfo() << text; + + VariableTag tag; + getRegisterFromWord(text, tag.cat, tag.idx, tag.arrayIdx); + + // for now since we don't have friendly naming, only highlight registers + if(tag.cat != VariableCategory::Unknown) + { + start = 0; + end = m_DisassemblyView->length(); + + for(int i = 0; i < ui->variables->topLevelItemCount(); i++) + { + RDTreeWidgetItem *item = ui->variables->topLevelItem(i); + if(item->tag().value() == tag) + item->setBackgroundColor(QColor::fromHslF( + 0.333f, 1.0f, qBound(0.25, palette().color(QPalette::Base).lightnessF(), 0.85))); + else + item->setBackground(QBrush()); + } + + for(int i = 0; i < ui->constants->topLevelItemCount(); i++) + { + RDTreeWidgetItem *item = ui->constants->topLevelItem(i); + if(item->tag().value() == tag) + item->setBackgroundColor(QColor::fromHslF( + 0.333f, 1.0f, qBound(0.25, palette().color(QPalette::Base).lightnessF(), 0.85))); + else + item->setBackground(QBrush()); + } + + m_DisassemblyView->setIndicatorCurrent(INDICATOR_REGHIGHLIGHT); + m_DisassemblyView->indicatorClearRange(start, end); + + sptr_t flags = SCFIND_MATCHCASE | SCFIND_WHOLEWORD; + + if(tag.cat != VariableCategory::Unknown) + { + flags |= SCFIND_REGEXP | SCFIND_POSIX; + text += lit("\\.[xyzwrgba]+"); + } + + QByteArray findUtf8 = text.toUtf8(); + + QPair result; + + do + { + result = m_DisassemblyView->findText(flags, findUtf8.data(), start, end); + + if(result.first >= 0) + m_DisassemblyView->indicatorFillRange(result.first, result.second - result.first); + + start = result.second; + + } while(result.first >= 0); + } + } + } +} + void ShaderViewer::watch_keyPress(QKeyEvent *event) { if(event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) @@ -1736,42 +1819,11 @@ void ShaderViewer::disasm_tooltipShow(int x, int y) if(!text.isEmpty()) { - const ShaderDebugState &state = m_Trace->states[m_CurrentStep]; + VariableTag tag; + getRegisterFromWord(text, tag.cat, tag.idx, tag.arrayIdx); - QChar regtype = text[0]; - QString regidx = text.mid(1); - - VariableCategory varCat = VariableCategory::Unknown; - - if(regtype == QLatin1Char('r')) - { - varCat = VariableCategory::Temporaries; - } - else if(regtype == QLatin1Char('v')) - { - varCat = VariableCategory::Inputs; - } - else if(regtype == QLatin1Char('o')) - { - varCat = VariableCategory::Outputs; - } - else - { - return; - } - - bool ok = false; - int regindex = regidx.toInt(&ok); - - const rdctype::array *vars = GetVariableList(varCat, 0); - - // if we have a list of registers and the index is in range, and we matched the whole word - // (i.e. v0foo is not the same as v0), then show the tooltip - if(vars && ok && regindex >= 0 && regindex < vars->count && - QFormatStr("%1%2").arg(regtype).arg(regindex) == text) - { - showVariableTooltip(varCat, regindex, 0); - } + if(tag.cat != VariableCategory::Unknown && tag.idx >= 0 && tag.arrayIdx >= 0) + showVariableTooltip(tag.cat, tag.idx, tag.arrayIdx); } } } @@ -1828,6 +1880,37 @@ const rdctype::array *ShaderViewer::GetVariableList(VariableCate return vars; } +void ShaderViewer::getRegisterFromWord(const QString &text, VariableCategory &varCat, int &varIdx, + int &arrayIdx) +{ + QChar regtype = text[0]; + QString regidx = text.mid(1); + + varCat = VariableCategory::Unknown; + varIdx = -1; + arrayIdx = 0; + + if(regtype == QLatin1Char('r')) + varCat = VariableCategory::Temporaries; + else if(regtype == QLatin1Char('v')) + varCat = VariableCategory::Inputs; + else if(regtype == QLatin1Char('o')) + varCat = VariableCategory::Outputs; + else + return; + + bool ok = false; + varIdx = regidx.toInt(&ok); + + // if we have a list of registers and the index is in range, and we matched the whole word + // (i.e. v0foo is not the same as v0), then show the tooltip + if(QFormatStr("%1%2").arg(regtype).arg(varIdx) != text) + { + varCat = VariableCategory::Unknown; + varIdx = -1; + } +} + void ShaderViewer::updateVariableTooltip() { if(m_TooltipVarIdx < 0) diff --git a/qrenderdoc/Windows/ShaderViewer.h b/qrenderdoc/Windows/ShaderViewer.h index 04f3235c1..3d818ba31 100644 --- a/qrenderdoc/Windows/ShaderViewer.h +++ b/qrenderdoc/Windows/ShaderViewer.h @@ -116,6 +116,7 @@ private slots: void readonly_keyPressed(QKeyEvent *event); void editable_keyPressed(QKeyEvent *event); void disassembly_contextMenu(const QPoint &pos); + void disassembly_buttonReleased(QMouseEvent *event); void watch_keyPress(QKeyEvent *event); void performFind(); void performFindAll(); @@ -151,6 +152,7 @@ private: bool eventFilter(QObject *watched, QEvent *event) override; const rdctype::array *GetVariableList(VariableCategory varCat, int arrayIdx); + void getRegisterFromWord(const QString &text, VariableCategory &varCat, int &varIdx, int &arrayIdx); void showVariableTooltip(VariableCategory varCat, int varIdx, int arrayIdx); void updateVariableTooltip();