diff --git a/framegen/include/vk/pool/shader_pool.hpp b/framegen/include/vk/pool/shader_pool.hpp new file mode 100644 index 0000000..75c858f --- /dev/null +++ b/framegen/include/vk/pool/shader_pool.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "vk/core/device.hpp" +#include "vk/core/pipeline.hpp" +#include "vk/core/shadermodule.hpp" +#include "vk/registry/shader_registry.hpp" + +#include +#include + +namespace VK::Pool { + + using ShaderInstance = std::pair; + + /// + /// Pool of initialized shader modules and pipelines. + /// + class ShaderPool { + public: + /// + /// Create a shader pool. + /// + ShaderPool() noexcept = default; + + /// + /// Get or create a shader module and pipeline. + /// + /// @param device Vulkan device + /// @param registry Shader registry + /// @param name Name of the shader module + /// @return Pair of shader module and pipeline + /// + /// @throws std::out_of_range if no such shader exists in the registry. + /// @throws VK::vulkan_error if shader module or pipeline creation fails. + /// + [[nodiscard]] const ShaderInstance& getOrCreate( + const Core::Device& device, + const Registry::ShaderRegistry& registry, + const std::string& name); + private: + std::unordered_map shaders; + }; + +} diff --git a/framegen/include/vk/registry/shader_registry.hpp b/framegen/include/vk/registry/shader_registry.hpp new file mode 100644 index 0000000..19f9b19 --- /dev/null +++ b/framegen/include/vk/registry/shader_registry.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace VK::Registry { + + /// Shader module information structure. + struct ShaderModuleInfo { + /// SPIR-V bytecode for the shader module. + std::vector code; + + /// Number of sampled images in the shader. + size_t sampledImages{0}; + /// Number of storage images in the shader. + size_t storageImages{0}; + /// Number of uniform/storage buffers in the shader. + size_t buffers{0}; + /// Number of samplers in the shader. + size_t samplers{0}; + }; + + /// + /// Registry of shader modules and their information. + /// + class ShaderRegistry { + public: + /// + /// Create a shader registry. + /// + ShaderRegistry() noexcept; + + /// + /// Register a shader module. + /// + /// @param name Name of the shader module. + /// @param info Shader module information. + /// + /// @throws std::logic_error if a shader module with the same name already exists. + /// + void registerModule(const std::string& name, const ShaderModuleInfo& info); + + /// + /// Get a shader module by name. + /// + /// @param name Name of the shader module. + /// @return Shader module information. + /// + /// @throws std::out_of_range if no shader module with the given name exists. + /// + [[nodiscard]] const ShaderModuleInfo& getModule(const std::string& name) const; + private: + std::unordered_map modules; + }; + +} diff --git a/framegen/src/vk/pool/shader_pool.cpp b/framegen/src/vk/pool/shader_pool.cpp new file mode 100644 index 0000000..ab0b711 --- /dev/null +++ b/framegen/src/vk/pool/shader_pool.cpp @@ -0,0 +1,27 @@ +#include "vk/pool/shader_pool.hpp" +#include "vk/registry/shader_registry.hpp" +#include "vk/core/shadermodule.hpp" +#include "vk/core/pipeline.hpp" + +using namespace VK::Pool; + +const ShaderInstance& ShaderPool::getOrCreate( + const Core::Device& device, + const Registry::ShaderRegistry& registry, + const std::string& name) { + const auto it = shaders.find(name); + if (it != shaders.end()) { + return it->second; + } + + // create shader module + const Registry::ShaderModuleInfo& info = registry.getModule(name); + + Core::ShaderModule shaderModule(device, info.code, + info.sampledImages, info.storageImages, info.buffers, info.sampledImages); + Core::Pipeline pipeline(device, shaderModule); + + const auto i = shaders.emplace(name, + std::make_pair(std::move(shaderModule), std::move(pipeline))); + return i.first->second; +} diff --git a/framegen/src/vk/registry/shader_registry.cpp b/framegen/src/vk/registry/shader_registry.cpp new file mode 100644 index 0000000..16b7295 --- /dev/null +++ b/framegen/src/vk/registry/shader_registry.cpp @@ -0,0 +1,22 @@ +#include "vk/registry/shader_registry.hpp" + +#include + +using namespace VK::Registry; + +void ShaderRegistry::registerModule(const std::string& name, const ShaderModuleInfo& info) { + if (modules.find(name) != modules.end()) { + throw std::logic_error("Shader module with name '" + name + "' already exists."); + } + + modules[name] = info; +} + +const ShaderModuleInfo& ShaderRegistry::getModule(const std::string& name) const { + auto it = modules.find(name); + if (it == modules.end()) { + throw std::out_of_range("No shader module with name '" + name + "' exists."); + } + + return it->second; +}