new text management, texts and textures are on the same level, new texture rendering management, fixing issues

This commit is contained in:
2024-01-11 05:23:16 +01:00
parent 875d73e3dd
commit 189764dc34
42 changed files with 721 additions and 434 deletions

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 17:55:21 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; t_mlx *mlx;
mlx = (t_mlx *)param; 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->logo, 100, 100);
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->img, 150, 60); 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) if (i == 0)
mlx_set_font_scale(mlx->mlx, mlx->win, "font.ttf", 16.f); 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"); mlx_string_put(mlx->mlx, mlx->win, 20, 50, 0xFFFFFFFF, "that's a text");

View File

@@ -6,11 +6,12 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 22:10:52 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 "application.h"
#include <renderer/texts/text_library.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <renderer/images/texture.h> #include <renderer/images/texture.h>
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
@@ -44,6 +45,14 @@ namespace mlx::core
for(auto& gs : _graphics) for(auto& gs : _graphics)
gs->render(); 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) void* Application::newTexture(int w, int h)
@@ -74,6 +83,7 @@ namespace mlx::core
Application::~Application() Application::~Application()
{ {
TextLibrary::get().clearLibrary();
if(__drop_sdl_responsability) if(__drop_sdl_responsability)
return; return;
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS); SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS);

View File

