diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp index 06603565a..bd8a79264 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp @@ -143,6 +143,16 @@ enum class FunctionRecord : uint32_t INST_CALLBR = 57, }; +enum class ParamAttrRecord : uint32_t +{ + ENTRY = 2, +}; + +enum class ParamAttrGroupRecord : uint32_t +{ + ENTRY = 3, +}; + enum class ValueSymtabRecord : uint32_t { ENTRY = 1, @@ -268,7 +278,7 @@ static rdcstr getName(uint32_t parentBlock, const LLVMBC::BlockOrRecord &block) break; } case KnownBlocks::PARAMATTR_BLOCK: - case KnownBlocks::PARAMATTR_GROUP_BLOCK: name = "ENTRY"; break; + case KnownBlocks::PARAMATTR_GROUP_BLOCK: return StringFormat::Fmt("ENTRY%u", block.id); break; case KnownBlocks::CONSTANTS_BLOCK: { ConstantsRecord code = ConstantsRecord(block.id); @@ -638,6 +648,84 @@ Program::Program(const byte *bytes, size_t length) { // do nothing, this is internal parse data } + else if(IS_KNOWN(rootchild.id, KnownBlocks::PARAMATTR_GROUP_BLOCK)) + { + for(const LLVMBC::BlockOrRecord &attrgroup : rootchild.children) + { + if(!IS_KNOWN(attrgroup.id, ParamAttrGroupRecord::ENTRY)) + { + RDCERR("Unexpected attribute group record ID %u", attrgroup.id); + continue; + } + + AttributeGroup group; + + size_t id = (size_t)attrgroup.ops[0]; + group.index = attrgroup.ops[1]; + + for(size_t i = 2; i < attrgroup.ops.size(); i++) + { + switch(attrgroup.ops[i]) + { + case 0: + { + group.params |= Attribute(1U << (attrgroup.ops[i + 1])); + i++; + break; + } + case 1: + { + uint64_t param = attrgroup.ops[i + 2]; + Attribute attr = Attribute(1U << attrgroup.ops[i + 1]); + group.params |= attr; + switch(attr) + { + case Attribute::Alignment: group.align = param; break; + case Attribute::StackAlignment: group.stackAlign = param; break; + case Attribute::Dereferenceable: group.derefBytes = param; break; + case Attribute::DereferenceableOrNull: group.derefOrNullBytes = param; break; + default: RDCERR("Unexpected attribute %llu with parameter", attr); + } + i += 2; + break; + } + default: + { + rdcstr a = attrgroup.getString(i + 1); + rdcstr b = attrgroup.getString(i + 1 + a.size() + 1); + group.strs.push_back({a, b}); + break; + } + } + } + + m_AttributeGroups.resize_for_index(id); + m_AttributeGroups[id] = group; + } + } + else if(IS_KNOWN(rootchild.id, KnownBlocks::PARAMATTR_BLOCK)) + { + for(const LLVMBC::BlockOrRecord ¶mattr : rootchild.children) + { + if(!IS_KNOWN(paramattr.id, ParamAttrRecord::ENTRY)) + { + RDCERR("Unexpected attribute record ID %u", paramattr.id); + continue; + } + + rdcarray groups; + + for(uint64_t g : paramattr.ops) + { + if(g < m_AttributeGroups.size()) + groups.push_back(&m_AttributeGroups[(size_t)g]); + else + RDCERR("Attribute refers to out of bounds group %llu", g); + } + + m_Attributes.push_back(groups); + } + } else if(IS_KNOWN(rootchild.id, KnownBlocks::FUNCTION_BLOCK)) { } @@ -893,6 +981,102 @@ void Program::MakeDisassemblyString() m_Disassembly += StringFormat::Fmt("target triple = \"%s\"\n", m_Triple.c_str()); m_Disassembly += StringFormat::Fmt("target datalayout = \"%s\"\n\n", m_Datalayout.c_str()); + for(size_t i = 0; i < m_Attributes.size(); i++) + { + m_Disassembly += StringFormat::Fmt("attributes #%zu =", i); + for(const AttributeGroup *g : m_Attributes[i]) + { + m_Disassembly += " {"; + Attribute params = g->params; + + if(params & Attribute::Alignment) + { + m_Disassembly += StringFormat::Fmt(" Alignment(%llu)", g->align); + params &= ~Attribute::Alignment; + } + if(params & Attribute::StackAlignment) + { + m_Disassembly += StringFormat::Fmt(" StackAlignment(%llu)", g->stackAlign); + params &= ~Attribute::StackAlignment; + } + if(params & Attribute::Dereferenceable) + { + m_Disassembly += StringFormat::Fmt(" Dereferenceable(%llu)", g->derefBytes); + params &= ~Attribute::Dereferenceable; + } + if(params & Attribute::DereferenceableOrNull) + { + m_Disassembly += StringFormat::Fmt(" DereferenceableOrNull(%llu)", g->derefOrNullBytes); + params &= ~Attribute::DereferenceableOrNull; + } + + if(params != Attribute::None) + { + m_Disassembly += " " + ToStr(params); + } + for(const rdcpair &str : g->strs) + m_Disassembly += " " + str.first + "=" + str.second; + m_Disassembly += " }"; + } + m_Disassembly += "\n"; + } + m_Disassembly += "; No disassembly implemented"; } }; + +template <> +rdcstr DoStringise(const DXIL::Attribute &el) +{ + BEGIN_BITFIELD_STRINGISE(DXIL::Attribute); + { + STRINGISE_BITFIELD_CLASS_VALUE_NAMED(None, ""); + + STRINGISE_BITFIELD_CLASS_BIT(Alignment); + STRINGISE_BITFIELD_CLASS_BIT(AlwaysInline); + STRINGISE_BITFIELD_CLASS_BIT(ByVal); + STRINGISE_BITFIELD_CLASS_BIT(InlineHint); + STRINGISE_BITFIELD_CLASS_BIT(InReg); + STRINGISE_BITFIELD_CLASS_BIT(MinSize); + STRINGISE_BITFIELD_CLASS_BIT(Naked); + STRINGISE_BITFIELD_CLASS_BIT(Nest); + STRINGISE_BITFIELD_CLASS_BIT(NoAlias); + STRINGISE_BITFIELD_CLASS_BIT(NoBuiltin); + STRINGISE_BITFIELD_CLASS_BIT(NoCapture); + STRINGISE_BITFIELD_CLASS_BIT(NoDuplicate); + STRINGISE_BITFIELD_CLASS_BIT(NoImplicitFloat); + STRINGISE_BITFIELD_CLASS_BIT(NoInline); + STRINGISE_BITFIELD_CLASS_BIT(NonLazyBind); + STRINGISE_BITFIELD_CLASS_BIT(NoRedZone); + STRINGISE_BITFIELD_CLASS_BIT(NoReturn); + STRINGISE_BITFIELD_CLASS_BIT(NoUnwind); + STRINGISE_BITFIELD_CLASS_BIT(OptimizeForSize); + STRINGISE_BITFIELD_CLASS_BIT(ReadNone); + STRINGISE_BITFIELD_CLASS_BIT(ReadOnly); + STRINGISE_BITFIELD_CLASS_BIT(Returned); + STRINGISE_BITFIELD_CLASS_BIT(ReturnsTwice); + STRINGISE_BITFIELD_CLASS_BIT(SExt); + STRINGISE_BITFIELD_CLASS_BIT(StackAlignment); + STRINGISE_BITFIELD_CLASS_BIT(StackProtect); + STRINGISE_BITFIELD_CLASS_BIT(StackProtectReq); + STRINGISE_BITFIELD_CLASS_BIT(StackProtectStrong); + STRINGISE_BITFIELD_CLASS_BIT(StructRet); + STRINGISE_BITFIELD_CLASS_BIT(SanitizeAddress); + STRINGISE_BITFIELD_CLASS_BIT(SanitizeThread); + STRINGISE_BITFIELD_CLASS_BIT(SanitizeMemory); + STRINGISE_BITFIELD_CLASS_BIT(UWTable); + STRINGISE_BITFIELD_CLASS_BIT(ZExt); + STRINGISE_BITFIELD_CLASS_BIT(Builtin); + STRINGISE_BITFIELD_CLASS_BIT(Cold); + STRINGISE_BITFIELD_CLASS_BIT(OptimizeNone); + STRINGISE_BITFIELD_CLASS_BIT(InAlloca); + STRINGISE_BITFIELD_CLASS_BIT(NonNull); + STRINGISE_BITFIELD_CLASS_BIT(JumpTable); + STRINGISE_BITFIELD_CLASS_BIT(Dereferenceable); + STRINGISE_BITFIELD_CLASS_BIT(DereferenceableOrNull); + STRINGISE_BITFIELD_CLASS_BIT(Convergent); + STRINGISE_BITFIELD_CLASS_BIT(SafeStack); + STRINGISE_BITFIELD_CLASS_BIT(ArgMemOnly); + } + END_BITFIELD_STRINGISE(); +} diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index 41fc1e61f..ae8bd3a41 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -26,6 +26,7 @@ #include +#include "api/replay/apidefs.h" #include "api/replay/rdcstr.h" #include "driver/dx/official/d3dcommon.h" #include "driver/shaders/dxbc/dxbc_common.h" @@ -63,10 +64,75 @@ struct Symbol size_t idx; }; +// this enum is ordered to match the serialised order of these attributes +enum class Attribute : uint64_t +{ + None = 0, + // 0 is unused, so no 1ULL << 0 + Alignment = 1ULL << 1, + AlwaysInline = 1ULL << 2, + ByVal = 1ULL << 3, + InlineHint = 1ULL << 4, + InReg = 1ULL << 5, + MinSize = 1ULL << 6, + Naked = 1ULL << 7, + Nest = 1ULL << 8, + NoAlias = 1ULL << 9, + NoBuiltin = 1ULL << 10, + NoCapture = 1ULL << 11, + NoDuplicate = 1ULL << 12, + NoImplicitFloat = 1ULL << 13, + NoInline = 1ULL << 14, + NonLazyBind = 1ULL << 15, + NoRedZone = 1ULL << 16, + NoReturn = 1ULL << 17, + NoUnwind = 1ULL << 18, + OptimizeForSize = 1ULL << 19, + ReadNone = 1ULL << 20, + ReadOnly = 1ULL << 21, + Returned = 1ULL << 22, + ReturnsTwice = 1ULL << 23, + SExt = 1ULL << 24, + StackAlignment = 1ULL << 25, + StackProtect = 1ULL << 26, + StackProtectReq = 1ULL << 27, + StackProtectStrong = 1ULL << 28, + StructRet = 1ULL << 29, + SanitizeAddress = 1ULL << 30, + SanitizeThread = 1ULL << 31, + SanitizeMemory = 1ULL << 32, + UWTable = 1ULL << 33, + ZExt = 1ULL << 34, + Builtin = 1ULL << 35, + Cold = 1ULL << 36, + OptimizeNone = 1ULL << 37, + InAlloca = 1ULL << 38, + NonNull = 1ULL << 39, + JumpTable = 1ULL << 40, + Dereferenceable = 1ULL << 41, + DereferenceableOrNull = 1ULL << 42, + Convergent = 1ULL << 43, + SafeStack = 1ULL << 44, + ArgMemOnly = 1ULL << 45, +}; + +BITMASK_OPERATORS(Attribute); + +struct AttributeGroup +{ + uint64_t index = 0; + + Attribute params = Attribute::None; + uint64_t align = 0, stackAlign = 0, derefBytes = 0, derefOrNullBytes = 0; + rdcarray> strs; +}; + class Program { public: Program(const byte *bytes, size_t length); + Program(const Program &o) = default; + Program &operator=(const Program &o) = default; void FetchComputeProperties(DXBC::Reflection *reflection); DXBC::Reflection *GetReflection(); @@ -96,9 +162,14 @@ private: rdcarray m_Kinds; + rdcarray m_AttributeGroups; + rdcarray> m_Attributes; + rdcstr m_Triple, m_Datalayout; rdcstr m_Disassembly; }; }; // namespace DXIL + +DECLARE_REFLECTION_ENUM(DXIL::Attribute);