mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Implement unstripped SPIR-V shader blob loading from magic value tags
This commit is contained in:
@@ -370,6 +370,7 @@ void Processor::Parse(const rdcarray<uint32_t> &spirvWords)
|
||||
if(packedVersion > VersionPacked)
|
||||
{
|
||||
RDCERR("Unsupported SPIR-V version: %08x", packedVersion);
|
||||
m_SPIRV.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -521,7 +521,7 @@ public:
|
||||
const rdcarray<EntryPoint> &GetEntries() { return entries; }
|
||||
const rdcarray<Variable> &GetGlobals() { return globals; }
|
||||
Id GetIDType(Id id) { return idTypes[id]; }
|
||||
rdcarray<uint32_t> GetSPIRV() const { return m_SPIRV; }
|
||||
const rdcarray<uint32_t> &GetSPIRV() const { return m_SPIRV; }
|
||||
protected:
|
||||
virtual void Parse(const rdcarray<uint32_t> &spirvWords);
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "vk_info.h"
|
||||
#include "core/settings.h"
|
||||
#include "lz4/lz4.h"
|
||||
|
||||
// for compatibility we use the same DXBC name since it's now configured by the UI
|
||||
RDOC_EXTERN_CONFIG(rdcarray<rdcstr>, DXBC_Debug_SearchDirPaths);
|
||||
|
||||
VkDynamicState ConvertDynamicState(VulkanDynamicStateIndex idx)
|
||||
{
|
||||
@@ -1378,6 +1383,127 @@ void VulkanCreationInfo::ShaderModule::Init(VulkanResourceManager *resourceMan,
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanCreationInfo::ShaderModule::Reinit()
|
||||
{
|
||||
bool lz4 = false;
|
||||
|
||||
rdcstr originalPath = unstrippedPath;
|
||||
|
||||
if(!strncmp(originalPath.c_str(), "lz4#", 4))
|
||||
{
|
||||
originalPath = originalPath.substr(4);
|
||||
lz4 = true;
|
||||
}
|
||||
// could support more if we're willing to compile in the decompressor
|
||||
|
||||
FILE *originalShaderFile = NULL;
|
||||
|
||||
const rdcarray<rdcstr> &searchPaths = DXBC_Debug_SearchDirPaths();
|
||||
|
||||
size_t numSearchPaths = searchPaths.size();
|
||||
|
||||
rdcstr foundPath;
|
||||
|
||||
// keep searching until we've exhausted all possible path options, or we've found a file that
|
||||
// opens
|
||||
while(originalShaderFile == NULL && !originalPath.empty())
|
||||
{
|
||||
// while we haven't found a file, keep trying through the search paths. For i==0
|
||||
// check the path on its own, in case it's an absolute path.
|
||||
for(size_t i = 0; originalShaderFile == NULL && i <= numSearchPaths; i++)
|
||||
{
|
||||
if(i == 0)
|
||||
{
|
||||
originalShaderFile = FileIO::fopen(originalPath, FileIO::ReadBinary);
|
||||
foundPath = originalPath;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const rdcstr &searchPath = searchPaths[i - 1];
|
||||
foundPath = searchPath + "/" + originalPath;
|
||||
originalShaderFile = FileIO::fopen(foundPath, FileIO::ReadBinary);
|
||||
}
|
||||
}
|
||||
|
||||
if(originalShaderFile == NULL)
|
||||
{
|
||||
// follow D3D's search behaviour for consistency: when presented with a
|
||||
// relative path containing subfolders like foo/bar/blah.pdb then we should first try to
|
||||
// append it to all search paths as-is, then strip off the top-level subdirectory to get
|
||||
// bar/blah.pdb and try that in all search directories, and keep going. So if we got here
|
||||
// and didn't open a file, try to strip off the the top directory and continue.
|
||||
int32_t offs = originalPath.find_first_of("\\/");
|
||||
|
||||
// if we couldn't find a directory separator there's nothing to do, stop looking
|
||||
if(offs == -1)
|
||||
break;
|
||||
|
||||
// otherwise strip up to there and keep going
|
||||
originalPath.erase(0, offs + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(originalShaderFile == NULL)
|
||||
return;
|
||||
|
||||
FileIO::fseek64(originalShaderFile, 0L, SEEK_END);
|
||||
uint64_t originalShaderSize = FileIO::ftell64(originalShaderFile);
|
||||
FileIO::fseek64(originalShaderFile, 0, SEEK_SET);
|
||||
|
||||
{
|
||||
bytebuf debugBytecode;
|
||||
|
||||
debugBytecode.resize((size_t)originalShaderSize);
|
||||
FileIO::fread(&debugBytecode[0], sizeof(byte), (size_t)originalShaderSize, originalShaderFile);
|
||||
|
||||
if(lz4)
|
||||
{
|
||||
rdcarray<byte> decompressed;
|
||||
|
||||
// first try decompressing to 1MB flat
|
||||
decompressed.resize(100 * 1024);
|
||||
|
||||
int ret = LZ4_decompress_safe((const char *)&debugBytecode[0], (char *)&decompressed[0],
|
||||
(int)debugBytecode.size(), (int)decompressed.size());
|
||||
|
||||
if(ret < 0)
|
||||
{
|
||||
// if it failed, either source is corrupt or we didn't allocate enough space.
|
||||
// Just allocate 255x compressed size since it can't need any more than that.
|
||||
decompressed.resize(255 * debugBytecode.size());
|
||||
|
||||
ret = LZ4_decompress_safe((const char *)&debugBytecode[0], (char *)&decompressed[0],
|
||||
(int)debugBytecode.size(), (int)decompressed.size());
|
||||
|
||||
if(ret < 0)
|
||||
{
|
||||
RDCERR("Failed to decompress LZ4 data from %s", foundPath.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RDCASSERT(ret > 0, ret);
|
||||
|
||||
// we resize and memcpy instead of just doing .swap() because that would
|
||||
// transfer over the over-large pessimistic capacity needed for decompression
|
||||
debugBytecode.resize(ret);
|
||||
memcpy(&debugBytecode[0], &decompressed[0], debugBytecode.size());
|
||||
}
|
||||
|
||||
rdcspv::Reflector reflTest;
|
||||
reflTest.Parse(rdcarray<uint32_t>((uint32_t *)(debugBytecode.data()),
|
||||
debugBytecode.size() / sizeof(uint32_t)));
|
||||
|
||||
if(!reflTest.GetSPIRV().empty())
|
||||
{
|
||||
spirv = reflTest;
|
||||
}
|
||||
}
|
||||
|
||||
FileIO::fclose(originalShaderFile);
|
||||
}
|
||||
|
||||
void VulkanCreationInfo::ShaderModuleReflection::Init(VulkanResourceManager *resourceMan,
|
||||
ResourceId id, const rdcspv::Reflector &spv,
|
||||
const rdcstr &entry,
|
||||
|
||||
@@ -638,6 +638,8 @@ struct VulkanCreationInfo
|
||||
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
|
||||
const VkShaderModuleCreateInfo *pCreateInfo);
|
||||
|
||||
void Reinit();
|
||||
|
||||
ShaderModuleReflection &GetReflection(ShaderStage stage, const rdcstr &entry, ResourceId pipe)
|
||||
{
|
||||
// look for one from this pipeline specifically, if it was specialised
|
||||
|
||||
@@ -2092,6 +2092,7 @@ bool WrappedVulkan::Serialise_SetShaderDebugPath(SerialiserType &ser, VkShaderMo
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
m_CreationInfo.m_ShaderModule[GetResID(ShaderObject)].unstrippedPath = DebugPath;
|
||||
m_CreationInfo.m_ShaderModule[GetResID(ShaderObject)].Reinit();
|
||||
|
||||
AddResourceCurChunk(GetResourceManager()->GetOriginalID(GetResID(ShaderObject)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user