mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 09:00:44 +00:00
Highlight variables/registers that have changed
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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``.
|
||||
)");
|
||||
|
||||
@@ -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 = ®isters[(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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user