@@ -35,6 +35,11 @@ namespace mlx::core
void Application::mouseMove(void* win, int x, int y) noexcept void Application::mouseMove(void* win, int x, int y) noexcept
{ {
CHECK_WINDOW_PTR(win); CHECK_WINDOW_PTR(win);
if(!_graphics[*static_cast<int*>(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<int*>(win)]->getWindow()->getNativeWindow(), x, y); SDL_WarpMouseInWindow(_graphics[*static_cast<int*>(win)]->getWindow()->getNativeWindow(), x, y);
SDL_PumpEvents(); SDL_PumpEvents();
SDL_FlushEvent(SDL_MOUSEMOTION); 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 void Application::onEvent(void* win, int event, int (*funct_ptr)(int, void*), void* param) noexcept
{ {
CHECK_WINDOW_PTR(win); CHECK_WINDOW_PTR(win);
if(!_graphics[*static_cast<int*>(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<int*>(win)]->getWindow()->getID(), event, funct_ptr, param); _in->onEvent(_graphics[*static_cast<int*>(win)]->getWindow()->getID(), event, funct_ptr, param);
} }
@@ -108,7 +118,7 @@ namespace mlx::core
} }
if(std::strlen(str) == 0) 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; return;
} }
_graphics[*static_cast<int*>(win)]->stringPut(x, y, color, str); _graphics[*static_cast<int*>(win)]->stringPut(x, y, color, str);

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 15:13:55 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) : GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, Texture* render_target, int id) :
_window(nullptr), _window(nullptr),
_text_put_pipeline(std::make_unique<TextPutPipeline>()),
_renderer(std::make_unique<Renderer>()), _renderer(std::make_unique<Renderer>()),
_width(w), _width(w),
_height(h), _height(h),
_id(id) _id(id),
_has_window(false)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_renderer->setWindow(nullptr); _renderer->setWindow(nullptr);
_renderer->init(render_target); _renderer->init(render_target);
_pixel_put_pipeline.init(w, h, *_renderer); _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) : GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id) :
_window(std::make_shared<MLX_Window>(w, h, title)), _window(std::make_shared<MLX_Window>(w, h, title)),
_text_put_pipeline(std::make_unique<TextPutPipeline>()),
_renderer(std::make_unique<Renderer>()), _renderer(std::make_unique<Renderer>()),
_width(w), _width(w),
_height(h), _height(h),
_id(id) _id(id),
_has_window(true)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_renderer->setWindow(_window.get()); _renderer->setWindow(_window.get());
_renderer->init(nullptr); _renderer->init(nullptr);
_pixel_put_pipeline.init(w, h, *_renderer); _pixel_put_pipeline.init(w, h, *_renderer);
_text_put_pipeline->init(_renderer.get()); _text_manager.init(*_renderer);
} }
void GraphicsSupport::render() noexcept void GraphicsSupport::render() noexcept
@@ -51,39 +51,21 @@ namespace mlx
return; return;
_proj = glm::ortho<float>(0, _width, 0, _height); _proj = glm::ortho<float>(0, _width, 0, _height);
_renderer->getUniformBuffer()->setData(sizeof(_proj), &_proj); _renderer->getUniformBuffer()->setData(sizeof(_proj), &_proj);
auto cmd_buff = _renderer->getActiveCmdBuffer().get();
static std::array<VkDescriptorSet, 2> sets = { static std::array<VkDescriptorSet, 2> sets = {
_renderer->getVertDescriptorSet().get(), _renderer->getVertDescriptorSet().get(),
VK_NULL_HANDLE VK_NULL_HANDLE
}; };
for(auto& data : _textures_to_render) for(auto& data : _drawlist)
{ data->render(sets, *_renderer);
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);
}
_pixel_put_pipeline.present(); _pixel_put_pipeline.render(sets, *_renderer);
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);
_renderer->endFrame(); _renderer->endFrame();
for(auto& data : _textures_to_render) for(auto& data : _drawlist)
data.texture->resetUpdate(); data->resetUpdate();
#ifdef GRAPHICS_MEMORY_DUMP #ifdef GRAPHICS_MEMORY_DUMP
// dump memory to file every two seconds // dump memory to file every two seconds
@@ -100,7 +82,7 @@ namespace mlx
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
vkDeviceWaitIdle(Render_Core::get().getDevice().get()); vkDeviceWaitIdle(Render_Core::get().getDevice().get());
_text_put_pipeline->destroy(); _text_manager.destroy();
_pixel_put_pipeline.destroy(); _pixel_put_pipeline.destroy();
_renderer->destroy(); _renderer->destroy();
if(_window) if(_window)

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 14:49:49 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 <platform/window.h> #include <platform/window.h>
#include <renderer/renderer.h> #include <renderer/renderer.h>
#include <renderer/pixel_put.h> #include <renderer/pixel_put.h>
#include <renderer/text_pipeline.h> #include <renderer/core/drawable_resource.h>
#include <renderer/images/texture_manager.h>
#include <renderer/texts/text_manager.h>
#include <utils/non_copyable.h> #include <utils/non_copyable.h>
#include <renderer/images/texture.h> #include <renderer/images/texture.h>
#include <mlx_profile.h> #include <mlx_profile.h>
@@ -48,20 +50,31 @@ namespace mlx
inline void texturePut(Texture* texture, int x, int y); inline void texturePut(Texture* texture, int x, int y);
inline void loadFont(const std::filesystem::path& filepath, float scale); inline void loadFont(const std::filesystem::path& filepath, float scale);
inline bool hasWindow() const noexcept { return _has_window; }
inline Renderer& getRenderer() { return *_renderer; } inline Renderer& getRenderer() { return *_renderer; }
~GraphicsSupport(); ~GraphicsSupport();
private: private:
std::vector<TextureRenderData> _textures_to_render; std::vector<DrawableResource*> _drawlist;
PixelPutPipeline _pixel_put_pipeline; PixelPutPipeline _pixel_put_pipeline;
TextManager _text_manager;
TextureManager _texture_manager;
glm::mat4 _proj = glm::mat4(1.0); glm::mat4 _proj = glm::mat4(1.0);
std::shared_ptr<MLX_Window> _window; std::shared_ptr<MLX_Window> _window;
std::unique_ptr<TextPutPipeline> _text_put_pipeline; // unique_ptr because of the size of the class
std::unique_ptr<Renderer> _renderer; std::unique_ptr<Renderer> _renderer;
std::size_t _width = 0; std::size_t _width = 0;
std::size_t _height = 0; std::size_t _height = 0;
int _id; int _id;
bool _has_window;
}; };
} }

View File

