diff --git a/example/main.c b/example/main.c index d2cb659..be15ad3 100644 --- a/example/main.c +++ b/example/main.c @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 17:55:21 by maldavid #+# #+# */ -/* Updated: 2024/01/10 20:21:45 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 20:36:57 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -30,9 +30,9 @@ int update(void *param) t_mlx *mlx; mlx = (t_mlx *)param; + mlx_string_put(mlx->mlx, mlx->win, 160, 120, 0xFFFF2066, "this text should be hidden"); mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo, 100, 100); mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->img, 150, 60); - mlx_string_put(mlx->mlx, mlx->win, 90, 120, 0xFFFF2066, "this text should be hidden"); if (i == 0) mlx_set_font_scale(mlx->mlx, mlx->win, "font.ttf", 16.f); mlx_string_put(mlx->mlx, mlx->win, 20, 50, 0xFFFFFFFF, "that's a text"); diff --git a/src/core/application.cpp b/src/core/application.cpp index dc7de9a..514df83 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -6,11 +6,12 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 22:10:52 by maldavid #+# #+# */ -/* Updated: 2024/01/10 16:44:14 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 05:08:42 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include "application.h" +#include #include #include #include @@ -44,6 +45,14 @@ namespace mlx::core for(auto& gs : _graphics) gs->render(); } + + Render_Core::get().getSingleTimeCmdManager().updateSingleTimesCmdBuffersSubmitState(); + + for(auto& gs : _graphics) + { + for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + gs->getRenderer().getCmdBuffer(i).waitForExecution(); + } } void* Application::newTexture(int w, int h) @@ -74,6 +83,7 @@ namespace mlx::core Application::~Application() { + TextLibrary::get().clearLibrary(); if(__drop_sdl_responsability) return; SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS); diff --git a/src/core/application.inl b/src/core/application.inl index 9249264..c942efb 100644 --- a/src/core/application.inl +++ b/src/core/application.inl @@ -35,6 +35,11 @@ namespace mlx::core void Application::mouseMove(void* win, int x, int y) noexcept { CHECK_WINDOW_PTR(win); + if(!_graphics[*static_cast(win)]->hasWindow()) + { + error::report(e_kind::warning, "trying to move the mouse relative to a window that is targeting an image and not a real window, this is not allowed (move ignored)"); + return; + } SDL_WarpMouseInWindow(_graphics[*static_cast(win)]->getWindow()->getNativeWindow(), x, y); SDL_PumpEvents(); SDL_FlushEvent(SDL_MOUSEMOTION); @@ -43,6 +48,11 @@ namespace mlx::core void Application::onEvent(void* win, int event, int (*funct_ptr)(int, void*), void* param) noexcept { CHECK_WINDOW_PTR(win); + if(!_graphics[*static_cast(win)]->hasWindow()) + { + error::report(e_kind::warning, "trying to add event hook for a window that is targeting an image and not a real window, this is not allowed (hook ignored)"); + return; + } _in->onEvent(_graphics[*static_cast(win)]->getWindow()->getID(), event, funct_ptr, param); } @@ -82,7 +92,7 @@ namespace mlx::core CHECK_WINDOW_PTR(win); _graphics[*static_cast(win)]->clearRenderData(); } - + void Application::destroyGraphicsSupport(void* win) { MLX_PROFILE_FUNCTION(); @@ -108,7 +118,7 @@ namespace mlx::core } if(std::strlen(str) == 0) { - core::error::report(e_kind::error, "trying to put an empty text"); + core::error::report(e_kind::warning, "trying to put an empty text"); return; } _graphics[*static_cast(win)]->stringPut(x, y, color, str); diff --git a/src/core/graphics.cpp b/src/core/graphics.cpp index 7f6cb3b..5092c88 100644 --- a/src/core/graphics.cpp +++ b/src/core/graphics.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/02 15:13:55 by maldavid #+# #+# */ -/* Updated: 2024/01/10 18:23:26 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 04:38:53 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,32 +16,32 @@ namespace mlx { GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, Texture* render_target, int id) : _window(nullptr), - _text_put_pipeline(std::make_unique()), _renderer(std::make_unique()), _width(w), _height(h), - _id(id) + _id(id), + _has_window(false) { MLX_PROFILE_FUNCTION(); _renderer->setWindow(nullptr); _renderer->init(render_target); _pixel_put_pipeline.init(w, h, *_renderer); - _text_put_pipeline->init(_renderer.get()); + _text_manager.init(*_renderer); } GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id) : _window(std::make_shared(w, h, title)), - _text_put_pipeline(std::make_unique()), _renderer(std::make_unique()), _width(w), _height(h), - _id(id) + _id(id), + _has_window(true) { MLX_PROFILE_FUNCTION(); _renderer->setWindow(_window.get()); _renderer->init(nullptr); _pixel_put_pipeline.init(w, h, *_renderer); - _text_put_pipeline->init(_renderer.get()); + _text_manager.init(*_renderer); } void GraphicsSupport::render() noexcept @@ -51,39 +51,21 @@ namespace mlx return; _proj = glm::ortho(0, _width, 0, _height); _renderer->getUniformBuffer()->setData(sizeof(_proj), &_proj); - auto cmd_buff = _renderer->getActiveCmdBuffer().get(); static std::array sets = { _renderer->getVertDescriptorSet().get(), VK_NULL_HANDLE }; - for(auto& data : _textures_to_render) - { - if(!data.texture->isInit()) - continue; - if(data.texture->getSet() == VK_NULL_HANDLE) - data.texture->setDescriptor(_renderer->getFragDescriptorSet().duplicate()); - if(data.texture->getLayout() != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - data.texture->transitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - if(!data.texture->hasBeenUpdated()) - data.texture->updateSet(0); - sets[1] = data.texture->getSet(); - vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); - data.texture->render(*_renderer, data.x, data.y); - } + for(auto& data : _drawlist) + data->render(sets, *_renderer); - _pixel_put_pipeline.present(); - sets[1] = _pixel_put_pipeline.getDescriptorSet(); - vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); - _pixel_put_pipeline.render(*_renderer); - - _text_put_pipeline->render(sets); + _pixel_put_pipeline.render(sets, *_renderer); _renderer->endFrame(); - for(auto& data : _textures_to_render) - data.texture->resetUpdate(); + for(auto& data : _drawlist) + data->resetUpdate(); #ifdef GRAPHICS_MEMORY_DUMP // dump memory to file every two seconds @@ -100,7 +82,7 @@ namespace mlx { MLX_PROFILE_FUNCTION(); vkDeviceWaitIdle(Render_Core::get().getDevice().get()); - _text_put_pipeline->destroy(); + _text_manager.destroy(); _pixel_put_pipeline.destroy(); _renderer->destroy(); if(_window) diff --git a/src/core/graphics.h b/src/core/graphics.h index 749db10..28b1d12 100644 --- a/src/core/graphics.h +++ b/src/core/graphics.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/02 14:49:49 by maldavid #+# #+# */ -/* Updated: 2024/01/10 19:59:58 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 04:39:23 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,7 +23,9 @@ #include #include #include -#include +#include +#include +#include #include #include #include @@ -48,20 +50,31 @@ namespace mlx inline void texturePut(Texture* texture, int x, int y); inline void loadFont(const std::filesystem::path& filepath, float scale); + inline bool hasWindow() const noexcept { return _has_window; } + inline Renderer& getRenderer() { return *_renderer; } ~GraphicsSupport(); private: - std::vector _textures_to_render; + std::vector _drawlist; + PixelPutPipeline _pixel_put_pipeline; + + TextManager _text_manager; + TextureManager _texture_manager; + glm::mat4 _proj = glm::mat4(1.0); + std::shared_ptr _window; - std::unique_ptr _text_put_pipeline; // unique_ptr because of the size of the class std::unique_ptr _renderer; + std::size_t _width = 0; std::size_t _height = 0; + int _id; + + bool _has_window; }; } diff --git a/src/core/graphics.inl b/src/core/graphics.inl index e1d4073..b485309 100644 --- a/src/core/graphics.inl +++ b/src/core/graphics.inl @@ -11,7 +11,7 @@ /* ************************************************************************** */ #include -#include +#include namespace mlx { @@ -21,9 +21,10 @@ namespace mlx void GraphicsSupport::clearRenderData() noexcept { MLX_PROFILE_FUNCTION(); - _textures_to_render.clear(); + _drawlist.clear(); _pixel_put_pipeline.clear(); - _text_put_pipeline->clear(); + _text_manager.clear(); + _texture_manager.clear(); } void GraphicsSupport::pixelPut(int x, int y, uint32_t color) noexcept @@ -35,21 +36,32 @@ namespace mlx void GraphicsSupport::stringPut(int x, int y, uint32_t color, std::string str) { MLX_PROFILE_FUNCTION(); - _text_put_pipeline->put(x, y, color, str); + std::pair res = _text_manager.registerText(x, y, color, str); + if(!res.second) // if this is not a completly new text draw + { + auto it = std::find(_drawlist.begin(), _drawlist.end(), res.first); + if(it != _drawlist.end()) + _drawlist.erase(it); + } + _drawlist.push_back(res.first); } void GraphicsSupport::texturePut(Texture* texture, int x, int y) { MLX_PROFILE_FUNCTION(); - _textures_to_render.emplace_back(texture, x, y); - auto it = std::find(_textures_to_render.begin(), _textures_to_render.end() - 1, _textures_to_render.back()); - if(it != _textures_to_render.end() - 1) - _textures_to_render.erase(it); + auto res = _texture_manager.registerTexture(texture, x, y); + if(!res.second) // if this is not a completly new texture draw + { + auto it = std::find(_drawlist.begin(), _drawlist.end(), res.first); + if(it != _drawlist.end()) + _drawlist.erase(it); + } + _drawlist.push_back(res.first); } void GraphicsSupport::loadFont(const std::filesystem::path& filepath, float scale) { MLX_PROFILE_FUNCTION(); - _text_put_pipeline->loadFont(filepath, scale); + _text_manager.loadFont(*_renderer, filepath, scale); } } diff --git a/src/renderer/buffers/vk_buffer.cpp b/src/renderer/buffers/vk_buffer.cpp index b00e21f..296611d 100644 --- a/src/renderer/buffers/vk_buffer.cpp +++ b/src/renderer/buffers/vk_buffer.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 18:55:57 by maldavid #+# #+# */ -/* Updated: 2024/01/10 18:30:31 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 05:21:20 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,7 +17,6 @@ #include #include #include -#include namespace mlx { @@ -56,15 +55,15 @@ namespace mlx { MLX_PROFILE_FUNCTION(); // not creating destroyer in `create` as some image may be copied (and so `this` will be invalid) - CmdResource::setDestroyer([this]() - { + //CmdResource::setDestroyer([this]() + //{ if(_is_mapped) unmapMem(); if(_buffer != VK_NULL_HANDLE) Render_Core::get().getAllocator().destroyBuffer(_allocation, _buffer); _buffer = VK_NULL_HANDLE; - }); - CmdResource::requireDestroy(); + //}); + //CmdResource::requireDestroy(); } void Buffer::createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, [[maybe_unused]] const char* name) diff --git a/src/renderer/buffers/vk_buffer.h b/src/renderer/buffers/vk_buffer.h index 65eebc1..f36b27f 100644 --- a/src/renderer/buffers/vk_buffer.h +++ b/src/renderer/buffers/vk_buffer.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 23:18:52 by maldavid #+# #+# */ -/* Updated: 2024/01/03 15:26:56 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 05:16:58 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/renderer/buffers/vk_ibo.h b/src/renderer/buffers/vk_ibo.h index ad49eed..f368e13 100644 --- a/src/renderer/buffers/vk_ibo.h +++ b/src/renderer/buffers/vk_ibo.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/25 15:05:05 by maldavid #+# #+# */ -/* Updated: 2024/01/03 15:27:02 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 23:05:15 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,7 +24,7 @@ namespace mlx { public: inline void create(uint32_t size, const uint16_t* data, const char* name) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, name, data); } - inline void bind(Renderer& renderer) noexcept { vkCmdBindIndexBuffer(renderer.getActiveCmdBuffer().get(), _buffer, _offset, VK_INDEX_TYPE_UINT16); } + inline void bind(Renderer& renderer) noexcept { renderer.getActiveCmdBuffer().bindIndexBuffer(*this); } }; } diff --git a/src/renderer/buffers/vk_vbo.h b/src/renderer/buffers/vk_vbo.h index 1bf2209..9079eea 100644 --- a/src/renderer/buffers/vk_vbo.h +++ b/src/renderer/buffers/vk_vbo.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:27:38 by maldavid #+# #+# */ -/* Updated: 2023/12/12 22:46:21 by kbz_8 ### ########.fr */ +/* Updated: 2024/01/10 23:04:40 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,7 +24,7 @@ namespace mlx public: inline void create(uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); } void setData(uint32_t size, const void* data); - inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); } + inline void bind(Renderer& renderer) noexcept { renderer.getActiveCmdBuffer().bindVertexBuffer(*this); } }; class D_VBO : public Buffer @@ -32,14 +32,14 @@ namespace mlx public: inline void create(uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::dynamic_device_local, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); } void setData(uint32_t size, const void* data); - inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); } + inline void bind(Renderer& renderer) noexcept { renderer.getActiveCmdBuffer().bindVertexBuffer(*this); } }; class C_VBO : public Buffer { public: inline void create(uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); } - inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); } + inline void bind(Renderer& renderer) noexcept { renderer.getActiveCmdBuffer().bindVertexBuffer(*this); } }; } diff --git a/src/renderer/command/single_time_cmd_manager.cpp b/src/renderer/command/single_time_cmd_manager.cpp index c4028d5..b4dcf7b 100644 --- a/src/renderer/command/single_time_cmd_manager.cpp +++ b/src/renderer/command/single_time_cmd_manager.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/12/15 19:57:49 by maldavid #+# #+# */ -/* Updated: 2024/01/07 01:30:49 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 03:13:21 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -52,7 +52,6 @@ namespace mlx cmd.waitForExecution(); } - void SingleTimeCmdManager::destroy() noexcept { std::for_each(_buffers.begin(), _buffers.end(), [](CmdBuffer& buf) diff --git a/src/renderer/core/cmd_resource.h b/src/renderer/core/cmd_resource.h index 695ae16..9603504 100644 --- a/src/renderer/core/cmd_resource.h +++ b/src/renderer/core/cmd_resource.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/12/16 20:44:29 by maldavid #+# #+# */ -/* Updated: 2024/01/07 01:19:10 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 05:12:42 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/renderer/core/drawable_resource.h b/src/renderer/core/drawable_resource.h new file mode 100644 index 0000000..8df2b98 --- /dev/null +++ b/src/renderer/core/drawable_resource.h @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* drawable_resource.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/10 21:00:37 by maldavid #+# #+# */ +/* Updated: 2024/01/11 01:21:15 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_DRAWABLE_RESOURCE__ +#define __MLX_DRAWABLE_RESOURCE__ + +#include +#include +#include + +namespace mlx +{ + class DrawableResource + { + public: + DrawableResource() = default; + virtual void render(std::array& sets, class Renderer& renderer) = 0; + virtual void resetUpdate() {} + virtual ~DrawableResource() = default; + }; +} + +#endif diff --git a/src/renderer/core/memory.cpp b/src/renderer/core/memory.cpp index 8c3c840..1e3ede0 100644 --- a/src/renderer/core/memory.cpp +++ b/src/renderer/core/memory.cpp @@ -6,7 +6,7 @@ /* By: kbz_8 +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/10/20 22:02:37 by kbz_8 #+# #+# */ -/* Updated: 2024/01/10 18:29:07 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:54:35 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -193,5 +193,8 @@ namespace mlx vmaDestroyAllocator(_allocator); _active_buffers_allocations = 0; _active_images_allocations = 0; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed a graphics allocator"); + #endif } } diff --git a/src/renderer/core/render_core.h b/src/renderer/core/render_core.h index 3caae7f..9251b7b 100644 --- a/src/renderer/core/render_core.h +++ b/src/renderer/core/render_core.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:16:32 by maldavid #+# #+# */ -/* Updated: 2024/01/10 18:36:58 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 05:14:03 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -54,6 +54,7 @@ namespace mlx void init(); void destroy(); + inline bool isInit() const noexcept { return _is_init; } inline Instance& getInstance() noexcept { return _instance; } inline Device& getDevice() noexcept { return _device; } inline Queues& getQueue() noexcept { return _queues; } diff --git a/src/renderer/core/vk_device.cpp b/src/renderer/core/vk_device.cpp index 0772839..95de2d2 100644 --- a/src/renderer/core/vk_device.cpp +++ b/src/renderer/core/vk_device.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:14:29 by maldavid #+# #+# */ -/* Updated: 2024/01/08 23:48:53 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:54:17 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -159,5 +159,8 @@ namespace mlx { vkDestroyDevice(_device, nullptr); _device = VK_NULL_HANDLE; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed a logical device"); + #endif } } diff --git a/src/renderer/core/vk_instance.cpp b/src/renderer/core/vk_instance.cpp index d93f342..bd9582b 100644 --- a/src/renderer/core/vk_instance.cpp +++ b/src/renderer/core/vk_instance.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:04:21 by maldavid #+# #+# */ -/* Updated: 2023/12/31 00:40:10 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:54:06 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -84,5 +84,8 @@ namespace mlx { vkDestroyInstance(_instance, nullptr); _instance = VK_NULL_HANDLE; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed an instance"); + #endif } } diff --git a/src/renderer/core/vk_queues.cpp b/src/renderer/core/vk_queues.cpp index 4c79962..7928cc3 100644 --- a/src/renderer/core/vk_queues.cpp +++ b/src/renderer/core/vk_queues.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:02:42 by maldavid #+# #+# */ -/* Updated: 2024/01/08 23:46:36 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:54:54 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -64,5 +64,8 @@ namespace mlx } vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->graphicsFamily.value(), 0, &_graphicsQueue); vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->presentFamily.value(), 0, &_presentQueue); + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : got graphics and present queues"); + #endif } } diff --git a/src/renderer/core/vk_semaphore.cpp b/src/renderer/core/vk_semaphore.cpp index 604d215..20f0803 100644 --- a/src/renderer/core/vk_semaphore.cpp +++ b/src/renderer/core/vk_semaphore.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:01:08 by maldavid #+# #+# */ -/* Updated: 2023/12/16 18:47:29 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:55:12 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,7 +26,7 @@ namespace mlx (res = vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_renderFinishedSemaphores)) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to create a synchronization object (semaphore), %s", RCore::verbaliseResultVk(res)); #ifdef DEBUG - core::error::report(e_kind::message, "Vulkan : created new semaphore"); + core::error::report(e_kind::message, "Vulkan : created new semaphores"); #endif } @@ -36,5 +36,8 @@ namespace mlx _renderFinishedSemaphores = VK_NULL_HANDLE; vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores, nullptr); _imageAvailableSemaphores = VK_NULL_HANDLE; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed semaphores"); + #endif } } diff --git a/src/renderer/core/vk_surface.cpp b/src/renderer/core/vk_surface.cpp index 3a5fed2..e2e2ac4 100644 --- a/src/renderer/core/vk_surface.cpp +++ b/src/renderer/core/vk_surface.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 18:58:49 by maldavid #+# #+# */ -/* Updated: 2023/12/30 23:14:54 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:55:21 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -42,5 +42,8 @@ namespace mlx { vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), _surface, nullptr); _surface = VK_NULL_HANDLE; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed a surface"); + #endif } } diff --git a/src/renderer/core/vk_validation_layers.cpp b/src/renderer/core/vk_validation_layers.cpp index 684843b..5b0cbea 100644 --- a/src/renderer/core/vk_validation_layers.cpp +++ b/src/renderer/core/vk_validation_layers.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/19 14:05:25 by maldavid #+# #+# */ -/* Updated: 2024/01/07 00:33:40 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:55:54 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -98,7 +98,12 @@ namespace mlx void ValidationLayers::destroy() { if constexpr(enableValidationLayers) + { destroyDebugUtilsMessengerEXT(nullptr); + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed validation layers"); + #endif + } } VkResult ValidationLayers::createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator) diff --git a/src/renderer/images/texture.cpp b/src/renderer/images/texture.cpp index 4443304..2206f64 100644 --- a/src/renderer/images/texture.cpp +++ b/src/renderer/images/texture.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/31 18:03:35 by maldavid #+# #+# */ -/* Updated: 2024/01/10 18:28:11 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 01:20:29 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -126,7 +126,7 @@ namespace mlx #endif } - void Texture::render(Renderer& renderer, int x, int y) + void Texture::render(std::array& sets, Renderer& renderer, int x, int y) { MLX_PROFILE_FUNCTION(); if(_has_been_modified) @@ -135,11 +135,19 @@ namespace mlx Image::copyFromBuffer(*_buf_map); _has_been_modified = false; } + if(!_set.isInit()) + _set = renderer.getFragDescriptorSet().duplicate(); + if(getLayout() != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + transitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + if(!_has_set_been_updated) + updateSet(0); auto cmd = renderer.getActiveCmdBuffer(); _vbo.bind(renderer); _ibo.bind(renderer); glm::vec2 translate(x, y); vkCmdPushConstants(cmd.get(), renderer.getPipeline().getPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(translate), &translate); + sets[1] = _set.get(); + vkCmdBindDescriptorSets(renderer.getActiveCmdBuffer().get(), VK_PIPELINE_BIND_POINT_GRAPHICS, renderer.getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); vkCmdDrawIndexed(cmd.get(), static_cast(_ibo.getSize() / sizeof(uint16_t)), 1, 0, 0, 0); } diff --git a/src/renderer/images/texture.h b/src/renderer/images/texture.h index a7690d6..5558886 100644 --- a/src/renderer/images/texture.h +++ b/src/renderer/images/texture.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/08 02:24:58 by maldavid #+# #+# */ -/* Updated: 2023/12/23 18:49:12 by kbz_8 ### ########.fr */ +/* Updated: 2024/01/11 01:18:25 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,13 +26,13 @@ namespace mlx { - class Texture : public Image + class Texture : public Image { public: Texture() = default; - + void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory = false); - void render(class Renderer& renderer, int x, int y); + void render(std::array& sets, class Renderer& renderer, int x, int y); void destroy() noexcept override; void setPixel(int x, int y, uint32_t color) noexcept; @@ -40,9 +40,9 @@ namespace mlx inline void setDescriptor(DescriptorSet&& set) noexcept { _set = set; } inline VkDescriptorSet getSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; } - inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, *this); _has_been_updated = true; } - inline bool hasBeenUpdated() const noexcept { return _has_been_updated; } - inline constexpr void resetUpdate() noexcept { _has_been_updated = false; } + inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, *this); _has_set_been_updated = true; } + inline bool hasBeenUpdated() const noexcept { return _has_set_been_updated; } + inline constexpr void resetUpdate() noexcept { _has_set_been_updated = false; } ~Texture() = default; @@ -60,20 +60,10 @@ namespace mlx std::optional _buf_map = std::nullopt; void* _map = nullptr; bool _has_been_modified = false; - bool _has_been_updated = false; + bool _has_set_been_updated = false; }; Texture stbTextureLoad(std::filesystem::path file, int* w, int* h); - - struct TextureRenderData - { - Texture* texture; - int x; - int y; - - TextureRenderData(Texture* _texture, int _x, int _y) : texture(_texture), x(_x), y(_y) {} - bool operator==(const TextureRenderData& rhs) const { return texture == rhs.texture && x == rhs.x && y == rhs.y; } - }; } #endif diff --git a/src/renderer/images/texture_descriptor.h b/src/renderer/images/texture_descriptor.h new file mode 100644 index 0000000..f3a2663 --- /dev/null +++ b/src/renderer/images/texture_descriptor.h @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* texture_descriptor.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 01:00:13 by maldavid #+# #+# */ +/* Updated: 2024/01/11 01:21:52 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_TEXTURE_DESCRIPTOR__ +#define __MLX_TEXTURE_DESCRIPTOR__ + +#include +#include +#include + +namespace mlx +{ + struct TextureRenderDescriptor : public DrawableResource + { + Texture* texture; + int x; + int y; + + TextureRenderDescriptor(Texture* _texture, int _x, int _y) : texture(_texture), x(_x), y(_y) {} + inline bool operator==(const TextureRenderDescriptor& rhs) const { return texture == rhs.texture && x == rhs.x && y == rhs.y; } + inline void render(std::array& sets, class Renderer& renderer) override + { + if(!texture->isInit()) + return; + texture->render(sets, renderer, x, y); + } + inline void resetUpdate() override + { + if(!texture->isInit()) + return; + texture->resetUpdate(); + } + }; +} + +namespace std +{ + template <> + struct hash + { + std::size_t operator()(const mlx::TextureRenderDescriptor& d) const noexcept + { + std::size_t hash = 0; + mlx::hashCombine(hash, d.texture, d.x, d.y); + return hash; + } + }; +} + +#endif diff --git a/src/renderer/images/texture_manager.h b/src/renderer/images/texture_manager.h new file mode 100644 index 0000000..35707e9 --- /dev/null +++ b/src/renderer/images/texture_manager.h @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* texture_manager.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 00:56:15 by maldavid #+# #+# */ +/* Updated: 2024/01/11 01:49:12 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_TEXTURE_MANAGER__ +#define __MLX_TEXTURE_MANAGER__ + +#include +#include +#include +#include + +namespace mlx +{ + class TextureManager + { + public: + TextureManager() = default; + + inline void clear() { _texture_descriptors.clear(); } + inline std::pair registerTexture(Texture* texture, int x, int y) + { + MLX_PROFILE_FUNCTION(); + auto res = _texture_descriptors.emplace(texture, x, y); + return std::make_pair(static_cast(&const_cast(*res.first)), res.second); + } + + ~TextureManager() = default; + + private: + std::unordered_set _texture_descriptors; + }; +} + +#endif diff --git a/src/renderer/pipeline/pipeline.cpp b/src/renderer/pipeline/pipeline.cpp index 8d234f7..b8ca2b6 100644 --- a/src/renderer/pipeline/pipeline.cpp +++ b/src/renderer/pipeline/pipeline.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/18 21:27:38 by maldavid #+# #+# */ -/* Updated: 2024/01/03 13:16:57 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:53:38 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -320,5 +320,9 @@ namespace mlx { vkDestroyPipeline(Render_Core::get().getDevice().get(), _graphicsPipeline, nullptr); vkDestroyPipelineLayout(Render_Core::get().getDevice().get(), _pipelineLayout, nullptr); + _graphicsPipeline = VK_NULL_HANDLE; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed a graphics pipeline"); + #endif } } diff --git a/src/renderer/pixel_put.cpp b/src/renderer/pixel_put.cpp index c8780bd..17ba007 100644 --- a/src/renderer/pixel_put.cpp +++ b/src/renderer/pixel_put.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/31 15:14:50 by maldavid #+# #+# */ -/* Updated: 2024/01/10 18:26:59 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 00:06:01 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -45,7 +45,7 @@ namespace mlx _has_been_modified = true; } - void PixelPutPipeline::present() noexcept + void PixelPutPipeline::render(std::array& sets, Renderer& renderer) noexcept { MLX_PROFILE_FUNCTION(); if(_has_been_modified) @@ -55,12 +55,7 @@ namespace mlx _has_been_modified = false; } _texture.updateSet(0); - } - - void PixelPutPipeline::render(Renderer& renderer) noexcept - { - MLX_PROFILE_FUNCTION(); - _texture.render(renderer, 0, 0); + _texture.render(sets, renderer, 0, 0); } void PixelPutPipeline::destroy() noexcept diff --git a/src/renderer/pixel_put.h b/src/renderer/pixel_put.h index eddae2f..b413132 100644 --- a/src/renderer/pixel_put.h +++ b/src/renderer/pixel_put.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/31 13:18:50 by maldavid #+# #+# */ -/* Updated: 2023/12/14 18:24:58 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 00:06:05 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,9 +27,7 @@ namespace mlx void init(uint32_t width, uint32_t height, class Renderer& renderer) noexcept; void setPixel(int x, int y, uint32_t color) noexcept; - void present() noexcept; - void render(class Renderer& renderer) noexcept; - inline VkDescriptorSet getDescriptorSet() noexcept { return _texture.getSet(); } + void render(std::array& sets, class Renderer& renderer) noexcept; void clear(); void destroy() noexcept; diff --git a/src/renderer/renderpass/vk_framebuffer.cpp b/src/renderer/renderpass/vk_framebuffer.cpp index c96c54d..20ac661 100644 --- a/src/renderer/renderpass/vk_framebuffer.cpp +++ b/src/renderer/renderpass/vk_framebuffer.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:18:06 by maldavid #+# #+# */ -/* Updated: 2024/01/03 13:17:27 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:52:51 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -45,5 +45,8 @@ namespace mlx { vkDestroyFramebuffer(Render_Core::get().getDevice().get(), _framebuffer, nullptr); _framebuffer = VK_NULL_HANDLE; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed a framebuffer"); + #endif } } diff --git a/src/renderer/renderpass/vk_render_pass.cpp b/src/renderer/renderpass/vk_render_pass.cpp index 94c7eb1..06b5e75 100644 --- a/src/renderer/renderpass/vk_render_pass.cpp +++ b/src/renderer/renderpass/vk_render_pass.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:21:36 by maldavid #+# #+# */ -/* Updated: 2024/01/10 18:27:43 by maldavid ### ########.fr */ +/* Updated: 2024/01/10 21:53:03 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -112,5 +112,8 @@ namespace mlx { vkDestroyRenderPass(Render_Core::get().getDevice().get(), _renderPass, nullptr); _renderPass = VK_NULL_HANDLE; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed a renderpass"); + #endif } } diff --git a/src/renderer/text_pipeline.cpp b/src/renderer/text_pipeline.cpp deleted file mode 100644 index aecc25d..0000000 --- a/src/renderer/text_pipeline.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* text_pipeline.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: maldavid +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2023/04/06 16:41:13 by maldavid #+# #+# */ -/* Updated: 2024/01/10 20:20:30 by maldavid ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include -#include -#include - -#include -#include -#include - -#define STB_RECT_PACK_IMPLEMENTATION -#include - -#include - -#define STB_TRUETYPE_IMPLEMENTATION -#define STB_malloc(x, u) ((void)(u), MemManager::malloc(x)) -#define STB_free(x, u) ((void)(u), MemManager::free(x)) -#include - -constexpr const int RANGE = 1024; - -namespace mlx -{ - TextDrawData::TextDrawData(std::string _text, uint32_t _color, int _x, int _y) : - x(_x), y(_y), color(_color), - text(std::move(_text)) - {} - - void TextDrawData::init(TextLibrary& library, Font* const font) noexcept - { - MLX_PROFILE_FUNCTION(); - std::vector vertexData; - std::vector indexData; - - float stb_x = 0.0f; - float stb_y = 0.0f; - - for(char c : text) - { - if(c < 32 && c != '\n') - continue; - - stbtt_aligned_quad q; - stbtt_GetPackedQuad(font->getCharData().data(), RANGE, RANGE, c - 32, &stb_x, &stb_y, &q, 1); - - std::size_t index = vertexData.size(); - - glm::vec4 vertex_color = { - static_cast((color & 0x000000FF)) / 255.f, - static_cast((color & 0x0000FF00) >> 8) / 255.f, - static_cast((color & 0x00FF0000) >> 16) / 255.f, - static_cast((color & 0xFF000000) >> 24) / 255.f - }; - - vertexData.emplace_back(glm::vec2{q.x0, q.y0}, vertex_color, glm::vec2{q.s0, q.t0}); - vertexData.emplace_back(glm::vec2{q.x1, q.y0}, vertex_color, glm::vec2{q.s1, q.t0}); - vertexData.emplace_back(glm::vec2{q.x1, q.y1}, vertex_color, glm::vec2{q.s1, q.t1}); - vertexData.emplace_back(glm::vec2{q.x0, q.y1}, vertex_color, glm::vec2{q.s0, q.t1}); - - indexData.emplace_back(index + 0); - indexData.emplace_back(index + 1); - indexData.emplace_back(index + 2); - indexData.emplace_back(index + 2); - indexData.emplace_back(index + 3); - indexData.emplace_back(index + 0); - } - std::shared_ptr text_data = std::make_shared(); - text_data->init(text, font, std::move(vertexData), std::move(indexData)); - id = library.addTextToLibrary(text_data); - - #ifdef DEBUG - core::error::report(e_kind::message, "Text put : registered new text to render"); - #endif - } - - void TextPutPipeline::init(Renderer* renderer) noexcept - { - MLX_PROFILE_FUNCTION(); - _renderer = renderer; - _font_in_use = &const_cast(*_font_set.emplace(*_renderer, "default", dogica_ttf, 6.0f).first); - } - - void TextPutPipeline::loadFont(const std::filesystem::path& filepath, float scale) - { - MLX_PROFILE_FUNCTION(); - if(filepath.string() == "default") // we're sure it is already loaded - _font_in_use = &const_cast(*_font_set.emplace(*_renderer, "default", dogica_ttf, scale).first); - else - _font_in_use = &const_cast(*_font_set.emplace(*_renderer, filepath, scale).first); - } - - void TextPutPipeline::put(int x, int y, uint32_t color, std::string str) - { - MLX_PROFILE_FUNCTION(); - auto res = _drawlist.emplace(std::move(str), color, x, y); - if(res.second) - const_cast(*res.first).init(_library, _font_in_use); - else - { - auto text_ptr = _library.getTextData(res.first->id); - if(*_font_in_use != text_ptr->getFontInUse()) - { - _library.removeTextFromLibrary(res.first->id); - const_cast(*res.first).init(_library, _font_in_use); - } - } - } - - void TextPutPipeline::render(std::array& sets) - { - MLX_PROFILE_FUNCTION(); - for(auto& draw : _drawlist) - { - std::shared_ptr draw_data = _library.getTextData(draw.id); - TextureAtlas& atlas = const_cast(draw_data->getFontInUse().getAtlas()); - draw_data->bind(*_renderer); - if(atlas.getSet() == VK_NULL_HANDLE) - atlas.setDescriptor(_renderer->getFragDescriptorSet().duplicate()); - if(!atlas.hasBeenUpdated()) - atlas.updateSet(0); - sets[1] = const_cast(atlas).getSet(); - vkCmdBindDescriptorSets(_renderer->getActiveCmdBuffer().get(), VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); - atlas.render(*_renderer, draw.x, draw.y, draw_data->getIBOsize()); - } - - for(auto& draw : _drawlist) - { - std::shared_ptr draw_data = _library.getTextData(draw.id); - TextureAtlas& atlas = const_cast(draw_data->getFontInUse().getAtlas()); - atlas.resetUpdate(); - } - } - - void TextPutPipeline::destroy() noexcept - { - MLX_PROFILE_FUNCTION(); - _library.clearLibrary(); - _drawlist.clear(); - _font_set.clear(); - } -} diff --git a/src/renderer/text_pipeline.h b/src/renderer/text_pipeline.h deleted file mode 100644 index caa6718..0000000 --- a/src/renderer/text_pipeline.h +++ /dev/null @@ -1,82 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* text_pipeline.h :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: maldavid +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2023/04/06 16:24:11 by maldavid #+# #+# */ -/* Updated: 2024/01/10 19:58:22 by maldavid ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef __MLX_TEXT_PIPELINE__ -#define __MLX_TEXT_PIPELINE__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mlx -{ - struct TextDrawData - { - TextID id; - int x; - int y; - uint32_t color; - std::string text; - - TextDrawData(std::string text, uint32_t _color, int _x, int _y); - void init(TextLibrary& library, Font* const font) noexcept; - bool operator==(const TextDrawData& rhs) const { return text == rhs.text && x == rhs.x && y == rhs.y && color == rhs.color; } - TextDrawData() = default; - }; -} - -namespace std -{ - template <> - struct hash - { - std::size_t operator()(const mlx::TextDrawData& d) const noexcept - { - std::size_t hash = 0; - mlx::hashCombine(hash, d.text, d.x, d.y, d.color); - return hash; - } - }; -} - -namespace mlx -{ - class TextPutPipeline - { - public: - TextPutPipeline() = default; - - void init(Renderer* renderer) noexcept; - void put(int x, int y, uint32_t color, std::string str); - inline void clear() { _drawlist.clear(); _library.clearLibrary(); } - void loadFont(const std::filesystem::path& filepath, float scale); - void render(std::array& sets); - void destroy() noexcept; - - ~TextPutPipeline() = default; - - private: - std::unordered_set _font_set; - TextLibrary _library; - std::unordered_set _drawlist; - Renderer* _renderer = nullptr; - Font* _font_in_use = nullptr; - }; -} - -#endif diff --git a/src/renderer/font.cpp b/src/renderer/texts/font.cpp similarity index 97% rename from src/renderer/font.cpp rename to src/renderer/texts/font.cpp index ad2f24e..c508c99 100644 --- a/src/renderer/font.cpp +++ b/src/renderer/texts/font.cpp @@ -6,11 +6,11 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/12/11 22:06:09 by kbz_8 #+# #+# */ -/* Updated: 2024/01/10 18:27:14 by maldavid ### ########.fr */ +/* Updated: 2024/01/11 01:23:20 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ -#include +#include #include #include #include diff --git a/src/renderer/font.h b/src/renderer/texts/font.h similarity index 100% rename from src/renderer/font.h rename to src/renderer/texts/font.h diff --git a/src/renderer/text_library.cpp b/src/renderer/texts/text.cpp similarity index 53% rename from src/renderer/text_library.cpp rename to src/renderer/texts/text.cpp index 63109e3..bf1823d 100644 --- a/src/renderer/text_library.cpp +++ b/src/renderer/texts/text.cpp @@ -1,24 +1,22 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* text_library.cpp :+: :+: :+: */ +/* text.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2023/04/10 11:59:57 by maldavid #+# #+# */ -/* Updated: 2024/01/10 18:26:44 by maldavid ### ########.fr */ +/* Created: 2024/01/11 00:11:56 by maldavid #+# #+# */ +/* Updated: 2024/01/11 03:31:57 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ -#include -#include -#include -#include #include +#include +#include namespace mlx { - void TextData::init(std::string text, Font const* font, std::vector vbo_data, std::vector ibo_data) + void Text::init(std::string text, Font const* font, std::vector vbo_data, std::vector ibo_data) { MLX_PROFILE_FUNCTION(); _text = std::move(text); @@ -34,64 +32,24 @@ namespace mlx #endif } - void TextData::bind(Renderer& renderer) noexcept + void Text::bind(Renderer& renderer) noexcept { MLX_PROFILE_FUNCTION(); _vbo[renderer.getActiveImageIndex()].bind(renderer); _ibo.bind(renderer); } - void TextData::updateVertexData(int frame, std::vector vbo_data) + void Text::updateVertexData(int frame, std::vector vbo_data) { MLX_PROFILE_FUNCTION(); _vbo[frame].setData(sizeof(Vertex) * vbo_data.size(), static_cast(vbo_data.data())); } - void TextData::destroy() noexcept + void Text::destroy() noexcept { MLX_PROFILE_FUNCTION(); for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) _vbo[i].destroy(); _ibo.destroy(); } - - std::shared_ptr TextLibrary::getTextData(TextID id) - { - MLX_PROFILE_FUNCTION(); - if(!_cache.count(id)) - core::error::report(e_kind::fatal_error, "Text Library : wrong text ID '%d'", id); - return _cache[id]; - } - - TextID TextLibrary::addTextToLibrary(std::shared_ptr text) - { - MLX_PROFILE_FUNCTION(); - auto it = std::find_if(_cache.begin(), _cache.end(), [=](const std::pair>& v) - { - return v.second->getText() == text->getText(); - }); - if(it != _cache.end()) - return it->first; - _cache[_current_id] = text; - _current_id++; - return _current_id - 1; - } - - void TextLibrary::removeTextFromLibrary(TextID id) - { - MLX_PROFILE_FUNCTION(); - if(_cache.count(id)) - { - _cache[id]->destroy(); - _cache.erase(id); - } - } - - void TextLibrary::clearLibrary() - { - MLX_PROFILE_FUNCTION(); - for(auto [id, text] : _cache) - text->destroy(); - _cache.clear(); - } } diff --git a/src/renderer/text_library.h b/src/renderer/texts/text.h similarity index 61% rename from src/renderer/text_library.h rename to src/renderer/texts/text.h index 1283a99..eff6f8a 100644 --- a/src/renderer/text_library.h +++ b/src/renderer/texts/text.h @@ -1,38 +1,30 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* text_library.h :+: :+: :+: */ +/* text.h :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2023/04/10 11:52:30 by maldavid #+# #+# */ -/* Updated: 2023/12/12 23:07:13 by kbz_8 ### ########.fr */ +/* Created: 2024/01/11 00:09:04 by maldavid #+# #+# */ +/* Updated: 2024/01/11 00:13:25 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef __MLX_TEXT_LIBRARY__ -#define __MLX_TEXT_LIBRARY__ +#ifndef __MLX_TEXT__ +#define __MLX_TEXT__ -#include -#include #include -#include -#include #include -#include -#include -#include -#include +#include +#include +#include namespace mlx { - using TextID = uint32_t; - constexpr TextID nulltext = 0; - - class TextData + class Text { public: - TextData() = default; + Text() = default; void init(std::string text, Font const* font, std::vector vbo_data, std::vector ibo_data); void bind(class Renderer& renderer) noexcept; @@ -42,32 +34,14 @@ namespace mlx inline const std::string& getText() const { return _text; } void destroy() noexcept; - ~TextData() = default; + ~Text() = default; private: std::array _vbo; C_IBO _ibo; std::string _text; Font const* _font = nullptr; - }; - - class TextLibrary - { - public: - TextLibrary() = default; - - std::shared_ptr getTextData(TextID id); - TextID addTextToLibrary(std::shared_ptr text); - void removeTextFromLibrary(TextID id); - - void clearLibrary(); - - ~TextLibrary() = default; - - private: - std::unordered_map> _cache; - TextID _current_id = 1; - }; + }; } #endif diff --git a/src/renderer/texts/text_descriptor.cpp b/src/renderer/texts/text_descriptor.cpp new file mode 100644 index 0000000..bc1f35a --- /dev/null +++ b/src/renderer/texts/text_descriptor.cpp @@ -0,0 +1,104 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* text_descriptor.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 00:23:11 by maldavid #+# #+# */ +/* Updated: 2024/01/11 03:40:54 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include +#include +#include + +#define STB_RECT_PACK_IMPLEMENTATION +#include + +#include + +#define STB_TRUETYPE_IMPLEMENTATION +#define STB_malloc(x, u) ((void)(u), MemManager::malloc(x)) +#define STB_free(x, u) ((void)(u), MemManager::free(x)) +#include + +constexpr const int RANGE = 1024; + +namespace mlx +{ + TextDrawDescriptor::TextDrawDescriptor(std::string text, uint32_t _color, int _x, int _y) : color(_color), x(_x), y(_y), _text(std::move(text)) + {} + + void TextDrawDescriptor::init(Font* const font) noexcept + { + MLX_PROFILE_FUNCTION(); + std::vector vertexData; + std::vector indexData; + + float stb_x = 0.0f; + float stb_y = 0.0f; + + for(char c : _text) + { + if(c < 32) + continue; + + stbtt_aligned_quad q; + stbtt_GetPackedQuad(font->getCharData().data(), RANGE, RANGE, c - 32, &stb_x, &stb_y, &q, 1); + + std::size_t index = vertexData.size(); + + glm::vec4 vertex_color = { + static_cast((color & 0x000000FF)) / 255.f, + static_cast((color & 0x0000FF00) >> 8) / 255.f, + static_cast((color & 0x00FF0000) >> 16) / 255.f, + static_cast((color & 0xFF000000) >> 24) / 255.f + }; + + vertexData.emplace_back(glm::vec2{q.x0, q.y0}, vertex_color, glm::vec2{q.s0, q.t0}); + vertexData.emplace_back(glm::vec2{q.x1, q.y0}, vertex_color, glm::vec2{q.s1, q.t0}); + vertexData.emplace_back(glm::vec2{q.x1, q.y1}, vertex_color, glm::vec2{q.s1, q.t1}); + vertexData.emplace_back(glm::vec2{q.x0, q.y1}, vertex_color, glm::vec2{q.s0, q.t1}); + + indexData.emplace_back(index + 0); + indexData.emplace_back(index + 1); + indexData.emplace_back(index + 2); + indexData.emplace_back(index + 2); + indexData.emplace_back(index + 3); + indexData.emplace_back(index + 0); + } + std::shared_ptr text_data = std::make_shared(); + text_data->init(_text, font, std::move(vertexData), std::move(indexData)); + id = TextLibrary::get().addTextToLibrary(text_data); + + #ifdef DEBUG + core::error::report(e_kind::message, "Text put : registered new text to render"); + #endif + } + + void TextDrawDescriptor::render(std::array& sets, Renderer& renderer) + { + MLX_PROFILE_FUNCTION(); + std::shared_ptr draw_data = TextLibrary::get().getTextData(id); + TextureAtlas& atlas = const_cast(draw_data->getFontInUse().getAtlas()); + draw_data->bind(renderer); + if(atlas.getSet() == VK_NULL_HANDLE) + atlas.setDescriptor(renderer.getFragDescriptorSet().duplicate()); + if(!atlas.hasBeenUpdated()) + atlas.updateSet(0); + sets[1] = const_cast(atlas).getSet(); + vkCmdBindDescriptorSets(renderer.getActiveCmdBuffer().get(), VK_PIPELINE_BIND_POINT_GRAPHICS, renderer.getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); + atlas.render(renderer, x, y, draw_data->getIBOsize()); + } + + void TextDrawDescriptor::resetUpdate() + { + std::shared_ptr draw_data = TextLibrary::get().getTextData(id); + TextureAtlas& atlas = const_cast(draw_data->getFontInUse().getAtlas()); + atlas.resetUpdate(); + } +} diff --git a/src/renderer/texts/text_descriptor.h b/src/renderer/texts/text_descriptor.h new file mode 100644 index 0000000..b44300b --- /dev/null +++ b/src/renderer/texts/text_descriptor.h @@ -0,0 +1,65 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* text_descriptor.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 00:13:34 by maldavid #+# #+# */ +/* Updated: 2024/01/11 04:28:58 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_TEXT_DESCRIPTOR__ +#define __MLX_TEXT_DESCRIPTOR__ + +#include +#include +#include +#include +#include +#include +#include + +namespace mlx +{ + class TextDrawDescriptor : public DrawableResource + { + friend class std::hash; + + public: + TextID id; + uint32_t color; + int x; + int y; + + public: + TextDrawDescriptor(std::string text, uint32_t _color, int _x, int _y); + + void init(Font* const font) noexcept; + bool operator==(const TextDrawDescriptor& rhs) const { return _text == rhs._text && x == rhs.x && y == rhs.y && color == rhs.color; } + void render(std::array& sets, Renderer& renderer) override; + void resetUpdate() override; + + TextDrawDescriptor() = default; + + private: + std::string _text; + }; +} + +namespace std +{ + template <> + struct hash + { + std::size_t operator()(const mlx::TextDrawDescriptor& d) const noexcept + { + std::size_t hash = 0; + mlx::hashCombine(hash, d.x, d.y, d.color, d._text); + return hash; + } + }; +} + +#endif diff --git a/src/renderer/texts/text_library.cpp b/src/renderer/texts/text_library.cpp new file mode 100644 index 0000000..9dd5658 --- /dev/null +++ b/src/renderer/texts/text_library.cpp @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* text_library.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/10 11:59:57 by maldavid #+# #+# */ +/* Updated: 2024/01/11 05:19:24 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include +#include +#include +#include +#include + +namespace mlx +{ + std::shared_ptr TextLibrary::getTextData(TextID id) + { + MLX_PROFILE_FUNCTION(); + if(!_cache.count(id) || std::find(_invalid_ids.begin(), _invalid_ids.end(), id) != _invalid_ids.end()) + core::error::report(e_kind::fatal_error, "Text Library : wrong text ID '%d'", id); + return _cache[id]; + } + + TextID TextLibrary::addTextToLibrary(std::shared_ptr text) + { + MLX_PROFILE_FUNCTION(); + auto it = std::find_if(_cache.begin(), _cache.end(), [&](const std::pair>& v) + { + return v.second->getText() == text->getText() && std::find(_invalid_ids.begin(), _invalid_ids.end(), v.first) == _invalid_ids.end(); + }); + if(it != _cache.end()) + return it->first; + _cache[_current_id] = text; + _current_id++; + return _current_id - 1; + } + + void TextLibrary::removeTextFromLibrary(TextID id) + { + MLX_PROFILE_FUNCTION(); + if(!_cache.count(id) || std::find(_invalid_ids.begin(), _invalid_ids.end(), id) != _invalid_ids.end()) + { + core::error::report(e_kind::warning, "Text Library : trying to remove a text with an unkown or invalid ID '%d'", id); + return; + } + _cache[id]->destroy(); + _invalid_ids.push_back(id); + } + + void TextLibrary::clearLibrary() + { + MLX_PROFILE_FUNCTION(); + for(auto& [id, text] : _cache) + { + text->destroy(); + _invalid_ids.push_back(id); + } + // do not `_cache.clear();` as it releases the texts and may not destroy Vertex and Index buffers that are in use by command buffers + } +} diff --git a/src/renderer/texts/text_library.h b/src/renderer/texts/text_library.h new file mode 100644 index 0000000..19ae1eb --- /dev/null +++ b/src/renderer/texts/text_library.h @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* text_library.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/10 11:52:30 by maldavid #+# #+# */ +/* Updated: 2024/01/11 05:08:04 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_TEXT_LIBRARY__ +#define __MLX_TEXT_LIBRARY__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mlx +{ + using TextID = uint32_t; + constexpr TextID nulltext = 0; + + class TextLibrary : public Singleton + { + friend class Singleton; + + public: + std::shared_ptr getTextData(TextID id); + TextID addTextToLibrary(std::shared_ptr text); + void removeTextFromLibrary(TextID id); + + void clearLibrary(); + + private: + TextLibrary() = default; + ~TextLibrary() = default; + + private: + std::unordered_map> _cache; + std::vector _invalid_ids; + TextID _current_id = 1; + }; +} + +#endif diff --git a/src/renderer/texts/text_manager.cpp b/src/renderer/texts/text_manager.cpp new file mode 100644 index 0000000..d4a9f82 --- /dev/null +++ b/src/renderer/texts/text_manager.cpp @@ -0,0 +1,66 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* text_manager.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/06 16:41:13 by maldavid #+# #+# */ +/* Updated: 2024/01/11 04:54:16 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace mlx +{ + void TextManager::init(Renderer& renderer) noexcept + { + MLX_PROFILE_FUNCTION(); + _font_in_use = &const_cast(*_font_set.emplace(renderer, "default", dogica_ttf, 6.0f).first); + } + + void TextManager::loadFont(Renderer& renderer, const std::filesystem::path& filepath, float scale) + { + MLX_PROFILE_FUNCTION(); + if(filepath.string() == "default") // we're sure it is already loaded + _font_in_use = &const_cast(*_font_set.emplace(renderer, "default", dogica_ttf, scale).first); + else + _font_in_use = &const_cast(*_font_set.emplace(renderer, filepath, scale).first); + } + + std::pair TextManager::registerText(int x, int y, uint32_t color, std::string str) + { + MLX_PROFILE_FUNCTION(); + auto res = _text_descriptors.emplace(std::move(str), color, x, y); + if(res.second) + { + const_cast(*res.first).init(_font_in_use); + return std::make_pair(static_cast(&const_cast(*res.first)), true); + } + + auto text_ptr = TextLibrary::get().getTextData(res.first->id); + if(*_font_in_use != text_ptr->getFontInUse()) + { + TextLibrary::get().removeTextFromLibrary(res.first->id); + const_cast(*res.first).init(_font_in_use); + } + return std::make_pair(static_cast(&const_cast(*res.first)), false); + } + + void TextManager::destroy() noexcept + { + MLX_PROFILE_FUNCTION(); + _text_descriptors.clear(); + _font_set.clear(); + } +} diff --git a/src/renderer/texts/text_manager.h b/src/renderer/texts/text_manager.h new file mode 100644 index 0000000..93cfedb --- /dev/null +++ b/src/renderer/texts/text_manager.h @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* text_manager.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/06 16:24:11 by maldavid #+# #+# */ +/* Updated: 2024/01/11 05:18:42 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_TEXT_MANAGER__ +#define __MLX_TEXT_MANAGER__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mlx +{ + class TextManager + { + public: + TextManager() = default; + + void init(Renderer& renderer) noexcept; + std::pair registerText(int x, int y, uint32_t color, std::string str); + inline void clear() { _text_descriptors.clear(); TextLibrary::get().clearLibrary(); } + void loadFont(Renderer& renderer, const std::filesystem::path& filepath, float scale); + void destroy() noexcept; + + ~TextManager() = default; + + private: + std::unordered_set _text_descriptors; + std::unordered_set _font_set; + Font* _font_in_use = nullptr; + }; +} + +#endif