WIP: Vulkan: Reuse shader modules. #122044
@ -487,6 +487,9 @@ VKShader::VKShader(const char *name) : Shader(name)
|
||||
void VKShader::init(const shader::ShaderCreateInfo &info)
|
||||
{
|
||||
create_info_ = &info;
|
||||
VKShaderInterface *vk_interface = new VKShaderInterface();
|
||||
vk_interface->init(info);
|
||||
interface = vk_interface;
|
||||
}
|
||||
|
||||
VKShader::~VKShader()
|
||||
@ -566,18 +569,23 @@ bool VKShader::finalize(const shader::ShaderCreateInfo *info)
|
||||
geometry_shader_from_glsl(sources);
|
||||
}
|
||||
|
||||
VKShaderInterface *vk_interface = new VKShaderInterface();
|
||||
vk_interface->init(*info);
|
||||
/* Create infos of none static compilation shaders can be destructed after the shader are
|
||||
* compiled. Better to reset the value to not confuse developers during debugging. */
|
||||
if (!create_info_->do_static_compilation_) {
|
||||
create_info_ = nullptr;
|
||||
}
|
||||
|
||||
const VKShaderInterface &vk_interface = interface_get();
|
||||
|
||||
VKDevice &device = VKBackend::get().device_get();
|
||||
if (!finalize_descriptor_set_layouts(device, *vk_interface)) {
|
||||
if (!finalize_descriptor_set_layouts(device, vk_interface)) {
|
||||
return false;
|
||||
}
|
||||
if (!finalize_pipeline_layout(device.device_get(), *vk_interface)) {
|
||||
if (!finalize_pipeline_layout(device.device_get(), vk_interface)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
push_constants = VKPushConstants(&vk_interface->push_constants_layout_get());
|
||||
push_constants = VKPushConstants(&vk_interface.push_constants_layout_get());
|
||||
|
||||
bool result;
|
||||
if (use_render_graph) {
|
||||
@ -601,11 +609,9 @@ bool VKShader::finalize(const shader::ShaderCreateInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
interface = vk_interface;
|
||||
}
|
||||
else {
|
||||
delete vk_interface;
|
||||
if (!result) {
|
||||
delete interface;
|
||||
interface = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -713,8 +719,7 @@ void VKShader::uniform_int(int location, int comp_len, int array_size, const int
|
||||
|
||||
std::string VKShader::resources_declare(const shader::ShaderCreateInfo &info) const
|
||||
{
|
||||
VKShaderInterface interface;
|
||||
interface.init(info);
|
||||
const VKShaderInterface &vk_interface = interface_get();
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "\n/* Specialization Constants (pass-through). */\n";
|
||||
@ -745,16 +750,16 @@ std::string VKShader::resources_declare(const shader::ShaderCreateInfo &info) co
|
||||
|
||||
ss << "\n/* Pass Resources. */\n";
|
||||
for (const ShaderCreateInfo::Resource &res : info.pass_resources_) {
|
||||
print_resource(ss, interface, res);
|
||||
print_resource(ss, vk_interface, res);
|
||||
}
|
||||
|
||||
ss << "\n/* Batch Resources. */\n";
|
||||
for (const ShaderCreateInfo::Resource &res : info.batch_resources_) {
|
||||
print_resource(ss, interface, res);
|
||||
print_resource(ss, vk_interface, res);
|
||||
}
|
||||
|
||||
/* Push constants. */
|
||||
const VKPushConstants::Layout &push_constants_layout = interface.push_constants_layout_get();
|
||||
const VKPushConstants::Layout &push_constants_layout = vk_interface.push_constants_layout_get();
|
||||
const VKPushConstants::StorageType push_constants_storage =
|
||||
push_constants_layout.storage_type_get();
|
||||
if (push_constants_storage != VKPushConstants::StorageType::NONE) {
|
||||
|
@ -6,6 +6,7 @@
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#include "BLI_hash.hh"
|
||||
#include "BLI_string_utils.hh"
|
||||
#include "BLI_time.h"
|
||||
|
||||
@ -21,43 +22,6 @@
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
bool VKShaderModules::construct(VKShader &shader,
|
||||
const shader::ShaderCreateInfo & /*info*/,
|
||||
Span<const char *> sources,
|
||||
shaderc_shader_kind stage,
|
||||
VkShaderModule *r_shader_module)
|
||||
{
|
||||
BLI_assert_msg(ELEM(stage,
|
||||
shaderc_vertex_shader,
|
||||
shaderc_geometry_shader,
|
||||
shaderc_fragment_shader,
|
||||
shaderc_compute_shader),
|
||||
"Only forced ShaderC shader kinds are supported.");
|
||||
Vector<uint32_t> spirv_module;
|
||||
if (!compile_glsl_to_spirv(shader, sources, stage, spirv_module)) {
|
||||
r_shader_module = VK_NULL_HANDLE;
|
||||
return false;
|
||||
}
|
||||
return build_shader_module(shader, spirv_module, r_shader_module);
|
||||
}
|
||||
|
||||
void VKShaderModules::destruct(VkShaderModule vk_shader_module)
|
||||
{
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vkDestroyShaderModule(device.device_get(), vk_shader_module, vk_allocation_callbacks);
|
||||
}
|
||||
|
||||
void VKShaderModules::free_data()
|
||||
{
|
||||
debug_print();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Frontend compilation (GLSL -> SpirV)
|
||||
*
|
||||
* \{ */
|
||||
|
||||
static const std::string to_stage_name(shaderc_shader_kind stage)
|
||||
{
|
||||
switch (stage) {
|
||||
@ -77,6 +41,79 @@ static const std::string to_stage_name(shaderc_shader_kind stage)
|
||||
return std::string("unknown stage");
|
||||
}
|
||||
|
||||
bool VKShaderModules::construct(VKShader &shader,
|
||||
const shader::ShaderCreateInfo &info,
|
||||
Span<const char *> sources,
|
||||
shaderc_shader_kind stage,
|
||||
VkShaderModule *r_shader_module)
|
||||
{
|
||||
BLI_assert_msg(ELEM(stage,
|
||||
shaderc_vertex_shader,
|
||||
shaderc_geometry_shader,
|
||||
shaderc_fragment_shader,
|
||||
shaderc_compute_shader),
|
||||
"Only forced ShaderC shader kinds are supported.");
|
||||
|
||||
Vector<uint32_t> spirv_module;
|
||||
if (!compile_glsl_to_spirv(shader, sources, stage, spirv_module)) {
|
||||
r_shader_module = VK_NULL_HANDLE;
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool use_module_cache = !info.do_static_compilation_;
|
||||
uint64_t cache_key = 0;
|
||||
if (use_module_cache) {
|
||||
cache_key = spirv_module.hash();
|
||||
VkShaderModule *shader_module = cache_.lookup_ptr(cache_key);
|
||||
if (shader_module) {
|
||||
printf("%s: %s.%s\n", __func__, info.name_.c_str(), to_stage_name(stage).c_str());
|
||||
stats_.shader_modules_reused += 1;
|
||||
*r_shader_module = *shader_module;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!build_shader_module(shader, spirv_module, r_shader_module)) {
|
||||
r_shader_module = VK_NULL_HANDLE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (use_module_cache) {
|
||||
cache_.add_new(cache_key, *r_shader_module);
|
||||
cached_values_.add_new(*r_shader_module);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void VKShaderModules::destruct(VkShaderModule vk_shader_module)
|
||||
{
|
||||
if (cached_values_.contains(vk_shader_module)) {
|
||||
return;
|
||||
}
|
||||
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vkDestroyShaderModule(device.device_get(), vk_shader_module, vk_allocation_callbacks);
|
||||
}
|
||||
|
||||
void VKShaderModules::free_data()
|
||||
{
|
||||
debug_print();
|
||||
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
for (VkShaderModule vk_shader_module : cached_values_) {
|
||||
vkDestroyShaderModule(device.device_get(), vk_shader_module, vk_allocation_callbacks);
|
||||
}
|
||||
cache_.clear();
|
||||
cached_values_.clear();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Frontend compilation (GLSL -> SpirV)
|
||||
*
|
||||
* \{ */
|
||||
|
||||
static std::string combine_sources(Span<const char *> sources)
|
||||
{
|
||||
char *sources_combined = BLI_string_join_arrayN((const char **)sources.data(), sources.size());
|
||||
@ -167,7 +204,8 @@ bool VKShaderModules::build_shader_module(const VKShader &shader,
|
||||
void VKShaderModules::debug_print() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "VKShaderModules(glsl_spirv_time=" << stats_.glsl_to_spirv_time << "s"
|
||||
ss << "VKShaderModules(reused_shader_modules=" << stats_.shader_modules_reused
|
||||
<< ", glsl_spirv_time=" << stats_.glsl_to_spirv_time << "s"
|
||||
<< ", spirv_shader_module_time" << stats_.spirv_to_shader_module_time << "s)\n";
|
||||
std::cout << ss.str();
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <BLI_map.hh>
|
||||
|
||||
#include "GPU_shader.hh"
|
||||
|
||||
#include "vk_common.hh"
|
||||
@ -30,9 +32,13 @@ class ShaderCreateInfo;
|
||||
*/
|
||||
class VKShaderModules {
|
||||
private:
|
||||
Map<uint64_t, VkShaderModule> cache_;
|
||||
Set<VkShaderModule> cached_values_;
|
||||
|
||||
struct {
|
||||
double glsl_to_spirv_time = 0.0;
|
||||
double spirv_to_shader_module_time = 0.0;
|
||||
int64_t shader_modules_reused = 0;
|
||||
} stats_;
|
||||
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user