mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-13 19:17:12 +00:00
Serialise pipeline cache in vkshaders.cache
This commit is contained in:
@@ -170,8 +170,8 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, V
|
||||
0,
|
||||
};
|
||||
|
||||
VkResult vkr = driver->vkCreateComputePipelines(driver->GetDev(), VK_NULL_HANDLE, 1,
|
||||
&compPipeInfo, NULL, pipe);
|
||||
VkResult vkr = driver->vkCreateComputePipelines(
|
||||
driver->GetDev(), driver->GetShaderCache()->GetPipeCache(), 1, &compPipeInfo, NULL, pipe);
|
||||
if(vkr != VK_SUCCESS)
|
||||
RDCERR("Failed creating object %s at line %i, vkr was %s", objName, line, ToStr(vkr).c_str());
|
||||
}
|
||||
@@ -213,8 +213,8 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, V
|
||||
0,
|
||||
};
|
||||
|
||||
vkr = driver->vkCreateComputePipelines(driver->GetDev(), VK_NULL_HANDLE, 1, &compPipeInfo, NULL,
|
||||
pipe);
|
||||
vkr = driver->vkCreateComputePipelines(driver->GetDev(), driver->GetShaderCache()->GetPipeCache(),
|
||||
1, &compPipeInfo, NULL, pipe);
|
||||
if(vkr != VK_SUCCESS)
|
||||
RDCERR("Failed creating object %s at line %i, vkr was %s", objName, line, ToStr(vkr).c_str());
|
||||
|
||||
@@ -389,8 +389,8 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, V
|
||||
-1, // base pipeline index
|
||||
};
|
||||
|
||||
VkResult vkr = driver->vkCreateGraphicsPipelines(driver->GetDev(), VK_NULL_HANDLE, 1,
|
||||
&graphicsPipeInfo, NULL, pipe);
|
||||
VkResult vkr = driver->vkCreateGraphicsPipelines(
|
||||
driver->GetDev(), driver->GetShaderCache()->GetPipeCache(), 1, &graphicsPipeInfo, NULL, pipe);
|
||||
if(vkr != VK_SUCCESS)
|
||||
RDCERR("Failed creating object %s at line %i, vkr was %s", objName, line, ToStr(vkr).c_str());
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
void CopyArrayToTex2DMS(VkImage destMS, VkImage srcArray, VkExtent3D extent, uint32_t layers,
|
||||
uint32_t samples, VkFormat fmt);
|
||||
|
||||
VkPipelineCache GetPipelineCache() { return m_PipelineCache; }
|
||||
VkPipeline GetCustomPipeline() { return m_Custom.TexPipeline; }
|
||||
VkImage GetCustomTexture() { return m_Custom.TexImg; }
|
||||
VkFramebuffer GetCustomFramebuffer() { return m_Custom.TexFB; }
|
||||
@@ -132,6 +133,8 @@ private:
|
||||
// one per depth/stencil output format, per sample count
|
||||
VkPipeline m_DepthArray2MSPipe[6][4] = {{VK_NULL_HANDLE}};
|
||||
|
||||
VkPipelineCache m_PipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
struct CustomShaderRendering
|
||||
{
|
||||
void Destroy(WrappedVulkan *driver);
|
||||
|
||||
@@ -120,6 +120,15 @@ struct VulkanBlobShaderCallbacks
|
||||
const byte *GetData(SPIRVBlob blob) const { return (const byte *)blob->data(); }
|
||||
} VulkanShaderCacheCallbacks;
|
||||
|
||||
struct VkPipeCacheHeader
|
||||
{
|
||||
uint32_t length;
|
||||
VkPipelineCacheHeaderVersion version;
|
||||
uint32_t vendorID;
|
||||
uint32_t deviceID;
|
||||
byte uuid[VK_UUID_SIZE];
|
||||
};
|
||||
|
||||
VulkanShaderCache::VulkanShaderCache(WrappedVulkan *driver)
|
||||
{
|
||||
// Load shader cache, if present
|
||||
@@ -224,11 +233,79 @@ VulkanShaderCache::VulkanShaderCache(WrappedVulkan *driver)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
VkPipelineCacheCreateInfo createInfo = {VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO};
|
||||
|
||||
GetPipeCacheBlob();
|
||||
|
||||
if(!m_PipeCacheBlob.empty())
|
||||
{
|
||||
if(m_PipeCacheBlob.size() < sizeof(VkPipeCacheHeader))
|
||||
{
|
||||
m_PipeCacheBlob.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
VkPipeCacheHeader *header = (VkPipeCacheHeader *)m_PipeCacheBlob.data();
|
||||
|
||||
// check explicitly for incompatibility
|
||||
if(header->length != sizeof(VkPipeCacheHeader))
|
||||
{
|
||||
m_PipeCacheBlob.clear();
|
||||
RDCLOG("Pipeline cache header length %u is unexpected, not using cache", header->length);
|
||||
}
|
||||
else if(header->version != VK_PIPELINE_CACHE_HEADER_VERSION_ONE)
|
||||
{
|
||||
m_PipeCacheBlob.clear();
|
||||
RDCLOG("Pipeline cache header version %u is unexpected, not using cache", header->version);
|
||||
}
|
||||
else if(header->vendorID != m_pDriver->GetDeviceProps().vendorID)
|
||||
{
|
||||
m_PipeCacheBlob.clear();
|
||||
RDCLOG("Pipeline cache header vendorID %u doesn't match %u", header->vendorID,
|
||||
m_pDriver->GetDeviceProps().vendorID);
|
||||
}
|
||||
else if(header->deviceID != m_pDriver->GetDeviceProps().deviceID)
|
||||
{
|
||||
m_PipeCacheBlob.clear();
|
||||
RDCLOG("Pipeline cache header deviceID %u doesn't match %u", header->deviceID,
|
||||
m_pDriver->GetDeviceProps().deviceID);
|
||||
}
|
||||
else if(memcmp(header->uuid, m_pDriver->GetDeviceProps().pipelineCacheUUID, VK_UUID_SIZE) != 0)
|
||||
{
|
||||
m_PipeCacheBlob.clear();
|
||||
RDCLOG("Pipeline cache UUID doesn't match");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_PipeCacheBlob.empty())
|
||||
{
|
||||
createInfo.initialDataSize = m_PipeCacheBlob.size();
|
||||
createInfo.pInitialData = m_PipeCacheBlob.data();
|
||||
}
|
||||
|
||||
VkResult vkr = driver->vkCreatePipelineCache(m_Device, &createInfo, NULL, &m_PipelineCache);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
SetCaching(false);
|
||||
}
|
||||
|
||||
VulkanShaderCache::~VulkanShaderCache()
|
||||
{
|
||||
if(m_PipelineCache != VK_NULL_HANDLE)
|
||||
{
|
||||
bytebuf blob;
|
||||
size_t size = 0;
|
||||
ObjDisp(m_Device)->GetPipelineCacheData(Unwrap(m_Device), Unwrap(m_PipelineCache), &size, NULL);
|
||||
blob.resize(size);
|
||||
ObjDisp(m_Device)->GetPipelineCacheData(Unwrap(m_Device), Unwrap(m_PipelineCache), &size,
|
||||
blob.data());
|
||||
SetPipeCacheBlob(blob);
|
||||
m_pDriver->vkDestroyPipelineCache(m_Device, m_PipelineCache, NULL);
|
||||
}
|
||||
|
||||
if(m_ShaderCacheDirty)
|
||||
{
|
||||
SaveShaderCache("vkshaders.cache", m_ShaderCacheMagic, m_ShaderCacheVersion, m_ShaderCache,
|
||||
@@ -289,6 +366,56 @@ rdcstr VulkanShaderCache::GetSPIRVBlob(const rdcspv::CompilationSettings &settin
|
||||
return errors;
|
||||
}
|
||||
|
||||
void VulkanShaderCache::GetPipeCacheBlob()
|
||||
{
|
||||
m_PipeCacheBlob.clear();
|
||||
|
||||
uint32_t hash = strhash(StringFormat::Fmt("PipelineCache%x%x", m_pDriver->GetDeviceProps().vendorID,
|
||||
m_pDriver->GetDeviceProps().deviceID)
|
||||
.c_str());
|
||||
|
||||
auto it = m_ShaderCache.find(hash);
|
||||
|
||||
if(it != m_ShaderCache.end())
|
||||
{
|
||||
SPIRVBlob blob = it->second;
|
||||
|
||||
// first uint32_t is the real byte size, since we rounded up to the nearest uint32 to store in a
|
||||
// SPIRVBlob
|
||||
uint32_t size = blob->at(0);
|
||||
if(size == rdcspv::MagicNumber)
|
||||
{
|
||||
RDCLOG("Hash collision - pipeline cache trampled");
|
||||
return;
|
||||
}
|
||||
m_PipeCacheBlob.resize(size);
|
||||
memcpy(m_PipeCacheBlob.data(), blob->data() + 1, m_PipeCacheBlob.size());
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanShaderCache::SetPipeCacheBlob(bytebuf &blob)
|
||||
{
|
||||
if(m_PipeCacheBlob == blob)
|
||||
return;
|
||||
|
||||
VkPipeCacheHeader *header = (VkPipeCacheHeader *)blob.data();
|
||||
|
||||
uint32_t hash =
|
||||
strhash(StringFormat::Fmt("PipelineCache%x%x", header->vendorID, header->deviceID).c_str());
|
||||
|
||||
rdcarray<uint32_t> *spirvBlob = new rdcarray<uint32_t>();
|
||||
|
||||
// align the size up to the nearest 4, and add one extra for us to store the real byte size
|
||||
spirvBlob->resize(AlignUp4(blob.size()) / 4 + 1);
|
||||
|
||||
// store the size, then the real data after that
|
||||
(*spirvBlob)[0] = (uint32_t)blob.size();
|
||||
memcpy(spirvBlob->data() + 1, blob.data(), blob.size());
|
||||
|
||||
m_ShaderCache[hash] = spirvBlob;
|
||||
m_ShaderCacheDirty = true;
|
||||
}
|
||||
|
||||
void VulkanShaderCache::MakeGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo &pipeCreateInfo,
|
||||
ResourceId pipeline)
|
||||
{
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
{
|
||||
return m_BuiltinShaderModules[(size_t)builtin];
|
||||
}
|
||||
|
||||
VkPipelineCache GetPipeCache() { return m_PipelineCache; }
|
||||
void MakeGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo &pipeCreateInfo, ResourceId pipeline);
|
||||
void MakeComputePipelineInfo(VkComputePipelineCreateInfo &pipeCreateInfo, ResourceId pipeline);
|
||||
|
||||
@@ -84,9 +84,15 @@ private:
|
||||
static const uint32_t m_ShaderCacheMagic = 0xf00d00d5;
|
||||
static const uint32_t m_ShaderCacheVersion = 1;
|
||||
|
||||
void GetPipeCacheBlob();
|
||||
void SetPipeCacheBlob(bytebuf &blob);
|
||||
|
||||
WrappedVulkan *m_pDriver = NULL;
|
||||
VkDevice m_Device = VK_NULL_HANDLE;
|
||||
|
||||
bytebuf m_PipeCacheBlob;
|
||||
VkPipelineCache m_PipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
rdcstr m_GlobalDefines;
|
||||
|
||||
bool m_ShaderCacheDirty = false, m_CacheShaders = false;
|
||||
|
||||
@@ -1170,8 +1170,9 @@ private:
|
||||
};
|
||||
|
||||
VkPipeline pipe = VK_NULL_HANDLE;
|
||||
VkResult vkr = m_pDriver->vkCreateGraphicsPipelines(m_pDriver->GetDev(), VK_NULL_HANDLE, 1,
|
||||
&graphicsPipeInfo, NULL, &pipe);
|
||||
VkResult vkr = m_pDriver->vkCreateGraphicsPipelines(m_pDriver->GetDev(),
|
||||
m_pDriver->GetShaderCache()->GetPipeCache(),
|
||||
1, &graphicsPipeInfo, NULL, &pipe);
|
||||
if(vkr != VK_SUCCESS)
|
||||
{
|
||||
RDCERR("Failed creating debug pipeline");
|
||||
@@ -3121,8 +3122,8 @@ ShaderDebugTrace *VulkanReplay::DebugPixel(uint32_t eventId, uint32_t x, uint32_
|
||||
}
|
||||
|
||||
VkPipeline inputsPipe;
|
||||
vkr =
|
||||
m_pDriver->vkCreateGraphicsPipelines(dev, VK_NULL_HANDLE, 1, &graphicsInfo, NULL, &inputsPipe);
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(dev, m_pDriver->GetShaderCache()->GetPipeCache(), 1,
|
||||
&graphicsInfo, NULL, &inputsPipe);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
// make copy of state to draw from
|
||||
|
||||
@@ -394,7 +394,7 @@ VkResult WrappedVulkan::vkGetPipelineCacheData(VkDevice device, VkPipelineCache
|
||||
|
||||
uint32_t *ptr = (uint32_t *)pData;
|
||||
|
||||
ptr[0] = (uint32_t)totalSize;
|
||||
ptr[0] = 16 + VK_UUID_SIZE;
|
||||
ptr[1] = VK_PIPELINE_CACHE_HEADER_VERSION_ONE;
|
||||
// just in case the user expects a valid vendorID/deviceID, write the real one
|
||||
// MULTIDEVICE need to get the right physical device for this device
|
||||
|
||||
Reference in New Issue
Block a user