mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
keep driver's pipelineCacheUUID valid and use it for replay
This commit is contained in:
committed by
Baldur Karlsson
parent
b400d4bc52
commit
2b01465c79
@@ -234,10 +234,6 @@ void WrappedVulkan::vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevic
|
||||
{
|
||||
ObjDisp(physicalDevice)->GetPhysicalDeviceProperties(Unwrap(physicalDevice), pProperties);
|
||||
|
||||
MakeFakeUUID();
|
||||
|
||||
memcpy(pProperties->pipelineCacheUUID, fakeRenderDocUUID, VK_UUID_SIZE);
|
||||
|
||||
ClampPhysDevAPIVersion(pProperties, physicalDevice);
|
||||
}
|
||||
|
||||
@@ -639,49 +635,8 @@ void WrappedVulkan::vkGetRenderAreaGranularity(VkDevice device, VkRenderPass ren
|
||||
VkResult WrappedVulkan::vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache,
|
||||
size_t *pDataSize, void *pData)
|
||||
{
|
||||
// required header and 4 NULL bytes
|
||||
size_t totalSize = sizeof(VkPipelineCacheHeaderVersionOne) + 4;
|
||||
|
||||
if(pDataSize && !pData)
|
||||
*pDataSize = totalSize;
|
||||
|
||||
if(pDataSize && pData)
|
||||
{
|
||||
if(*pDataSize < totalSize)
|
||||
{
|
||||
memset(pData, 0, *pDataSize);
|
||||
return VK_INCOMPLETE;
|
||||
}
|
||||
|
||||
VkPipelineCacheHeaderVersionOne *header = (VkPipelineCacheHeaderVersionOne *)pData;
|
||||
|
||||
RDCCOMPILE_ASSERT(sizeof(VkPipelineCacheHeaderVersionOne) == 16 + VK_UUID_SIZE,
|
||||
"Pipeline cache header size is wrong");
|
||||
|
||||
header->headerSize = sizeof(VkPipelineCacheHeaderVersionOne);
|
||||
header->headerVersion = 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
|
||||
header->vendorID = m_PhysicalDeviceData.props.vendorID;
|
||||
header->deviceID = m_PhysicalDeviceData.props.deviceID;
|
||||
|
||||
MakeFakeUUID();
|
||||
|
||||
memcpy(header->pipelineCacheUUID, fakeRenderDocUUID, VK_UUID_SIZE);
|
||||
|
||||
RDCCOMPILE_ASSERT(VK_UUID_SIZE == 16, "VK_UUID_SIZE has changed");
|
||||
|
||||
// empty bytes
|
||||
uint32_t *ptr = (uint32_t *)(header + 1);
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
// we don't want the application to use pipeline caches at all, and especially
|
||||
// don't want to return any data for future use. We thus return a technically
|
||||
// valid but empty pipeline cache. Our UUID changes every run so in theory the
|
||||
// application should never provide an old cache, but just in case we will nop
|
||||
// it out in create pipeline cache
|
||||
return VK_SUCCESS;
|
||||
return ObjDisp(device)->GetPipelineCacheData(Unwrap(device), Unwrap(pipelineCache), pDataSize,
|
||||
pData);
|
||||
}
|
||||
|
||||
VkResult WrappedVulkan::vkMergePipelineCaches(VkDevice device, VkPipelineCache destCache,
|
||||
@@ -689,7 +644,16 @@ VkResult WrappedVulkan::vkMergePipelineCaches(VkDevice device, VkPipelineCache d
|
||||
const VkPipelineCache *pSrcCaches)
|
||||
{
|
||||
// do nothing, our pipeline caches are always dummies
|
||||
return VK_SUCCESS;
|
||||
rdcarray<VkPipelineCache> unwrappedPipelineCaches;
|
||||
|
||||
unwrappedPipelineCaches.reserve(srcCacheCount);
|
||||
for(uint32_t cacheIndex = 0; cacheIndex < srcCacheCount; cacheIndex++)
|
||||
{
|
||||
unwrappedPipelineCaches.push_back(Unwrap(pSrcCaches[cacheIndex]));
|
||||
}
|
||||
|
||||
return ObjDisp(device)->MergePipelineCaches(Unwrap(device), Unwrap(destCache), srcCacheCount,
|
||||
unwrappedPipelineCaches.data());
|
||||
}
|
||||
|
||||
VkResult WrappedVulkan::vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
|
||||
@@ -893,10 +857,6 @@ void WrappedVulkan::vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevi
|
||||
{
|
||||
ObjDisp(physicalDevice)->GetPhysicalDeviceProperties2(Unwrap(physicalDevice), pProperties);
|
||||
|
||||
MakeFakeUUID();
|
||||
|
||||
memcpy(pProperties->properties.pipelineCacheUUID, fakeRenderDocUUID, VK_UUID_SIZE);
|
||||
|
||||
ClampPhysDevAPIVersion(&pProperties->properties, physicalDevice);
|
||||
|
||||
// internal RenderDoc UUID for shader object binary
|
||||
@@ -906,6 +866,8 @@ void WrappedVulkan::vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevi
|
||||
|
||||
if(shadObj)
|
||||
{
|
||||
MakeFakeUUID();
|
||||
|
||||
memcpy(shadObj->shaderBinaryUUID, fakeRenderDocUUID, VK_UUID_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,16 +29,22 @@
|
||||
|
||||
RDOC_EXTERN_CONFIG(bool, Replay_Debug_SingleThreadedCompilation);
|
||||
|
||||
static RDResult DeferredPipelineCompile(VkDevice device,
|
||||
RDOC_CONFIG(bool, Vulkan_Debug_UsePipelineCacheForReplay, true,
|
||||
"Use application-provided pipeline cache when compiling shaders on replay");
|
||||
|
||||
static RDResult DeferredPipelineCompile(VkDevice device, VkPipelineCache pipelineCache,
|
||||
const VkGraphicsPipelineCreateInfo &createInfo,
|
||||
WrappedVkPipeline *wrappedPipe)
|
||||
{
|
||||
if(!Vulkan_Debug_UsePipelineCacheForReplay())
|
||||
pipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
byte *mem = AllocAlignedBuffer(GetNextPatchSize(&createInfo));
|
||||
VkGraphicsPipelineCreateInfo *unwrapped =
|
||||
UnwrapStructAndChain(CaptureState::LoadingReplaying, mem, &createInfo);
|
||||
|
||||
VkPipeline realPipe;
|
||||
VkResult ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), VK_NULL_HANDLE, 1,
|
||||
VkResult ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), Unwrap(pipelineCache), 1,
|
||||
unwrapped, NULL, &realPipe);
|
||||
|
||||
FreeAlignedBuffer((byte *)unwrapped);
|
||||
@@ -54,16 +60,19 @@ static RDResult DeferredPipelineCompile(VkDevice device,
|
||||
return ResultCode::Succeeded;
|
||||
}
|
||||
|
||||
static RDResult DeferredPipelineCompile(VkDevice device,
|
||||
static RDResult DeferredPipelineCompile(VkDevice device, VkPipelineCache pipelineCache,
|
||||
const VkComputePipelineCreateInfo &createInfo,
|
||||
WrappedVkPipeline *wrappedPipe)
|
||||
{
|
||||
if(!Vulkan_Debug_UsePipelineCacheForReplay())
|
||||
pipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
byte *mem = AllocAlignedBuffer(GetNextPatchSize(&createInfo));
|
||||
VkComputePipelineCreateInfo *unwrapped =
|
||||
UnwrapStructAndChain(CaptureState::LoadingReplaying, mem, &createInfo);
|
||||
|
||||
VkPipeline realPipe;
|
||||
VkResult ret = ObjDisp(device)->CreateComputePipelines(Unwrap(device), VK_NULL_HANDLE, 1,
|
||||
VkResult ret = ObjDisp(device)->CreateComputePipelines(Unwrap(device), Unwrap(pipelineCache), 1,
|
||||
unwrapped, NULL, &realPipe);
|
||||
|
||||
FreeAlignedBuffer((byte *)unwrapped);
|
||||
@@ -79,12 +88,15 @@ static RDResult DeferredPipelineCompile(VkDevice device,
|
||||
return ResultCode::Succeeded;
|
||||
}
|
||||
|
||||
static RDResult DeferredPipelineCompile(VkDevice device,
|
||||
static RDResult DeferredPipelineCompile(VkDevice device, VkPipelineCache pipelineCache,
|
||||
const VkRayTracingPipelineCreateInfoKHR &createInfo,
|
||||
const bytebuf &replayHandles,
|
||||
uint32_t captureReplayHandleSize,
|
||||
WrappedVkPipeline *wrappedPipe)
|
||||
{
|
||||
if(!Vulkan_Debug_UsePipelineCacheForReplay())
|
||||
pipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
byte *mem = AllocAlignedBuffer(GetNextPatchSize(&createInfo));
|
||||
VkRayTracingPipelineCreateInfoKHR *unwrapped =
|
||||
UnwrapStructAndChain(CaptureState::LoadingReplaying, mem, &createInfo);
|
||||
@@ -98,7 +110,7 @@ static RDResult DeferredPipelineCompile(VkDevice device,
|
||||
|
||||
VkPipeline realPipe;
|
||||
VkResult ret = ObjDisp(device)->CreateRayTracingPipelinesKHR(
|
||||
Unwrap(device), VK_NULL_HANDLE, VK_NULL_HANDLE, 1, unwrapped, NULL, &realPipe);
|
||||
Unwrap(device), VK_NULL_HANDLE, Unwrap(pipelineCache), 1, unwrapped, NULL, &realPipe);
|
||||
|
||||
FreeAlignedBuffer((byte *)unwrapped);
|
||||
|
||||
@@ -660,18 +672,7 @@ VkResult WrappedVulkan::vkCreatePipelineCache(VkDevice device,
|
||||
const VkAllocationCallbacks *,
|
||||
VkPipelineCache *pPipelineCache)
|
||||
{
|
||||
// pretend the user didn't provide any cache data
|
||||
|
||||
VkPipelineCacheCreateInfo createInfo = *pCreateInfo;
|
||||
createInfo.initialDataSize = 0;
|
||||
createInfo.pInitialData = NULL;
|
||||
|
||||
if(pCreateInfo->initialDataSize > 0)
|
||||
{
|
||||
RDCWARN(
|
||||
"Application provided pipeline cache data! This is invalid, as RenderDoc reports "
|
||||
"incompatibility with previous caches");
|
||||
}
|
||||
|
||||
VkResult ret;
|
||||
SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreatePipelineCache(Unwrap(device), &createInfo, NULL,
|
||||
@@ -726,10 +727,6 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines(
|
||||
VkPipeline pipe = VK_NULL_HANDLE;
|
||||
|
||||
VkRenderPass origRP = CreateInfo.renderPass;
|
||||
VkPipelineCache origCache = pipelineCache;
|
||||
|
||||
// don't use pipeline caches on replay
|
||||
pipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
// if we have pipeline executable properties, capture the data
|
||||
if(GetExtensions(NULL).ext_KHR_pipeline_executable_properties)
|
||||
@@ -852,8 +849,8 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines(
|
||||
}
|
||||
|
||||
DerivedResource(device, Pipeline);
|
||||
if(origCache != VK_NULL_HANDLE)
|
||||
DerivedResource(origCache, Pipeline);
|
||||
if(pipelineCache != VK_NULL_HANDLE)
|
||||
DerivedResource(pipelineCache, Pipeline);
|
||||
if(OrigCreateInfo.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT)
|
||||
{
|
||||
if(OrigCreateInfo.basePipelineHandle != VK_NULL_HANDLE)
|
||||
@@ -887,8 +884,8 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines(
|
||||
{
|
||||
for(rdcpair<VkGraphicsPipelineCreateInfo, VkPipeline> &deferredPipe : pipelinesToCompile)
|
||||
{
|
||||
RDResult res =
|
||||
DeferredPipelineCompile(device, deferredPipe.first, GetWrapped(deferredPipe.second));
|
||||
RDResult res = DeferredPipelineCompile(device, pipelineCache, deferredPipe.first,
|
||||
GetWrapped(deferredPipe.second));
|
||||
|
||||
if(res != ResultCode::Succeeded)
|
||||
{
|
||||
@@ -908,10 +905,11 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines(
|
||||
{
|
||||
WrappedVkPipeline *wrappedPipe = GetWrapped(deferredPipe.second);
|
||||
wrappedPipe->deferredJob = Threading::JobSystem::AddJob(
|
||||
[wrappedVulkan = this, device, createInfo = deferredPipe.first, wrappedPipe]() {
|
||||
[wrappedVulkan = this, device, pipelineCache, createInfo = deferredPipe.first,
|
||||
wrappedPipe]() {
|
||||
PerformanceTimer timer;
|
||||
wrappedVulkan->CheckDeferredResult(
|
||||
DeferredPipelineCompile(device, createInfo, wrappedPipe));
|
||||
DeferredPipelineCompile(device, pipelineCache, createInfo, wrappedPipe));
|
||||
wrappedVulkan->AddDeferredTime(timer.GetMilliseconds());
|
||||
},
|
||||
parents);
|
||||
@@ -1074,11 +1072,6 @@ bool WrappedVulkan::Serialise_vkCreateComputePipelines(SerialiserType &ser, VkDe
|
||||
{
|
||||
VkPipeline pipe = VK_NULL_HANDLE;
|
||||
|
||||
VkPipelineCache origCache = pipelineCache;
|
||||
|
||||
// don't use pipeline caches on replay
|
||||
pipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
// if we have pipeline executable properties, capture the data
|
||||
if(GetExtensions(NULL).ext_KHR_pipeline_executable_properties)
|
||||
{
|
||||
@@ -1152,7 +1145,7 @@ bool WrappedVulkan::Serialise_vkCreateComputePipelines(SerialiserType &ser, VkDe
|
||||
|
||||
if(Replay_Debug_SingleThreadedCompilation())
|
||||
{
|
||||
RDResult res = DeferredPipelineCompile(device, OrigCreateInfo, GetWrapped(pipe));
|
||||
RDResult res = DeferredPipelineCompile(device, pipelineCache, OrigCreateInfo, GetWrapped(pipe));
|
||||
Deserialise(OrigCreateInfo);
|
||||
|
||||
if(res != ResultCode::Succeeded)
|
||||
@@ -1164,11 +1157,11 @@ bool WrappedVulkan::Serialise_vkCreateComputePipelines(SerialiserType &ser, VkDe
|
||||
else
|
||||
{
|
||||
WrappedVkPipeline *wrappedPipe = GetWrapped(pipe);
|
||||
wrappedPipe->deferredJob =
|
||||
Threading::JobSystem::AddJob([wrappedVulkan = this, device, OrigCreateInfo, wrappedPipe]() {
|
||||
wrappedPipe->deferredJob = Threading::JobSystem::AddJob(
|
||||
[wrappedVulkan = this, device, pipelineCache, OrigCreateInfo, wrappedPipe]() {
|
||||
PerformanceTimer timer;
|
||||
wrappedVulkan->CheckDeferredResult(
|
||||
DeferredPipelineCompile(device, OrigCreateInfo, wrappedPipe));
|
||||
DeferredPipelineCompile(device, pipelineCache, OrigCreateInfo, wrappedPipe));
|
||||
wrappedVulkan->AddDeferredTime(timer.GetMilliseconds());
|
||||
|
||||
Deserialise(OrigCreateInfo);
|
||||
@@ -1176,8 +1169,8 @@ bool WrappedVulkan::Serialise_vkCreateComputePipelines(SerialiserType &ser, VkDe
|
||||
}
|
||||
|
||||
DerivedResource(device, Pipeline);
|
||||
if(origCache != VK_NULL_HANDLE)
|
||||
DerivedResource(origCache, Pipeline);
|
||||
if(pipelineCache != VK_NULL_HANDLE)
|
||||
DerivedResource(pipelineCache, Pipeline);
|
||||
if(OrigCreateInfo.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT)
|
||||
{
|
||||
if(OrigCreateInfo.basePipelineHandle != VK_NULL_HANDLE)
|
||||
@@ -1360,11 +1353,6 @@ bool WrappedVulkan::Serialise_vkCreateRayTracingPipelinesKHR(
|
||||
|
||||
VkPipeline pipe = VK_NULL_HANDLE;
|
||||
|
||||
VkPipelineCache origCache = pipelineCache;
|
||||
|
||||
// don't use pipeline caches on replay
|
||||
pipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
// don't fail when a compile is required because we don't currently replay caches so this will
|
||||
// always happen. This still allows application to use this flag at runtime where it will be
|
||||
// valid
|
||||
@@ -1390,8 +1378,8 @@ bool WrappedVulkan::Serialise_vkCreateRayTracingPipelinesKHR(
|
||||
pipeInfo.Init(GetResourceManager(), m_CreationInfo, live, &OrigCreateInfo);
|
||||
|
||||
DerivedResource(device, Pipeline);
|
||||
if(origCache != VK_NULL_HANDLE)
|
||||
DerivedResource(origCache, Pipeline);
|
||||
if(pipelineCache != VK_NULL_HANDLE)
|
||||
DerivedResource(pipelineCache, Pipeline);
|
||||
if(OrigCreateInfo.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT)
|
||||
{
|
||||
if(OrigCreateInfo.basePipelineHandle != VK_NULL_HANDLE)
|
||||
@@ -1418,8 +1406,9 @@ bool WrappedVulkan::Serialise_vkCreateRayTracingPipelinesKHR(
|
||||
|
||||
if(Replay_Debug_SingleThreadedCompilation())
|
||||
{
|
||||
RDResult res = DeferredPipelineCompile(device, OrigCreateInfo, *OrigReplayHandles,
|
||||
captureReplayHandleSize, GetWrapped(pipe));
|
||||
RDResult res =
|
||||
DeferredPipelineCompile(device, pipelineCache, OrigCreateInfo, *OrigReplayHandles,
|
||||
captureReplayHandleSize, GetWrapped(pipe));
|
||||
if(res == ResultCode::APIHardwareUnsupported)
|
||||
res.message = rdcstr(res.message) + "\n" + GetPhysDeviceCompatString(false, false);
|
||||
Deserialise(OrigCreateInfo);
|
||||
@@ -1435,11 +1424,12 @@ bool WrappedVulkan::Serialise_vkCreateRayTracingPipelinesKHR(
|
||||
{
|
||||
WrappedVkPipeline *wrappedPipe = GetWrapped(pipe);
|
||||
wrappedPipe->deferredJob = Threading::JobSystem::AddJob(
|
||||
[wrappedVulkan = this, device, OrigCreateInfo, OrigReplayHandles, captureReplayHandleSize,
|
||||
wrappedPipe]() {
|
||||
[wrappedVulkan = this, device, pipelineCache, OrigCreateInfo, OrigReplayHandles,
|
||||
captureReplayHandleSize, wrappedPipe]() {
|
||||
PerformanceTimer timer;
|
||||
RDResult res = DeferredPipelineCompile(device, OrigCreateInfo, *OrigReplayHandles,
|
||||
captureReplayHandleSize, wrappedPipe);
|
||||
RDResult res =
|
||||
DeferredPipelineCompile(device, pipelineCache, OrigCreateInfo, *OrigReplayHandles,
|
||||
captureReplayHandleSize, wrappedPipe);
|
||||
wrappedVulkan->AddDeferredTime(timer.GetMilliseconds());
|
||||
if(res == ResultCode::APIHardwareUnsupported)
|
||||
res.message = rdcstr(res.message) + "\n" +
|
||||
|
||||
Reference in New Issue
Block a user