@@ -11,7 +11,7 @@
/* ************************************************************************** */ /* ************************************************************************** */
#include <core/graphics.h> #include <core/graphics.h>
#include <type_traits> #include <iostream>
namespace mlx namespace mlx
{ {
@@ -21,9 +21,10 @@ namespace mlx
void GraphicsSupport::clearRenderData() noexcept void GraphicsSupport::clearRenderData() noexcept
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_textures_to_render.clear(); _drawlist.clear();
_pixel_put_pipeline.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 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) void GraphicsSupport::stringPut(int x, int y, uint32_t color, std::string str)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_text_put_pipeline->put(x, y, color, str); std::pair<DrawableResource*, bool> 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) void GraphicsSupport::texturePut(Texture* texture, int x, int y)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_textures_to_render.emplace_back(texture, x, y); auto res = _texture_manager.registerTexture(texture, x, y);
auto it = std::find(_textures_to_render.begin(), _textures_to_render.end() - 1, _textures_to_render.back()); if(!res.second) // if this is not a completly new texture draw
if(it != _textures_to_render.end() - 1) {
_textures_to_render.erase(it); 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) void GraphicsSupport::loadFont(const std::filesystem::path& filepath, float scale)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_text_put_pipeline->loadFont(filepath, scale); _text_manager.loadFont(*_renderer, filepath, scale);
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 18:55:57 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 <core/profiler.h> #include <core/profiler.h>
#include <vma.h> #include <vma.h>
#include <cstring> #include <cstring>
#include <iostream>
namespace mlx namespace mlx
{ {
@@ -56,15 +55,15 @@ namespace mlx
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
// not creating destroyer in `create` as some image may be copied (and so `this` will be invalid) // 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) if(_is_mapped)
unmapMem(); unmapMem();
if(_buffer != VK_NULL_HANDLE) if(_buffer != VK_NULL_HANDLE)
Render_Core::get().getAllocator().destroyBuffer(_allocation, _buffer); Render_Core::get().getAllocator().destroyBuffer(_allocation, _buffer);
_buffer = VK_NULL_HANDLE; _buffer = VK_NULL_HANDLE;
}); //});
CmdResource::requireDestroy(); //CmdResource::requireDestroy();
} }
void Buffer::createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, [[maybe_unused]] const char* name) void Buffer::createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, [[maybe_unused]] const char* name)

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 23:18:52 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 */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/25 15:05:05 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: 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 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); }
}; };
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:27:38 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: 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); } 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); 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 class D_VBO : public Buffer
@@ -32,14 +32,14 @@ namespace mlx
public: 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); } 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); 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 class C_VBO : public Buffer
{ {
public: 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 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); }
}; };
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/15 19:57:49 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(); cmd.waitForExecution();
} }
void SingleTimeCmdManager::destroy() noexcept void SingleTimeCmdManager::destroy() noexcept
{ {
std::for_each(_buffers.begin(), _buffers.end(), [](CmdBuffer& buf) std::for_each(_buffers.begin(), _buffers.end(), [](CmdBuffer& buf)

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/16 20:44:29 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 */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

32
src/renderer/core/drawable_resource.h git.filemode.normal_file
View File

@@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* drawable_resource.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <mlx_profile.h>
#include <volk.h>
#include <array>
namespace mlx
{
class DrawableResource
{
public:
DrawableResource() = default;
virtual void render(std::array<VkDescriptorSet, 2>& sets, class Renderer& renderer) = 0;
virtual void resetUpdate() {}
virtual ~DrawableResource() = default;
};
}
#endif

View File

@@ -6,7 +6,7 @@
/* By: kbz_8 <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: kbz_8 <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/20 22:02:37 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); vmaDestroyAllocator(_allocator);
_active_buffers_allocations = 0; _active_buffers_allocations = 0;
_active_images_allocations = 0; _active_images_allocations = 0;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a graphics allocator");
#endif
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:16:32 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 init();
void destroy(); void destroy();
inline bool isInit() const noexcept { return _is_init; }
inline Instance& getInstance() noexcept { return _instance; } inline Instance& getInstance() noexcept { return _instance; }
inline Device& getDevice() noexcept { return _device; } inline Device& getDevice() noexcept { return _device; }
inline Queues& getQueue() noexcept { return _queues; } inline Queues& getQueue() noexcept { return _queues; }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:14:29 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); vkDestroyDevice(_device, nullptr);
_device = VK_NULL_HANDLE; _device = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a logical device");
#endif
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:04:21 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); vkDestroyInstance(_instance, nullptr);
_instance = VK_NULL_HANDLE; _instance = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed an instance");
#endif
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:02:42 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->graphicsFamily.value(), 0, &_graphicsQueue);
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->presentFamily.value(), 0, &_presentQueue); 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
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:01:08 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) (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)); core::error::report(e_kind::fatal_error, "Vulkan : failed to create a synchronization object (semaphore), %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new semaphore"); core::error::report(e_kind::message, "Vulkan : created new semaphores");
#endif #endif
} }
@@ -36,5 +36,8 @@ namespace mlx
_renderFinishedSemaphores = VK_NULL_HANDLE; _renderFinishedSemaphores = VK_NULL_HANDLE;
vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores, nullptr); vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores, nullptr);
_imageAvailableSemaphores = VK_NULL_HANDLE; _imageAvailableSemaphores = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed semaphores");
#endif
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 18:58:49 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); vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), _surface, nullptr);
_surface = VK_NULL_HANDLE; _surface = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a surface");
#endif
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/19 14:05:25 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() void ValidationLayers::destroy()
{ {
if constexpr(enableValidationLayers) if constexpr(enableValidationLayers)
{
destroyDebugUtilsMessengerEXT(nullptr); destroyDebugUtilsMessengerEXT(nullptr);
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed validation layers");
#endif
}
} }
VkResult ValidationLayers::createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator) VkResult ValidationLayers::createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator)

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/03/31 18:03:35 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 #endif
} }
void Texture::render(Renderer& renderer, int x, int y) void Texture::render(std::array<VkDescriptorSet, 2>& sets, Renderer& renderer, int x, int y)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
if(_has_been_modified) if(_has_been_modified)
@@ -135,11 +135,19 @@ namespace mlx
Image::copyFromBuffer(*_buf_map); Image::copyFromBuffer(*_buf_map);
_has_been_modified = false; _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(); auto cmd = renderer.getActiveCmdBuffer();
_vbo.bind(renderer); _vbo.bind(renderer);
_ibo.bind(renderer); _ibo.bind(renderer);
glm::vec2 translate(x, y); glm::vec2 translate(x, y);
vkCmdPushConstants(cmd.get(), renderer.getPipeline().getPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(translate), &translate); 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<uint32_t>(_ibo.getSize() / sizeof(uint16_t)), 1, 0, 0, 0); vkCmdDrawIndexed(cmd.get(), static_cast<uint32_t>(_ibo.getSize() / sizeof(uint16_t)), 1, 0, 0, 0);
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/03/08 02:24:58 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 */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -32,7 +32,7 @@ namespace mlx
Texture() = default; Texture() = default;
void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory = false); 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<VkDescriptorSet, 2>& sets, class Renderer& renderer, int x, int y);
void destroy() noexcept override; void destroy() noexcept override;
void setPixel(int x, int y, uint32_t color) noexcept; 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 void setDescriptor(DescriptorSet&& set) noexcept { _set = set; }
inline VkDescriptorSet getSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; } 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 void updateSet(int binding) noexcept { _set.writeDescriptor(binding, *this); _has_set_been_updated = true; }
inline bool hasBeenUpdated() const noexcept { return _has_been_updated; } inline bool hasBeenUpdated() const noexcept { return _has_set_been_updated; }
inline constexpr void resetUpdate() noexcept { _has_been_updated = false; } inline constexpr void resetUpdate() noexcept { _has_set_been_updated = false; }
~Texture() = default; ~Texture() = default;
@@ -60,20 +60,10 @@ namespace mlx
std::optional<Buffer> _buf_map = std::nullopt; std::optional<Buffer> _buf_map = std::nullopt;
void* _map = nullptr; void* _map = nullptr;
bool _has_been_modified = false; 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); 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 #endif

