mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 21:30:53 +00:00
Handle compare and select operations
This commit is contained in:
@@ -1499,6 +1499,94 @@ Program::Program(const byte *bytes, size_t length)
|
||||
|
||||
f.instructions.push_back(inst);
|
||||
}
|
||||
else if(IS_KNOWN(op.id, FunctionRecord::INST_CMP) ||
|
||||
IS_KNOWN(op.id, FunctionRecord::INST_CMP2))
|
||||
{
|
||||
Instruction inst;
|
||||
|
||||
// a
|
||||
inst.args.push_back(getSymbol(op.ops[0]));
|
||||
// b
|
||||
inst.args.push_back(getSymbol(op.ops[1]));
|
||||
|
||||
switch(op.ops[2])
|
||||
{
|
||||
case 0: inst.op = Instruction::FOrdFalse; break;
|
||||
case 1: inst.op = Instruction::FOrdEqual; break;
|
||||
case 2: inst.op = Instruction::FOrdGreater; break;
|
||||
case 3: inst.op = Instruction::FOrdGreaterEqual; break;
|
||||
case 4: inst.op = Instruction::FOrdLess; break;
|
||||
case 5: inst.op = Instruction::FOrdLessEqual; break;
|
||||
case 6: inst.op = Instruction::FOrdNotEqual; break;
|
||||
case 7: inst.op = Instruction::FOrd; break;
|
||||
case 8: inst.op = Instruction::FUnord; break;
|
||||
case 9: inst.op = Instruction::FUnordEqual; break;
|
||||
case 10: inst.op = Instruction::FUnordGreater; break;
|
||||
case 11: inst.op = Instruction::FUnordGreaterEqual; break;
|
||||
case 12: inst.op = Instruction::FUnordLess; break;
|
||||
case 13: inst.op = Instruction::FUnordLessEqual; break;
|
||||
case 14: inst.op = Instruction::FUnordNotEqual; break;
|
||||
case 15: inst.op = Instruction::FOrdTrue; break;
|
||||
|
||||
case 32: inst.op = Instruction::IEqual; break;
|
||||
case 33: inst.op = Instruction::INotEqual; break;
|
||||
case 34: inst.op = Instruction::UGreater; break;
|
||||
case 35: inst.op = Instruction::UGreaterEqual; break;
|
||||
case 36: inst.op = Instruction::ULess; break;
|
||||
case 37: inst.op = Instruction::ULessEqual; break;
|
||||
case 38: inst.op = Instruction::SGreater; break;
|
||||
case 39: inst.op = Instruction::SGreaterEqual; break;
|
||||
case 40: inst.op = Instruction::SLess; break;
|
||||
case 41: inst.op = Instruction::SLessEqual; break;
|
||||
}
|
||||
|
||||
// fast math flags
|
||||
if(op.ops.size() > 3)
|
||||
inst.opFlags = InstructionFlags(op.ops[3]);
|
||||
|
||||
inst.type = GetBoolType();
|
||||
|
||||
// if we're comparing vectors, the return type is an equal sized bool vector
|
||||
const Type *argType = GetSymbolType(f, inst.args[0]);
|
||||
if(argType->type == Type::Vector)
|
||||
{
|
||||
for(const Type &t : m_Types)
|
||||
{
|
||||
if(t.type == Type::Vector && t.inner == inst.type &&
|
||||
t.elemCount == argType->elemCount)
|
||||
{
|
||||
inst.type = &t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RDCASSERT(inst.type->type == argType->type);
|
||||
|
||||
m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()});
|
||||
|
||||
f.instructions.push_back(inst);
|
||||
}
|
||||
else if(IS_KNOWN(op.id, FunctionRecord::INST_SELECT) ||
|
||||
IS_KNOWN(op.id, FunctionRecord::INST_VSELECT))
|
||||
{
|
||||
Instruction inst;
|
||||
|
||||
inst.op = Instruction::Select;
|
||||
|
||||
// if true
|
||||
inst.args.push_back(getSymbol(op.ops[0]));
|
||||
// if false
|
||||
inst.args.push_back(getSymbol(op.ops[1]));
|
||||
// selector
|
||||
inst.args.push_back(getSymbol(op.ops[2]));
|
||||
|
||||
inst.type = GetSymbolType(f, inst.args[0]);
|
||||
|
||||
m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()});
|
||||
|
||||
f.instructions.push_back(inst);
|
||||
}
|
||||
else if(IS_KNOWN(op.id, FunctionRecord::INST_LANDINGPAD) ||
|
||||
IS_KNOWN(op.id, FunctionRecord::INST_LANDINGPAD_OLD) ||
|
||||
IS_KNOWN(op.id, FunctionRecord::INST_VAARG) ||
|
||||
@@ -1649,6 +1737,27 @@ const DXIL::Type *Program::GetVoidType()
|
||||
return m_VoidType;
|
||||
}
|
||||
|
||||
const DXIL::Type *Program::GetBoolType()
|
||||
{
|
||||
if(m_BoolType)
|
||||
return m_BoolType;
|
||||
|
||||
for(size_t i = 0; i < m_Types.size(); i++)
|
||||
{
|
||||
if(m_Types[i].type == Type::Scalar && m_Types[i].scalarType == Type::Int &&
|
||||
m_Types[i].bitWidth == 1)
|
||||
{
|
||||
m_BoolType = &m_Types[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_BoolType)
|
||||
RDCERR("Couldn't find void type");
|
||||
|
||||
return m_BoolType;
|
||||
}
|
||||
|
||||
Metadata::~Metadata()
|
||||
{
|
||||
SAFE_DELETE(dwarf);
|
||||
|
||||
@@ -336,6 +336,33 @@ struct Instruction
|
||||
GetElementPtr,
|
||||
Load,
|
||||
Store,
|
||||
FOrdFalse,
|
||||
FOrdEqual,
|
||||
FOrdGreater,
|
||||
FOrdGreaterEqual,
|
||||
FOrdLess,
|
||||
FOrdLessEqual,
|
||||
FOrdNotEqual,
|
||||
FOrd,
|
||||
FUnord,
|
||||
FUnordEqual,
|
||||
FUnordGreater,
|
||||
FUnordGreaterEqual,
|
||||
FUnordLess,
|
||||
FUnordLessEqual,
|
||||
FUnordNotEqual,
|
||||
FOrdTrue,
|
||||
IEqual,
|
||||
INotEqual,
|
||||
UGreater,
|
||||
UGreaterEqual,
|
||||
ULess,
|
||||
ULessEqual,
|
||||
SGreater,
|
||||
SGreaterEqual,
|
||||
SLess,
|
||||
SLessEqual,
|
||||
Select,
|
||||
} op = Unknown;
|
||||
|
||||
InstructionFlags opFlags = InstructionFlags::NoFlags;
|
||||
@@ -412,6 +439,7 @@ private:
|
||||
const Value *GetFunctionValue(const Function &f, uint64_t v);
|
||||
const Metadata *GetFunctionMetadata(const Function &f, uint64_t v);
|
||||
const Type *GetVoidType();
|
||||
const Type *GetBoolType();
|
||||
|
||||
DXBC::ShaderType m_Type;
|
||||
uint32_t m_Major, m_Minor;
|
||||
@@ -425,6 +453,7 @@ private:
|
||||
|
||||
rdcarray<Type> m_Types;
|
||||
const Type *m_VoidType = NULL;
|
||||
const Type *m_BoolType = NULL;
|
||||
|
||||
rdcarray<Attributes> m_AttributeGroups;
|
||||
rdcarray<Attributes> m_Attributes;
|
||||
|
||||
@@ -638,6 +638,102 @@ void Program::MakeDisassemblyString()
|
||||
m_Disassembly += StringFormat::Fmt(", align %u", inst.align);
|
||||
break;
|
||||
}
|
||||
case Instruction::FOrdFalse:
|
||||
case Instruction::FOrdEqual:
|
||||
case Instruction::FOrdGreater:
|
||||
case Instruction::FOrdGreaterEqual:
|
||||
case Instruction::FOrdLess:
|
||||
case Instruction::FOrdLessEqual:
|
||||
case Instruction::FOrdNotEqual:
|
||||
case Instruction::FOrd:
|
||||
case Instruction::FUnord:
|
||||
case Instruction::FUnordEqual:
|
||||
case Instruction::FUnordGreater:
|
||||
case Instruction::FUnordGreaterEqual:
|
||||
case Instruction::FUnordLess:
|
||||
case Instruction::FUnordLessEqual:
|
||||
case Instruction::FUnordNotEqual:
|
||||
case Instruction::FOrdTrue:
|
||||
{
|
||||
m_Disassembly += "fcmp ";
|
||||
rdcstr opFlagsStr = ToStr(inst.opFlags);
|
||||
{
|
||||
int offs = opFlagsStr.indexOf('|');
|
||||
while(offs >= 0)
|
||||
{
|
||||
opFlagsStr.erase((size_t)offs, 2);
|
||||
offs = opFlagsStr.indexOf('|');
|
||||
}
|
||||
}
|
||||
m_Disassembly += opFlagsStr;
|
||||
if(inst.opFlags != InstructionFlags::NoFlags)
|
||||
m_Disassembly += " ";
|
||||
switch(inst.op)
|
||||
{
|
||||
case Instruction::FOrdFalse: m_Disassembly += "false "; break;
|
||||
case Instruction::FOrdEqual: m_Disassembly += "oeq "; break;
|
||||
case Instruction::FOrdGreater: m_Disassembly += "ogt "; break;
|
||||
case Instruction::FOrdGreaterEqual: m_Disassembly += "oge "; break;
|
||||
case Instruction::FOrdLess: m_Disassembly += "olt "; break;
|
||||
case Instruction::FOrdLessEqual: m_Disassembly += "ole "; break;
|
||||
case Instruction::FOrdNotEqual: m_Disassembly += "one "; break;
|
||||
case Instruction::FOrd: m_Disassembly += "ord "; break;
|
||||
case Instruction::FUnord: m_Disassembly += "uno "; break;
|
||||
case Instruction::FUnordEqual: m_Disassembly += "ueq "; break;
|
||||
case Instruction::FUnordGreater: m_Disassembly += "ugt "; break;
|
||||
case Instruction::FUnordGreaterEqual: m_Disassembly += "uge "; break;
|
||||
case Instruction::FUnordLess: m_Disassembly += "ult "; break;
|
||||
case Instruction::FUnordLessEqual: m_Disassembly += "ule "; break;
|
||||
case Instruction::FUnordNotEqual: m_Disassembly += "une "; break;
|
||||
case Instruction::FOrdTrue: m_Disassembly += "true "; break;
|
||||
default: break;
|
||||
}
|
||||
m_Disassembly += argToString(inst.args[0], true);
|
||||
m_Disassembly += ", ";
|
||||
m_Disassembly += argToString(inst.args[1], false);
|
||||
break;
|
||||
}
|
||||
case Instruction::IEqual:
|
||||
case Instruction::INotEqual:
|
||||
case Instruction::UGreater:
|
||||
case Instruction::UGreaterEqual:
|
||||
case Instruction::ULess:
|
||||
case Instruction::ULessEqual:
|
||||
case Instruction::SGreater:
|
||||
case Instruction::SGreaterEqual:
|
||||
case Instruction::SLess:
|
||||
case Instruction::SLessEqual:
|
||||
{
|
||||
m_Disassembly += "icmp ";
|
||||
switch(inst.op)
|
||||
{
|
||||
case Instruction::IEqual: m_Disassembly += "eq "; break;
|
||||
case Instruction::INotEqual: m_Disassembly += "ne "; break;
|
||||
case Instruction::UGreater: m_Disassembly += "ugt "; break;
|
||||
case Instruction::UGreaterEqual: m_Disassembly += "uge "; break;
|
||||
case Instruction::ULess: m_Disassembly += "ult "; break;
|
||||
case Instruction::ULessEqual: m_Disassembly += "ule "; break;
|
||||
case Instruction::SGreater: m_Disassembly += "sgt "; break;
|
||||
case Instruction::SGreaterEqual: m_Disassembly += "sge "; break;
|
||||
case Instruction::SLess: m_Disassembly += "slt "; break;
|
||||
case Instruction::SLessEqual: m_Disassembly += "sle "; break;
|
||||
default: break;
|
||||
}
|
||||
m_Disassembly += argToString(inst.args[0], true);
|
||||
m_Disassembly += ", ";
|
||||
m_Disassembly += argToString(inst.args[1], false);
|
||||
break;
|
||||
}
|
||||
case Instruction::Select:
|
||||
{
|
||||
m_Disassembly += "select ";
|
||||
m_Disassembly += argToString(inst.args[2], true);
|
||||
m_Disassembly += ", ";
|
||||
m_Disassembly += argToString(inst.args[0], true);
|
||||
m_Disassembly += ", ";
|
||||
m_Disassembly += argToString(inst.args[1], true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(inst.debugLoc != ~0U)
|
||||
|
||||
Reference in New Issue
Block a user