Highlight variables/registers that have changed

This commit is contained in:
baldurk
2018-06-08 19:05:44 +01:00
parent 5b3a12cd0c
commit 1761f5ab36
7 changed files with 126 additions and 6 deletions
+1
View File
@@ -265,6 +265,7 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ShaderResource)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ShaderSampler)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ShaderSourceFile)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ShaderVariable)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, RegisterRange)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, LocalVariableMapping)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, SigParameter)
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, TextureDescription)
@@ -97,6 +97,8 @@ public:
m_fore = foreground;
dataChanged(0, Qt::ForegroundRole);
}
inline QBrush background() { return m_back; }
inline QBrush foreground() { return m_fore; }
inline QString text(int column) const { return m_text[column].toString(); }
inline void setText(int column, const QVariant &value)
{
+81
View File
@@ -1470,6 +1470,11 @@ void ShaderViewer::combineStructures(RDTreeWidgetItem *root)
if(!isArray)
item->setText(0, item->text(0).mid(sepIndex + 1));
parent->addChild(item);
if(item->background().color().isValid())
parent->setBackground(item->background());
if(item->foreground().color().isValid())
parent->setForeground(item->foreground());
}
// recurse and combine members of this object if a struct
@@ -1752,11 +1757,22 @@ void ShaderViewer::updateDebugging()
else if(l.type == VarType::Double)
typeName = lit("double");
bool modified = false;
if(l.registers[0].type == RegisterType::IndexedTemporary)
{
typeName += lit("[]");
regNames = QFormatStr("x%1").arg(l.registers[0].index);
for(const RegisterRange &mr : state.modified)
{
if(mr.type == RegisterType::IndexedTemporary && mr.index == l.registers[0].index)
{
modified = true;
break;
}
}
}
else
{
@@ -1770,6 +1786,15 @@ void ShaderViewer::updateDebugging()
const RegisterRange &r = l.registers[i];
const ShaderVariable *var = NULL;
for(const RegisterRange &mr : state.modified)
{
if(mr.type == r.type && mr.index == r.index && mr.component == r.component)
{
modified = true;
break;
}
}
if(!value.isEmpty())
value += lit(", ");
if(!regNames.isEmpty())
@@ -1832,6 +1857,9 @@ void ShaderViewer::updateDebugging()
RDTreeWidgetItem *node = new RDTreeWidgetItem({localName, regNames, typeName, value});
if(modified)
node->setForegroundColor(QColor(Qt::red));
if(l.registers[0].type == RegisterType::IndexedTemporary)
{
const ShaderVariable *var = NULL;
@@ -1891,16 +1919,53 @@ void ShaderViewer::updateDebugging()
node->setText(2, stringRep(state.registers[i], false));
node->setTag(QVariant::fromValue(VariableTag(VariableCategory::Temporaries, i)));
bool modified = false;
for(const RegisterRange &mr : state.modified)
{
if(mr.type == RegisterType::Temporary && mr.index == i)
{
modified = true;
break;
}
}
if(modified)
node->setForegroundColor(QColor(Qt::red));
else
node->setForeground(QBrush());
}
for(int i = 0; i < state.indexableTemps.count(); i++)
{
RDTreeWidgetItem *node = ui->registers->topLevelItem(v++);
bool modified = false;
for(const RegisterRange &mr : state.modified)
{
if(mr.type == RegisterType::IndexedTemporary && mr.index == i)
{
modified = true;
break;
}
}
if(modified)
node->setForegroundColor(QColor(Qt::red));
else
node->setForeground(QBrush());
for(int t = 0; t < state.indexableTemps[i].members.count(); t++)
{
RDTreeWidgetItem *child = node->child(t);
if(modified)
child->setForegroundColor(QColor(Qt::red));
else
child->setForeground(QBrush());
child->setText(2, stringRep(state.indexableTemps[i].members[t], false));
child->setTag(QVariant::fromValue(VariableTag(VariableCategory::IndexTemporaries, t, i)));
}
@@ -1912,6 +1977,22 @@ void ShaderViewer::updateDebugging()
node->setText(2, stringRep(state.outputs[i], false));
node->setTag(QVariant::fromValue(VariableTag(VariableCategory::Outputs, i)));
bool modified = false;
for(const RegisterRange &mr : state.modified)
{
if(mr.type == RegisterType::Output && mr.index == i)
{
modified = true;
break;
}
}
if(modified)
node->setForegroundColor(QColor(Qt::red));
else
node->setForeground(QBrush());
}
ui->registers->endUpdate();
+3
View File
@@ -418,6 +418,9 @@ to which registers, and their type
)");
rdcarray<LocalVariableMapping> locals;
DOCUMENT("A list of registers that were modified.");
rdcarray<RegisterRange> modified;
DOCUMENT(R"(The next instruction to be executed after this state. The initial state before any
shader execution happened will have ``nextInstruction == 0``.
)");
+36 -4
View File
@@ -587,7 +587,7 @@ bool State::Finished() const
return dxbc && (done || nextInstruction >= (int)dxbc->GetNumInstructions());
}
void State::AssignValue(ShaderVariable &dst, uint32_t dstIndex, const ShaderVariable &src,
bool State::AssignValue(ShaderVariable &dst, uint32_t dstIndex, const ShaderVariable &src,
uint32_t srcIndex)
{
if(src.type == VarType::Float)
@@ -603,7 +603,11 @@ void State::AssignValue(ShaderVariable &dst, uint32_t dstIndex, const ShaderVari
flags |= ShaderEvents::GeneratedNanOrInf;
}
bool ret = (dst.value.uv[dstIndex] != src.value.uv[srcIndex]);
dst.value.uv[dstIndex] = src.value.uv[srcIndex];
return ret;
}
void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const ShaderVariable &val)
@@ -629,10 +633,14 @@ void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const Shad
}
}
RegisterRange range;
range.index = uint16_t(indices[0]);
switch(dstoper.type)
{
case TYPE_TEMP:
{
range.type = RegisterType::Temporary;
RDCASSERT(indices[0] < (uint32_t)registers.size());
if(indices[0] < (uint32_t)registers.size())
v = &registers[(size_t)indices[0]];
@@ -640,6 +648,7 @@ void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const Shad
}
case TYPE_INDEXABLE_TEMP:
{
range.type = RegisterType::IndexedTemporary;
RDCASSERT(dstoper.indices.size() == 2);
if(dstoper.indices.size() == 2)
@@ -658,6 +667,7 @@ void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const Shad
}
case TYPE_OUTPUT:
{
range.type = RegisterType::Output;
RDCASSERT(indices[0] < (uint32_t)outputs.size());
if(indices[0] < (uint32_t)outputs.size())
v = &outputs[(size_t)indices[0]];
@@ -772,7 +782,13 @@ void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const Shad
{
RDCASSERT(dstoper.comps[0] != 0xff);
AssignValue(*v, dstoper.comps[0], right, 0);
bool changed = AssignValue(*v, dstoper.comps[0], right, 0);
if(changed && range.type != RegisterType::Undefined)
{
range.component = dstoper.comps[0];
modified.push_back(range);
}
}
else
{
@@ -783,13 +799,27 @@ void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const Shad
if(dstoper.comps[i] != 0xff)
{
RDCASSERT(dstoper.comps[i] < v->columns);
AssignValue(*v, dstoper.comps[i], right, dstoper.comps[i]);
bool changed = AssignValue(*v, dstoper.comps[i], right, dstoper.comps[i]);
compsWritten++;
if(changed && range.type != RegisterType::Undefined)
{
range.component = dstoper.comps[i];
modified.push_back(range);
}
}
}
if(compsWritten == 0)
AssignValue(*v, 0, right, 0);
{
bool changed = AssignValue(*v, 0, right, 0);
if(changed && range.type != RegisterType::Undefined)
{
range.component = 0;
modified.push_back(range);
}
}
}
}
}
@@ -1167,6 +1197,8 @@ State State::GetNext(GlobalState &global, State quad[4]) const
{
State s = *this;
s.modified.clear();
if(s.nextInstruction >= s.dxbc->GetNumInstructions())
return s;
+1 -1
View File
@@ -164,7 +164,7 @@ private:
bool done;
// validates assignment for generation of non-normal values
void AssignValue(ShaderVariable &dst, uint32_t dstIndex, const ShaderVariable &src,
bool AssignValue(ShaderVariable &dst, uint32_t dstIndex, const ShaderVariable &src,
uint32_t srcIndex);
// sets the destination operand by looking up in the register
// file and applying any masking or swizzling
+2 -1
View File
@@ -385,10 +385,11 @@ void DoSerialise(SerialiserType &ser, ShaderDebugState &el)
SERIALISE_MEMBER(outputs);
SERIALISE_MEMBER(indexableTemps);
SERIALISE_MEMBER(locals);
SERIALISE_MEMBER(modified);
SERIALISE_MEMBER(nextInstruction);
SERIALISE_MEMBER(flags);
SIZE_CHECK(72);
SIZE_CHECK(88);
}
template <typename SerialiserType>