From 03048340085dab7ab75e743c6079b038078592f5 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Mon, 21 Oct 2024 01:48:01 +0200 Subject: [PATCH] fixing put pixel, adding scene change checker --- runtime/Includes/Core/Enums.h | 1 - runtime/Includes/Core/Graphics.h | 2 + runtime/Includes/Core/Graphics.inl | 8 +- runtime/Includes/Graphics/Mesh.h | 15 ++ runtime/Includes/Graphics/Scene.h | 11 +- runtime/Includes/Graphics/Sprite.h | 20 ++- runtime/Includes/Renderer/Descriptor.h | 41 ++--- runtime/Includes/Renderer/Enums.h | 7 +- runtime/Includes/Renderer/Image.h | 1 + runtime/Includes/Renderer/Pipelines/Shader.h | 15 +- runtime/Includes/Renderer/RenderCore.h | 7 +- .../Includes/Renderer/RenderPasses/2DPass.h | 2 +- .../Renderer/RenderPasses/FinalPass.h | 2 +- runtime/Includes/Renderer/Renderer.h | 3 - runtime/Includes/Utils/CallOnExit.h | 33 ++++ runtime/Includes/Utils/CallOnExit.inl | 29 ++++ runtime/Sources/Core/Application.cpp | 6 +- runtime/Sources/Core/Graphics.cpp | 13 +- runtime/Sources/Graphics/PutPixelManager.cpp | 8 +- runtime/Sources/Graphics/Scene.cpp | 19 ++- runtime/Sources/Graphics/Sprite.cpp | 9 +- runtime/Sources/Renderer/Descriptor.cpp | 161 +++++++++++------- runtime/Sources/Renderer/Image.cpp | 46 +++-- runtime/Sources/Renderer/Pipelines/Shader.cpp | 1 - runtime/Sources/Renderer/RenderCore.cpp | 5 + .../Sources/Renderer/RenderPasses/2DPass.cpp | 18 +- .../Renderer/RenderPasses/FinalPass.cpp | 7 +- runtime/Sources/Renderer/Renderer.cpp | 13 -- 28 files changed, 302 insertions(+), 201 deletions(-) create mode 100644 runtime/Includes/Utils/CallOnExit.h create mode 100644 runtime/Includes/Utils/CallOnExit.inl diff --git a/runtime/Includes/Core/Enums.h b/runtime/Includes/Core/Enums.h index 7eb6984..ef15390 100644 --- a/runtime/Includes/Core/Enums.h +++ b/runtime/Includes/Core/Enums.h @@ -19,7 +19,6 @@ namespace mlx enum class Event { - DescriptorPoolResetEventCode = 55, ResizeEventCode = 56, FrameBeginEventCode = 57, FatalErrorEventCode = 168, diff --git a/runtime/Includes/Core/Graphics.h b/runtime/Includes/Core/Graphics.h index c2be4c0..6a4e5e6 100644 --- a/runtime/Includes/Core/Graphics.h +++ b/runtime/Includes/Core/Graphics.h @@ -44,6 +44,8 @@ namespace mlx std::shared_ptr p_window; std::unique_ptr p_scene; + std::uint64_t m_draw_layer = 0; + int m_id; bool m_has_window; diff --git a/runtime/Includes/Core/Graphics.inl b/runtime/Includes/Core/Graphics.inl index 2ba4a09..f0db34e 100644 --- a/runtime/Includes/Core/Graphics.inl +++ b/runtime/Includes/Core/Graphics.inl @@ -9,6 +9,7 @@ namespace mlx p_scene->ResetSprites(); m_put_pixel_manager.ResetRenderData(); m_insert_new_pixel_put_texture = true; + m_draw_layer = 0; } void GraphicsSupport::PixelPut(int x, int y, std::uint32_t color) noexcept @@ -19,6 +20,7 @@ namespace mlx { Sprite& new_sprite = p_scene->CreateSprite(texture); new_sprite.SetPosition(Vec2f{ 0.0f, 0.0f }); + m_draw_layer++; } m_insert_new_pixel_put_texture = false; } @@ -42,8 +44,12 @@ namespace mlx new_sprite.SetPosition(Vec2f{ static_cast(x), static_cast(y) }); m_insert_new_pixel_put_texture = true; } - else + else if(!p_scene->IsTextureAtGivenDrawLayer(texture, m_draw_layer)) + { p_scene->BringToFront(std::move(sprite)); + m_insert_new_pixel_put_texture = true; + } + m_draw_layer++; } void GraphicsSupport::LoadFont(const std::filesystem::path& filepath, float scale) diff --git a/runtime/Includes/Graphics/Mesh.h b/runtime/Includes/Graphics/Mesh.h index 215736b..fc55023 100644 --- a/runtime/Includes/Graphics/Mesh.h +++ b/runtime/Includes/Graphics/Mesh.h @@ -48,6 +48,21 @@ namespace mlx private: std::vector m_sub_meshes; }; + + class MeshRegistry + { + public: + MeshRegistry() = default; + + inline void RegisterMesh(std::shared_ptr mesh); + inline void UnregisterMesh(std::shared_ptr mesh); + inline bool IsMeshKnown(std::shared_ptr mesh); + + ~MeshRegistry() = default; + + private: + std::unordered_set> m_mesh_registry; + }; } #endif diff --git a/runtime/Includes/Graphics/Scene.h b/runtime/Includes/Graphics/Scene.h index 4c7f6a7..05a0bc0 100644 --- a/runtime/Includes/Graphics/Scene.h +++ b/runtime/Includes/Graphics/Scene.h @@ -7,32 +7,25 @@ namespace mlx { - struct SceneDescriptor - { - NonOwningPtr renderer; - // More description may come in future - }; - class Scene { public: - Scene(SceneDescriptor desc); + Scene() = default; Sprite& CreateSprite(NonOwningPtr texture) noexcept; NonOwningPtr GetSpriteFromTextureAndPosition(NonOwningPtr texture, const Vec2f& position) const; void BringToFront(NonOwningPtr sprite); void TryEraseSpriteFromTexture(NonOwningPtr texture); + bool IsTextureAtGivenDrawLayer(NonOwningPtr texture, std::uint64_t draw_layer) const; inline void ResetSprites() { m_sprites.clear(); } [[nodiscard]] MLX_FORCEINLINE const std::vector>& GetSprites() const noexcept { return m_sprites; } - [[nodiscard]] MLX_FORCEINLINE const SceneDescriptor& GetDescription() const noexcept { return m_descriptor; } [[nodiscard]] MLX_FORCEINLINE ViewerData& GetViewerData() noexcept { return m_viewer_data; } ~Scene() = default; private: - SceneDescriptor m_descriptor; std::vector> m_sprites; ViewerData m_viewer_data; }; diff --git a/runtime/Includes/Graphics/Sprite.h b/runtime/Includes/Graphics/Sprite.h index 757e30d..8efcf8d 100644 --- a/runtime/Includes/Graphics/Sprite.h +++ b/runtime/Includes/Graphics/Sprite.h @@ -14,7 +14,7 @@ namespace mlx friend class Render2DPass; public: - Sprite(class Renderer& renderer, NonOwningPtr texture); + Sprite(NonOwningPtr texture); inline void SetColor(Vec4f color) noexcept { m_color = color; } inline void SetPosition(Vec2f position) noexcept { m_position = position; } @@ -24,25 +24,27 @@ namespace mlx [[nodiscard]] MLX_FORCEINLINE std::shared_ptr GetMesh() const { return p_mesh; } [[nodiscard]] MLX_FORCEINLINE NonOwningPtr GetTexture() const { return p_texture; } - ~Sprite() = default; + inline ~Sprite() { if(p_set) p_set->ReturnDescriptorSetToPool(); } private: - [[nodiscard]] inline bool IsSetInit() const noexcept { return m_set.IsInit(); } - [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return m_set.GetSet(frame_index); } + [[nodiscard]] inline bool IsSetInit() const noexcept { return p_set && p_set->IsInit(); } + [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return p_set ? p_set->GetSet(frame_index) : VK_NULL_HANDLE; } - inline void UpdateDescriptorSet(const DescriptorSet& set) + inline void UpdateDescriptorSet(std::shared_ptr set) { - m_set = set.Duplicate(); + p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(set->GetShaderLayout(), set->GetShaderType()); } inline void Bind(std::size_t frame_index, VkCommandBuffer cmd) { - m_set.SetImage(frame_index, 0, *p_texture); - m_set.Update(frame_index, cmd); + if(!p_set) + return; + p_set->SetImage(frame_index, 0, *p_texture); + p_set->Update(frame_index, cmd); } private: - DescriptorSet m_set; + std::shared_ptr p_set; NonOwningPtr p_texture; std::shared_ptr p_mesh; Vec4f m_color = Vec4f{ 1.0f, 1.0f, 1.0f, 1.0f }; diff --git a/runtime/Includes/Renderer/Descriptor.h b/runtime/Includes/Renderer/Descriptor.h index 8689d3f..0a3b9e9 100644 --- a/runtime/Includes/Renderer/Descriptor.h +++ b/runtime/Includes/Renderer/Descriptor.h @@ -13,7 +13,6 @@ namespace mlx NonOwningPtr uniform_buffer_ptr; NonOwningPtr image_ptr; VkDescriptorType type; - ShaderType shader_type; std::uint32_t binding; }; @@ -25,17 +24,18 @@ namespace mlx void Init() noexcept; void Destroy() noexcept; - VkDescriptorSet AllocateDescriptorSet(std::uint32_t frame_index, VkDescriptorSetLayout layout); + std::shared_ptr RequestDescriptorSet(const ShaderSetLayout& layout, ShaderType shader_type); + void ReturnDescriptorSet(std::shared_ptr set); - void ResetPoolFromFrameIndex(std::size_t frame_index); - - [[nodiscard]] inline VkDescriptorPool Get(std::uint32_t index) const noexcept { return m_pools[index]; } + [[nodiscard]] inline VkDescriptorPool Get() const noexcept { return m_pool; } [[nodiscard]] MLX_FORCEINLINE std::size_t GetNumberOfSetsAllocated() const noexcept { return m_allocation_count; } ~DescriptorPool() = default; private: - std::array m_pools; + std::vector> m_free_sets; + std::vector> m_used_sets; + VkDescriptorPool m_pool; std::size_t m_allocation_count = 0; }; @@ -44,42 +44,45 @@ namespace mlx public: DescriptorPoolManager() = default; - void ResetPoolsFromFrameIndex(std::size_t frame_index); DescriptorPool& GetAvailablePool(); void Destroy(); ~DescriptorPoolManager() = default; private: - std::list m_pools; + std::vector m_pools; }; - class DescriptorSet + class DescriptorSet : public std::enable_shared_from_this { - public: - DescriptorSet() { m_set.fill(VK_NULL_HANDLE); } - DescriptorSet(DescriptorPoolManager& pools_manager, const ShaderSetLayout& layout, VkDescriptorSetLayout vklayout, ShaderType shader_type); + friend DescriptorPool; + public: void SetImage(std::size_t i, std::uint32_t binding, class Image& image); void SetStorageBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer); void SetUniformBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer); void Update(std::size_t i, VkCommandBuffer cmd = VK_NULL_HANDLE) noexcept; - void Reallocate(std::size_t frame_index) noexcept; - [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t i) const noexcept { return m_set[i]; } - [[nodiscard]] inline DescriptorSet Duplicate() const { return DescriptorSet{ *p_pools_manager, m_set_layout, m_descriptors }; } - [[nodiscard]] inline bool IsInit() const noexcept { return m_set[0] != VK_NULL_HANDLE; } + void ReturnDescriptorSetToPool(); + + [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t i) const noexcept { return m_sets[i]; } + [[nodiscard]] MLX_FORCEINLINE bool IsInit() const noexcept { return m_sets[0] != VK_NULL_HANDLE; } + [[nodiscard]] MLX_FORCEINLINE VkDescriptorSetLayout GetVulkanLayout() const noexcept { return m_set_layout; } + [[nodiscard]] MLX_FORCEINLINE const ShaderSetLayout& GetShaderLayout() const { return m_shader_layout; } + [[nodiscard]] MLX_FORCEINLINE ShaderType GetShaderType() const noexcept { return m_shader_type; } ~DescriptorSet() = default; private: - DescriptorSet(DescriptorPoolManager& pools_manager, VkDescriptorSetLayout layout, const std::vector& descriptors); + DescriptorSet(DescriptorPool& pool, VkDescriptorSetLayout vulkan_layout, const ShaderSetLayout& layout, std::array vulkan_sets, ShaderType shader_type); private: + ShaderSetLayout m_shader_layout; std::vector m_descriptors; - std::array m_set; + std::array m_sets; VkDescriptorSetLayout m_set_layout; - NonOwningPtr p_pools_manager; + ShaderType m_shader_type; + DescriptorPool& m_pool; }; } diff --git a/runtime/Includes/Renderer/Enums.h b/runtime/Includes/Renderer/Enums.h index ddc0487..80431a1 100644 --- a/runtime/Includes/Renderer/Enums.h +++ b/runtime/Includes/Renderer/Enums.h @@ -17,11 +17,16 @@ namespace mlx enum class ImageType { Color = 0, - Depth, EndEnum }; constexpr std::size_t ImageTypeCount = static_cast(ImageType::EndEnum); + + enum class ShaderType + { + Vertex, + Fragment + }; } #endif diff --git a/runtime/Includes/Renderer/Image.h b/runtime/Includes/Renderer/Image.h index c857089..d787e9f 100644 --- a/runtime/Includes/Renderer/Image.h +++ b/runtime/Includes/Renderer/Image.h @@ -77,6 +77,7 @@ namespace mlx } void Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format, bool is_multisampled, [[maybe_unused]] std::string_view debug_name); + void Destroy() noexcept override; void SetPixel(int x, int y, std::uint32_t color) noexcept; int GetPixel(int x, int y) noexcept; diff --git a/runtime/Includes/Renderer/Pipelines/Shader.h b/runtime/Includes/Renderer/Pipelines/Shader.h index d1c59db..54cbc7d 100644 --- a/runtime/Includes/Renderer/Pipelines/Shader.h +++ b/runtime/Includes/Renderer/Pipelines/Shader.h @@ -1,13 +1,17 @@ #ifndef __MLX_SHADER__ #define __MLX_SHADER__ +#include + namespace mlx { struct ShaderSetLayout { - std::vector > binds; + std::vector> binds; ShaderSetLayout(std::vector > b) : binds(std::move(b)) {} + + inline bool operator==(const ShaderSetLayout& rhs) const { return binds == rhs.binds; } }; struct ShaderPushConstantLayout @@ -20,19 +24,12 @@ namespace mlx struct ShaderLayout { - std::vector > set_layouts; + std::vector> set_layouts; std::vector push_constants; ShaderLayout(std::vector > s, std::vector pc) : set_layouts(std::move(s)), push_constants(std::move(pc)) {} }; - enum class ShaderType - { - Vertex, - Fragment, - Compute - }; - struct ShaderPipelineLayoutPart { std::vector push_constants; diff --git a/runtime/Includes/Renderer/RenderCore.h b/runtime/Includes/Renderer/RenderCore.h index 97f764a..9f139c6 100644 --- a/runtime/Includes/Renderer/RenderCore.h +++ b/runtime/Includes/Renderer/RenderCore.h @@ -1,12 +1,13 @@ #ifndef __MLX_RENDER_CORE__ #define __MLX_RENDER_CORE__ +constexpr const int MAX_FRAMES_IN_FLIGHT = 3; + #include +#include namespace mlx { - constexpr const int MAX_FRAMES_IN_FLIGHT = 3; - #if defined(DEBUG) && defined(VK_EXT_debug_utils) #define MLX_HAS_DEBUG_UTILS_FUNCTIONS #endif @@ -21,6 +22,7 @@ namespace mlx [[nodiscard]] MLX_FORCEINLINE VkDevice GetDevice() const noexcept { return m_device; } [[nodiscard]] MLX_FORCEINLINE VkPhysicalDevice GetPhysicalDevice() const noexcept { return m_physical_device; } [[nodiscard]] MLX_FORCEINLINE GPUAllocator& GetAllocator() noexcept { return m_allocator; } + [[nodiscard]] inline DescriptorPoolManager& GetDescriptorPoolManager() noexcept { return m_descriptor_pool_manager; } inline void WaitDeviceIdle() const noexcept { vkDeviceWaitIdle(m_device); } @@ -45,6 +47,7 @@ namespace mlx private: static RenderCore* s_instance; + DescriptorPoolManager m_descriptor_pool_manager; GPUAllocator m_allocator; VkInstance m_instance = VK_NULL_HANDLE; VkDevice m_device = VK_NULL_HANDLE; diff --git a/runtime/Includes/Renderer/RenderPasses/2DPass.h b/runtime/Includes/Renderer/RenderPasses/2DPass.h index dc78aeb..8486818 100644 --- a/runtime/Includes/Renderer/RenderPasses/2DPass.h +++ b/runtime/Includes/Renderer/RenderPasses/2DPass.h @@ -1,7 +1,7 @@ #ifndef __MLX_2D_PASS__ #define __MLX_2D_PASS__ -#include +#include #include #include diff --git a/runtime/Includes/Renderer/RenderPasses/FinalPass.h b/runtime/Includes/Renderer/RenderPasses/FinalPass.h index fe5571c..e1baa1f 100644 --- a/runtime/Includes/Renderer/RenderPasses/FinalPass.h +++ b/runtime/Includes/Renderer/RenderPasses/FinalPass.h @@ -1,7 +1,7 @@ #ifndef __MLX_FINAL_PASS__ #define __MLX_FINAL_PASS__ -#include +#include #include #include diff --git a/runtime/Includes/Renderer/Renderer.h b/runtime/Includes/Renderer/Renderer.h index 1bcba3a..a2df8cd 100644 --- a/runtime/Includes/Renderer/Renderer.h +++ b/runtime/Includes/Renderer/Renderer.h @@ -5,7 +5,6 @@ #include #include #include -#include #include namespace mlx @@ -32,7 +31,6 @@ namespace mlx [[nodiscard]] inline std::size_t GetSwapchainImageIndex() const noexcept { return m_swapchain_image_index; } [[nodiscard]] inline std::size_t GetCurrentFrameIndex() const noexcept { return m_current_frame_index; } [[nodiscard]] inline NonOwningPtr GetWindow() const noexcept { return p_window; } - [[nodiscard]] inline DescriptorPoolManager& GetDescriptorPoolManager() noexcept { return m_descriptor_pool_manager; } MLX_FORCEINLINE constexpr void RequireFramebufferResize() noexcept { m_framebuffers_resize = true; } @@ -45,7 +43,6 @@ namespace mlx void DestroySwapchain(); private: - DescriptorPoolManager m_descriptor_pool_manager; std::array m_image_available_semaphores; std::array m_render_finished_semaphores; std::array m_cmd_buffers; diff --git a/runtime/Includes/Utils/CallOnExit.h b/runtime/Includes/Utils/CallOnExit.h new file mode 100644 index 0000000..5e86f5d --- /dev/null +++ b/runtime/Includes/Utils/CallOnExit.h @@ -0,0 +1,33 @@ +#ifndef __MLX_CALL_ON_EXIT__ +#define __MLX_CALL_ON_EXIT__ + +namespace mlx +{ + template + class CallOnExit + { + public: + CallOnExit() = default; + CallOnExit(F&& functor); + CallOnExit(const CallOnExit&) = delete; + CallOnExit(CallOnExit&&) = delete; + + void CallAndReset(); + void Reset(); + + CallOnExit& operator=(const CallOnExit&) = delete; + CallOnExit& operator=(CallOnExit&&) = default; + + ~CallOnExit(); + + private: + std::optional m_functor; + }; + + template + CallOnExit(F) -> CallOnExit; +} + +#include + +#endif diff --git a/runtime/Includes/Utils/CallOnExit.inl b/runtime/Includes/Utils/CallOnExit.inl new file mode 100644 index 0000000..69fa3ab --- /dev/null +++ b/runtime/Includes/Utils/CallOnExit.inl @@ -0,0 +1,29 @@ +#pragma once +#include + +namespace mlx +{ + template + CallOnExit::CallOnExit(F&& functor) : m_functor(std::move(functor)) {} + + template + CallOnExit::~CallOnExit() + { + if(m_functor.has_value()) + (*m_functor)(); + } + + template + void CallOnExit::CallAndReset() + { + if(m_functor.has_value()) + (*m_functor)(); + m_functor.reset(); + } + + template + void CallOnExit::Reset() + { + m_functor.reset(); + } +} diff --git a/runtime/Sources/Core/Application.cpp b/runtime/Sources/Core/Application.cpp index 5b7c18b..03f5cb2 100644 --- a/runtime/Sources/Core/Application.cpp +++ b/runtime/Sources/Core/Application.cpp @@ -10,7 +10,7 @@ namespace mlx { Application::Application() : p_mem_manager(std::make_unique()), p_sdl_manager(std::make_unique()), m_fps(), m_in() { - EventBus::RegisterListener({[](const EventBase& event) + EventBus::RegisterListener({ [](const EventBase& event) { if(event.What() == Event::FatalErrorEventCode) std::abort(); @@ -53,7 +53,7 @@ namespace mlx MLX_PROFILE_FUNCTION(); Texture* texture; try { texture = new Texture({}, w, h, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_user_image"); } - catch(...) { return NULL; } + catch(...) { return nullptr; } m_image_registry.RegisterTexture(texture); return texture; } @@ -63,7 +63,7 @@ namespace mlx MLX_PROFILE_FUNCTION(); Texture* texture = StbTextureLoad(file, w, h); if(texture == nullptr) - return NULL; // NULL for C compatibility + return nullptr; m_image_registry.RegisterTexture(texture); return texture; } diff --git a/runtime/Sources/Core/Graphics.cpp b/runtime/Sources/Core/Graphics.cpp index 184831b..bd6149f 100644 --- a/runtime/Sources/Core/Graphics.cpp +++ b/runtime/Sources/Core/Graphics.cpp @@ -13,10 +13,7 @@ namespace mlx // TODO : re-enable render targets m_renderer.Init(nullptr); m_scene_renderer.Init(m_renderer); - - SceneDescriptor descriptor{}; - descriptor.renderer = &m_renderer; - p_scene = std::make_unique(std::move(descriptor)); + p_scene = std::make_unique(); } GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id) : @@ -28,10 +25,7 @@ namespace mlx MLX_PROFILE_FUNCTION(); m_renderer.Init(p_window.get()); m_scene_renderer.Init(m_renderer); - - SceneDescriptor descriptor{}; - descriptor.renderer = &m_renderer; - p_scene = std::make_unique(std::move(descriptor)); + p_scene = std::make_unique(); } void GraphicsSupport::Render() noexcept @@ -39,6 +33,7 @@ namespace mlx MLX_PROFILE_FUNCTION(); if(m_renderer.BeginFrame()) { + m_draw_layer = 0; m_scene_renderer.Render(*p_scene, m_renderer); m_renderer.EndFrame(); } @@ -47,7 +42,7 @@ namespace mlx // dump memory to file every two seconds using namespace std::chrono_literals; static std::int64_t timer = static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); - if(std::chrono::duration{static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()) - timer} >= 1s) + if(std::chrono::duration{ static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()) - timer } >= 1s) { RenderCore::Get().GetAllocator().DumpMemoryToJson(); timer = static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); diff --git a/runtime/Sources/Graphics/PutPixelManager.cpp b/runtime/Sources/Graphics/PutPixelManager.cpp index 929e504..b41e047 100644 --- a/runtime/Sources/Graphics/PutPixelManager.cpp +++ b/runtime/Sources/Graphics/PutPixelManager.cpp @@ -19,8 +19,12 @@ namespace mlx #endif texture.Clear(VK_NULL_HANDLE, Vec4f{ 0.0f }); } - m_textures.back().SetPixel(x, y, color); - return (insert_new_texture ? &m_textures.back() : nullptr); + if(!m_textures.empty()) + { + m_textures.back().SetPixel(x, y, color); + return (insert_new_texture ? &m_textures.back() : nullptr); + } + return nullptr; } void PutPixelManager::ResetRenderData() diff --git a/runtime/Sources/Graphics/Scene.cpp b/runtime/Sources/Graphics/Scene.cpp index e1bf59b..1a76ec6 100644 --- a/runtime/Sources/Graphics/Scene.cpp +++ b/runtime/Sources/Graphics/Scene.cpp @@ -5,17 +5,10 @@ namespace mlx { - Scene::Scene(SceneDescriptor desc) - : m_descriptor(std::move(desc)) - { - MLX_PROFILE_FUNCTION(); - Verify((bool)m_descriptor.renderer, "invalid renderer"); - } - Sprite& Scene::CreateSprite(NonOwningPtr texture) noexcept { MLX_PROFILE_FUNCTION(); - std::shared_ptr sprite = std::make_shared(*m_descriptor.renderer, texture); + std::shared_ptr sprite = std::make_shared(texture); m_sprites.push_back(sprite); return *sprite; } @@ -52,7 +45,15 @@ namespace mlx { return sprite->GetTexture() == texture; }); - m_sprites.erase(it); + if(it != m_sprites.end()) + m_sprites.erase(it); } while(it != m_sprites.end()); } + + bool Scene::IsTextureAtGivenDrawLayer(NonOwningPtr texture, std::uint64_t draw_layer) const + { + if(draw_layer >= m_sprites.size()) + return false; + return m_sprites[draw_layer]->GetTexture() == texture; + } } diff --git a/runtime/Sources/Graphics/Sprite.cpp b/runtime/Sources/Graphics/Sprite.cpp index a30df18..e9fd03f 100644 --- a/runtime/Sources/Graphics/Sprite.cpp +++ b/runtime/Sources/Graphics/Sprite.cpp @@ -37,18 +37,11 @@ namespace mlx return mesh; } - Sprite::Sprite(Renderer& renderer, NonOwningPtr texture) + Sprite::Sprite(NonOwningPtr texture) { MLX_PROFILE_FUNCTION(); Verify((bool)texture, "Sprite: invalid texture (internal mlx issue, please report to devs)"); p_mesh = CreateQuad(0, 0, texture->GetWidth(), texture->GetHeight()); p_texture = texture; - - func::function functor = [this, &renderer](const EventBase& event) - { - if(event.What() == Event::DescriptorPoolResetEventCode) - m_set.Reallocate(renderer.GetCurrentFrameIndex()); - }; - EventBus::RegisterListener({ functor, "__MlxSprite" + std::to_string(reinterpret_cast(this)) }); } } diff --git a/runtime/Sources/Renderer/Descriptor.cpp b/runtime/Sources/Renderer/Descriptor.cpp index 96e8b57..4349fd9 100644 --- a/runtime/Sources/Renderer/Descriptor.cpp +++ b/runtime/Sources/Renderer/Descriptor.cpp @@ -24,6 +24,7 @@ namespace mlx void DescriptorPool::Init() noexcept { + MLX_PROFILE_FUNCTION(); VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, MAX_SETS_PER_POOL }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_SETS_PER_POOL }, @@ -38,99 +39,143 @@ namespace mlx { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, MAX_SETS_PER_POOL } }; - VkDescriptorPoolCreateInfo poolInfo{}; - poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.poolSizeCount = sizeof(pool_sizes) / sizeof(pool_sizes[0]); - poolInfo.pPoolSizes = pool_sizes; - poolInfo.maxSets = MAX_SETS_PER_POOL; - poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - kvfCheckVk(RenderCore::Get().vkCreateDescriptorPool(RenderCore::Get().GetDevice(), &poolInfo, nullptr, &m_pools[i])); + VkDescriptorPoolCreateInfo pool_info{}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.poolSizeCount = sizeof(pool_sizes) / sizeof(pool_sizes[0]); + pool_info.pPoolSizes = pool_sizes; + pool_info.maxSets = MAX_SETS_PER_POOL; + pool_info.flags = 0; + kvfCheckVk(RenderCore::Get().vkCreateDescriptorPool(RenderCore::Get().GetDevice(), &pool_info, nullptr, &m_pool)); m_allocation_count = 0; } void DescriptorPool::Destroy() noexcept { - for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - { - if(m_pools[i] == VK_NULL_HANDLE) - continue; - RenderCore::Get().vkDestroyDescriptorPool(RenderCore::Get().GetDevice(), m_pools[i], nullptr); - m_pools[i] = VK_NULL_HANDLE; - } + MLX_PROFILE_FUNCTION(); + if(m_pool == VK_NULL_HANDLE) + return; + for(auto& set : m_free_sets) + kvfDestroyDescriptorSetLayout(RenderCore::Get().GetDevice(), set->m_set_layout); + for(auto& set : m_used_sets) + kvfDestroyDescriptorSetLayout(RenderCore::Get().GetDevice(), set->m_set_layout); + RenderCore::Get().vkDestroyDescriptorPool(RenderCore::Get().GetDevice(), m_pool, nullptr); + m_pool = VK_NULL_HANDLE; m_allocation_count = 0; + m_free_sets.clear(); + m_used_sets.clear(); } - VkDescriptorSet DescriptorPool::AllocateDescriptorSet(std::uint32_t frame_index, VkDescriptorSetLayout layout) + std::shared_ptr DescriptorPool::RequestDescriptorSet(const ShaderSetLayout& layout, ShaderType shader_type) { - VkDescriptorSet set; - VkDescriptorSetAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorPool = m_pools[frame_index]; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &layout; - kvfCheckVk(RenderCore::Get().vkAllocateDescriptorSets(RenderCore::Get().GetDevice(), &alloc_info, &set)); - m_allocation_count++; + MLX_PROFILE_FUNCTION(); + auto it = std::find_if(m_free_sets.begin(), m_free_sets.end(), [&](std::shared_ptr set) + { + return shader_type == set->GetShaderType() && layout == set->GetShaderLayout(); + }); + if(it != m_free_sets.end()) + { + std::shared_ptr set = *it; + m_free_sets.erase(it); + m_used_sets.push_back(set); + return set; + } + + std::array vulkan_sets; + + VkShaderStageFlagBits vulkan_shader_stage; + switch(shader_type) + { + case ShaderType::Vertex: vulkan_shader_stage = VK_SHADER_STAGE_VERTEX_BIT; break; + case ShaderType::Fragment: vulkan_shader_stage = VK_SHADER_STAGE_FRAGMENT_BIT; break; + + default : FatalError("wtf"); break; + } + + std::vector bindings(layout.binds.size()); + for(std::size_t i = 0; i < layout.binds.size(); i++) + { + bindings[i].binding = layout.binds[i].first; + bindings[i].descriptorCount = 1; + bindings[i].descriptorType = layout.binds[i].second; + bindings[i].pImmutableSamplers = nullptr; + bindings[i].stageFlags = vulkan_shader_stage; + } + VkDescriptorSetLayout vulkan_layout = kvfCreateDescriptorSetLayout(RenderCore::Get().GetDevice(), bindings.data(), bindings.size()); + + for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = m_pool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &vulkan_layout; + VkDescriptorSet vulkan_set; + kvfCheckVk(RenderCore::Get().vkAllocateDescriptorSets(RenderCore::Get().GetDevice(), &alloc_info, &vulkan_set)); + m_allocation_count++; + vulkan_sets[i] = vulkan_set; + } + + std::shared_ptr set(new DescriptorSet(*this, vulkan_layout, layout, std::move(vulkan_sets), shader_type)); + m_used_sets.push_back(set); return set; } - void DescriptorPool::ResetPoolFromFrameIndex(std::size_t frame_index) + void DescriptorPool::ReturnDescriptorSet(std::shared_ptr set) { - Assert(frame_index < MAX_FRAMES_IN_FLIGHT, "invalid frame index"); - RenderCore::Get().vkResetDescriptorPool(RenderCore::Get().GetDevice(), m_pools[frame_index], 0); - } - - void DescriptorPoolManager::ResetPoolsFromFrameIndex(std::size_t frame_index) - { - for(auto& pool : m_pools) - pool.ResetPoolFromFrameIndex(frame_index); + auto it = std::find_if(m_used_sets.begin(), m_used_sets.end(), [&](std::shared_ptr rhs_set) + { + return set == rhs_set; + }); + if(it == m_used_sets.end()) + { + Error("Vulkan : cannot return descriptor set to pool, invalid pool"); + return; + } + m_used_sets.erase(it); + m_free_sets.push_back(set); } DescriptorPool& DescriptorPoolManager::GetAvailablePool() { + MLX_PROFILE_FUNCTION(); for(auto& pool : m_pools) { if(pool.GetNumberOfSetsAllocated() < MAX_SETS_PER_POOL) return pool; } - m_pools.emplace_front().Init(); - return m_pools.front(); + m_pools.emplace_back().Init(); + return m_pools.back(); } void DescriptorPoolManager::Destroy() { + MLX_PROFILE_FUNCTION(); #pragma omp parallel for for(auto& pool : m_pools) pool.Destroy(); + m_pools.clear(); } - DescriptorSet::DescriptorSet(DescriptorPoolManager& pools_manager, const ShaderSetLayout& layout, VkDescriptorSetLayout vklayout, ShaderType shader_type) - : m_set_layout(vklayout), p_pools_manager(&pools_manager) + DescriptorSet::DescriptorSet(DescriptorPool& pool, VkDescriptorSetLayout vulkan_layout, const ShaderSetLayout& layout, std::array vulkan_sets, ShaderType shader_type) : + m_shader_layout(layout), + m_sets(std::move(vulkan_sets)), + m_set_layout(vulkan_layout), + m_shader_type(shader_type), + m_pool(pool) { MLX_PROFILE_FUNCTION(); for(auto& [binding, type] : layout.binds) { m_descriptors.emplace_back(); m_descriptors.back().type = type; - m_descriptors.back().shader_type = shader_type; m_descriptors.back().binding = binding; } - for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - m_set[i] = p_pools_manager->GetAvailablePool().AllocateDescriptorSet(i, vklayout); - } - - DescriptorSet::DescriptorSet(DescriptorPoolManager& pools_manager, VkDescriptorSetLayout layout, const std::vector& descriptors) - : m_descriptors(descriptors), m_set_layout(layout), p_pools_manager(&pools_manager) - { - MLX_PROFILE_FUNCTION(); - for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - m_set[i] = p_pools_manager->GetAvailablePool().AllocateDescriptorSet(i, layout); } void DescriptorSet::SetImage(std::size_t i, std::uint32_t binding, class Image& image) { MLX_PROFILE_FUNCTION(); - Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor"); + Verify(m_sets[i] != VK_NULL_HANDLE, "invalid descriptor"); auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor) { return binding == descriptor.binding; @@ -151,7 +196,7 @@ namespace mlx void DescriptorSet::SetStorageBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer) { MLX_PROFILE_FUNCTION(); - Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor"); + Verify(m_sets[i] != VK_NULL_HANDLE, "invalid descriptor"); auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor) { return binding == descriptor.binding; @@ -172,7 +217,7 @@ namespace mlx void DescriptorSet::SetUniformBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer) { MLX_PROFILE_FUNCTION(); - Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor"); + Verify(m_sets[i] != VK_NULL_HANDLE, "invalid descriptor"); auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor) { return binding == descriptor.binding; @@ -193,7 +238,7 @@ namespace mlx void DescriptorSet::Update(std::size_t i, VkCommandBuffer cmd) noexcept { MLX_PROFILE_FUNCTION(); - Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor"); + Verify(m_sets[i] != VK_NULL_HANDLE, "invalid descriptor"); std::vector writes; std::vector buffer_infos; std::vector image_infos; @@ -207,7 +252,7 @@ namespace mlx info.imageLayout = descriptor.image_ptr->GetLayout(); info.imageView = descriptor.image_ptr->GetImageView(); image_infos.push_back(info); - writes.push_back(kvfWriteImageToDescriptorSet(RenderCore::Get().GetDevice(), m_set[i], &image_infos.back(), descriptor.binding)); + writes.push_back(kvfWriteImageToDescriptorSet(RenderCore::Get().GetDevice(), m_sets[i], &image_infos.back(), descriptor.binding)); } else if(descriptor.uniform_buffer_ptr) { @@ -216,7 +261,7 @@ namespace mlx info.offset = descriptor.uniform_buffer_ptr->GetOffset(); info.range = VK_WHOLE_SIZE; buffer_infos.push_back(info); - writes.push_back(kvfWriteUniformBufferToDescriptorSet(RenderCore::Get().GetDevice(), m_set[i], &buffer_infos.back(), descriptor.binding)); + writes.push_back(kvfWriteUniformBufferToDescriptorSet(RenderCore::Get().GetDevice(), m_sets[i], &buffer_infos.back(), descriptor.binding)); } else if(descriptor.storage_buffer_ptr) { @@ -225,16 +270,14 @@ namespace mlx info.offset = descriptor.storage_buffer_ptr->GetOffset(); info.range = VK_WHOLE_SIZE; buffer_infos.push_back(info); - writes.push_back(kvfWriteStorageBufferToDescriptorSet(RenderCore::Get().GetDevice(), m_set[i], &buffer_infos.back(), descriptor.binding)); + writes.push_back(kvfWriteStorageBufferToDescriptorSet(RenderCore::Get().GetDevice(), m_sets[i], &buffer_infos.back(), descriptor.binding)); } } RenderCore::Get().vkUpdateDescriptorSets(RenderCore::Get().GetDevice(), writes.size(), writes.data(), 0, nullptr); } - void DescriptorSet::Reallocate(std::size_t frame_index) noexcept + void DescriptorSet::ReturnDescriptorSetToPool() { - MLX_PROFILE_FUNCTION(); - Assert(!p_pools_manager, "invalid pools manager"); - m_set[frame_index] = p_pools_manager->GetAvailablePool().AllocateDescriptorSet(frame_index, m_set_layout); + m_pool.ReturnDescriptorSet(shared_from_this()); } } diff --git a/runtime/Sources/Renderer/Image.cpp b/runtime/Sources/Renderer/Image.cpp index 9b8a0b7..ab4c58b 100644 --- a/runtime/Sources/Renderer/Image.cpp +++ b/runtime/Sources/Renderer/Image.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #define STB_IMAGE_IMPLEMENTATION #ifdef MLX_COMPILER_GCC @@ -80,14 +81,7 @@ namespace mlx bool is_single_time_cmd_buffer = (cmd == VK_NULL_HANDLE); if(is_single_time_cmd_buffer) cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice()); - KvfImageType kvf_type = KVF_IMAGE_OTHER; - switch(m_type) - { - case ImageType::Color: kvf_type = KVF_IMAGE_COLOR; break; - case ImageType::Depth: kvf_type = KVF_IMAGE_DEPTH; break; - default: break; - } - kvfTransitionImageLayout(RenderCore::Get().GetDevice(), m_image, kvf_type, cmd, m_format, m_layout, new_layout, is_single_time_cmd_buffer); + kvfTransitionImageLayout(RenderCore::Get().GetDevice(), m_image, KVF_IMAGE_COLOR, cmd, m_format, m_layout, new_layout, is_single_time_cmd_buffer); m_layout = new_layout; } @@ -109,18 +103,9 @@ namespace mlx VkImageLayout old_layout = m_layout; TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, cmd); - if(m_type == ImageType::Color) - { - subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - VkClearColorValue clear_color = VkClearColorValue({ { color.x, color.y, color.z, color.w } }); - RenderCore::Get().vkCmdClearColorImage(cmd, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); - } - else if(m_type == ImageType::Depth) - { - VkClearDepthStencilValue clear_depth_stencil = { 1.0f, 1 }; - subresource_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - RenderCore::Get().vkCmdClearDepthStencilImage(cmd, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_depth_stencil, 1, &subresource_range); - } + subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + VkClearColorValue clear_color = VkClearColorValue({ { color.x, color.y, color.z, color.w } }); + RenderCore::Get().vkCmdClearColorImage(cmd, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &subresource_range); TransitionLayout(old_layout, cmd); if(is_single_time_cmd_buffer) @@ -189,6 +174,13 @@ namespace mlx TransitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } + void Texture::Destroy() noexcept + { + if(m_staging_buffer.has_value()) + m_staging_buffer->Destroy(); + Image::Destroy(); + } + void Texture::SetPixel(int x, int y, std::uint32_t color) noexcept { MLX_PROFILE_FUNCTION(); @@ -266,6 +258,9 @@ namespace mlx MLX_PROFILE_FUNCTION(); std::string filename = file.string(); + if(file.stem() == "banana") + Message("banana, banana, banana, banana, terracotta banana terracotta, terracotta pie"); + if(!std::filesystem::exists(file)) { Error("Image : file not found %", file); @@ -280,14 +275,15 @@ namespace mlx int dummy_h; int channels; std::uint8_t* data = stbi_load(filename.c_str(), (w == nullptr ? &dummy_w : w), (h == nullptr ? &dummy_h : h), &channels, 4); + + CallOnExit defer([=]() { stbi_image_free(data); }); + CPUBuffer buffer((w == nullptr ? dummy_w : *w) * (h == nullptr ? dummy_h : *h) * 4); std::memcpy(buffer.GetData(), data, buffer.GetSize()); - Texture* texture; - try { texture = new Texture(buffer, (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h), VK_FORMAT_R8G8B8A8_SRGB, false, std::move(filename)); } - catch(...) { return NULL; } - - stbi_image_free(data); + Texture* texture; + try { texture = new Texture(std::move(buffer), (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h), VK_FORMAT_R8G8B8A8_SRGB, false, std::move(filename)); } + catch(...) { return nullptr; } return texture; } } diff --git a/runtime/Sources/Renderer/Pipelines/Shader.cpp b/runtime/Sources/Renderer/Pipelines/Shader.cpp index 0e527f2..26c7d91 100644 --- a/runtime/Sources/Renderer/Pipelines/Shader.cpp +++ b/runtime/Sources/Renderer/Pipelines/Shader.cpp @@ -11,7 +11,6 @@ namespace mlx { case ShaderType::Vertex : m_stage = VK_SHADER_STAGE_VERTEX_BIT; break; case ShaderType::Fragment : m_stage = VK_SHADER_STAGE_FRAGMENT_BIT; break; - case ShaderType::Compute : m_stage = VK_SHADER_STAGE_COMPUTE_BIT; break; default : FatalError("wtf"); break; } diff --git a/runtime/Sources/Renderer/RenderCore.cpp b/runtime/Sources/Renderer/RenderCore.cpp index 872406e..58d3d54 100644 --- a/runtime/Sources/Renderer/RenderCore.cpp +++ b/runtime/Sources/Renderer/RenderCore.cpp @@ -47,6 +47,8 @@ namespace mlx RenderCore::RenderCore() { + if(s_instance != nullptr) + return; s_instance = this; loader = std::make_unique(); @@ -193,7 +195,10 @@ namespace mlx RenderCore::~RenderCore() { + if(s_instance == nullptr) + return; WaitDeviceIdle(); + m_descriptor_pool_manager.Destroy(); m_allocator.Destroy(); kvfDestroyDevice(m_device); DebugLog("Vulkan : logical device destroyed"); diff --git a/runtime/Sources/Renderer/RenderPasses/2DPass.cpp b/runtime/Sources/Renderer/RenderPasses/2DPass.cpp index 642804e..6283a18 100644 --- a/runtime/Sources/Renderer/RenderPasses/2DPass.cpp +++ b/runtime/Sources/Renderer/RenderPasses/2DPass.cpp @@ -45,23 +45,15 @@ namespace mlx }; p_fragment_shader = std::make_shared(fragment_shader_code, ShaderType::Fragment, std::move(fragment_shader_layout)); - func::function functor = [this, &renderer](const EventBase& event) + func::function functor = [this](const EventBase& event) { if(event.What() == Event::ResizeEventCode) m_pipeline.Destroy(); - if(event.What() == Event::DescriptorPoolResetEventCode) - { - std::uint32_t frame_index = renderer.GetCurrentFrameIndex(); - p_texture_set->Reallocate(frame_index); - p_viewer_data_set->Reallocate(frame_index); - p_viewer_data_set->SetUniformBuffer(frame_index, 0, p_viewer_data_buffer->Get(frame_index)); - p_viewer_data_set->Update(frame_index); - } }; EventBus::RegisterListener({ functor, "__MlxRender2DPass" }); - p_viewer_data_set = std::make_shared(renderer.GetDescriptorPoolManager(), p_vertex_shader->GetShaderLayout().set_layouts[0].second, p_vertex_shader->GetPipelineLayout().set_layouts[0], ShaderType::Vertex); - p_texture_set = std::make_shared(renderer.GetDescriptorPoolManager(), p_fragment_shader->GetShaderLayout().set_layouts[0].second, p_fragment_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment); + p_viewer_data_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_vertex_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Vertex); + p_texture_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); p_viewer_data_buffer = std::make_shared(); p_viewer_data_buffer->Init(sizeof(ViewerData), "mlx_2d_pass_viewer_data"); @@ -106,7 +98,7 @@ namespace mlx { // Check every textures and update modified ones to GPU before starting the render pass if(!sprite->IsSetInit()) - sprite->UpdateDescriptorSet(*p_texture_set); + sprite->UpdateDescriptorSet(p_texture_set); Verify((bool)sprite->GetTexture(), "a sprite has no texture attached (internal mlx issue, please report to the devs)"); sprite->GetTexture()->Update(cmd); } @@ -136,8 +128,10 @@ namespace mlx m_pipeline.Destroy(); p_vertex_shader.reset(); p_fragment_shader.reset(); + p_viewer_data_set->ReturnDescriptorSetToPool(); p_viewer_data_set.reset(); p_viewer_data_buffer->Destroy(); + p_texture_set->ReturnDescriptorSetToPool(); p_texture_set.reset(); } } diff --git a/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp b/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp index a0b42af..ac9b73e 100644 --- a/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp +++ b/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp @@ -31,16 +31,14 @@ namespace mlx }; p_fragment_shader = std::make_shared(fragment_shader_code, ShaderType::Fragment, std::move(fragment_shader_layout)); - func::function functor = [this, &renderer](const EventBase& event) + func::function functor = [this](const EventBase& event) { if(event.What() == Event::ResizeEventCode) m_pipeline.Destroy(); - if(event.What() == Event::DescriptorPoolResetEventCode) - p_set->Reallocate(renderer.GetCurrentFrameIndex()); }; EventBus::RegisterListener({ functor, "__MlxFinalPass" }); - p_set = std::make_shared(renderer.GetDescriptorPoolManager(), p_fragment_shader->GetShaderLayout().set_layouts[0].second, p_fragment_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment); + p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); } void FinalPass::Pass([[maybe_unused]] Scene& scene, Renderer& renderer, Texture& render_target) @@ -80,6 +78,7 @@ namespace mlx m_pipeline.Destroy(); p_vertex_shader.reset(); p_fragment_shader.reset(); + p_set->ReturnDescriptorSetToPool(); p_set.reset(); } } diff --git a/runtime/Sources/Renderer/Renderer.cpp b/runtime/Sources/Renderer/Renderer.cpp index d128f79..31b12a9 100644 --- a/runtime/Sources/Renderer/Renderer.cpp +++ b/runtime/Sources/Renderer/Renderer.cpp @@ -18,11 +18,6 @@ namespace mlx { Event What() const override { return Event::FrameBeginEventCode; } }; - - struct DescriptorPoolResetEventBroadcast : public EventBase - { - Event What() const override { return Event::DescriptorPoolResetEventCode; } - }; } void Renderer::Init(NonOwningPtr window) @@ -59,13 +54,6 @@ namespace mlx { MLX_PROFILE_FUNCTION(); kvfWaitForFence(RenderCore::Get().GetDevice(), m_cmd_fences[m_current_frame_index]); - static bool first_run = true; - if(!first_run) - { - m_descriptor_pool_manager.ResetPoolsFromFrameIndex(m_current_frame_index); - EventBus::SendBroadcast(Internal::DescriptorPoolResetEventBroadcast{}); - } - first_run = false; VkResult result = RenderCore::Get().vkAcquireNextImageKHR(RenderCore::Get().GetDevice(), m_swapchain, UINT64_MAX, m_image_available_semaphores[m_current_frame_index], VK_NULL_HANDLE, &m_swapchain_image_index); if(result == VK_ERROR_OUT_OF_DATE_KHR) { @@ -150,7 +138,6 @@ namespace mlx DebugLog("Vulkan : fence destroyed"); } - m_descriptor_pool_manager.Destroy(); DestroySwapchain(); RenderCore::Get().vkDestroySurfaceKHR(RenderCore::Get().GetInstance(), m_surface, nullptr); DebugLog("Vulkan : surface destroyed");