diff --git a/src/Graphics/Material.hpp b/src/Graphics/Material.hpp index 12f4578..825c075 100644 --- a/src/Graphics/Material.hpp +++ b/src/Graphics/Material.hpp @@ -4,6 +4,12 @@ #include namespace Dynamo::Graphics { + /** + * @brief Material handle. + * + */ + DYN_DEFINE_ID_TYPE(Material); + /** * @brief Topology modes. * @@ -38,7 +44,7 @@ namespace Dynamo::Graphics { * @brief Material descriptor. * */ - struct Material { + struct MaterialDescriptor { /** * @brief Vertex shader handle. * @@ -76,7 +82,7 @@ namespace Dynamo::Graphics { * @return true * @return false */ - inline bool operator==(const Material &other) const { + inline bool operator==(const MaterialDescriptor &other) const { return vertex == other.vertex && fragment == other.fragment && topology == other.topology && fill == other.fill && cull == other.cull; } @@ -84,13 +90,13 @@ namespace Dynamo::Graphics { } // namespace Dynamo::Graphics /** - * @brief Hash function implementation for Graphics Material. + * @brief Hash function implementation for Graphics MaterialDescriptor. * * @tparam */ template <> -struct std::hash { - inline size_t operator()(const Dynamo::Graphics::Material &material) const { +struct std::hash { + inline size_t operator()(const Dynamo::Graphics::MaterialDescriptor &material) const { size_t hash0 = std::hash{}(material.vertex); size_t hash1 = std::hash{}(material.fragment); size_t hash2 = std::hash{}(static_cast(material.topology)); diff --git a/src/Graphics/Renderer.cpp b/src/Graphics/Renderer.cpp index 8b8c4fb..77729c7 100644 --- a/src/Graphics/Renderer.cpp +++ b/src/Graphics/Renderer.cpp @@ -110,6 +110,10 @@ namespace Dynamo::Graphics::Vulkan { void Renderer::destroy_shader(Shader shader) { _shaders.destroy(shader); } + Material Renderer::build_material(const MaterialDescriptor &descriptor) { + return _materials.build(descriptor, _swapchain, _shaders); + } + void Renderer::render() { const FrameContext &frame = _frame_contexts.next(); vkWaitForFences(_device, 1, &frame.sync_fence, VK_TRUE, UINT64_MAX); @@ -155,7 +159,7 @@ namespace Dynamo::Graphics::Vulkan { // Iterate over models and draw for (Model model : _models) { - MaterialInstance pipeline_pass = _materials.get(model.material, _swapchain, _shaders); + MaterialInstance pipeline_pass = _materials.get(model.material); FramebufferSettings framebuffer_settings; framebuffer_settings.view = _swapchain.views[image_index]; diff --git a/src/Graphics/Renderer.hpp b/src/Graphics/Renderer.hpp index 5d06eb0..f655739 100644 --- a/src/Graphics/Renderer.hpp +++ b/src/Graphics/Renderer.hpp @@ -116,6 +116,14 @@ namespace Dynamo::Graphics::Vulkan { */ void destroy_shader(Shader shader); + /** + * @brief Build a material. + * + * @param descriptor + * @return Material + */ + Material build_material(const MaterialDescriptor &descriptor); + /** * @brief Draw a model in the current frame. * diff --git a/src/Graphics/Vulkan/MaterialRegistry.cpp b/src/Graphics/Vulkan/MaterialRegistry.cpp index 3957ed6..f95dedf 100644 --- a/src/Graphics/Vulkan/MaterialRegistry.cpp +++ b/src/Graphics/Vulkan/MaterialRegistry.cpp @@ -193,11 +193,12 @@ namespace Dynamo::Graphics::Vulkan { return pipeline; } - MaterialInstance - MaterialRegistry::build(const Material &material, const Swapchain &swapchain, const ShaderSet &shaders) { + Material MaterialRegistry::build(const MaterialDescriptor &descriptor, + const Swapchain &swapchain, + const ShaderSet &shaders) { MaterialInstance instance; - const ShaderModule &vertex_module = shaders.get(material.vertex); - const ShaderModule &fragment_module = shaders.get(material.fragment); + const ShaderModule &vertex_module = shaders.get(descriptor.vertex); + const ShaderModule &fragment_module = shaders.get(descriptor.fragment); // Aggregate descriptor layouts std::vector descriptor_layouts; @@ -251,9 +252,9 @@ namespace Dynamo::Graphics::Vulkan { GraphicsPipelineSettings pipeline_settings; pipeline_settings.vertex = vertex_module; pipeline_settings.fragment = fragment_module; - pipeline_settings.topology = convert_topology(material.topology); - pipeline_settings.cull_mode = convert_cull(material.cull); - pipeline_settings.polygon_mode = convert_fill(material.fill); + pipeline_settings.topology = convert_topology(descriptor.topology); + pipeline_settings.cull_mode = convert_cull(descriptor.cull); + pipeline_settings.polygon_mode = convert_fill(descriptor.fill); pipeline_settings.renderpass = instance.renderpass; pipeline_settings.layout = instance.layout; auto pipeline_it = _pipelines.find(pipeline_settings); @@ -264,22 +265,13 @@ namespace Dynamo::Graphics::Vulkan { _pipelines.emplace(pipeline_settings, instance.pipeline); } - return instance; - } - - MaterialInstance - MaterialRegistry::get(const Material &material, const Swapchain &swapchain, const ShaderSet &shaders) { - // It's expensive to index into pipeline/layout/pass caches every time, so check if dirty before rebuilding - auto instance_it = _instances.find(material); - if (instance_it != _instances.end()) { - return instance_it->second; - } - - MaterialInstance instance = build(material, swapchain, shaders); + Material material = IdGenerator::generate(); _instances.emplace(material, instance); - return instance; + return material; } + MaterialInstance &MaterialRegistry::get(Material material) { return _instances.at(material); } + void MaterialRegistry::destroy() { // Clean up pipelines vkDestroyPipelineCache(_device, _pipeline_cache, nullptr); diff --git a/src/Graphics/Vulkan/MaterialRegistry.hpp b/src/Graphics/Vulkan/MaterialRegistry.hpp index 6acf44e..87769ad 100644 --- a/src/Graphics/Vulkan/MaterialRegistry.hpp +++ b/src/Graphics/Vulkan/MaterialRegistry.hpp @@ -173,29 +173,27 @@ namespace Dynamo::Graphics::Vulkan { */ VkPipeline build_pipeline(const GraphicsPipelineSettings &settings) const; + public: + MaterialRegistry(VkDevice device, const std::string &filename); + MaterialRegistry() = default; + /** - * @brief Build the material instance. + * @brief Build a material and its resources. * - * @param material + * @param descriptor * @param swapchain * @param shaders * @return MaterialInstance */ - MaterialInstance build(const Material &material, const Swapchain &swapchain, const ShaderSet &shaders); - - public: - MaterialRegistry(VkDevice device, const std::string &filename); - MaterialRegistry() = default; + Material build(const MaterialDescriptor &descriptor, const Swapchain &swapchain, const ShaderSet &shaders); /** - * @brief Build a Vulkan material instance. + * @brief Get a material instance. * * @param material - * @param swapchain - * @param shaders - * @return MaterialInstance + * @return MaterialInstance& */ - MaterialInstance get(const Material &material, const Swapchain &swapchain, const ShaderSet &shaders); + MaterialInstance &get(Material material); /** * @brief Destroy all Vulkan resources.