diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp index 60e26a590..67eeb104b 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp @@ -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); diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index 575c942a6..94642b40c 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -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 m_Types; const Type *m_VoidType = NULL; + const Type *m_BoolType = NULL; rdcarray m_AttributeGroups; rdcarray m_Attributes; diff --git a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp index d6585288c..ec041939d 100644 --- a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp @@ -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)