vk_pipeline_cache: Make pipeline cache reads more robust (#7194)

This commit is contained in:
GPUCode 2023-11-23 09:09:12 +02:00 committed by GitHub
parent 85bd1be852
commit 1dc0fa7bb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -8,6 +8,7 @@
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/microprofile.h" #include "common/microprofile.h"
#include "common/scope_exit.h"
#include "common/settings.h" #include "common/settings.h"
#include "video_core/renderer_vulkan/pica_to_vk.h" #include "video_core/renderer_vulkan/pica_to_vk.h"
#include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_instance.h"
@ -128,57 +129,66 @@ void PipelineCache::LoadDiskCache() {
return; return;
} }
const std::string cache_file_path = fmt::format("{}{:x}{:x}.bin", GetPipelineCacheDir(), const auto cache_dir = GetPipelineCacheDir();
instance.GetVendorID(), instance.GetDeviceID()); const u32 vendor_id = instance.GetVendorID();
vk::PipelineCacheCreateInfo cache_info = { const u32 device_id = instance.GetDeviceID();
.initialDataSize = 0, const auto cache_file_path = fmt::format("{}{:x}{:x}.bin", cache_dir, vendor_id, device_id);
.pInitialData = nullptr,
};
vk::PipelineCacheCreateInfo cache_info{};
std::vector<u8> cache_data; std::vector<u8> cache_data;
FileUtil::IOFile cache_file{cache_file_path, "r"};
if (cache_file.IsOpen()) { SCOPE_EXIT({
LOG_INFO(Render_Vulkan, "Loading pipeline cache"); const vk::Device device = instance.GetDevice();
pipeline_cache = device.createPipelineCacheUnique(cache_info);
});
FileUtil::IOFile cache_file{cache_file_path, "rb"};
if (!cache_file.IsOpen()) {
LOG_INFO(Render_Vulkan, "No pipeline cache found for device");
return;
}
const u64 cache_file_size = cache_file.GetSize(); const u64 cache_file_size = cache_file.GetSize();
cache_data.resize(cache_file_size); cache_data.resize(cache_file_size);
if (cache_file.ReadBytes(cache_data.data(), cache_file_size)) { if (cache_file.ReadBytes(cache_data.data(), cache_file_size) != cache_file_size) {
LOG_ERROR(Render_Vulkan, "Error during pipeline cache read");
return;
}
if (!IsCacheValid(cache_data)) { if (!IsCacheValid(cache_data)) {
LOG_WARNING(Render_Vulkan, "Pipeline cache provided invalid, ignoring"); LOG_WARNING(Render_Vulkan, "Pipeline cache provided invalid, removing");
} else { cache_file.Close();
FileUtil::Delete(cache_file_path);
return;
}
LOG_INFO(Render_Vulkan, "Loading pipeline cache with size {} KB", cache_file_size / 1024);
cache_info.initialDataSize = cache_file_size; cache_info.initialDataSize = cache_file_size;
cache_info.pInitialData = cache_data.data(); cache_info.pInitialData = cache_data.data();
} }
}
cache_file.Close();
}
vk::Device device = instance.GetDevice();
pipeline_cache = device.createPipelineCacheUnique(cache_info);
}
void PipelineCache::SaveDiskCache() { void PipelineCache::SaveDiskCache() {
if (!Settings::values.use_disk_shader_cache || !EnsureDirectories() || !pipeline_cache) { if (!Settings::values.use_disk_shader_cache || !EnsureDirectories() || !pipeline_cache) {
return; return;
} }
const std::string cache_file_path = fmt::format("{}{:x}{:x}.bin", GetPipelineCacheDir(), const auto cache_dir = GetPipelineCacheDir();
instance.GetVendorID(), instance.GetDeviceID()); const u32 vendor_id = instance.GetVendorID();
const u32 device_id = instance.GetDeviceID();
const auto cache_file_path = fmt::format("{}{:x}{:x}.bin", cache_dir, vendor_id, device_id);
FileUtil::IOFile cache_file{cache_file_path, "wb"}; FileUtil::IOFile cache_file{cache_file_path, "wb"};
if (!cache_file.IsOpen()) { if (!cache_file.IsOpen()) {
LOG_ERROR(Render_Vulkan, "Unable to open pipeline cache for writing"); LOG_ERROR(Render_Vulkan, "Unable to open pipeline cache for writing");
return; return;
} }
vk::Device device = instance.GetDevice(); const vk::Device device = instance.GetDevice();
auto cache_data = device.getPipelineCacheData(*pipeline_cache); const auto cache_data = device.getPipelineCacheData(*pipeline_cache);
if (!cache_file.WriteBytes(cache_data.data(), cache_data.size())) { if (cache_file.WriteBytes(cache_data.data(), cache_data.size()) != cache_data.size()) {
LOG_ERROR(Render_Vulkan, "Error during pipeline cache write"); LOG_ERROR(Render_Vulkan, "Error during pipeline cache write");
return; return;
} }
cache_file.Close();
} }
bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) { bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) {