59
src/renderer/images/texture_descriptor.h git.filemode.normal_file
View File

@@ -0,0 +1,59 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* texture_descriptor.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <renderer/images/texture.h>
#include <renderer/core/drawable_resource.h>
#include <utils/combine_hash.h>
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<VkDescriptorSet, 2>& 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<mlx::TextureRenderDescriptor>
{
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

43
src/renderer/images/texture_manager.h git.filemode.normal_file
View File

@@ -0,0 +1,43 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* texture_manager.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <unordered_set>
#include <renderer/images/texture_descriptor.h>
#include <core/profiler.h>
#include <utility>
namespace mlx
{
class TextureManager
{
public:
TextureManager() = default;
inline void clear() { _texture_descriptors.clear(); }
inline std::pair<DrawableResource*, bool> registerTexture(Texture* texture, int x, int y)
{
MLX_PROFILE_FUNCTION();
auto res = _texture_descriptors.emplace(texture, x, y);
return std::make_pair(static_cast<DrawableResource*>(&const_cast<TextureRenderDescriptor&>(*res.first)), res.second);
}
~TextureManager() = default;
private:
std::unordered_set<TextureRenderDescriptor> _texture_descriptors;
};
}
#endif

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/18 21:27:38 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); vkDestroyPipeline(Render_Core::get().getDevice().get(), _graphicsPipeline, nullptr);
vkDestroyPipelineLayout(Render_Core::get().getDevice().get(), _pipelineLayout, 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
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/03/31 15:14:50 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; _has_been_modified = true;
} }
void PixelPutPipeline::present() noexcept void PixelPutPipeline::render(std::array<VkDescriptorSet, 2>& sets, Renderer& renderer) noexcept
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
if(_has_been_modified) if(_has_been_modified)
@@ -55,12 +55,7 @@ namespace mlx
_has_been_modified = false; _has_been_modified = false;
} }
_texture.updateSet(0); _texture.updateSet(0);
} _texture.render(sets, renderer, 0, 0);
void PixelPutPipeline::render(Renderer& renderer) noexcept
{
MLX_PROFILE_FUNCTION();
_texture.render(renderer, 0, 0);
} }
void PixelPutPipeline::destroy() noexcept void PixelPutPipeline::destroy() noexcept

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/03/31 13:18:50 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 init(uint32_t width, uint32_t height, class Renderer& renderer) noexcept;
void setPixel(int x, int y, uint32_t color) noexcept; void setPixel(int x, int y, uint32_t color) noexcept;
void present() noexcept; void render(std::array<VkDescriptorSet, 2>& sets, class Renderer& renderer) noexcept;
void render(class Renderer& renderer) noexcept;
inline VkDescriptorSet getDescriptorSet() noexcept { return _texture.getSet(); }
void clear(); void clear();
void destroy() noexcept; void destroy() noexcept;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:18:06 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); vkDestroyFramebuffer(Render_Core::get().getDevice().get(), _framebuffer, nullptr);
_framebuffer = VK_NULL_HANDLE; _framebuffer = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a framebuffer");
#endif
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:21:36 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); vkDestroyRenderPass(Render_Core::get().getDevice().get(), _renderPass, nullptr);
_renderPass = VK_NULL_HANDLE; _renderPass = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a renderpass");
#endif
} }
} }

