Adds a SPIR-V cache that skips frontend compilation for shaders that are already compiled in a previous run of Blender. Initially this was postponed to 4.4 but it was observed that the vulkan backend didn't perform well on Windows in debug builds. The reason is that the compiler would also be a debug build which makes compiling a shader really slow. Starting Blender on a debug build could take minutes. So the decision was made to give this task a higher priority so the vulkan backend would become more usable to developers as well. The cache is stored in the application cache dir. The SPIR-V binaries can be used by different Blender versions so there is no version specific cache folder. **Sidecar**: SPIR-V files are a stream of bytes. There is no header information that allow us to validate the stream. To add basic validations we could add our custom header or a sidecar. It was chosen to use a sidecar as having the SPIR-V files unmodified allows us to load them directly in debug tools for analyzing. **Retention**: Shaders that are not used are automatically removed with a retention period of 30 days. **Shader builder**: Shader builder cannot use the SPIR-V cache as it uses stubs that returns invalid cache directories. This would load/save the cache to the location where you started the build. Pull Request: https://projects.blender.org/blender/blender/pulls/128741
69 lines
1.9 KiB
C++
69 lines
1.9 KiB
C++
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup gpu
|
|
*/
|
|
|
|
#include "vk_shader_module.hh"
|
|
#include "vk_backend.hh"
|
|
#include "vk_memory.hh"
|
|
#include "vk_shader.hh"
|
|
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
|
|
namespace blender::gpu {
|
|
VKShaderModule::~VKShaderModule()
|
|
{
|
|
VKDevice &device = VKBackend::get().device;
|
|
VKDiscardPool &discard_pool = device.discard_pool_for_current_thread();
|
|
if (vk_shader_module != VK_NULL_HANDLE) {
|
|
discard_pool.discard_shader_module(vk_shader_module);
|
|
vk_shader_module = VK_NULL_HANDLE;
|
|
}
|
|
}
|
|
|
|
void VKShaderModule::finalize(StringRefNull name)
|
|
{
|
|
BLI_assert(vk_shader_module == VK_NULL_HANDLE);
|
|
if (compilation_result.GetCompilationStatus() != shaderc_compilation_status_success &&
|
|
spirv_binary.is_empty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
VK_ALLOCATION_CALLBACKS;
|
|
|
|
VkShaderModuleCreateInfo create_info = {};
|
|
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
if (!spirv_binary.is_empty()) {
|
|
create_info.codeSize = spirv_binary.size() * sizeof(uint32_t);
|
|
create_info.pCode = spirv_binary.data();
|
|
}
|
|
else {
|
|
create_info.codeSize = (compilation_result.end() - compilation_result.begin()) *
|
|
sizeof(uint32_t);
|
|
create_info.pCode = compilation_result.begin();
|
|
}
|
|
|
|
const VKDevice &device = VKBackend::get().device;
|
|
vkCreateShaderModule(
|
|
device.vk_handle(), &create_info, vk_allocation_callbacks, &vk_shader_module);
|
|
debug::object_label(vk_shader_module, name.c_str());
|
|
}
|
|
|
|
void VKShaderModule::build_sources_hash()
|
|
{
|
|
DefaultHash<std::string> hasher;
|
|
BLI_assert(!combined_sources.empty());
|
|
uint64_t hash = hasher(combined_sources);
|
|
std::stringstream ss;
|
|
ss << std::setfill('0') << std::setw(sizeof(uint64_t) * 2) << std::hex << hash;
|
|
sources_hash = ss.str();
|
|
BLI_assert(!sources_hash.empty());
|
|
}
|
|
|
|
} // namespace blender::gpu
|