From 9cf9fae453272eab44257805ca7b1ad9b4dbc70c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 12 Aug 2025 00:09:54 +0200 Subject: [PATCH] Add Vulkan device cache customization per-platform and reuse code --- .../GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 92 +++++++++---------- .../Vulkan/VulkanPlatformBase.h | 3 + 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index 2820d5777..8c91501d7 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -1498,17 +1498,28 @@ PixelFormat GPUDeviceVulkan::GetClosestSupportedPixelFormat(PixelFormat format, return format; } -#if VULKAN_USE_PIPELINE_CACHE - -void GetPipelineCachePath(String& path) +bool VulkanPlatformBase::LoadCache(const String& folder, const Char* filename, Array& data) { -#if USE_EDITOR - path = Globals::ProjectCacheFolder / TEXT("VulkanPipeline.cache"); -#else - path = Globals::ProductLocalFolder / TEXT("VulkanPipeline.cache"); -#endif + String path = folder / filename; + if (FileSystem::FileExists(path)) + { + LOG(Info, "Loading Vulkan cache from file '{}'", path); + return File::ReadAllBytes(path, data); + } + return false; } +bool VulkanPlatformBase::SaveCache(const String& folder, const Char* filename, const Array& data) +{ + String path = folder / filename; + LOG(Info, "Saving Vulkan cache to file '{}' ({} kB)", path, data.Count() / 1024); + return File::WriteAllBytes(path, data); +} + +#if USE_EDITOR +#define CACHE_FOLDER Globals::ProjectCacheFolder +#else +#define CACHE_FOLDER Globals::ProductLocalFolder #endif bool GPUDeviceVulkan::SavePipelineCache() @@ -1516,6 +1527,8 @@ bool GPUDeviceVulkan::SavePipelineCache() #if VULKAN_USE_PIPELINE_CACHE if (PipelineCache == VK_NULL_HANDLE || !vkGetPipelineCacheData) return false; + PROFILE_CPU(); + PROFILE_MEM(Graphics); // Query data size size_t dataSize = 0; @@ -1531,9 +1544,7 @@ bool GPUDeviceVulkan::SavePipelineCache() LOG_VULKAN_RESULT_WITH_RETURN(result); // Save data - String path; - GetPipelineCachePath(path); - return File::WriteAllBytes(path, data); + return VulkanPlatform::SaveCache(CACHE_FOLDER, TEXT("VulkanPipeline.cache"), data); #else return false; #endif @@ -1541,19 +1552,12 @@ bool GPUDeviceVulkan::SavePipelineCache() #if VULKAN_USE_VALIDATION_CACHE -void GetValidationCachePath(String& path) -{ -#if USE_EDITOR - path = Globals::ProjectCacheFolder / TEXT("VulkanValidation.cache"); -#else - path = Globals::ProductLocalFolder / TEXT("VulkanValidation.cache"); -#endif -} - bool GPUDeviceVulkan::SaveValidationCache() { if (ValidationCache == VK_NULL_HANDLE || !vkGetValidationCacheDataEXT) return false; + PROFILE_CPU(); + PROFILE_MEM(Graphics); // Query data size size_t dataSize = 0; @@ -1569,9 +1573,7 @@ bool GPUDeviceVulkan::SaveValidationCache() LOG_VULKAN_RESULT_WITH_RETURN(result); // Save data - String path; - GetValidationCachePath(path); - return File::WriteAllBytes(path, data); + return VulkanPlatform::SaveCache(CACHE_FOLDER, TEXT("VulkanValidation.cache"), data); } #endif @@ -1987,13 +1989,7 @@ bool GPUDeviceVulkan::Init() if (vkCreatePipelineCache) { Array data; - String path; - GetPipelineCachePath(path); - if (FileSystem::FileExists(path)) - { - LOG(Info, "Trying to load Vulkan pipeline cache file {0}", path); - File::ReadAllBytes(path, data); - } + VulkanPlatform::LoadCache(CACHE_FOLDER, TEXT("VulkanPipeline.cache"), data); VkPipelineCacheCreateInfo pipelineCacheCreateInfo; RenderToolsVulkan::ZeroStruct(pipelineCacheCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO); pipelineCacheCreateInfo.initialDataSize = data.Count(); @@ -2006,36 +2002,30 @@ bool GPUDeviceVulkan::Init() if (OptionalDeviceExtensions.HasEXTValidationCache && vkCreateValidationCacheEXT && vkDestroyValidationCacheEXT) { Array data; - String path; - GetValidationCachePath(path); - if (FileSystem::FileExists(path)) + VulkanPlatform::LoadCache(CACHE_FOLDER, TEXT("VulkanValidation.cache"), data); + if (data.HasItems()) { - LOG(Info, "Trying to load Vulkan validation cache file {0}", path); - File::ReadAllBytes(path, data); - if (data.HasItems()) + int32* dataPtr = (int32*)data.Get(); + if (*dataPtr > 0) { - int32* dataPtr = (int32*)data.Get(); - if (*dataPtr > 0) + const int32 cacheSize = *dataPtr++; + const int32 cacheVersion = *dataPtr++; + const int32 cacheVersionExpected = VK_PIPELINE_CACHE_HEADER_VERSION_ONE; + if (cacheVersion == cacheVersionExpected) { - const int32 cacheSize = *dataPtr++; - const int32 cacheVersion = *dataPtr++; - const int32 cacheVersionExpected = VK_PIPELINE_CACHE_HEADER_VERSION_ONE; - if (cacheVersion == cacheVersionExpected) - { - dataPtr += VK_UUID_SIZE / sizeof(int32); - } - else - { - LOG(Warning, "Bad validation cache file, version: {0}, expected: {1}", cacheVersion, cacheVersionExpected); - data.Clear(); - } + dataPtr += VK_UUID_SIZE / sizeof(int32); } else { - LOG(Warning, "Bad validation cache file, header size: {0}", *dataPtr); + LOG(Warning, "Bad validation cache file, version: {0}, expected: {1}", cacheVersion, cacheVersionExpected); data.Clear(); } } + else + { + LOG(Warning, "Bad validation cache file, header size: {0}", *dataPtr); + data.Clear(); + } } VkValidationCacheCreateInfoEXT validationCreateInfo; RenderToolsVulkan::ZeroStruct(validationCreateInfo, VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT); diff --git a/Source/Engine/GraphicsDevice/Vulkan/VulkanPlatformBase.h b/Source/Engine/GraphicsDevice/Vulkan/VulkanPlatformBase.h index 4cfbd2716..2122b3709 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/VulkanPlatformBase.h +++ b/Source/Engine/GraphicsDevice/Vulkan/VulkanPlatformBase.h @@ -49,6 +49,9 @@ public: featuresToEnable.sparseResidency8Samples = VK_FALSE; featuresToEnable.sparseResidencyAliased = VK_FALSE; } + + static bool LoadCache(const String& folder, const Char* filename, Array& data); + static bool SaveCache(const String& folder, const Char* filename, const Array& data); }; #endif