View File

@@ -1,152 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_pipeline.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/06 16:41:13 by maldavid #+# #+# */
/* Updated: 2024/01/10 20:20:30 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <renderer/text_pipeline.h>
#include <core/profiler.h>
#include <fstream>
#include <utils/dogica_ttf.h>
#include <iostream>
#include <cstdio>
#define STB_RECT_PACK_IMPLEMENTATION
#include <stb_rect_pack.h>
#include <core/memory.h>
#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 <stb_truetype.h>
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<Vertex> vertexData;
std::vector<uint16_t> 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<float>((color & 0x000000FF)) / 255.f,
static_cast<float>((color & 0x0000FF00) >> 8) / 255.f,
static_cast<float>((color & 0x00FF0000) >> 16) / 255.f,
static_cast<float>((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<TextData> text_data = std::make_shared<TextData>();
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&>(*_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&>(*_font_set.emplace(*_renderer, "default", dogica_ttf, scale).first);
else
_font_in_use = &const_cast<Font&>(*_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<TextDrawData&>(*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<TextDrawData&>(*res.first).init(_library, _font_in_use);
}
}
}
void TextPutPipeline::render(std::array<VkDescriptorSet, 2>& sets)
{
MLX_PROFILE_FUNCTION();
for(auto& draw : _drawlist)
{
std::shared_ptr<TextData> draw_data = _library.getTextData(draw.id);
TextureAtlas& atlas = const_cast<TextureAtlas&>(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<TextureAtlas&>(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<TextData> draw_data = _library.getTextData(draw.id);
TextureAtlas& atlas = const_cast<TextureAtlas&>(draw_data->getFontInUse().getAtlas());
atlas.resetUpdate();
}
}
void TextPutPipeline::destroy() noexcept
{
MLX_PROFILE_FUNCTION();
_library.clearLibrary();
_drawlist.clear();
_font_set.clear();
}
}

View File

@@ -1,82 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_pipeline.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <renderer/renderer.h>
#include <renderer/images/texture_atlas.h>
#include <string>
#include <stb_truetype.h>
#include <cstdint>
#include <unordered_set>
#include <renderer/text_library.h>
#include <mlx_profile.h>
#include <utils/combine_hash.h>
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<mlx::TextDrawData>
{
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<VkDescriptorSet, 2>& sets);
void destroy() noexcept;
~TextPutPipeline() = default;
private:
std::unordered_set<Font> _font_set;
TextLibrary _library;
std::unordered_set<TextDrawData> _drawlist;
Renderer* _renderer = nullptr;
Font* _font_in_use = nullptr;
};
}
#endif

View File

@@ -6,11 +6,11 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/11 22:06:09 by kbz_8 #+# #+# */ /* 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 <renderer/font.h> #include <renderer/texts/font.h>
#include <renderer/renderer.h> #include <renderer/renderer.h>
#include <core/profiler.h> #include <core/profiler.h>
#include <fstream> #include <fstream>

View File

@@ -1,24 +1,22 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* text_library.cpp :+: :+: :+: */ /* text.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/10 11:59:57 by maldavid #+# #+# */ /* Created: 2024/01/11 00:11:56 by maldavid #+# #+# */
/* Updated: 2024/01/10 18:26:44 by maldavid ### ########.fr */ /* Updated: 2024/01/11 03:31:57 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include <renderer/text_library.h>
#include <core/errors.h>
#include <renderer/renderer.h>
#include <algorithm>
#include <core/profiler.h> #include <core/profiler.h>
#include <renderer/texts/text.h>
#include <renderer/renderer.h>
namespace mlx namespace mlx
{ {
void TextData::init(std::string text, Font const* font, std::vector<Vertex> vbo_data, std::vector<uint16_t> ibo_data) void Text::init(std::string text, Font const* font, std::vector<Vertex> vbo_data, std::vector<uint16_t> ibo_data)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_text = std::move(text); _text = std::move(text);
@@ -34,64 +32,24 @@ namespace mlx
#endif #endif
} }
void TextData::bind(Renderer& renderer) noexcept void Text::bind(Renderer& renderer) noexcept
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_vbo[renderer.getActiveImageIndex()].bind(renderer); _vbo[renderer.getActiveImageIndex()].bind(renderer);
_ibo.bind(renderer); _ibo.bind(renderer);
} }
void TextData::updateVertexData(int frame, std::vector<Vertex> vbo_data) void Text::updateVertexData(int frame, std::vector<Vertex> vbo_data)
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
_vbo[frame].setData(sizeof(Vertex) * vbo_data.size(), static_cast<const void*>(vbo_data.data())); _vbo[frame].setData(sizeof(Vertex) * vbo_data.size(), static_cast<const void*>(vbo_data.data()));
} }
void TextData::destroy() noexcept void Text::destroy() noexcept
{ {
MLX_PROFILE_FUNCTION(); MLX_PROFILE_FUNCTION();
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
_vbo[i].destroy(); _vbo[i].destroy();
_ibo.destroy(); _ibo.destroy();
} }
std::shared_ptr<TextData> 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<TextData> text)
{
MLX_PROFILE_FUNCTION();
auto it = std::find_if(_cache.begin(), _cache.end(), [=](const std::pair<TextID, std::shared_ptr<TextData>>& 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();
}
} }

View File

@@ -1,38 +1,30 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* text_library.h :+: :+: :+: */ /* text.h :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/10 11:52:30 by maldavid #+# #+# */ /* Created: 2024/01/11 00:09:04 by maldavid #+# #+# */
/* Updated: 2023/12/12 23:07:13 by kbz_8 ### ########.fr */ /* Updated: 2024/01/11 00:13:25 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_TEXT_LIBRARY__ #ifndef __MLX_TEXT__
#define __MLX_TEXT_LIBRARY__ #define __MLX_TEXT__
#include <renderer/buffers/vk_vbo.h>
#include <renderer/buffers/vk_ibo.h>
#include <string> #include <string>
#include <unordered_map>
#include <memory>
#include <vector> #include <vector>
#include <cstdint> #include <renderer/texts/font.h>
#include <mlx_profile.h> #include <renderer/buffers/vk_ibo.h>
#include <renderer/font.h> #include <renderer/buffers/vk_vbo.h>
#include <renderer/core/render_core.h>
namespace mlx namespace mlx
{ {
using TextID = uint32_t; class Text
constexpr TextID nulltext = 0;
class TextData
{ {
public: public:
TextData() = default; Text() = default;
void init(std::string text, Font const* font, std::vector<Vertex> vbo_data, std::vector<uint16_t> ibo_data); void init(std::string text, Font const* font, std::vector<Vertex> vbo_data, std::vector<uint16_t> ibo_data);
void bind(class Renderer& renderer) noexcept; void bind(class Renderer& renderer) noexcept;
@@ -42,7 +34,7 @@ namespace mlx
inline const std::string& getText() const { return _text; } inline const std::string& getText() const { return _text; }
void destroy() noexcept; void destroy() noexcept;
~TextData() = default; ~Text() = default;
private: private:
std::array<D_VBO, MAX_FRAMES_IN_FLIGHT> _vbo; std::array<D_VBO, MAX_FRAMES_IN_FLIGHT> _vbo;
@@ -50,24 +42,6 @@ namespace mlx
std::string _text; std::string _text;
Font const* _font = nullptr; Font const* _font = nullptr;
}; };
class TextLibrary
{
public:
TextLibrary() = default;
std::shared_ptr<TextData> getTextData(TextID id);
TextID addTextToLibrary(std::shared_ptr<TextData> text);
void removeTextFromLibrary(TextID id);
void clearLibrary();
~TextLibrary() = default;
private:
std::unordered_map<TextID, std::shared_ptr<TextData>> _cache;
TextID _current_id = 1;
};
} }
#endif #endif

104
src/renderer/texts/text_descriptor.cpp git.filemode.normal_file
View File

@@ -0,0 +1,104 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_descriptor.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 00:23:11 by maldavid #+# #+# */
/* Updated: 2024/01/11 03:40:54 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <core/profiler.h>
#include <renderer/texts/text_descriptor.h>
#include <renderer/images/texture_atlas.h>
#include <renderer/texts/font.h>
#include <renderer/texts/text.h>
#define STB_RECT_PACK_IMPLEMENTATION
#include <stb_rect_pack.h>
#include <core/memory.h>
#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 <stb_truetype.h>
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<Vertex> vertexData;
std::vector<uint16_t> 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<float>((color & 0x000000FF)) / 255.f,
static_cast<float>((color & 0x0000FF00) >> 8) / 255.f,
static_cast<float>((color & 0x00FF0000) >> 16) / 255.f,
static_cast<float>((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> text_data = std::make_shared<Text>();
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<VkDescriptorSet, 2>& sets, Renderer& renderer)
{
MLX_PROFILE_FUNCTION();
std::shared_ptr<Text> draw_data = TextLibrary::get().getTextData(id);
TextureAtlas& atlas = const_cast<TextureAtlas&>(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<TextureAtlas&>(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<Text> draw_data = TextLibrary::get().getTextData(id);
TextureAtlas& atlas = const_cast<TextureAtlas&>(draw_data->getFontInUse().getAtlas());
atlas.resetUpdate();
}
}

65
src/renderer/texts/text_descriptor.h git.filemode.normal_file
View File

@@ -0,0 +1,65 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_descriptor.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <string>
#include <mlx_profile.h>
#include <volk.h>
#include <utils/combine_hash.h>
#include <renderer/core/drawable_resource.h>
#include <renderer/texts/text_library.h>
#include <array>
namespace mlx
{
class TextDrawDescriptor : public DrawableResource
{
friend class std::hash<TextDrawDescriptor>;
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<VkDescriptorSet, 2>& sets, Renderer& renderer) override;
void resetUpdate() override;
TextDrawDescriptor() = default;
private:
std::string _text;
};
}
namespace std
{
template <>
struct hash<mlx::TextDrawDescriptor>
{
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

67
src/renderer/texts/text_library.cpp git.filemode.normal_file
View File

@@ -0,0 +1,67 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_library.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/10 11:59:57 by maldavid #+# #+# */
/* Updated: 2024/01/11 05:19:24 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <iostream>
#include <renderer/texts/text_library.h>
#include <renderer/texts/text.h>
#include <core/errors.h>
#include <renderer/renderer.h>
#include <algorithm>
#include <core/profiler.h>
namespace mlx
{
std::shared_ptr<Text> 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> text)
{
MLX_PROFILE_FUNCTION();
auto it = std::find_if(_cache.begin(), _cache.end(), [&](const std::pair<TextID, std::shared_ptr<Text>>& 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
}
}

55
src/renderer/texts/text_library.h git.filemode.normal_file
View File

@@ -0,0 +1,55 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_library.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <renderer/buffers/vk_vbo.h>
#include <renderer/buffers/vk_ibo.h>
#include <string>
#include <unordered_map>
#include <memory>
#include <vector>
#include <cstdint>
#include <mlx_profile.h>
#include <renderer/texts/font.h>
#include <renderer/core/render_core.h>
#include <utils/singleton.h>
namespace mlx
{
using TextID = uint32_t;
constexpr TextID nulltext = 0;
class TextLibrary : public Singleton<TextLibrary>
{
friend class Singleton<TextLibrary>;
public:
std::shared_ptr<class Text> getTextData(TextID id);
TextID addTextToLibrary(std::shared_ptr<Text> text);
void removeTextFromLibrary(TextID id);
void clearLibrary();
private:
TextLibrary() = default;
~TextLibrary() = default;
private:
std::unordered_map<TextID, std::shared_ptr<class Text>> _cache;
std::vector<TextID> _invalid_ids;
TextID _current_id = 1;
};
}
#endif

66
src/renderer/texts/text_manager.cpp git.filemode.normal_file
View File

@@ -0,0 +1,66 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_manager.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/06 16:41:13 by maldavid #+# #+# */
/* Updated: 2024/01/11 04:54:16 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <renderer/texts/text_descriptor.h>
#include <renderer/texts/text_library.h>
#include <renderer/texts/text.h>
#include <renderer/texts/text_manager.h>
#include <array>
#include <core/profiler.h>
#include <fstream>
#include <utils/dogica_ttf.h>
#include <cstdio>
namespace mlx
{
void TextManager::init(Renderer& renderer) noexcept
{
MLX_PROFILE_FUNCTION();
_font_in_use = &const_cast<Font&>(*_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&>(*_font_set.emplace(renderer, "default", dogica_ttf, scale).first);
else
_font_in_use = &const_cast<Font&>(*_font_set.emplace(renderer, filepath, scale).first);
}
std::pair<DrawableResource*, bool> 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<TextDrawDescriptor&>(*res.first).init(_font_in_use);
return std::make_pair(static_cast<DrawableResource*>(&const_cast<TextDrawDescriptor&>(*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<TextDrawDescriptor&>(*res.first).init(_font_in_use);
}
return std::make_pair(static_cast<DrawableResource*>(&const_cast<TextDrawDescriptor&>(*res.first)), false);
}
void TextManager::destroy() noexcept
{
MLX_PROFILE_FUNCTION();
_text_descriptors.clear();
_font_set.clear();
}
}

48
src/renderer/texts/text_manager.h git.filemode.normal_file
View File

@@ -0,0 +1,48 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_manager.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <renderer/renderer.h>
#include <renderer/images/texture_atlas.h>
#include <string>
#include <stb_truetype.h>
#include <cstdint>
#include <unordered_set>
#include <mlx_profile.h>
#include <renderer/texts/text_descriptor.h>
#include <renderer/texts/text_library.h>
namespace mlx
{
class TextManager
{
public:
TextManager() = default;
void init(Renderer& renderer) noexcept;
std::pair<DrawableResource*, bool> 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<TextDrawDescriptor> _text_descriptors;
std::unordered_set<Font> _font_set;
Font* _font_in_use = nullptr;
};
}
#endif