mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-28 12:51:03 +00:00
Create DXBC reflection data for shaders in pipelines
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user