Add DXBC container helpers for manipulating single-chunk containers

This commit is contained in:
baldurk
2024-08-30 13:28:40 +01:00
parent 632cf5af46
commit 2eb41f860d
2 changed files with 60 additions and 6 deletions
@@ -124,6 +124,12 @@ struct FileHeader
// uint32 chunkOffsets[numChunks]; follows
};
struct PartHeader
{
uint32_t fourcc;
uint32_t partLength;
};
struct ILDNHeader
{
uint16_t Flags;
@@ -820,38 +826,44 @@ void DXBCContainer::ReplaceChunk(bytebuf &ByteCode, uint32_t fourcc, const byte
HashContainer(ByteCode.data(), ByteCode.size());
}
const byte *DXBCContainer::FindChunk(const bytebuf &ByteCode, uint32_t fourcc, size_t &size)
const byte *DXBCContainer::FindChunk(const byte *ByteCode, size_t ByteCodeLength, uint32_t fourcc,
size_t &size)
{
const FileHeader *header = (const FileHeader *)ByteCode.data();
const FileHeader *header = (const FileHeader *)ByteCode;
size = 0;
if(header->fourcc != FOURCC_DXBC)
return NULL;
if(header->fileLength != (uint32_t)ByteCode.size())
if(header->fileLength != (uint32_t)ByteCodeLength)
return NULL;
const uint32_t *chunkOffsets =
(const uint32_t *)(ByteCode.data() + sizeof(FileHeader)); // right after the header
(const uint32_t *)(ByteCode + sizeof(FileHeader)); // right after the header
for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++)
{
uint32_t offs = chunkOffsets[chunkIdx];
const uint32_t *chunkFourcc = (uint32_t *)(ByteCode.data() + offs);
const uint32_t *chunkFourcc = (uint32_t *)(ByteCode + offs);
const uint32_t *chunkSize = (uint32_t *)(chunkFourcc + 1);
if(*chunkFourcc == fourcc)
{
size = *chunkSize;
return ByteCode.data() + offs + 8;
return ByteCode + offs + 8;
}
}
return NULL;
}
const byte *DXBCContainer::FindChunk(const bytebuf &ByteCode, uint32_t fourcc, size_t &size)
{
return FindChunk(ByteCode.data(), ByteCode.size(), fourcc, size);
}
void DXBCContainer::GetHash(uint32_t hash[4], const void *ByteCode, size_t BytecodeLength)
{
if(BytecodeLength < sizeof(FileHeader) || ByteCode == NULL)
@@ -892,6 +904,43 @@ void DXBCContainer::GetHash(uint32_t hash[4], const void *ByteCode, size_t Bytec
}
}
bytebuf DXBCContainer::MakeContainerForChunk(uint32_t fourcc, const byte *chunk, uint64_t chunkSize)
{
FileHeader dxbcHeader;
PartHeader partHeader;
dxbcHeader.fourcc = FOURCC_DXBC;
dxbcHeader.containerVersion = 1;
dxbcHeader.fileLength =
uint32_t(sizeof(FileHeader) + sizeof(uint32_t) + sizeof(PartHeader) + chunkSize);
dxbcHeader.numChunks = 1;
partHeader.fourcc = fourcc;
partHeader.partLength = (uint32_t)chunkSize;
uint32_t chunkOffset = sizeof(FileHeader) + sizeof(uint32_t);
bytebuf ret;
ret.resize(dxbcHeader.fileLength);
byte *write = ret.data();
memcpy(write, &dxbcHeader, sizeof(dxbcHeader));
write += sizeof(dxbcHeader);
memcpy(write, &chunkOffset, sizeof(chunkOffset));
write += sizeof(chunkOffset);
memcpy(write, &partHeader, sizeof(partHeader));
write += sizeof(partHeader);
memcpy(write, chunk, chunkSize);
HashContainer(ret.data(), ret.size());
return ret;
}
bool DXBCContainer::IsHashedContainer(const void *ByteCode, size_t BytecodeLength)
{
if(BytecodeLength < sizeof(FileHeader) || ByteCode == NULL)
@@ -221,6 +221,8 @@ public:
}
static const byte *FindChunk(const bytebuf &ByteCode, uint32_t fourcc, size_t &size);
static const byte *FindChunk(const byte *ByteCode, size_t ByteCodeLength, uint32_t fourcc,
size_t &size);
const DXBCBytecode::Program *GetDXBCByteCode() const { return m_DXBCByteCode; }
DXBCBytecode::Program *GetDXBCByteCode() { return m_DXBCByteCode; }
@@ -233,6 +235,9 @@ public:
return m_ShaderBlob.data() + m_NonDebugDXILByteCodeOffset;
}
size_t GetNonDebugDXILByteCodeSize() const { return m_NonDebugDXILByteCodeSize; }
static bytebuf MakeContainerForChunk(uint32_t fourcc, const byte *chunk, uint64_t chunkSize);
static bool IsHashedContainer(const void *ByteCode, size_t BytecodeLength);
static bool HashContainer(void *ByteCode, size_t BytecodeLength);