mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-05-10 19:21:42 +00:00
feat(bindless): Persist shader cache
This commit is contained in:
parent
5438886234
commit
08452e9771
3 changed files with 118 additions and 18 deletions
|
|
@ -516,7 +516,15 @@ Pipeline::Pipeline(
|
|||
});
|
||||
}
|
||||
|
||||
this->m_cache = vkhelper::createPipelineCache(dld, device);
|
||||
const std::string_view cacheTag{perf ? "performance" : "quality"};
|
||||
auto [cache, isCacheValid] = vkhelper::createPipelineCache(
|
||||
dld,
|
||||
device,
|
||||
physdev,
|
||||
cacheTag
|
||||
);
|
||||
this->m_cache = std::move(cache);
|
||||
|
||||
std::vector<vk::UniquePipeline> pipelines{
|
||||
device.createComputePipelinesUnique(
|
||||
*this->m_cache,
|
||||
|
|
@ -526,6 +534,18 @@ Pipeline::Pipeline(
|
|||
).value
|
||||
};
|
||||
|
||||
if (!isCacheValid) {
|
||||
LOG_DEBUG(" Pipeline cache is not valid, persisting new cache data")
|
||||
|
||||
vkhelper::persistPipelineCache(
|
||||
dld,
|
||||
device,
|
||||
physdev,
|
||||
*this->m_cache,
|
||||
cacheTag
|
||||
);
|
||||
}
|
||||
|
||||
this->m_pipelines.reserve(signature.shaders.size());
|
||||
for (size_t i = 0; i < signature.shaders.size(); i++) {
|
||||
const auto& name{signature.shaders.at(i).first};
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -183,24 +184,57 @@ vk::UniqueShaderModule vkhelper::createShaderModule(
|
|||
return device.createShaderModuleUnique(shaderInfo, nullptr, dld);
|
||||
}
|
||||
|
||||
vk::UniquePipelineCache vkhelper::createPipelineCache(
|
||||
namespace {
|
||||
/// Find the cache file path
|
||||
std::filesystem::path findPipelineCache(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::PhysicalDevice& physdev,
|
||||
std::string_view tag
|
||||
) {
|
||||
// First find the base path
|
||||
std::filesystem::path path{"/tmp/lsfg-vk"};
|
||||
|
||||
const char* xdgCacheHome{std::getenv("XDG_CACHE_HOME")};
|
||||
if (xdgCacheHome && *xdgCacheHome != '\0')
|
||||
path = std::filesystem::path(xdgCacheHome) / "lsfg-vk";
|
||||
|
||||
const char* home{std::getenv("HOME")};
|
||||
if (home && *home != '\0')
|
||||
path = std::filesystem::path(home) / ".cache" / "lsfg-vk";
|
||||
|
||||
// Ensure the directory exists
|
||||
if (!std::filesystem::exists(path))
|
||||
std::filesystem::create_directories(path);
|
||||
|
||||
// Calculate the physical device UUID
|
||||
vk::PhysicalDeviceProperties2 info{};
|
||||
physdev.getProperties2(&info, dld);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
for (uint32_t i = 0; i < 16; i++) {
|
||||
ss << std::setw(2) << static_cast<uint32_t>(info.properties.pipelineCacheUUID.at(i));
|
||||
if (i == 3 || i == 5 || i == 7 || i == 9) {
|
||||
ss << "-";
|
||||
}
|
||||
}
|
||||
|
||||
// Return the full path
|
||||
return path / ("cache_" + std::string(tag) + "_" + ss.str() + ".bin");
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<vk::UniquePipelineCache, bool> vkhelper::createPipelineCache(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device
|
||||
const vk::Device& device,
|
||||
const vk::PhysicalDevice& physdev,
|
||||
std::string_view tag
|
||||
) {
|
||||
// Find the cache file path
|
||||
std::filesystem::path path{"/tmp/lsfg-vk_pipeline_cache.bin"};
|
||||
|
||||
const char* xdgCacheHome{std::getenv("XDG_CACHE_HOME")};
|
||||
if (xdgCacheHome && *xdgCacheHome != '\0')
|
||||
path = std::filesystem::path(xdgCacheHome) / "lsfg-vk_pipeline_cache.bin";
|
||||
|
||||
const char* home{std::getenv("HOME")};
|
||||
if (home && *home != '\0')
|
||||
path = std::filesystem::path(home) / ".cache" / "lsfg-vk_pipeline_cache.bin";
|
||||
const std::filesystem::path path{findPipelineCache(dld, physdev, tag)};
|
||||
const bool valid{std::filesystem::exists(path) && std::filesystem::file_size(path) > 32};
|
||||
|
||||
// Read cache data (if any)
|
||||
std::vector<uint8_t> cacheData{};
|
||||
|
||||
if (std::filesystem::exists(path)) {
|
||||
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||
if (!file.is_open())
|
||||
|
|
@ -219,7 +253,32 @@ vk::UniquePipelineCache vkhelper::createPipelineCache(
|
|||
.initialDataSize = cacheData.size(),
|
||||
.pInitialData = cacheData.data()
|
||||
};
|
||||
return device.createPipelineCacheUnique(pipelineCacheInfo, nullptr, dld);
|
||||
return { device.createPipelineCacheUnique(pipelineCacheInfo, nullptr, dld), valid };
|
||||
}
|
||||
|
||||
void vkhelper::persistPipelineCache(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
const vk::PhysicalDevice& physdev,
|
||||
const vk::PipelineCache& cache,
|
||||
std::string_view tag
|
||||
) {
|
||||
const std::filesystem::path path{findPipelineCache(dld, physdev, tag)};
|
||||
|
||||
std::ofstream file(path, std::ios::binary | std::ios::trunc);
|
||||
if (!file.is_open())
|
||||
throw std::runtime_error("Unable to open pipeline cache file for writing");
|
||||
|
||||
const std::vector<uint8_t> cacheData{
|
||||
device.getPipelineCacheData(cache, dld)
|
||||
};
|
||||
file.write(
|
||||
reinterpret_cast<const char*>(cacheData.data()), // NOLINT (unsafe cast)
|
||||
static_cast<std::streamsize>(cacheData.size())
|
||||
);
|
||||
|
||||
file.flush();
|
||||
file.close();
|
||||
}
|
||||
|
||||
std::pair<vk::UniqueDescriptorSetLayout, vk::UniquePipelineLayout> vkhelper::createLayout(
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -124,15 +125,35 @@ namespace vkhelper {
|
|||
///
|
||||
/// @param dld Dynamic dispatch loader
|
||||
/// @param device Vulkan device
|
||||
/// @param physdev Physical device
|
||||
/// @param tag Cache tag for different pipelines
|
||||
/// @return RAII-wrapped Vulkan pipeline cache
|
||||
/// @throws std::runtime_error on failure
|
||||
///
|
||||
vk::UniquePipelineCache createPipelineCache(
|
||||
std::pair<vk::UniquePipelineCache, bool> createPipelineCache(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device
|
||||
const vk::Device& device,
|
||||
const vk::PhysicalDevice& physdev,
|
||||
std::string_view tag
|
||||
);
|
||||
|
||||
// TODO: Persist pipeline cache
|
||||
///
|
||||
/// Persist the Vulkan pipeline cache to disk
|
||||
///
|
||||
/// @param dld Dynamic dispatch loader
|
||||
/// @param device Vulkan device
|
||||
/// @param physdev Physical device
|
||||
/// @param cache Vulkan pipeline cache
|
||||
/// @param tag Cache tag for different pipelines
|
||||
/// @throws std::runtime_error on failure
|
||||
///
|
||||
void persistPipelineCache(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
const vk::PhysicalDevice& physdev,
|
||||
const vk::PipelineCache& cache,
|
||||
std::string_view tag
|
||||
);
|
||||
|
||||
///
|
||||
/// Create a Vulkan descriptor set layout
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue