Show tooltips for known local variables and constants

This commit is contained in:
baldurk
2018-06-08 20:28:03 +01:00
parent 2a6a0f0f95
commit c0317855f8
2 changed files with 188 additions and 44 deletions
+183 -44
View File
@@ -353,13 +353,6 @@ void ShaderViewer::debugShader(const ShaderBindpointMapping *bind, const ShaderR
}
m_DisassemblyFrame->layout()->removeWidget(m_DisassemblyToolbar);
m_DisassemblyView->setMouseDwellTime(500);
QObject::connect(m_DisassemblyView, &ScintillaEdit::dwellStart, this,
&ShaderViewer::disasm_tooltipShow);
QObject::connect(m_DisassemblyView, &ScintillaEdit::dwellEnd, this,
&ShaderViewer::disasm_tooltipHide);
}
if(shader && !shader->debugInfo.files.isEmpty())
@@ -512,6 +505,11 @@ void ShaderViewer::debugShader(const ShaderBindpointMapping *bind, const ShaderR
edit->setContextMenuPolicy(Qt::CustomContextMenu);
QObject::connect(edit, &ScintillaEdit::customContextMenuRequested, this,
&ShaderViewer::debug_contextMenu);
edit->setMouseDwellTime(500);
QObject::connect(edit, &ScintillaEdit::dwellStart, this, &ShaderViewer::disasm_tooltipShow);
QObject::connect(edit, &ScintillaEdit::dwellEnd, this, &ShaderViewer::disasm_tooltipHide);
}
// register the shortcuts globally for this shader viewer so it works regardless of the active
@@ -1763,6 +1761,8 @@ void ShaderViewer::updateDebugging()
QString regNames, typeName;
QString value;
bool modified = false;
if(l.type == VarType::UInt)
typeName = lit("uint");
else if(l.type == VarType::Int)
@@ -1772,8 +1772,6 @@ void ShaderViewer::updateDebugging()
else if(l.type == VarType::Double)
typeName = lit("double");
bool modified = false;
if(l.registers[0].type == RegisterType::IndexedTemporary)
{
typeName += lit("[]");
@@ -1799,7 +1797,6 @@ void ShaderViewer::updateDebugging()
for(uint32_t i = 0; i < l.regCount; i++)
{
const RegisterRange &r = l.registers[i];
const ShaderVariable *var = NULL;
for(const RegisterRange &mr : state.modified)
{
@@ -1815,29 +1812,15 @@ void ShaderViewer::updateDebugging()
if(!regNames.isEmpty())
regNames += lit(", ");
switch(r.type)
if(r.type == RegisterType::Undefined)
{
case RegisterType::Undefined:
regNames += lit("-");
value += lit("?");
continue;
case RegisterType::Input:
if(r.index < m_Trace->inputs.size())
var = &m_Trace->inputs[r.index];
break;
case RegisterType::Temporary:
if(r.index < state.registers.size())
var = &state.registers[r.index];
break;
case RegisterType::IndexedTemporary:
qCritical() << "unexpected indexed temporary";
break;
case RegisterType::Output:
if(r.index < state.outputs.size())
var = &state.outputs[r.index];
break;
regNames += lit("-");
value += lit("?");
continue;
}
const ShaderVariable *var = GetRegisterVariable(r);
if(var)
{
// if the previous register was the same, just append our component
@@ -2194,6 +2177,35 @@ void ShaderViewer::updateDebugging()
updateVariableTooltip();
}
const ShaderVariable *ShaderViewer::GetRegisterVariable(const RegisterRange &r)
{
const ShaderDebugState &state = m_Trace->states[m_CurrentStep];
const ShaderVariable *var = NULL;
switch(r.type)
{
case RegisterType::Undefined: break;
case RegisterType::Input:
if(r.index < m_Trace->inputs.size())
var = &m_Trace->inputs[r.index];
break;
case RegisterType::Temporary:
if(r.index < state.registers.size())
var = &state.registers[r.index];
break;
case RegisterType::IndexedTemporary:
if(r.index < state.indexableTemps.size())
var = &state.indexableTemps[r.index];
break;
case RegisterType::Output:
if(r.index < state.outputs.size())
var = &state.outputs[r.index];
break;
}
return var;
}
void ShaderViewer::ensureLineScrolled(ScintillaEdit *s, int line)
{
int firstLine = s->firstVisibleLine();
@@ -2674,27 +2686,39 @@ void ShaderViewer::disasm_tooltipShow(int x, int y)
if(!m_Trace || m_CurrentStep < 0 || m_CurrentStep >= m_Trace->states.count())
return;
// ignore any messages if we're already outside the viewport
if(!m_DisassemblyView->rect().contains(m_DisassemblyView->mapFromGlobal(QCursor::pos())))
ScintillaEdit *sc = qobject_cast<ScintillaEdit *>(QObject::sender());
if(!sc)
return;
if(m_DisassemblyView->isVisible())
// ignore any messages if we're already outside the viewport
if(!sc->rect().contains(sc->mapFromGlobal(QCursor::pos())))
return;
if(sc->isVisible())
{
sptr_t scintillaPos = m_DisassemblyView->positionFromPoint(x, y);
sptr_t scintillaPos = sc->positionFromPoint(x, y);
sptr_t start = m_DisassemblyView->wordStartPosition(scintillaPos, true);
sptr_t end = m_DisassemblyView->wordEndPosition(scintillaPos, true);
sptr_t start = sc->wordStartPosition(scintillaPos, true);
sptr_t end = sc->wordEndPosition(scintillaPos, true);
QString text = QString::fromUtf8(m_DisassemblyView->textRange(start, end));
do
{
// expand leftwards through simple struct . access
// TODO handle arrays
while(isspace(sc->charAt(start - 1)))
start--;
if(sc->charAt(start - 1) == '.')
start = sc->wordStartPosition(start - 2, true);
else
break;
} while(true);
QString text = QString::fromUtf8(sc->textRange(start, end)).trimmed();
if(!text.isEmpty())
{
VariableTag tag;
getRegisterFromWord(text, tag.cat, tag.idx, tag.arrayIdx);
if(tag.cat != VariableCategory::Unknown && tag.idx >= 0 && tag.arrayIdx >= 0)
showVariableTooltip(tag.cat, tag.idx, tag.arrayIdx);
}
showVariableTooltip(text);
}
}
@@ -2714,6 +2738,7 @@ void ShaderViewer::showVariableTooltip(VariableCategory varCat, int varIdx, int
}
m_TooltipVarCat = varCat;
m_TooltipName = QString();
m_TooltipVarIdx = varIdx;
m_TooltipArrayIdx = arrayIdx;
m_TooltipPos = QCursor::pos();
@@ -2721,6 +2746,23 @@ void ShaderViewer::showVariableTooltip(VariableCategory varCat, int varIdx, int
updateVariableTooltip();
}
void ShaderViewer::showVariableTooltip(QString name)
{
VariableCategory varCat;
int varIdx;
int arrayIdx;
getRegisterFromWord(name, varCat, varIdx, arrayIdx);
if(varCat != VariableCategory::Unknown)
showVariableTooltip(varCat, varIdx, arrayIdx);
m_TooltipVarCat = VariableCategory::ByString;
m_TooltipName = name;
m_TooltipPos = QCursor::pos();
updateVariableTooltip();
}
const rdcarray<ShaderVariable> *ShaderViewer::GetVariableList(VariableCategory varCat, int arrayIdx)
{
const rdcarray<ShaderVariable> *vars = NULL;
@@ -2734,6 +2776,7 @@ const rdcarray<ShaderVariable> *ShaderViewer::GetVariableList(VariableCategory v
switch(varCat)
{
case VariableCategory::ByString:
case VariableCategory::Unknown: vars = NULL; break;
case VariableCategory::Temporaries: vars = &state.registers; break;
case VariableCategory::IndexTemporaries:
@@ -2783,6 +2826,101 @@ void ShaderViewer::getRegisterFromWord(const QString &text, VariableCategory &va
void ShaderViewer::updateVariableTooltip()
{
if(!m_Trace || m_CurrentStep < 0 || m_CurrentStep >= m_Trace->states.count())
return;
const ShaderDebugState &state = m_Trace->states[m_CurrentStep];
if(m_TooltipVarCat == VariableCategory::ByString)
{
if(m_TooltipName.isEmpty())
return;
// first check the constants
QString bracketedName = lit("(") + m_TooltipName;
QString commaName = lit(", ") + m_TooltipName;
QList<ShaderVariable> constants;
for(ShaderVariable &block : m_Trace->constantBlocks)
{
for(ShaderVariable &c : block.members)
{
QString cname = c.name;
// this is a hack for now :(.
if(cname.startsWith(m_TooltipName) || cname.contains(bracketedName) ||
cname.contains(commaName))
constants.push_back(c);
}
}
if(constants.count() == 1)
{
QToolTip::showText(
m_TooltipPos,
QFormatStr("<pre>%1: %2</pre>").arg(constants[0].name).arg(RowString(constants[0], 0)));
return;
}
else if(constants.count() > 1)
{
QString tooltip =
QFormatStr("<pre>%1: %2\n").arg(m_TooltipName).arg(RowString(constants[0], 0));
QString spacing = QString(m_TooltipName.length(), QLatin1Char(' '));
for(int i = 1; i < constants.count(); i++)
tooltip += QFormatStr("%1 %2\n").arg(spacing).arg(RowString(constants[i], 0));
tooltip += lit("</pre>");
QToolTip::showText(m_TooltipPos, tooltip);
return;
}
// now check locals (if there are any)
for(const LocalVariableMapping &l : state.locals)
{
if(QString(l.localName) == m_TooltipName)
{
QString tooltip = QFormatStr("<pre>%1: ").arg(m_TooltipName);
for(uint32_t i = 0; i < l.regCount; i++)
{
const RegisterRange &r = l.registers[i];
if(i > 0)
tooltip += lit(", ");
if(r.type == RegisterType::Undefined)
{
tooltip += lit("?");
continue;
}
const ShaderVariable *var = GetRegisterVariable(r);
if(var)
{
if(l.type == VarType::UInt)
tooltip += Formatter::Format(var->value.uv[r.component]);
else if(l.type == VarType::Int)
tooltip += Formatter::Format(var->value.iv[r.component]);
else if(l.type == VarType::Float)
tooltip += Formatter::Format(var->value.fv[r.component]);
else if(l.type == VarType::Double)
tooltip += Formatter::Format(var->value.dv[r.component]);
}
else
{
tooltip += lit("&lt;error&gt;");
}
}
tooltip += lit("</pre>");
QToolTip::showText(m_TooltipPos, tooltip);
return;
}
}
return;
}
if(m_TooltipVarIdx < 0)
return;
@@ -2824,6 +2962,7 @@ void ShaderViewer::hideVariableTooltip()
{
QToolTip::hideText();
m_TooltipVarIdx = -1;
m_TooltipName = QString();
}
bool ShaderViewer::isSourceDebugging()
+5
View File
@@ -53,6 +53,7 @@ enum class VariableCategory
IndexTemporaries,
Temporaries,
Outputs,
ByString,
};
class ShaderViewer : public QFrame, public IShaderViewer, public ICaptureViewer
@@ -159,12 +160,14 @@ private:
void updateWindowTitle();
void showVariableTooltip(VariableCategory varCat, int varIdx, int arrayIdx);
void showVariableTooltip(QString name);
void updateVariableTooltip();
void hideVariableTooltip();
bool isSourceDebugging();
VariableCategory m_TooltipVarCat = VariableCategory::Temporaries;
QString m_TooltipName;
int m_TooltipVarIdx = -1;
int m_TooltipArrayIdx = -1;
QPoint m_TooltipPos;
@@ -242,6 +245,8 @@ private:
void updateDebugging();
const ShaderVariable *GetRegisterVariable(const RegisterRange &r);
void ensureLineScrolled(ScintillaEdit *s, int i);
void find(bool down);