diff --git a/example/main.c b/example/main.c index f243767..8b04bf6 100644 --- a/example/main.c +++ b/example/main.c @@ -69,7 +69,7 @@ void* create_image(mlx_t* mlx) pixel[1] = j; pixel[2] = k; pixel[3] = 0x99; - mlx_set_image_pixel(mlx->mlx, img, j, k, *((int *)pixel)); + mlx_set_image_pixel(mlx->mlx, img, j, k, *((int*)pixel)); } } return img; diff --git a/runtime/Includes/Core/Graphics.h b/runtime/Includes/Core/Graphics.h index 6a4e5e6..9da8029 100644 --- a/runtime/Includes/Core/Graphics.h +++ b/runtime/Includes/Core/Graphics.h @@ -49,8 +49,6 @@ namespace mlx int m_id; bool m_has_window; - - bool m_insert_new_pixel_put_texture = false; }; } diff --git a/runtime/Includes/Core/Graphics.inl b/runtime/Includes/Core/Graphics.inl index f0db34e..185ebfa 100644 --- a/runtime/Includes/Core/Graphics.inl +++ b/runtime/Includes/Core/Graphics.inl @@ -8,21 +8,18 @@ namespace mlx MLX_PROFILE_FUNCTION(); p_scene->ResetSprites(); m_put_pixel_manager.ResetRenderData(); - m_insert_new_pixel_put_texture = true; m_draw_layer = 0; } void GraphicsSupport::PixelPut(int x, int y, std::uint32_t color) noexcept { MLX_PROFILE_FUNCTION(); - NonOwningPtr texture = m_put_pixel_manager.DrawPixel(x, y, m_insert_new_pixel_put_texture, color); + NonOwningPtr texture = m_put_pixel_manager.DrawPixel(x, y, m_draw_layer, color); if(texture) { Sprite& new_sprite = p_scene->CreateSprite(texture); new_sprite.SetPosition(Vec2f{ 0.0f, 0.0f }); - m_draw_layer++; } - m_insert_new_pixel_put_texture = false; } void GraphicsSupport::StringPut(int x, int y, std::uint32_t color, std::string str) @@ -42,14 +39,10 @@ namespace mlx { Sprite& new_sprite = p_scene->CreateSprite(texture); new_sprite.SetPosition(Vec2f{ static_cast(x), static_cast(y) }); - m_insert_new_pixel_put_texture = true; + m_draw_layer++; } else if(!p_scene->IsTextureAtGivenDrawLayer(texture, m_draw_layer)) - { p_scene->BringToFront(std::move(sprite)); - m_insert_new_pixel_put_texture = true; - } - m_draw_layer++; } void GraphicsSupport::LoadFont(const std::filesystem::path& filepath, float scale) diff --git a/runtime/Includes/Core/Memory.h b/runtime/Includes/Core/Memory.h index 7597f01..174be18 100644 --- a/runtime/Includes/Core/Memory.h +++ b/runtime/Includes/Core/Memory.h @@ -20,7 +20,7 @@ namespace mlx private: static MemManager* s_instance; - inline static std::list s_blocks; + inline static std::vector s_blocks; }; } diff --git a/runtime/Includes/Graphics/Font.h b/runtime/Includes/Graphics/Font.h new file mode 100644 index 0000000..55b6927 --- /dev/null +++ b/runtime/Includes/Graphics/Font.h @@ -0,0 +1,37 @@ +#ifndef __MLX_FONT__ +#define __MLX_FONT__ + +#include + +namespace mlx +{ + class Font + { + public: + Font(const std::filesystem::path& path, float scale) : m_build_data(path), m_name(path.string()), m_scale(scale) {} + Font(const std::string& name, const std::vector& ttf_data, float scale) : m_build_data(ttf_data), m_name(name), m_scale(scale) {} + + void Destroy(); + + inline const std::string& GetName() const { return m_name; } + inline float GetScale() const noexcept { return m_scale; } + inline const std::array& GetCharData() const { return m_cdata; } + inline const Texture& GetTexture() const noexcept { return m_atlas; } + inline bool operator==(const Font& rhs) const { return rhs.m_name == m_name && rhs.m_scale == m_scale; } + inline bool operator!=(const Font& rhs) const { return rhs.m_name != m_name || rhs.m_scale != m_scale; } + + inline ~Font() { Destroy(); } + + private: + void BuildFont(); + + private: + std::array m_cdata; + Texture m_atlas; + std::variant> m_build_data; + std::string m_name; + float m_scale; + }; +} + +#endif diff --git a/runtime/Includes/Graphics/Mesh.h b/runtime/Includes/Graphics/Mesh.h index fc55023..627b808 100644 --- a/runtime/Includes/Graphics/Mesh.h +++ b/runtime/Includes/Graphics/Mesh.h @@ -16,20 +16,7 @@ namespace mlx IndexBuffer ibo; std::size_t triangle_count = 0; - inline SubMesh(const std::vector& vertices, const std::vector& indices) - { - CPUBuffer vb(vertices.size() * sizeof(Vertex)); - std::memcpy(vb.GetData(), vertices.data(), vb.GetSize()); - vbo.Init(vb.GetSize(), 0, "mlx_mesh"); - vbo.SetData(std::move(vb)); - - CPUBuffer ib(indices.size() * sizeof(std::uint32_t)); - std::memcpy(ib.GetData(), indices.data(), ib.GetSize()); - ibo.Init(ib.GetSize(), 0, "mlx_mesh"); - ibo.SetData(std::move(ib)); - - triangle_count = vertices.size() / 3; - } + inline SubMesh(const std::vector& vertices, const std::vector& indices); }; public: @@ -48,21 +35,8 @@ namespace mlx private: std::vector m_sub_meshes; }; - - class MeshRegistry - { - public: - MeshRegistry() = default; - - inline void RegisterMesh(std::shared_ptr mesh); - inline void UnregisterMesh(std::shared_ptr mesh); - inline bool IsMeshKnown(std::shared_ptr mesh); - - ~MeshRegistry() = default; - - private: - std::unordered_set> m_mesh_registry; - }; } +#include + #endif diff --git a/runtime/Includes/Graphics/Mesh.inl b/runtime/Includes/Graphics/Mesh.inl new file mode 100644 index 0000000..2713ff0 --- /dev/null +++ b/runtime/Includes/Graphics/Mesh.inl @@ -0,0 +1,20 @@ +#pragma once +#include + +namespace mlx +{ + Mesh::SubMesh::SubMesh(const std::vector& vertices, const std::vector& indices) + { + CPUBuffer vb(vertices.size() * sizeof(Vertex)); + std::memcpy(vb.GetData(), vertices.data(), vb.GetSize()); + vbo.Init(vb.GetSize(), 0, "mlx_mesh"); + vbo.SetData(std::move(vb)); + + CPUBuffer ib(indices.size() * sizeof(std::uint32_t)); + std::memcpy(ib.GetData(), indices.data(), ib.GetSize()); + ibo.Init(ib.GetSize(), 0, "mlx_mesh"); + ibo.SetData(std::move(ib)); + + triangle_count = vertices.size() / 3; + } +} diff --git a/runtime/Includes/Graphics/PutPixelManager.h b/runtime/Includes/Graphics/PutPixelManager.h index 5249045..5f76609 100644 --- a/runtime/Includes/Graphics/PutPixelManager.h +++ b/runtime/Includes/Graphics/PutPixelManager.h @@ -11,13 +11,13 @@ namespace mlx PutPixelManager(NonOwningPtr renderer) : p_renderer(renderer) {} // Return a valid pointer when a new texture has been created - NonOwningPtr DrawPixel(int x, int y, bool insert_new_texture, std::uint32_t color); + NonOwningPtr DrawPixel(int x, int y, std::uint64_t draw_layer, std::uint32_t color); void ResetRenderData(); ~PutPixelManager(); private: - std::list m_textures; + std::unordered_map m_textures; NonOwningPtr p_renderer; }; } diff --git a/runtime/Includes/Graphics/Sprite.h b/runtime/Includes/Graphics/Sprite.h index 8efcf8d..49bde83 100644 --- a/runtime/Includes/Graphics/Sprite.h +++ b/runtime/Includes/Graphics/Sprite.h @@ -15,6 +15,7 @@ namespace mlx public: Sprite(NonOwningPtr texture); + Sprite(std::shared_ptr mesh, NonOwningPtr texture); inline void SetColor(Vec4f color) noexcept { m_color = color; } inline void SetPosition(Vec2f position) noexcept { m_position = position; } diff --git a/runtime/Includes/PreCompiled.h b/runtime/Includes/PreCompiled.h index fde27c8..11b2a78 100644 --- a/runtime/Includes/PreCompiled.h +++ b/runtime/Includes/PreCompiled.h @@ -54,7 +54,7 @@ #include #endif -#if defined(MLX_PLAT_LINUX) +#ifdef MLX_PLAT_LINUX #include // sincos #endif diff --git a/runtime/Includes/Renderer/Image.h b/runtime/Includes/Renderer/Image.h index d787e9f..b262224 100644 --- a/runtime/Includes/Renderer/Image.h +++ b/runtime/Includes/Renderer/Image.h @@ -48,6 +48,10 @@ namespace mlx [[nodiscard]] MLX_FORCEINLINE bool IsInit() const noexcept { return m_image != VK_NULL_HANDLE; } [[nodiscard]] MLX_FORCEINLINE ImageType GetType() const noexcept { return m_type; } + #ifdef DEBUG + [[nodiscard]] MLX_FORCEINLINE const std::string& GetDebugName() const { return m_debug_name; } + #endif + virtual ~Image() = default; protected: diff --git a/runtime/Includes/Renderer/RenderPasses/2DPass.h b/runtime/Includes/Renderer/RenderPasses/2DPass.h index 8486818..a9cc015 100644 --- a/runtime/Includes/Renderer/RenderPasses/2DPass.h +++ b/runtime/Includes/Renderer/RenderPasses/2DPass.h @@ -11,7 +11,7 @@ namespace mlx { public: Render2DPass() = default; - void Init(class Renderer& renderer); + void Init(); void Pass(class Scene& scene, class Renderer& renderer, class Texture& render_target); void Destroy(); ~Render2DPass() = default; diff --git a/runtime/Includes/Renderer/RenderPasses/FinalPass.h b/runtime/Includes/Renderer/RenderPasses/FinalPass.h index e1baa1f..ead2c3a 100644 --- a/runtime/Includes/Renderer/RenderPasses/FinalPass.h +++ b/runtime/Includes/Renderer/RenderPasses/FinalPass.h @@ -11,7 +11,7 @@ namespace mlx { public: FinalPass() = default; - void Init(class Renderer& renderer); + void Init(); void Pass(class Scene& scene, class Renderer& renderer, class Texture& render_target); void Destroy(); ~FinalPass() = default; diff --git a/runtime/Includes/Renderer/RenderPasses/Passes.h b/runtime/Includes/Renderer/RenderPasses/Passes.h index 3888a23..56aa74d 100644 --- a/runtime/Includes/Renderer/RenderPasses/Passes.h +++ b/runtime/Includes/Renderer/RenderPasses/Passes.h @@ -11,9 +11,11 @@ namespace mlx { public: RenderPasses() = default; + void Init(class Renderer& renderer); void Pass(class Scene& scene, class Renderer& renderer); void Destroy(); + ~RenderPasses() = default; private: diff --git a/runtime/Sources/Graphics/Font.cpp b/runtime/Sources/Graphics/Font.cpp new file mode 100644 index 0000000..294bc9a --- /dev/null +++ b/runtime/Sources/Graphics/Font.cpp @@ -0,0 +1,7 @@ +#include + +#include + +namespace mlx +{ +} diff --git a/runtime/Sources/Graphics/PutPixelManager.cpp b/runtime/Sources/Graphics/PutPixelManager.cpp index b41e047..0523164 100644 --- a/runtime/Sources/Graphics/PutPixelManager.cpp +++ b/runtime/Sources/Graphics/PutPixelManager.cpp @@ -5,26 +5,20 @@ namespace mlx { - NonOwningPtr PutPixelManager::DrawPixel(int x, int y, bool insert_new_texture, std::uint32_t color) + NonOwningPtr PutPixelManager::DrawPixel(int x, int y, std::uint64_t draw_layer, std::uint32_t color) { Verify((bool)p_renderer, "invalid renderer pointer"); VkExtent2D swapchain_extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain()); - if(insert_new_texture) - { - #ifdef DEBUG - Texture& texture = m_textures.emplace_back(CPUBuffer{}, swapchain_extent.width, swapchain_extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_put_pixel_layer_" + std::to_string(m_textures.size())); - #else - Texture& texture = m_textures.emplace_back(CPUBuffer{}, swapchain_extent.width, swapchain_extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, std::string_view{}); - #endif - texture.Clear(VK_NULL_HANDLE, Vec4f{ 0.0f }); - } - if(!m_textures.empty()) - { - m_textures.back().SetPixel(x, y, color); - return (insert_new_texture ? &m_textures.back() : nullptr); - } - return nullptr; + #ifdef DEBUG + auto res = m_textures.try_emplace(draw_layer, CPUBuffer{}, swapchain_extent.width, swapchain_extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_put_pixel_layer_" + std::to_string(draw_layer)); + #else + auto res = m_textures.try_emplace(draw_layer, CPUBuffer{}, swapchain_extent.width, swapchain_extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, std::string_view{}); + #endif + if(res.second) + res.first->second.Clear(VK_NULL_HANDLE, Vec4f{ 0.0f }); + res.first->second.SetPixel(x, y, color); + return (res.second ? &res.first->second : nullptr); } void PutPixelManager::ResetRenderData() diff --git a/runtime/Sources/Graphics/Scene.cpp b/runtime/Sources/Graphics/Scene.cpp index 1a76ec6..6335974 100644 --- a/runtime/Sources/Graphics/Scene.cpp +++ b/runtime/Sources/Graphics/Scene.cpp @@ -8,6 +8,19 @@ namespace mlx Sprite& Scene::CreateSprite(NonOwningPtr texture) noexcept { MLX_PROFILE_FUNCTION(); + Verify((bool)texture, "Scene: invalid texture (internal mlx issue, please report to devs)"); + + #pragma omp parallel for + for(auto& sprite : m_sprites) + { + if(texture->GetWidth() == sprite->GetTexture()->GetWidth() && texture->GetHeight() == sprite->GetTexture()->GetHeight()) + { + std::shared_ptr new_sprite = std::make_shared(sprite->GetMesh(), texture); + m_sprites.push_back(new_sprite); + return *new_sprite; + } + } + std::shared_ptr sprite = std::make_shared(texture); m_sprites.push_back(sprite); return *sprite; @@ -52,6 +65,7 @@ namespace mlx bool Scene::IsTextureAtGivenDrawLayer(NonOwningPtr texture, std::uint64_t draw_layer) const { + MLX_PROFILE_FUNCTION(); if(draw_layer >= m_sprites.size()) return false; return m_sprites[draw_layer]->GetTexture() == texture; diff --git a/runtime/Sources/Graphics/Sprite.cpp b/runtime/Sources/Graphics/Sprite.cpp index e9fd03f..caa0c64 100644 --- a/runtime/Sources/Graphics/Sprite.cpp +++ b/runtime/Sources/Graphics/Sprite.cpp @@ -44,4 +44,13 @@ namespace mlx p_mesh = CreateQuad(0, 0, texture->GetWidth(), texture->GetHeight()); p_texture = texture; } + + Sprite::Sprite(std::shared_ptr mesh, NonOwningPtr texture) + { + MLX_PROFILE_FUNCTION(); + Verify((bool)texture, "Sprite: invalid texture (internal mlx issue, please report to devs)"); + Verify((bool)mesh, "Sprite: invalid mesh (internal mlx issue, please report to devs)"); + p_mesh = mesh; + p_texture = texture; + } } diff --git a/runtime/Sources/Renderer/Pipelines/Graphics.cpp b/runtime/Sources/Renderer/Pipelines/Graphics.cpp index 7013dfd..401a877 100644 --- a/runtime/Sources/Renderer/Pipelines/Graphics.cpp +++ b/runtime/Sources/Renderer/Pipelines/Graphics.cpp @@ -7,7 +7,7 @@ namespace mlx { - void GraphicPipeline::Init(const GraphicPipelineDescriptor& descriptor, std::string_view debug_name) + void GraphicPipeline::Init(const GraphicPipelineDescriptor& descriptor, [[maybe_unused]] std::string_view debug_name) { MLX_PROFILE_FUNCTION(); if(!descriptor.vertex_shader || !descriptor.fragment_shader) diff --git a/runtime/Sources/Renderer/RenderPasses/2DPass.cpp b/runtime/Sources/Renderer/RenderPasses/2DPass.cpp index 6283a18..1cd2e25 100644 --- a/runtime/Sources/Renderer/RenderPasses/2DPass.cpp +++ b/runtime/Sources/Renderer/RenderPasses/2DPass.cpp @@ -14,7 +14,7 @@ namespace mlx Vec4f position; }; - void Render2DPass::Init(Renderer& renderer) + void Render2DPass::Init() { MLX_PROFILE_FUNCTION(); diff --git a/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp b/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp index ac9b73e..7464c6e 100644 --- a/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp +++ b/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp @@ -7,7 +7,7 @@ namespace mlx { - void FinalPass::Init(Renderer& renderer) + void FinalPass::Init() { MLX_PROFILE_FUNCTION(); ShaderLayout vertex_shader_layout( diff --git a/runtime/Sources/Renderer/RenderPasses/Passes.cpp b/runtime/Sources/Renderer/RenderPasses/Passes.cpp index ce31c2c..9f5dc12 100644 --- a/runtime/Sources/Renderer/RenderPasses/Passes.cpp +++ b/runtime/Sources/Renderer/RenderPasses/Passes.cpp @@ -7,8 +7,8 @@ namespace mlx { void RenderPasses::Init(Renderer& renderer) { - m_2Dpass.Init(renderer); - m_final.Init(renderer); + m_2Dpass.Init(); + m_final.Init(); func::function functor = [this, renderer](const EventBase& event) { if(event.What() == Event::ResizeEventCode)