mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-24 07:26:34 +00:00
Add stubbed out DXIL bytecode decoder
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include "api/app/renderdoc_app.h"
|
||||
#include "common/common.h"
|
||||
#include "driver/dx/official/d3dcompiler.h"
|
||||
#include "driver/shaders/dxil/dxil_bytecode.h"
|
||||
#include "serialise/serialiser.h"
|
||||
#include "strings/string_utils.h"
|
||||
#include "dxbc_bytecode.h"
|
||||
@@ -103,11 +104,15 @@ struct FileHeader
|
||||
// uint32 chunkOffsets[numChunks]; follows
|
||||
};
|
||||
|
||||
struct ILDNHeader
|
||||
{
|
||||
uint16_t Flags;
|
||||
uint16_t NameLength;
|
||||
char Name[1];
|
||||
};
|
||||
|
||||
struct RDEFHeader
|
||||
{
|
||||
uint32_t fourcc; // "RDEF"
|
||||
uint32_t chunkLength; // length of this chunk
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// offsets are relative to this position in the file.
|
||||
// NOT the end of this structure. Note this differs
|
||||
@@ -151,9 +156,6 @@ struct RDEFResource
|
||||
|
||||
struct SIGNHeader
|
||||
{
|
||||
uint32_t fourcc; // "ISGN", "OSGN, "OSG5", "PCSG"
|
||||
uint32_t chunkLength; // length of this chunk
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// offsets are relative to this position in the file.
|
||||
// NOT the end of this structure. Note this differs
|
||||
@@ -244,6 +246,9 @@ static const uint32_t FOURCC_OSG5 = MAKE_FOURCC('O', 'S', 'G', '5');
|
||||
static const uint32_t FOURCC_PCSG = MAKE_FOURCC('P', 'C', 'S', 'G');
|
||||
static const uint32_t FOURCC_Aon9 = MAKE_FOURCC('A', 'o', 'n', '9');
|
||||
static const uint32_t FOURCC_PRIV = MAKE_FOURCC('P', 'R', 'I', 'V');
|
||||
static const uint32_t FOURCC_DXIL = MAKE_FOURCC('D', 'X', 'I', 'L');
|
||||
static const uint32_t FOURCC_ILDB = MAKE_FOURCC('I', 'L', 'D', 'B');
|
||||
static const uint32_t FOURCC_ILDN = MAKE_FOURCC('I', 'L', 'D', 'N');
|
||||
|
||||
int TypeByteSize(VariableType t)
|
||||
{
|
||||
@@ -473,6 +478,8 @@ D3D_PRIMITIVE_TOPOLOGY DXBCContainer::GetOutputTopology()
|
||||
|
||||
if(m_DXBCByteCode)
|
||||
m_OutputTopology = m_DXBCByteCode->GetOutputTopology();
|
||||
else if(m_DXILByteCode)
|
||||
m_OutputTopology = m_DXILByteCode->GetOutputTopology();
|
||||
}
|
||||
|
||||
return m_OutputTopology;
|
||||
@@ -490,6 +497,8 @@ const std::string &DXBCContainer::GetDisassembly()
|
||||
|
||||
if(m_DXBCByteCode)
|
||||
m_Disassembly += m_DXBCByteCode->GetDisassembly();
|
||||
else if(m_DXILByteCode)
|
||||
m_Disassembly += m_DXILByteCode->GetDisassembly();
|
||||
}
|
||||
|
||||
return m_Disassembly;
|
||||
@@ -631,13 +640,13 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
|
||||
for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++)
|
||||
{
|
||||
uint32_t *fourcc = (uint32_t *)(data + chunkOffsets[chunkIdx]);
|
||||
uint32_t *chunkSize = (uint32_t *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t));
|
||||
uint32_t *chunkSize = (uint32_t *)(fourcc + 1);
|
||||
|
||||
char *chunkContents = (char *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t) * 2);
|
||||
char *chunkContents = (char *)(chunkSize + 1);
|
||||
|
||||
if(*fourcc == FOURCC_RDEF)
|
||||
{
|
||||
RDEFHeader *h = (RDEFHeader *)fourcc;
|
||||
RDEFHeader *h = (RDEFHeader *)chunkContents;
|
||||
|
||||
// for target version 0x500, unknown[0] is FOURCC_RD11.
|
||||
// for 0x501 it's "\x13\x13\D%"
|
||||
@@ -920,6 +929,46 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
|
||||
{
|
||||
m_DXBCByteCode = new DXBCBytecode::Program((const byte *)chunkContents, *chunkSize);
|
||||
}
|
||||
else if(*fourcc == FOURCC_ILDN)
|
||||
{
|
||||
ILDNHeader *h = (ILDNHeader *)chunkContents;
|
||||
|
||||
m_DebugFileName = rdcstr(h->Name, h->NameLength);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_DXBCByteCode == NULL)
|
||||
{
|
||||
// prefer ILDB if present
|
||||
for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++)
|
||||
{
|
||||
uint32_t *fourcc = (uint32_t *)(data + chunkOffsets[chunkIdx]);
|
||||
uint32_t *chunkSize = (uint32_t *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t));
|
||||
|
||||
char *chunkContents = (char *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t) * 2);
|
||||
|
||||
if(*fourcc == FOURCC_ILDB)
|
||||
{
|
||||
m_DXILByteCode = new DXIL::Program((const byte *)chunkContents, *chunkSize);
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find it, look for DXIL
|
||||
if(m_DXILByteCode == NULL)
|
||||
{
|
||||
for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++)
|
||||
{
|
||||
uint32_t *fourcc = (uint32_t *)(data + chunkOffsets[chunkIdx]);
|
||||
uint32_t *chunkSize = (uint32_t *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t));
|
||||
|
||||
char *chunkContents = (char *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t) * 2);
|
||||
|
||||
if(*fourcc == FOURCC_DXIL)
|
||||
{
|
||||
m_DXILByteCode = new DXIL::Program((const byte *)chunkContents, *chunkSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get type/version that's used regularly and cheap to fetch
|
||||
@@ -929,6 +978,12 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
|
||||
m_Version.Major = m_DXBCByteCode->GetMajorVersion();
|
||||
m_Version.Minor = m_DXBCByteCode->GetMinorVersion();
|
||||
}
|
||||
else if(m_DXILByteCode)
|
||||
{
|
||||
m_Type = m_DXILByteCode->GetShaderType();
|
||||
m_Version.Major = m_DXILByteCode->GetMajorVersion();
|
||||
m_Version.Minor = m_DXILByteCode->GetMinorVersion();
|
||||
}
|
||||
|
||||
// if reflection information was stripped, attempt to reverse engineer basic info from
|
||||
// declarations
|
||||
@@ -937,19 +992,21 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
|
||||
// need to disassemble now to guess resources
|
||||
if(m_DXBCByteCode)
|
||||
m_Reflection = m_DXBCByteCode->GuessReflection();
|
||||
else if(m_DXILByteCode)
|
||||
m_Reflection = m_DXILByteCode->GetReflection();
|
||||
}
|
||||
|
||||
for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++)
|
||||
{
|
||||
uint32_t *fourcc = (uint32_t *)(data + chunkOffsets[chunkIdx]);
|
||||
// uint32_t *chunkSize = (uint32_t *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t));
|
||||
// uint32_t *chunkSize = (uint32_t *)(fourcc + 1);
|
||||
|
||||
char *chunkContents = (char *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t) * 2);
|
||||
char *chunkContents = (char *)(fourcc + 2);
|
||||
|
||||
if(*fourcc == FOURCC_ISGN || *fourcc == FOURCC_OSGN || *fourcc == FOURCC_ISG1 ||
|
||||
*fourcc == FOURCC_OSG1 || *fourcc == FOURCC_OSG5 || *fourcc == FOURCC_PCSG)
|
||||
{
|
||||
SIGNHeader *sign = (SIGNHeader *)fourcc;
|
||||
SIGNHeader *sign = (SIGNHeader *)chunkContents;
|
||||
|
||||
std::vector<SigParameter> *sig = NULL;
|
||||
|
||||
@@ -1122,6 +1179,8 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
|
||||
{
|
||||
if(m_DXBCByteCode)
|
||||
m_DXBCByteCode->FetchComputeProperties(m_Reflection);
|
||||
else if(m_DXILByteCode)
|
||||
m_DXILByteCode->FetchComputeProperties(m_Reflection);
|
||||
}
|
||||
|
||||
// initialise debug chunks last
|
||||
@@ -1345,7 +1404,7 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
|
||||
|
||||
// if we had bytecode in this container, ensure we had reflection. If it's a blob with only an
|
||||
// input signature then we can do without reflection.
|
||||
if(m_DXBCByteCode)
|
||||
if(m_DXBCByteCode || m_DXILByteCode)
|
||||
{
|
||||
RDCASSERT(m_Reflection);
|
||||
}
|
||||
@@ -1355,6 +1414,7 @@ DXBCContainer::~DXBCContainer()
|
||||
{
|
||||
SAFE_DELETE(m_DebugInfo);
|
||||
SAFE_DELETE(m_DXBCByteCode);
|
||||
SAFE_DELETE(m_DXILByteCode);
|
||||
SAFE_DELETE(m_Reflection);
|
||||
}
|
||||
|
||||
@@ -1478,6 +1538,26 @@ ShaderCompileFlags EncodeFlags(const IDebugInfo *dbg)
|
||||
|
||||
#include "3rdparty/catch/catch.hpp"
|
||||
|
||||
#if 0
|
||||
|
||||
TEST_CASE("DO NOT COMMIT - convenience test", "[dxbc]")
|
||||
{
|
||||
// this test loads a file from disk and passes it through DXBC::DXBCContainer. Useful for when you
|
||||
// are iterating on a shader and don't want to have to load a whole capture.
|
||||
std::vector<byte> buf;
|
||||
FileIO::slurp("/path/to/container_file.dxbc", buf);
|
||||
|
||||
DXBC::DXBCContainer container(buf.data(), buf.size());
|
||||
|
||||
// the only thing fetched lazily is the disassembly, so grab that here
|
||||
|
||||
std::string disasm = container.GetDisassembly();
|
||||
|
||||
RDCLOG("%s", disasm.c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE("Check DXBC flags are non-overlapping", "[dxbc]")
|
||||
{
|
||||
for(const DXBC::FxcArg &a : DXBC::fxc_flags)
|
||||
|
||||
@@ -39,6 +39,11 @@ namespace DXBCBytecode
|
||||
class Program;
|
||||
};
|
||||
|
||||
namespace DXIL
|
||||
{
|
||||
class Program;
|
||||
};
|
||||
|
||||
namespace DXBC
|
||||
{
|
||||
class IDebugInfo;
|
||||
@@ -151,6 +156,7 @@ public:
|
||||
const std::string &GetDisassembly();
|
||||
|
||||
const DXBCBytecode::Program *GetDXBCByteCode() { return m_DXBCByteCode; }
|
||||
const DXIL::Program *GetDXILByteCode() { return m_DXILByteCode; }
|
||||
static void GetHash(uint32_t hash[4], const void *ByteCode, size_t BytecodeLength);
|
||||
|
||||
static bool CheckForDebugInfo(const void *ByteCode, size_t ByteCodeLength);
|
||||
@@ -168,8 +174,11 @@ private:
|
||||
CBufferVariableType ParseRDEFType(RDEFHeader *h, char *chunk, uint32_t offset);
|
||||
std::map<uint32_t, CBufferVariableType> m_Variables;
|
||||
|
||||
rdcstr m_DebugFileName;
|
||||
|
||||
ShaderStatistics m_ShaderStats;
|
||||
DXBCBytecode::Program *m_DXBCByteCode = NULL;
|
||||
DXIL::Program *m_DXILByteCode = NULL;
|
||||
IDebugInfo *m_DebugInfo = NULL;
|
||||
Reflection *m_Reflection = NULL;
|
||||
};
|
||||
|
||||
@@ -124,6 +124,11 @@
|
||||
<ClInclude Include="official\cvinfo.h" />
|
||||
<ClInclude Include="precompiled.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\dxil\renderdoc_dxil.vcxproj">
|
||||
<Project>{8ae46ec2-ea46-441f-bee2-94097101d6a3}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
@@ -23,7 +23,776 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "dxil_bytecode.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include "common/common.h"
|
||||
#include "llvm_decoder.h"
|
||||
|
||||
// undef some annoying defines that might come from OS headers
|
||||
#undef VOID
|
||||
#undef FLOAT
|
||||
#undef LABEL
|
||||
#undef OPAQUE
|
||||
|
||||
namespace DXIL
|
||||
{
|
||||
struct ProgramHeader
|
||||
{
|
||||
uint16_t ProgramVersion;
|
||||
uint16_t ProgramType;
|
||||
uint32_t SizeInUint32; // Size in uint32_t units including this header.
|
||||
uint32_t DxilMagic; // 0x4C495844, ASCII "DXIL".
|
||||
uint32_t DxilVersion; // DXIL version.
|
||||
uint32_t BitcodeOffset; // Offset to LLVM bitcode (from DxilMagic).
|
||||
uint32_t BitcodeSize; // Size of LLVM bitcode.
|
||||
};
|
||||
|
||||
enum class KnownBlocks : uint32_t
|
||||
{
|
||||
BLOCKINFO = 0,
|
||||
|
||||
// 1-7 reserved,
|
||||
|
||||
MODULE_BLOCK = 8,
|
||||
PARAMATTR_BLOCK = 9,
|
||||
PARAMATTR_GROUP_BLOCK = 10,
|
||||
CONSTANTS_BLOCK = 11,
|
||||
FUNCTION_BLOCK = 12,
|
||||
TYPE_SYMTAB_BLOCK = 13,
|
||||
VALUE_SYMTAB_BLOCK = 14,
|
||||
METADATA_BLOCK = 15,
|
||||
METADATA_ATTACHMENT = 16,
|
||||
TYPE_BLOCK = 17,
|
||||
};
|
||||
|
||||
enum class ModuleRecord : uint32_t
|
||||
{
|
||||
VERSION = 1,
|
||||
TRIPLE = 2,
|
||||
DATALAYOUT = 3,
|
||||
FUNCTION = 8,
|
||||
};
|
||||
|
||||
enum class ConstantsRecord : uint32_t
|
||||
{
|
||||
SETTYPE = 1,
|
||||
CONST_NULL = 2,
|
||||
UNDEF = 3,
|
||||
INTEGER = 4,
|
||||
WIDE_INTEGER = 5,
|
||||
FLOAT = 6,
|
||||
AGGREGATE = 7,
|
||||
STRING = 8,
|
||||
DATA = 22,
|
||||
};
|
||||
|
||||
enum class FunctionRecord : uint32_t
|
||||
{
|
||||
DECLAREBLOCKS = 1,
|
||||
INST_BINOP = 2,
|
||||
INST_CAST = 3,
|
||||
INST_GEP_OLD = 4,
|
||||
INST_SELECT = 5,
|
||||
INST_EXTRACTELT = 6,
|
||||
INST_INSERTELT = 7,
|
||||
INST_SHUFFLEVEC = 8,
|
||||
INST_CMP = 9,
|
||||
INST_RET = 10,
|
||||
INST_BR = 11,
|
||||
INST_SWITCH = 12,
|
||||
INST_INVOKE = 13,
|
||||
INST_UNREACHABLE = 15,
|
||||
INST_PHI = 16,
|
||||
INST_ALLOCA = 19,
|
||||
INST_LOAD = 20,
|
||||
INST_VAARG = 23,
|
||||
INST_STORE_OLD = 24,
|
||||
INST_EXTRACTVAL = 26,
|
||||
INST_INSERTVAL = 27,
|
||||
INST_CMP2 = 28,
|
||||
INST_VSELECT = 29,
|
||||
INST_INBOUNDS_GEP_OLD = 30,
|
||||
INST_INDIRECTBR = 31,
|
||||
DEBUG_LOC_AGAIN = 33,
|
||||
INST_CALL = 34,
|
||||
DEBUG_LOC = 35,
|
||||
INST_FENCE = 36,
|
||||
INST_CMPXCHG_OLD = 37,
|
||||
INST_ATOMICRMW = 38,
|
||||
INST_RESUME = 39,
|
||||
INST_LANDINGPAD_OLD = 40,
|
||||
INST_LOADATOMIC = 41,
|
||||
INST_STOREATOMIC_OLD = 42,
|
||||
INST_GEP = 43,
|
||||
INST_STORE = 44,
|
||||
INST_STOREATOMIC = 45,
|
||||
INST_CMPXCHG = 46,
|
||||
INST_LANDINGPAD = 47,
|
||||
INST_CLEANUPRET = 48,
|
||||
INST_CATCHRET = 49,
|
||||
INST_CATCHPAD = 50,
|
||||
INST_CLEANUPPAD = 51,
|
||||
INST_CATCHSWITCH = 52,
|
||||
OPERAND_BUNDLE = 55,
|
||||
INST_UNOP = 56,
|
||||
INST_CALLBR = 57,
|
||||
};
|
||||
|
||||
enum class ValueSymtabRecord : uint32_t
|
||||
{
|
||||
ENTRY = 1,
|
||||
BBENTRY = 2,
|
||||
FNENTRY = 3,
|
||||
COMBINED_ENTRY = 5,
|
||||
};
|
||||
|
||||
enum class MetaDataRecord : uint32_t
|
||||
{
|
||||
STRING_OLD = 1,
|
||||
VALUE = 2,
|
||||
NODE = 3,
|
||||
NAME = 4,
|
||||
DISTINCT_NODE = 5,
|
||||
KIND = 6,
|
||||
LOCATION = 7,
|
||||
OLD_NODE = 8,
|
||||
OLD_FN_NODE = 9,
|
||||
NAMED_NODE = 10,
|
||||
ATTACHMENT = 11,
|
||||
GENERIC_DEBUG = 12,
|
||||
SUBRANGE = 13,
|
||||
ENUMERATOR = 14,
|
||||
BASIC_TYPE = 15,
|
||||
FILE = 16,
|
||||
DERIVED_TYPE = 17,
|
||||
COMPOSITE_TYPE = 18,
|
||||
SUBROUTINE_TYPE = 19,
|
||||
COMPILE_UNIT = 20,
|
||||
SUBPROGRAM = 21,
|
||||
LEXICAL_BLOCK = 22,
|
||||
LEXICAL_BLOCK_FILE = 23,
|
||||
NAMESPACE = 24,
|
||||
TEMPLATE_TYPE = 25,
|
||||
TEMPLATE_VALUE = 26,
|
||||
GLOBAL_VAR = 27,
|
||||
LOCAL_VAR = 28,
|
||||
EXPRESSION = 29,
|
||||
OBJC_PROPERTY = 30,
|
||||
IMPORTED_ENTITY = 31,
|
||||
MODULE = 32,
|
||||
MACRO = 33,
|
||||
MACRO_FILE = 34,
|
||||
STRINGS = 35,
|
||||
GLOBAL_DECL_ATTACHMENT = 36,
|
||||
GLOBAL_VAR_EXPR = 37,
|
||||
INDEX_OFFSET = 38,
|
||||
INDEX = 39,
|
||||
LABEL = 40,
|
||||
COMMON_BLOCK = 44,
|
||||
};
|
||||
|
||||
enum class TypeRecord : uint32_t
|
||||
{
|
||||
NUMENTRY = 1,
|
||||
VOID = 2,
|
||||
FLOAT = 3,
|
||||
DOUBLE = 4,
|
||||
LABEL = 5,
|
||||
OPAQUE = 6,
|
||||
INTEGER = 7,
|
||||
POINTER = 8,
|
||||
FUNCTION_OLD = 9,
|
||||
HALF = 10,
|
||||
ARRAY = 11,
|
||||
VECTOR = 12,
|
||||
METADATA = 16,
|
||||
STRUCT_ANON = 18,
|
||||
STRUCT_NAME = 19,
|
||||
STRUCT_NAMED = 20,
|
||||
FUNCTION = 21,
|
||||
TOKEN = 22,
|
||||
};
|
||||
|
||||
static std::string getName(uint32_t parentBlock, const LLVMBC::BlockOrRecord &block)
|
||||
{
|
||||
const char *name = NULL;
|
||||
|
||||
if(block.IsBlock())
|
||||
{
|
||||
// GetBlockName in BitcodeAnalyzer.cpp
|
||||
switch(KnownBlocks(block.id))
|
||||
{
|
||||
case KnownBlocks::BLOCKINFO: name = "BLOCKINFO"; break;
|
||||
case KnownBlocks::MODULE_BLOCK: name = "MODULE_BLOCK"; break;
|
||||
case KnownBlocks::PARAMATTR_BLOCK: name = "PARAMATTR_BLOCK"; break;
|
||||
case KnownBlocks::PARAMATTR_GROUP_BLOCK: name = "PARAMATTR_GROUP_BLOCK"; break;
|
||||
case KnownBlocks::CONSTANTS_BLOCK: name = "CONSTANTS_BLOCK"; break;
|
||||
case KnownBlocks::FUNCTION_BLOCK: name = "FUNCTION_BLOCK"; break;
|
||||
case KnownBlocks::TYPE_SYMTAB_BLOCK: name = "TYPE_SYMTAB_BLOCK"; break;
|
||||
case KnownBlocks::VALUE_SYMTAB_BLOCK: name = "VALUE_SYMTAB_BLOCK"; break;
|
||||
case KnownBlocks::METADATA_BLOCK: name = "METADATA_BLOCK"; break;
|
||||
case KnownBlocks::METADATA_ATTACHMENT: name = "METADATA_ATTACHMENT"; break;
|
||||
case KnownBlocks::TYPE_BLOCK: name = "TYPE_BLOCK"; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#define STRINGISE_RECORD(a) \
|
||||
case decltype(code)::a: name = #a; break;
|
||||
|
||||
// GetCodeName in BitcodeAnalyzer.cpp
|
||||
switch(KnownBlocks(parentBlock))
|
||||
{
|
||||
case KnownBlocks::MODULE_BLOCK:
|
||||
{
|
||||
ModuleRecord code = ModuleRecord(block.id);
|
||||
switch(code)
|
||||
{
|
||||
STRINGISE_RECORD(VERSION);
|
||||
STRINGISE_RECORD(TRIPLE);
|
||||
STRINGISE_RECORD(DATALAYOUT);
|
||||
STRINGISE_RECORD(FUNCTION);
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KnownBlocks::PARAMATTR_BLOCK:
|
||||
case KnownBlocks::PARAMATTR_GROUP_BLOCK: name = "ENTRY"; break;
|
||||
case KnownBlocks::CONSTANTS_BLOCK:
|
||||
{
|
||||
ConstantsRecord code = ConstantsRecord(block.id);
|
||||
switch(code)
|
||||
{
|
||||
STRINGISE_RECORD(SETTYPE);
|
||||
STRINGISE_RECORD(UNDEF);
|
||||
STRINGISE_RECORD(INTEGER);
|
||||
STRINGISE_RECORD(WIDE_INTEGER);
|
||||
STRINGISE_RECORD(FLOAT);
|
||||
STRINGISE_RECORD(AGGREGATE);
|
||||
STRINGISE_RECORD(STRING);
|
||||
STRINGISE_RECORD(DATA);
|
||||
case ConstantsRecord::CONST_NULL: name = "NULL"; break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KnownBlocks::FUNCTION_BLOCK:
|
||||
{
|
||||
FunctionRecord code = FunctionRecord(block.id);
|
||||
switch(code)
|
||||
{
|
||||
STRINGISE_RECORD(DECLAREBLOCKS);
|
||||
STRINGISE_RECORD(INST_BINOP);
|
||||
STRINGISE_RECORD(INST_CAST);
|
||||
STRINGISE_RECORD(INST_GEP_OLD);
|
||||
STRINGISE_RECORD(INST_SELECT);
|
||||
STRINGISE_RECORD(INST_EXTRACTELT);
|
||||
STRINGISE_RECORD(INST_INSERTELT);
|
||||
STRINGISE_RECORD(INST_SHUFFLEVEC);
|
||||
STRINGISE_RECORD(INST_CMP);
|
||||
STRINGISE_RECORD(INST_RET);
|
||||
STRINGISE_RECORD(INST_BR);
|
||||
STRINGISE_RECORD(INST_SWITCH);
|
||||
STRINGISE_RECORD(INST_INVOKE);
|
||||
STRINGISE_RECORD(INST_UNREACHABLE);
|
||||
STRINGISE_RECORD(INST_PHI);
|
||||
STRINGISE_RECORD(INST_ALLOCA);
|
||||
STRINGISE_RECORD(INST_LOAD);
|
||||
STRINGISE_RECORD(INST_VAARG);
|
||||
STRINGISE_RECORD(INST_STORE_OLD);
|
||||
STRINGISE_RECORD(INST_EXTRACTVAL);
|
||||
STRINGISE_RECORD(INST_INSERTVAL);
|
||||
STRINGISE_RECORD(INST_CMP2);
|
||||
STRINGISE_RECORD(INST_VSELECT);
|
||||
STRINGISE_RECORD(INST_INBOUNDS_GEP_OLD);
|
||||
STRINGISE_RECORD(INST_INDIRECTBR);
|
||||
STRINGISE_RECORD(DEBUG_LOC_AGAIN);
|
||||
STRINGISE_RECORD(INST_CALL);
|
||||
STRINGISE_RECORD(DEBUG_LOC);
|
||||
STRINGISE_RECORD(INST_FENCE);
|
||||
STRINGISE_RECORD(INST_CMPXCHG_OLD);
|
||||
STRINGISE_RECORD(INST_ATOMICRMW);
|
||||
STRINGISE_RECORD(INST_RESUME);
|
||||
STRINGISE_RECORD(INST_LANDINGPAD_OLD);
|
||||
STRINGISE_RECORD(INST_LOADATOMIC);
|
||||
STRINGISE_RECORD(INST_STOREATOMIC_OLD);
|
||||
STRINGISE_RECORD(INST_GEP);
|
||||
STRINGISE_RECORD(INST_STORE);
|
||||
STRINGISE_RECORD(INST_STOREATOMIC);
|
||||
STRINGISE_RECORD(INST_CMPXCHG);
|
||||
STRINGISE_RECORD(INST_LANDINGPAD);
|
||||
STRINGISE_RECORD(INST_CLEANUPRET);
|
||||
STRINGISE_RECORD(INST_CATCHRET);
|
||||
STRINGISE_RECORD(INST_CATCHPAD);
|
||||
STRINGISE_RECORD(INST_CLEANUPPAD);
|
||||
STRINGISE_RECORD(INST_CATCHSWITCH);
|
||||
STRINGISE_RECORD(OPERAND_BUNDLE);
|
||||
STRINGISE_RECORD(INST_UNOP);
|
||||
STRINGISE_RECORD(INST_CALLBR);
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KnownBlocks::VALUE_SYMTAB_BLOCK:
|
||||
{
|
||||
ValueSymtabRecord code = ValueSymtabRecord(block.id);
|
||||
switch(code)
|
||||
{
|
||||
STRINGISE_RECORD(ENTRY);
|
||||
STRINGISE_RECORD(BBENTRY);
|
||||
STRINGISE_RECORD(FNENTRY);
|
||||
STRINGISE_RECORD(COMBINED_ENTRY);
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KnownBlocks::METADATA_BLOCK:
|
||||
{
|
||||
MetaDataRecord code = MetaDataRecord(block.id);
|
||||
switch(code)
|
||||
{
|
||||
STRINGISE_RECORD(STRING_OLD);
|
||||
STRINGISE_RECORD(VALUE);
|
||||
STRINGISE_RECORD(NODE);
|
||||
STRINGISE_RECORD(NAME);
|
||||
STRINGISE_RECORD(DISTINCT_NODE);
|
||||
STRINGISE_RECORD(KIND);
|
||||
STRINGISE_RECORD(LOCATION);
|
||||
STRINGISE_RECORD(OLD_NODE);
|
||||
STRINGISE_RECORD(OLD_FN_NODE);
|
||||
STRINGISE_RECORD(NAMED_NODE);
|
||||
STRINGISE_RECORD(ATTACHMENT);
|
||||
STRINGISE_RECORD(GENERIC_DEBUG);
|
||||
STRINGISE_RECORD(SUBRANGE);
|
||||
STRINGISE_RECORD(ENUMERATOR);
|
||||
STRINGISE_RECORD(BASIC_TYPE);
|
||||
STRINGISE_RECORD(FILE);
|
||||
STRINGISE_RECORD(DERIVED_TYPE);
|
||||
STRINGISE_RECORD(COMPOSITE_TYPE);
|
||||
STRINGISE_RECORD(SUBROUTINE_TYPE);
|
||||
STRINGISE_RECORD(COMPILE_UNIT);
|
||||
STRINGISE_RECORD(SUBPROGRAM);
|
||||
STRINGISE_RECORD(LEXICAL_BLOCK);
|
||||
STRINGISE_RECORD(LEXICAL_BLOCK_FILE);
|
||||
STRINGISE_RECORD(NAMESPACE);
|
||||
STRINGISE_RECORD(TEMPLATE_TYPE);
|
||||
STRINGISE_RECORD(TEMPLATE_VALUE);
|
||||
STRINGISE_RECORD(GLOBAL_VAR);
|
||||
STRINGISE_RECORD(LOCAL_VAR);
|
||||
STRINGISE_RECORD(EXPRESSION);
|
||||
STRINGISE_RECORD(OBJC_PROPERTY);
|
||||
STRINGISE_RECORD(IMPORTED_ENTITY);
|
||||
STRINGISE_RECORD(MODULE);
|
||||
STRINGISE_RECORD(MACRO);
|
||||
STRINGISE_RECORD(MACRO_FILE);
|
||||
STRINGISE_RECORD(STRINGS);
|
||||
STRINGISE_RECORD(GLOBAL_DECL_ATTACHMENT);
|
||||
STRINGISE_RECORD(GLOBAL_VAR_EXPR);
|
||||
STRINGISE_RECORD(INDEX_OFFSET);
|
||||
STRINGISE_RECORD(INDEX);
|
||||
STRINGISE_RECORD(LABEL);
|
||||
STRINGISE_RECORD(COMMON_BLOCK);
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KnownBlocks::TYPE_BLOCK:
|
||||
{
|
||||
TypeRecord code = TypeRecord(block.id);
|
||||
switch(code)
|
||||
{
|
||||
STRINGISE_RECORD(NUMENTRY);
|
||||
STRINGISE_RECORD(VOID);
|
||||
STRINGISE_RECORD(FLOAT);
|
||||
STRINGISE_RECORD(DOUBLE);
|
||||
STRINGISE_RECORD(LABEL);
|
||||
STRINGISE_RECORD(OPAQUE);
|
||||
STRINGISE_RECORD(INTEGER);
|
||||
STRINGISE_RECORD(POINTER);
|
||||
STRINGISE_RECORD(FUNCTION_OLD);
|
||||
STRINGISE_RECORD(HALF);
|
||||
STRINGISE_RECORD(ARRAY);
|
||||
STRINGISE_RECORD(VECTOR);
|
||||
STRINGISE_RECORD(METADATA);
|
||||
STRINGISE_RECORD(STRUCT_ANON);
|
||||
STRINGISE_RECORD(STRUCT_NAME);
|
||||
STRINGISE_RECORD(STRUCT_NAMED);
|
||||
STRINGISE_RECORD(FUNCTION);
|
||||
STRINGISE_RECORD(TOKEN);
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fallback
|
||||
if(name)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(block.IsBlock())
|
||||
return StringFormat::Fmt("BLOCK%u", block.id);
|
||||
else
|
||||
return StringFormat::Fmt("RECORD%u", block.id);
|
||||
}
|
||||
}
|
||||
|
||||
static rdcstr escapeString(rdcstr str)
|
||||
{
|
||||
for(size_t i = 0; i < str.size(); i++)
|
||||
{
|
||||
if(str[i] == '\r')
|
||||
{
|
||||
str[i] = 'r';
|
||||
str.insert(i, "\\", 1);
|
||||
i++;
|
||||
}
|
||||
else if(str[i] == '\n')
|
||||
{
|
||||
str[i] = 'n';
|
||||
str.insert(i, "\\", 1);
|
||||
i++;
|
||||
}
|
||||
else if(str[i] == '\t')
|
||||
{
|
||||
str[i] = 't';
|
||||
str.insert(i, "\\", 1);
|
||||
i++;
|
||||
}
|
||||
else if(str[i] == '\'' || str[i] == '\\')
|
||||
{
|
||||
str.insert(i, "\\", 1);
|
||||
i++;
|
||||
}
|
||||
else if(!isprint(str[i]))
|
||||
{
|
||||
str.insert(i + 1, StringFormat::Fmt("x%02x", str[i]));
|
||||
str[i] = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static void dumpRecord(uint32_t parentBlock, const LLVMBC::BlockOrRecord &record, int indent)
|
||||
{
|
||||
std::string line(indent, ' ');
|
||||
|
||||
line += "<" + getName(parentBlock, record);
|
||||
|
||||
if(KnownBlocks(parentBlock) == KnownBlocks::METADATA_BLOCK &&
|
||||
(MetaDataRecord(record.id) == MetaDataRecord::STRING_OLD ||
|
||||
MetaDataRecord(record.id) == MetaDataRecord::NAME ||
|
||||
MetaDataRecord(record.id) == MetaDataRecord::KIND))
|
||||
{
|
||||
line += " record string = '" + escapeString(record.getString()) + "'";
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i = 0; i < record.ops.size(); i++)
|
||||
line += StringFormat::Fmt(" op%u=%llu", (uint32_t)i, record.ops[i]);
|
||||
}
|
||||
|
||||
if(record.blob)
|
||||
line += StringFormat::Fmt(" with blob of %u bytes", (uint32_t)record.blobLength);
|
||||
|
||||
line += "/>";
|
||||
|
||||
RDCLOG("%s", line.c_str());
|
||||
}
|
||||
|
||||
static void dumpBlock(const LLVMBC::BlockOrRecord &block, int indent)
|
||||
{
|
||||
std::string line(indent, ' ');
|
||||
|
||||
if(block.children.empty() || KnownBlocks(block.id) == KnownBlocks::BLOCKINFO)
|
||||
{
|
||||
line += StringFormat::Fmt("<%s/>", getName(0, block).c_str());
|
||||
RDCLOG("%s", line.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
line += StringFormat::Fmt("<%s NumWords=%u>", getName(0, block).c_str(), block.blockDwordLength);
|
||||
RDCLOG("%s", line.c_str());
|
||||
|
||||
for(const LLVMBC::BlockOrRecord &child : block.children)
|
||||
{
|
||||
if(child.IsBlock())
|
||||
dumpBlock(child, indent + 2);
|
||||
else
|
||||
dumpRecord(block.id, child, indent + 2);
|
||||
}
|
||||
|
||||
line = std::string(indent, ' ');
|
||||
line += StringFormat::Fmt("</%s>", getName(0, block).c_str());
|
||||
RDCLOG("%s", line.c_str());
|
||||
}
|
||||
|
||||
Program::Program(const byte *bytes, size_t length)
|
||||
{
|
||||
const byte *ptr = bytes;
|
||||
const ProgramHeader *header = (const ProgramHeader *)ptr;
|
||||
RDCASSERT(header->DxilMagic == MAKE_FOURCC('D', 'X', 'I', 'L'));
|
||||
|
||||
const byte *bitcode = ((const byte *)&header->DxilMagic) + header->BitcodeOffset;
|
||||
RDCASSERT(bitcode + header->BitcodeSize == ptr + length);
|
||||
|
||||
LLVMBC::BitcodeReader reader(bitcode, header->BitcodeSize);
|
||||
|
||||
LLVMBC::BlockOrRecord root = reader.ReadToplevelBlock();
|
||||
|
||||
// the top-level block should be MODULE_BLOCK
|
||||
RDCASSERT(KnownBlocks(root.id) == KnownBlocks::MODULE_BLOCK);
|
||||
|
||||
// we should have consumed all bits, only one top-level block
|
||||
RDCASSERT(reader.AtEndOfStream());
|
||||
|
||||
m_Type = DXBC::ShaderType(header->ProgramType);
|
||||
m_Major = (header->ProgramVersion & 0xf0) >> 4;
|
||||
m_Minor = header->ProgramVersion & 0xf;
|
||||
|
||||
// Input signature and Output signature haven't changed.
|
||||
// Pipeline Runtime Information we have decoded just not implemented here
|
||||
|
||||
rdcstr datalayout, triple;
|
||||
|
||||
#define IS_KNOWN(val, KnownID) (decltype(KnownID)(val) == KnownID)
|
||||
|
||||
for(const LLVMBC::BlockOrRecord &rootblock : root.children)
|
||||
{
|
||||
if(rootblock.IsRecord() && IS_KNOWN(rootblock.id, ModuleRecord::TRIPLE))
|
||||
{
|
||||
m_Triple = rootblock.getString();
|
||||
}
|
||||
else if(rootblock.IsRecord() && IS_KNOWN(rootblock.id, ModuleRecord::DATALAYOUT))
|
||||
{
|
||||
m_Datalayout = rootblock.getString();
|
||||
}
|
||||
else if(rootblock.IsBlock() && IS_KNOWN(rootblock.id, KnownBlocks::VALUE_SYMTAB_BLOCK))
|
||||
{
|
||||
for(const LLVMBC::BlockOrRecord &symtab : rootblock.children)
|
||||
{
|
||||
RDCLOG("function %llu is \"%s\"\n", symtab.ops[0], symtab.getString(1).c_str());
|
||||
}
|
||||
}
|
||||
else if(rootblock.IsBlock() && IS_KNOWN(rootblock.id, KnownBlocks::METADATA_BLOCK))
|
||||
{
|
||||
for(size_t i = 0; i < rootblock.children.size(); i++)
|
||||
{
|
||||
const LLVMBC::BlockOrRecord &meta = rootblock.children[i];
|
||||
if(IS_KNOWN(meta.id, MetaDataRecord::NAME))
|
||||
{
|
||||
rdcstr metaName = meta.getString();
|
||||
i++;
|
||||
const LLVMBC::BlockOrRecord &namedNode = rootblock.children[i];
|
||||
RDCASSERT(IS_KNOWN(namedNode.id, MetaDataRecord::NAMED_NODE));
|
||||
|
||||
std::string namedMeta = StringFormat::Fmt("!%s = !{", metaName.c_str());
|
||||
|
||||
bool first = true;
|
||||
for(uint64_t op : namedNode.ops)
|
||||
{
|
||||
if(!first)
|
||||
namedMeta += ", ";
|
||||
namedMeta += ToStr(op);
|
||||
first = false;
|
||||
}
|
||||
namedMeta += "}";
|
||||
|
||||
RDCLOG("%s", namedMeta.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IS_KNOWN(meta.id, MetaDataRecord::KIND))
|
||||
{
|
||||
RDCLOG("Kind[%llu] = %s\n", meta.ops[0], meta.getString(1).c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string metastr = StringFormat::Fmt("!%u = ", (uint32_t)i);
|
||||
|
||||
auto getMetaString = [&rootblock](uint64_t id) -> rdcstr {
|
||||
return id ? rootblock.children[id - 1].getString() : "NULL";
|
||||
};
|
||||
|
||||
if(IS_KNOWN(meta.id, MetaDataRecord::STRING_OLD))
|
||||
{
|
||||
metastr += "\"" + escapeString(meta.getString()) + "\"";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::FILE))
|
||||
{
|
||||
if(meta.ops[0])
|
||||
metastr += "distinct ";
|
||||
|
||||
metastr += "!DIFile(";
|
||||
metastr += StringFormat::Fmt("filename: \"%s\"",
|
||||
escapeString(getMetaString(meta.ops[1])).c_str());
|
||||
metastr += StringFormat::Fmt(", directory: \"%s\"",
|
||||
escapeString(getMetaString(meta.ops[2])).c_str());
|
||||
metastr += ")";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::NODE) ||
|
||||
IS_KNOWN(meta.id, MetaDataRecord::DISTINCT_NODE))
|
||||
{
|
||||
if(IS_KNOWN(meta.id, MetaDataRecord::DISTINCT_NODE))
|
||||
metastr += "distinct ";
|
||||
|
||||
metastr += "!{";
|
||||
bool first = true;
|
||||
for(uint64_t op : meta.ops)
|
||||
{
|
||||
if(!first)
|
||||
metastr += ", ";
|
||||
metastr += ToStr(op - 1);
|
||||
first = false;
|
||||
}
|
||||
metastr += "}";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::BASIC_TYPE))
|
||||
{
|
||||
metastr += "!DIBasicType()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::DERIVED_TYPE))
|
||||
{
|
||||
metastr += "!DIDerivedType()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::COMPOSITE_TYPE))
|
||||
{
|
||||
metastr += "!DICompositeType()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::SUBROUTINE_TYPE))
|
||||
{
|
||||
metastr += "!DISubroutineType()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::TEMPLATE_TYPE))
|
||||
{
|
||||
metastr += "!DITemplateTypeParameter()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::TEMPLATE_VALUE))
|
||||
{
|
||||
metastr += "!DITemplateValueParameter()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::SUBPROGRAM))
|
||||
{
|
||||
metastr += "!DISubprogram()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::LOCATION))
|
||||
{
|
||||
metastr += "!DILocation()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::LOCAL_VAR))
|
||||
{
|
||||
metastr += "!DILocalVariable()";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::VALUE))
|
||||
{
|
||||
// need to decode CONSTANTS_BLOCK and TYPE_BLOCK for this
|
||||
metastr += StringFormat::Fmt("!{values[%llu] interpreted as types[%llu]}", meta.ops[1],
|
||||
meta.ops[0]);
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::EXPRESSION))
|
||||
{
|
||||
// don't decode this yet
|
||||
metastr += "!DIExpression(";
|
||||
bool first = true;
|
||||
for(uint64_t op : meta.ops)
|
||||
{
|
||||
if(!first)
|
||||
metastr += ", ";
|
||||
metastr += ToStr(op);
|
||||
first = false;
|
||||
}
|
||||
metastr += ")";
|
||||
}
|
||||
else if(IS_KNOWN(meta.id, MetaDataRecord::COMPILE_UNIT))
|
||||
{
|
||||
// should be at least 14 parameters
|
||||
RDCASSERT(meta.ops.size() >= 14);
|
||||
|
||||
// we expect it to be marked as distinct, but we'll always treat it that way
|
||||
if(meta.ops[0])
|
||||
metastr += "distinct ";
|
||||
else
|
||||
metastr += "distinct? ";
|
||||
|
||||
metastr += "!DICompileUnit(";
|
||||
{
|
||||
metastr += StringFormat::Fmt(
|
||||
"language: %s", meta.ops[1] == 0x4 ? "DW_LANG_C_plus_plus" : "DW_LANG_unknown");
|
||||
metastr += StringFormat::Fmt(", file: !%llu", meta.ops[2] - 1);
|
||||
metastr += StringFormat::Fmt(", producer: \"%s\"",
|
||||
escapeString(getMetaString(meta.ops[3])).c_str());
|
||||
metastr += StringFormat::Fmt(", isOptimized: %s", meta.ops[4] ? "true" : "false");
|
||||
metastr += StringFormat::Fmt(", flags: \"%s\"",
|
||||
escapeString(getMetaString(meta.ops[5])).c_str());
|
||||
metastr += StringFormat::Fmt(", runtimeVersion: %llu", meta.ops[6]);
|
||||
metastr += StringFormat::Fmt(", splitDebugFilename: \"%s\"",
|
||||
escapeString(getMetaString(meta.ops[7])).c_str());
|
||||
metastr += StringFormat::Fmt(", emissionKind: %llu", meta.ops[8]);
|
||||
metastr += StringFormat::Fmt(", enums: !%llu", meta.ops[9] - 1);
|
||||
metastr += StringFormat::Fmt(", retainedTypes: !%llu", meta.ops[10] - 1);
|
||||
metastr += StringFormat::Fmt(", subprograms: !%llu", meta.ops[11] - 1);
|
||||
metastr += StringFormat::Fmt(", globals: !%llu", meta.ops[12] - 1);
|
||||
metastr += StringFormat::Fmt(", imports: !%llu", meta.ops[13] - 1);
|
||||
if(meta.ops.size() >= 15)
|
||||
metastr += StringFormat::Fmt(", dwoId: 0x%llu", meta.ops[14]);
|
||||
}
|
||||
metastr += ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("unhandled metadata type %u", meta.id);
|
||||
}
|
||||
|
||||
RDCLOG("%s", metastr.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dumpBlock(root, 0);
|
||||
}
|
||||
|
||||
void Program::FetchComputeProperties(DXBC::Reflection *reflection)
|
||||
{
|
||||
RDCERR("Unimplemented DXIL::Program::FetchComputeProperties()");
|
||||
reflection->DispatchThreadsDimension[0] = 1;
|
||||
reflection->DispatchThreadsDimension[1] = 1;
|
||||
reflection->DispatchThreadsDimension[2] = 1;
|
||||
}
|
||||
|
||||
DXBC::Reflection *Program::GetReflection()
|
||||
{
|
||||
RDCERR("Unimplemented DXIL::Program::GetReflection()");
|
||||
return new DXBC::Reflection;
|
||||
}
|
||||
|
||||
D3D_PRIMITIVE_TOPOLOGY Program::GetOutputTopology()
|
||||
{
|
||||
RDCERR("Unimplemented DXIL::Program::GetOutputTopology()");
|
||||
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
}
|
||||
|
||||
void Program::MakeDisassemblyString()
|
||||
{
|
||||
RDCERR("Unimplemented DXIL::Program::MakeDisassemblyString()");
|
||||
|
||||
const char *shaderName[] = {
|
||||
"Pixel", "Vertex", "Geometry", "Hull", "Domain",
|
||||
"Compute", "Library", "RayGeneration", "Intersection", "AnyHit",
|
||||
"ClosestHit", "Miss", "Callable", "Mesh", "Amplification",
|
||||
};
|
||||
|
||||
m_Disassembly = StringFormat::Fmt("; %s Shader, compiled under SM%u.%u\n",
|
||||
shaderName[int(m_Type)], m_Major, m_Minor);
|
||||
m_Disassembly += StringFormat::Fmt("target triple = \"%s\"\n", m_Triple.c_str());
|
||||
m_Disassembly += StringFormat::Fmt("target datalayout = \"%s\"\n", m_Datalayout.c_str());
|
||||
|
||||
m_Disassembly += "; No disassembly implemented";
|
||||
}
|
||||
};
|
||||
@@ -26,6 +26,39 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "driver/dx/official/d3dcommon.h"
|
||||
#include "driver/shaders/dxbc/dxbc_common.h"
|
||||
|
||||
namespace DXIL
|
||||
{
|
||||
class Program
|
||||
{
|
||||
public:
|
||||
Program(const byte *bytes, size_t length);
|
||||
|
||||
void FetchComputeProperties(DXBC::Reflection *reflection);
|
||||
DXBC::Reflection *GetReflection();
|
||||
|
||||
DXBC::ShaderType GetShaderType() { return m_Type; }
|
||||
uint32_t GetMajorVersion() { return m_Major; }
|
||||
uint32_t GetMinorVersion() { return m_Minor; }
|
||||
D3D_PRIMITIVE_TOPOLOGY GetOutputTopology();
|
||||
const std::string &GetDisassembly()
|
||||
{
|
||||
if(m_Disassembly.empty())
|
||||
MakeDisassemblyString();
|
||||
return m_Disassembly;
|
||||
}
|
||||
|
||||
private:
|
||||
void MakeDisassemblyString();
|
||||
|
||||
DXBC::ShaderType m_Type;
|
||||
uint32_t m_Major, m_Minor;
|
||||
|
||||
rdcstr m_Triple, m_Datalayout;
|
||||
|
||||
std::string m_Disassembly;
|
||||
};
|
||||
|
||||
}; // namespace DXIL
|
||||
|
||||
@@ -317,7 +317,7 @@ private:
|
||||
byte data = *m_Bits & mask;
|
||||
|
||||
// check if we overlap into the next destination byte
|
||||
if(dstoffs + bitsToRead < 8)
|
||||
if(dstoffs + bitsToRead <= 8)
|
||||
{
|
||||
*dst |= data << dstoffs;
|
||||
}
|
||||
|
||||
@@ -303,18 +303,21 @@ size_t BitcodeReader::abbrevSize() const
|
||||
|
||||
const AbbrevDesc &BitcodeReader::getAbbrev(uint32_t blockId, uint32_t abbrevID)
|
||||
{
|
||||
const BlockInfo &info = *blockInfo[blockId];
|
||||
const BlockInfo *info = blockInfo[blockId];
|
||||
|
||||
// IDs start at the first application specified ID. Rebase to that to get 0-base indices
|
||||
RDCASSERT(abbrevID >= APPLICATION_ABBREV);
|
||||
abbrevID -= APPLICATION_ABBREV;
|
||||
|
||||
// IDs are first assigned to those permanently from BLOCKINFO
|
||||
if(abbrevID < info.abbrevs.size())
|
||||
return info.abbrevs[abbrevID];
|
||||
if(info)
|
||||
{
|
||||
// IDs are first assigned to those permanently from BLOCKINFO
|
||||
if(abbrevID < info->abbrevs.size())
|
||||
return info->abbrevs[abbrevID];
|
||||
|
||||
// block-local IDs start after the BLOCKINFO ones
|
||||
abbrevID -= (uint32_t)info.abbrevs.size();
|
||||
// block-local IDs start after the BLOCKINFO ones
|
||||
abbrevID -= (uint32_t)info->abbrevs.size();
|
||||
}
|
||||
|
||||
RDCASSERT(!blockStack.empty());
|
||||
RDCASSERT(abbrevID < blockStack.back()->abbrevs.size());
|
||||
|
||||
Reference in New Issue
Block a user