renderer_vulkan: Pipeline cache fixes
This commit is contained in:
@ -3,6 +3,7 @@
|
|||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#define VULKAN_HPP_NO_CONSTRUCTORS
|
#define VULKAN_HPP_NO_CONSTRUCTORS
|
||||||
|
#include <filesystem>
|
||||||
#include "common/common_paths.h"
|
#include "common/common_paths.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
@ -150,6 +151,7 @@ PipelineCache::~PipelineCache() {
|
|||||||
SaveDiskCache();
|
SaveDiskCache();
|
||||||
|
|
||||||
device.destroyPipelineLayout(layout);
|
device.destroyPipelineLayout(layout);
|
||||||
|
device.destroyPipelineCache(pipeline_cache);
|
||||||
device.destroyShaderModule(trivial_vertex_shader);
|
device.destroyShaderModule(trivial_vertex_shader);
|
||||||
for (std::size_t i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
for (std::size_t i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
||||||
device.destroyDescriptorSetLayout(descriptor_set_layouts[i]);
|
device.destroyDescriptorSetLayout(descriptor_set_layouts[i]);
|
||||||
@ -595,39 +597,45 @@ void PipelineCache::BindDescriptorSets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::LoadDiskCache() {
|
void PipelineCache::LoadDiskCache() {
|
||||||
const std::string cache_path =
|
if (!EnsureDirectories()) {
|
||||||
FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir) + DIR_SEP "vulkan" + DIR_SEP "pipelines.bin";
|
|
||||||
|
|
||||||
FileUtil::IOFile cache_file{cache_path, "r"};
|
|
||||||
if (!cache_file.IsOpen()) {
|
|
||||||
LOG_INFO(Render_Vulkan, "No pipeline cache found");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string cache_file_path = GetPipelineCacheDir() + DIR_SEP "pipelines.bin";
|
||||||
|
vk::PipelineCacheCreateInfo cache_info = {
|
||||||
|
.initialDataSize = 0,
|
||||||
|
.pInitialData = nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
FileUtil::IOFile cache_file{cache_file_path, "r"};
|
||||||
|
if (cache_file.IsOpen()) {
|
||||||
|
LOG_INFO(Render_Vulkan, "Loading pipeline cache");
|
||||||
|
|
||||||
const u32 cache_file_size = cache_file.GetSize();
|
const u32 cache_file_size = cache_file.GetSize();
|
||||||
auto cache_data = std::vector<u8>(cache_file_size);
|
auto cache_data = std::vector<u8>(cache_file_size);
|
||||||
if (!cache_file.ReadBytes(cache_data.data(), cache_file_size)) {
|
if (cache_file.ReadBytes(cache_data.data(), cache_file_size)) {
|
||||||
LOG_WARNING(Render_Vulkan, "Error during pipeline cache read");
|
if (!IsCacheValid(cache_data.data(), cache_file_size)) {
|
||||||
return;
|
LOG_WARNING(Render_Vulkan, "Pipeline cache provided invalid");
|
||||||
|
} else {
|
||||||
|
cache_info.initialDataSize = cache_file_size;
|
||||||
|
cache_info.pInitialData = cache_data.data();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_file.Close();
|
cache_file.Close();
|
||||||
|
}
|
||||||
const bool is_valid = ValidateData(cache_data.data(), cache_file_size);
|
|
||||||
const vk::PipelineCacheCreateInfo cache_info = {
|
|
||||||
.initialDataSize = is_valid ? cache_file_size : 0,
|
|
||||||
.pInitialData = cache_data.data()
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
pipeline_cache = device.createPipelineCache(cache_info);
|
pipeline_cache = device.createPipelineCache(cache_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::SaveDiskCache() {
|
void PipelineCache::SaveDiskCache() {
|
||||||
const std::string cache_path =
|
if (!EnsureDirectories()) {
|
||||||
FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir) + "vulkan" + DIR_SEP "pipelines.bin";
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FileUtil::IOFile cache_file{cache_path, "wb"};
|
const std::string cache_file_path = GetPipelineCacheDir() + DIR_SEP "pipelines.bin";
|
||||||
|
FileUtil::IOFile cache_file{cache_file_path, "wb"};
|
||||||
if (!cache_file.IsOpen()) {
|
if (!cache_file.IsOpen()) {
|
||||||
LOG_INFO(Render_Vulkan, "Unable to open pipeline cache for writing");
|
LOG_INFO(Render_Vulkan, "Unable to open pipeline cache for writing");
|
||||||
return;
|
return;
|
||||||
@ -643,7 +651,7 @@ void PipelineCache::SaveDiskCache() {
|
|||||||
cache_file.Close();
|
cache_file.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PipelineCache::ValidateData(const u8* data, u32 size) {
|
bool PipelineCache::IsCacheValid(const u8* data, u32 size) const {
|
||||||
if (size < sizeof(vk::PipelineCacheHeaderVersionOne)) {
|
if (size < sizeof(vk::PipelineCacheHeaderVersionOne)) {
|
||||||
LOG_ERROR(Render_Vulkan, "Pipeline cache failed validation: Invalid header");
|
LOG_ERROR(Render_Vulkan, "Pipeline cache failed validation: Invalid header");
|
||||||
return false;
|
return false;
|
||||||
@ -683,4 +691,22 @@ bool PipelineCache::ValidateData(const u8* data, u32 size) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PipelineCache::EnsureDirectories() const {
|
||||||
|
const auto CreateDir = [](const std::string& dir) {
|
||||||
|
if (!FileUtil::CreateDir(dir)) {
|
||||||
|
LOG_ERROR(Render_Vulkan, "Failed to create directory={}", dir);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
return CreateDir(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)) &&
|
||||||
|
CreateDir(GetPipelineCacheDir());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PipelineCache::GetPipelineCacheDir() const {
|
||||||
|
return FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir) + "vulkan";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -198,10 +198,6 @@ public:
|
|||||||
/// Marks all descriptor sets as dirty
|
/// Marks all descriptor sets as dirty
|
||||||
void MarkDescriptorSetsDirty();
|
void MarkDescriptorSetsDirty();
|
||||||
|
|
||||||
vk::ImageView GetTexture(u32 set, u32 binding) const {
|
|
||||||
return update_data[set][binding].image_info.imageView;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Binds a resource to the provided binding
|
/// Binds a resource to the provided binding
|
||||||
void SetBinding(u32 set, u32 binding, DescriptorData data);
|
void SetBinding(u32 set, u32 binding, DescriptorData data);
|
||||||
@ -224,8 +220,14 @@ private:
|
|||||||
/// Stores the generated pipeline cache to disk
|
/// Stores the generated pipeline cache to disk
|
||||||
void SaveDiskCache();
|
void SaveDiskCache();
|
||||||
|
|
||||||
/// Ensures the disk data was generated from the same driver
|
/// Returns true when the disk data can be used by the current driver
|
||||||
bool ValidateData(const u8* data, u32 size);
|
bool IsCacheValid(const u8* data, u32 size) const;
|
||||||
|
|
||||||
|
/// Create shader disk cache directories. Returns true on success.
|
||||||
|
bool EnsureDirectories() const;
|
||||||
|
|
||||||
|
/// Returns the pipeline cache storage dir
|
||||||
|
std::string GetPipelineCacheDir() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
|
Reference in New Issue
Block a user