Handle (but skip) STAT DXIL chunk

This commit is contained in:
baldurk
2020-06-03 13:05:03 +01:00
parent 8727b2aa88
commit d28bab8c79
6 changed files with 75 additions and 20 deletions
@@ -382,13 +382,13 @@ rdcstr TypeName(CBufferVariableType::Descriptor desc)
return ret;
}
CBufferVariableType DXBCContainer::ParseRDEFType(RDEFHeader *h, char *chunkContents,
CBufferVariableType DXBCContainer::ParseRDEFType(const RDEFHeader *h, const byte *chunkContents,
uint32_t typeOffset)
{
if(m_Variables.find(typeOffset) != m_Variables.end())
return m_Variables[typeOffset];
RDEFCBufferType *type = (RDEFCBufferType *)(chunkContents + typeOffset);
const RDEFCBufferType *type = (const RDEFCBufferType *)(chunkContents + typeOffset);
CBufferVariableType ret;
@@ -405,7 +405,7 @@ CBufferVariableType DXBCContainer::ParseRDEFType(RDEFHeader *h, char *chunkConte
{
if(h->targetVersion >= 0x500 && type->nameOffset > 0)
{
ret.descriptor.name += " " + rdcstr(chunkContents + type->nameOffset);
ret.descriptor.name += " " + rdcstr((const char *)chunkContents + type->nameOffset);
}
else
{
@@ -418,7 +418,7 @@ CBufferVariableType DXBCContainer::ParseRDEFType(RDEFHeader *h, char *chunkConte
{
if(h->targetVersion >= 0x500 && type->nameOffset > 0)
{
ret.descriptor.name = chunkContents + type->nameOffset;
ret.descriptor.name = (const char *)chunkContents + type->nameOffset;
}
else
{
@@ -428,7 +428,8 @@ CBufferVariableType DXBCContainer::ParseRDEFType(RDEFHeader *h, char *chunkConte
if(type->memberOffset)
{
RDEFCBufferChildType *members = (RDEFCBufferChildType *)(chunkContents + type->memberOffset);
const RDEFCBufferChildType *members =
(const RDEFCBufferChildType *)(chunkContents + type->memberOffset);
ret.members.reserve(type->numMembers);
@@ -438,7 +439,7 @@ CBufferVariableType DXBCContainer::ParseRDEFType(RDEFHeader *h, char *chunkConte
{
CBufferVariable v;
v.name = chunkContents + members[j].nameOffset;
v.name = (const char *)(chunkContents + members[j].nameOffset);
v.type = ParseRDEFType(h, chunkContents, members[j].typeOffset);
v.descriptor.offset = members[j].memberOffset;
@@ -738,14 +739,14 @@ 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 *)(fourcc + 1);
const uint32_t *fourcc = (const uint32_t *)(data + chunkOffsets[chunkIdx]);
const uint32_t *chunkSize = (const uint32_t *)(fourcc + 1);
char *chunkContents = (char *)(chunkSize + 1);
const byte *chunkContents = (const byte *)(chunkSize + 1);
if(*fourcc == FOURCC_RDEF)
{
RDEFHeader *h = (RDEFHeader *)chunkContents;
const RDEFHeader *h = (const RDEFHeader *)chunkContents;
// for target version 0x500, unknown[0] is FOURCC_RD11.
// for 0x501 it's "\x13\x13\D%"
@@ -793,7 +794,7 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
ShaderInputBind desc;
desc.name = chunkContents + res->nameOffset;
desc.name = (const char *)(chunkContents + res->nameOffset);
desc.type = (ShaderInputBind::InputType)res->type;
desc.space = h->targetVersion >= 0x501 ? res->space : 0;
desc.reg = res->bindPoint;
@@ -907,9 +908,9 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
if(cbuf->nameOffset == 0)
continue;
cb.name = chunkContents + cbuf->nameOffset;
cb.name = (const char *)(chunkContents + cbuf->nameOffset);
cb.descriptor.name = chunkContents + cbuf->nameOffset;
cb.descriptor.name = (const char *)(chunkContents + cbuf->nameOffset);
cb.descriptor.byteSize = cbuf->size;
cb.descriptor.type = (CBuffer::Descriptor::Type)cbuf->type;
cb.descriptor.flags = cbuf->flags;
@@ -949,7 +950,7 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
CBufferVariable v;
v.name = chunkContents + var->nameOffset;
v.name = (const char *)(chunkContents + var->nameOffset);
v.descriptor.defaultValue.resize(var->size);
@@ -1007,7 +1008,15 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
}
else if(*fourcc == FOURCC_STAT)
{
if(*chunkSize == STATSizeDX10)
if(DXIL::Program::Valid(chunkContents, *chunkSize))
{
RDCEraseEl(m_ShaderStats);
m_ShaderStats.version = ShaderStatistics::STATS_DX12;
/*
DXIL::Program prog(chunkContents, *chunkSize);
*/
}
else if(*chunkSize == STATSizeDX10)
{
memcpy(&m_ShaderStats, chunkContents, STATSizeDX10);
m_ShaderStats.version = ShaderStatistics::STATS_DX10;
@@ -1024,20 +1033,35 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength)
}
else if(*fourcc == FOURCC_SHEX || *fourcc == FOURCC_SHDR)
{
m_DXBCByteCode = new DXBCBytecode::Program((const byte *)chunkContents, *chunkSize);
m_DXBCByteCode = new DXBCBytecode::Program(chunkContents, *chunkSize);
}
else if(*fourcc == FOURCC_ILDB || *fourcc == FOURCC_DXIL)
{
// we avoiding parsing these immediately because you can get both in a dxbc, so we prefer the
// debug version.
}
else if(*fourcc == FOURCC_ILDN)
{
ILDNHeader *h = (ILDNHeader *)chunkContents;
const ILDNHeader *h = (const ILDNHeader *)chunkContents;
m_DebugFileName = rdcstr(h->Name, h->NameLength);
}
else if(*fourcc == FOURCC_HASH)
{
HASHHeader *h = (HASHHeader *)chunkContents;
const HASHHeader *h = (const HASHHeader *)chunkContents;
memcpy(m_Hash, h->hashValue, sizeof(h->hashValue));
}
else if(*fourcc == FOURCC_ISGN || *fourcc == FOURCC_OSGN || *fourcc == FOURCC_ISG1 ||
*fourcc == FOURCC_OSG1 || *fourcc == FOURCC_OSG5 || *fourcc == FOURCC_PCSG)
{
// processed later
}
else
{
RDCWARN("Unknown chunk %c%c%c%c", ((const char *)fourcc)[0], ((const char *)fourcc)[1],
((const char *)fourcc)[2], ((const char *)fourcc)[3]);
}
}
if(m_DXBCByteCode == NULL)
@@ -104,6 +104,7 @@ struct ShaderStatistics
STATS_UNKNOWN = 0,
STATS_DX10,
STATS_DX11,
STATS_DX12,
} version;
};
@@ -176,7 +177,7 @@ private:
D3D_PRIMITIVE_TOPOLOGY m_OutputTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
CBufferVariableType ParseRDEFType(RDEFHeader *h, char *chunk, uint32_t offset);
CBufferVariableType ParseRDEFType(const RDEFHeader *h, const byte *chunk, uint32_t offset);
std::map<uint32_t, CBufferVariableType> m_Variables;
uint32_t m_Hash[4];
@@ -569,6 +569,25 @@ static void dumpBlock(const LLVMBC::BlockOrRecord &block, int indent)
RDCLOG("%s", line.c_str());
}
bool Program::Valid(const byte *bytes, size_t length)
{
if(length < sizeof(ProgramHeader))
return false;
const byte *ptr = bytes;
const ProgramHeader *header = (const ProgramHeader *)ptr;
if(header->DxilMagic != MAKE_FOURCC('D', 'X', 'I', 'L'))
return false;
size_t expected = offsetof(ProgramHeader, DxilMagic) + header->BitcodeOffset + header->BitcodeSize;
if(expected != length)
return false;
return LLVMBC::BitcodeReader::Valid(
ptr + offsetof(ProgramHeader, DxilMagic) + header->BitcodeOffset, header->BitcodeSize);
}
Program::Program(const byte *bytes, size_t length)
{
const byte *ptr = bytes;
@@ -183,6 +183,8 @@ public:
Program(const Program &o) = default;
Program &operator=(const Program &o) = default;
static bool Valid(const byte *bytes, size_t length);
void FetchComputeProperties(DXBC::Reflection *reflection);
DXBC::Reflection *GetReflection();
@@ -82,11 +82,18 @@ enum class BlockInfoRecord
SETRECORDNAME = 3,
};
static const uint32_t BitcodeMagic = MAKE_FOURCC('B', 'C', 0xC0, 0xDE);
bool BitcodeReader::Valid(const byte *bitcode, size_t length)
{
return length >= 4 && memcmp(bitcode, &BitcodeMagic, sizeof(uint32_t)) == 0;
}
BitcodeReader::BitcodeReader(const byte *bitcode, size_t length) : b(bitcode, length)
{
uint32_t magic = b.Read<uint32_t>();
RDCASSERT(magic == MAKE_FOURCC('B', 'C', 0xC0, 0xDE));
RDCASSERT(magic == BitcodeMagic);
}
BitcodeReader::~BitcodeReader()
@@ -64,6 +64,8 @@ public:
BlockOrRecord ReadToplevelBlock();
bool AtEndOfStream();
static bool Valid(const byte *bitcode, size_t length);
private:
BitReader b;