Create DXBC reflection data for shaders in pipelines

This commit is contained in:
baldurk
2016-09-20 17:28:18 +02:00
parent 8b1a26287d
commit dbb0e4702e
7 changed files with 255 additions and 8 deletions
+27 -7
View File
@@ -287,13 +287,6 @@ void Serialiser::Serialise(const char *name, D3D12_SHADER_BYTECODE &el)
SerialiseBuffer("pShaderBytecode", (byte *&)el.pShaderBytecode, sz);
}
template <>
void Serialiser::Deserialise(const D3D12_SHADER_BYTECODE *const el) const
{
if(m_Mode == READING)
delete[](byte *)(el->pShaderBytecode);
}
template <>
void Serialiser::Serialise(const char *name, D3D12_SO_DECLARATION_ENTRY &el)
{
@@ -569,6 +562,19 @@ void Serialiser::Serialise(const char *name, D3D12_GRAPHICS_PIPELINE_STATE_DESC
}
}
template <>
void Serialiser::Deserialise(const D3D12_GRAPHICS_PIPELINE_STATE_DESC *const el) const
{
if(m_Mode == READING)
{
delete[](byte *)(el->VS.pShaderBytecode);
delete[](byte *)(el->PS.pShaderBytecode);
delete[](byte *)(el->DS.pShaderBytecode);
delete[](byte *)(el->HS.pShaderBytecode);
delete[](byte *)(el->GS.pShaderBytecode);
}
}
template <>
void Serialiser::Serialise(const char *name, D3D12_COMPUTE_PIPELINE_STATE_DESC &el)
{
@@ -586,6 +592,13 @@ void Serialiser::Serialise(const char *name, D3D12_COMPUTE_PIPELINE_STATE_DESC &
}
}
template <>
void Serialiser::Deserialise(const D3D12_COMPUTE_PIPELINE_STATE_DESC *const el) const
{
if(m_Mode == READING)
delete[](byte *)(el->CS.pShaderBytecode);
}
template <>
void Serialiser::Serialise(const char *name, D3D12_VERTEX_BUFFER_VIEW &el)
{
@@ -1032,6 +1045,13 @@ void Serialiser::Serialise(const char *name, D3D12_DISCARD_REGION &el)
SerialiseComplexArray("pRects", (D3D12_RECT *&)el.pRects, el.NumRects);
}
template <>
void Serialiser::Deserialise(const D3D12_DISCARD_REGION *const el) const
{
if(m_Mode == READING)
delete[] el->pRects;
}
template <>
void Serialiser::Serialise(const char *name, D3D12_SAMPLER_DESC &el)
{
+8
View File
@@ -33,6 +33,8 @@
#include "driver/shaders/dxbc/dxbc_compile.h"
#include "serialise/serialiser.h"
ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc);
// similar to RDCUNIMPLEMENTED but for things that are hit often so we don't want to fire the
// debugbreak.
#define D3D12NOTIMP(...) \
@@ -167,8 +169,12 @@ void Serialiser::Serialise(const char *name, D3D12_SHADER_BYTECODE &el);
template <>
void Serialiser::Serialise(const char *name, D3D12_GRAPHICS_PIPELINE_STATE_DESC &el);
template <>
void Serialiser::Deserialise(const D3D12_GRAPHICS_PIPELINE_STATE_DESC *const el) const;
template <>
void Serialiser::Serialise(const char *name, D3D12_COMPUTE_PIPELINE_STATE_DESC &el);
template <>
void Serialiser::Deserialise(const D3D12_COMPUTE_PIPELINE_STATE_DESC *const el) const;
template <>
void Serialiser::Serialise(const char *name, D3D12_INDEX_BUFFER_VIEW &el);
template <>
void Serialiser::Serialise(const char *name, D3D12_VERTEX_BUFFER_VIEW &el);
@@ -206,6 +212,8 @@ template <>
void Serialiser::Serialise(const char *name, D3D12_TEXTURE_COPY_LOCATION &el);
template <>
void Serialiser::Serialise(const char *name, D3D12_DISCARD_REGION &el);
template <>
void Serialiser::Deserialise(const D3D12_DISCARD_REGION *const el) const;
struct D3D12Descriptor;
template <>
@@ -278,6 +278,36 @@ bool WrappedID3D12Device::Serialise_CreateGraphicsPipelineState(
{
ret = new WrappedID3D12PipelineState(ret, this);
WrappedID3D12PipelineState *wrapped = (WrappedID3D12PipelineState *)ret;
wrapped->graphics = new D3D12_GRAPHICS_PIPELINE_STATE_DESC(Descriptor);
D3D12_SHADER_BYTECODE *shaders[] = {
&wrapped->graphics->VS, &wrapped->graphics->HS, &wrapped->graphics->DS,
&wrapped->graphics->GS, &wrapped->graphics->PS,
};
for(size_t i = 0; i < ARRAY_COUNT(shaders); i++)
{
if(shaders[i]->BytecodeLength == 0)
{
shaders[i]->pShaderBytecode = NULL;
}
else
{
WrappedID3D12PipelineState::DXBCKey *key =
new WrappedID3D12PipelineState::DXBCKey(*shaders[i]);
if(WrappedID3D12PipelineState::m_Shaders[*key] == NULL)
WrappedID3D12PipelineState::m_Shaders[*key] =
new WrappedID3D12PipelineState::ShaderEntry(*shaders[i]);
else
WrappedID3D12PipelineState::m_Shaders[*key]->AddRef();
shaders[i]->pShaderBytecode = key;
}
}
GetResourceManager()->AddLiveResource(Pipe, ret);
}
}
@@ -352,6 +382,21 @@ bool WrappedID3D12Device::Serialise_CreateComputePipelineState(
{
ret = new WrappedID3D12PipelineState(ret, this);
WrappedID3D12PipelineState *wrapped = (WrappedID3D12PipelineState *)ret;
wrapped->compute = new D3D12_COMPUTE_PIPELINE_STATE_DESC(Descriptor);
WrappedID3D12PipelineState::DXBCKey *key =
new WrappedID3D12PipelineState::DXBCKey(wrapped->compute->CS);
if(WrappedID3D12PipelineState::m_Shaders[*key] == NULL)
WrappedID3D12PipelineState::m_Shaders[*key] =
new WrappedID3D12PipelineState::ShaderEntry(wrapped->compute->CS);
else
WrappedID3D12PipelineState::m_Shaders[*key]->AddRef();
wrapped->compute->CS.pShaderBytecode = key;
GetResourceManager()->AddLiveResource(Pipe, ret);
}
}
@@ -28,6 +28,8 @@
std::vector<WrappedID3D12Resource::AddressRange> WrappedID3D12Resource::m_Addresses;
std::map<ResourceId, WrappedID3D12Resource *> WrappedID3D12Resource::m_List;
std::map<WrappedID3D12PipelineState::DXBCKey, WrappedID3D12PipelineState::ShaderEntry *>
WrappedID3D12PipelineState::m_Shaders;
#undef D3D12_TYPE_MACRO
#define D3D12_TYPE_MACRO(iface) WRAPPED_POOL_INST(CONCAT(Wrapped, iface));
+158 -1
View File
@@ -416,6 +416,114 @@ class WrappedID3D12PipelineState : public WrappedDeviceChild12<ID3D12PipelineSta
public:
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12PipelineState);
D3D12_GRAPHICS_PIPELINE_STATE_DESC *graphics;
D3D12_COMPUTE_PIPELINE_STATE_DESC *compute;
struct DXBCKey
{
DXBCKey(const D3D12_SHADER_BYTECODE &byteCode)
{
byteLen = (uint32_t)byteCode.BytecodeLength;
DXBC::DXBCFile::GetHash(hash, byteCode.pShaderBytecode, byteCode.BytecodeLength);
}
// assume that byte length + hash is enough to uniquely identify a shader bytecode
uint32_t byteLen;
uint32_t hash[4];
bool operator<(const DXBCKey &o) const
{
if(byteLen != o.byteLen)
return byteLen < o.byteLen;
for(size_t i = 0; i < 4; i++)
if(hash[i] != o.hash[i])
return hash[i] < o.hash[i];
return false;
}
bool operator==(const DXBCKey &o) const
{
return byteLen == o.byteLen && hash[0] == o.hash[0] && hash[1] == o.hash[1] &&
hash[2] == o.hash[2] && hash[3] == o.hash[3];
}
};
class ShaderEntry
{
public:
ShaderEntry() : m_DebugInfoSearchPaths(NULL), m_DXBCFile(NULL), m_Details(NULL) {}
ShaderEntry(const D3D12_SHADER_BYTECODE &byteCode)
{
const byte *code = (const byte *)byteCode.pShaderBytecode;
m_Bytecode.assign(code, code + byteCode.BytecodeLength);
m_DebugInfoSearchPaths = NULL;
m_DXBCFile = NULL;
m_Details = NULL;
m_RefCount = 1;
}
~ShaderEntry()
{
m_Bytecode.clear();
SAFE_DELETE(m_DXBCFile);
SAFE_DELETE(m_Details);
}
void AddRef() { m_RefCount++; }
bool Release()
{
m_RefCount--;
if(m_RefCount <= 0)
{
delete this;
return true;
}
return false;
}
void SetDebugInfoPath(vector<std::string> *searchPaths, const std::string &path)
{
m_DebugInfoSearchPaths = searchPaths;
m_DebugInfoPath = path;
}
DXBC::DXBCFile *GetDXBC()
{
if(m_DXBCFile == NULL && !m_Bytecode.empty())
{
TryReplaceOriginalByteCode();
m_DXBCFile = new DXBC::DXBCFile((const void *)&m_Bytecode[0], m_Bytecode.size());
}
return m_DXBCFile;
}
ShaderReflection *GetDetails()
{
if(m_Details == NULL && GetDXBC() != NULL)
m_Details = MakeShaderReflection(m_DXBCFile);
return m_Details;
}
private:
ShaderEntry(const ShaderEntry &e);
void TryReplaceOriginalByteCode();
ShaderEntry &operator=(const ShaderEntry &e);
int m_RefCount;
std::string m_DebugInfoPath;
vector<std::string> *m_DebugInfoSearchPaths;
vector<byte> m_Bytecode;
DXBC::DXBCFile *m_DXBCFile;
ShaderReflection *m_Details;
};
static map<DXBCKey, ShaderEntry *> m_Shaders;
enum
{
TypeEnum = Resource_PipelineState,
@@ -424,8 +532,57 @@ public:
WrappedID3D12PipelineState(ID3D12PipelineState *real, WrappedID3D12Device *device)
: WrappedDeviceChild12(real, device)
{
graphics = NULL;
}
virtual ~WrappedID3D12PipelineState() { Shutdown(); }
virtual ~WrappedID3D12PipelineState()
{
Shutdown();
if(graphics)
{
DXBCKey *vs = (DXBCKey *)graphics->VS.pShaderBytecode;
DXBCKey *hs = (DXBCKey *)graphics->HS.pShaderBytecode;
DXBCKey *ds = (DXBCKey *)graphics->DS.pShaderBytecode;
DXBCKey *gs = (DXBCKey *)graphics->GS.pShaderBytecode;
DXBCKey *ps = (DXBCKey *)graphics->PS.pShaderBytecode;
if(m_Shaders[*vs]->Release())
m_Shaders.erase(*vs);
if(m_Shaders[*hs]->Release())
m_Shaders.erase(*hs);
if(m_Shaders[*ds]->Release())
m_Shaders.erase(*ds);
if(m_Shaders[*gs]->Release())
m_Shaders.erase(*gs);
if(m_Shaders[*ps]->Release())
m_Shaders.erase(*ps);
SAFE_DELETE(vs);
SAFE_DELETE(hs);
SAFE_DELETE(ds);
SAFE_DELETE(gs);
SAFE_DELETE(ps);
SAFE_DELETE(graphics);
}
if(compute)
{
DXBCKey *cs = (DXBCKey *)compute->CS.pShaderBytecode;
if(m_Shaders[*cs]->Release())
m_Shaders.erase(*cs);
SAFE_DELETE(cs);
SAFE_DELETE(compute);
}
}
//////////////////////////////
// implement ID3D12PipelineState
@@ -448,6 +448,19 @@ CBufferVariableType DXBCFile::ParseRDEFType(RDEFHeader *h, char *chunkContents,
return ret;
}
void DXBCFile::GetHash(uint32_t hash[4], const void *ByteCode, size_t BytecodeLength)
{
if(BytecodeLength < sizeof(FileHeader))
{
memset(hash, 0, sizeof(uint32_t) * 4);
return;
}
FileHeader *header = (FileHeader *)ByteCode;
memcmp(hash, header->hashValue, sizeof(header->hashValue));
}
bool DXBCFile::CheckForDebugInfo(const void *ByteCode, size_t ByteCodeLength)
{
FileHeader *header = (FileHeader *)ByteCode;
@@ -370,6 +370,8 @@ public:
const ASMOperation &GetInstruction(size_t i) { return m_Instructions[i]; }
size_t NumOperands(OpcodeType op);
static void GetHash(uint32_t hash[4], const void *ByteCode, size_t BytecodeLength);
static bool CheckForDebugInfo(const void *ByteCode, size_t ByteCodeLength);
static string GetDebugBinaryPath(const void *ByteCode, size_t ByteCodeLength);