From ab4d67d7649e493cc1b0e761aefd48fa0aeab498 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Mon, 16 Dec 2024 01:24:25 +0100 Subject: [PATCH] finxing memory usages --- example/build.sh | 4 +- example/main.c | 13 ++- includes/mlx.h | 3 +- includes/mlx_extended.h | 12 +-- runtime/Includes/Core/Application.h | 2 + runtime/Includes/Core/Graphics.h | 2 +- runtime/Includes/Core/Graphics.inl | 6 +- runtime/Includes/Core/SDLManager.h | 6 ++ runtime/Includes/Graphics/Mesh.h | 26 ++++++ runtime/Includes/Graphics/Mesh.inl | 59 ++++++++++++- runtime/Includes/Graphics/PutPixelManager.h | 8 +- runtime/Includes/Graphics/Scene.h | 2 +- runtime/Includes/Platform/Window.h | 37 ++++---- runtime/Includes/Renderer/Vertex.h | 4 +- runtime/Includes/Renderer/Vertex.inl | 5 ++ runtime/Sources/Core/Application.cpp | 7 +- runtime/Sources/Core/Bridge.cpp | 90 +++++++++++++++++++- runtime/Sources/Core/Memory.cpp | 9 +- runtime/Sources/Core/SDLManager.cpp | 27 ++++++ runtime/Sources/Graphics/PutPixelManager.cpp | 49 +++++++---- runtime/Sources/Graphics/Scene.cpp | 6 +- runtime/Sources/Graphics/Sprite.cpp | 6 +- runtime/Sources/Graphics/Text.cpp | 9 +- runtime/Sources/Renderer/Swapchain.cpp | 2 +- 24 files changed, 315 insertions(+), 79 deletions(-) diff --git a/example/build.sh b/example/build.sh index ab5882b..249b0f5 100755 --- a/example/build.sh +++ b/example/build.sh @@ -5,7 +5,7 @@ if [ -e a.out ]; then fi if [ $(uname -s) = 'Darwin' ]; then - clang main.c ../libmlx.dylib -L /opt/homebrew/lib -lSDL2 -g; + clang main.c ../libmlx.dylib -L /opt/homebrew/lib -lSDL2 -lm -g; else - clang main.c ../libmlx.so -lSDL2 -g -Wall -Wextra -Werror; + clang main.c ../libmlx.so -lSDL2 -lm -g -Wall -Wextra -Werror; fi diff --git a/example/main.c b/example/main.c index 205f7dc..a9f5cb7 100644 --- a/example/main.c +++ b/example/main.c @@ -1,5 +1,7 @@ #include +#include #include "../includes/mlx.h" +#include "../includes/mlx_extended.h" typedef struct { @@ -16,8 +18,11 @@ int update(void* param) static int i = 0; mlx_t* mlx = (mlx_t*)param; - if(i == 200) + if(i > 200) + { mlx_clear_window(mlx->mlx, mlx->win, 0x334D4DFF); + mlx_put_transformed_image_to_window(mlx->mlx, mlx->win, mlx->logo_bmp, 220, 40, 0.5f, 0.5f, i); + } if(i >= 250) mlx_set_font_scale(mlx->mlx, "default", 16.f); @@ -27,7 +32,6 @@ int update(void* param) mlx_string_put(mlx->mlx, mlx->win, 160, 120, 0xFF2066FF, "this text should be hidden"); mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_png, 100, 100); - //mlx_transform_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_bmp, 220, 40, 0.5f, 75.0f); mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->img, 150, 60); mlx_set_font(mlx->mlx, "default"); @@ -40,7 +44,10 @@ int update(void* param) color += (color < 255); } - //mlx_transform_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_jpg, 210, 150, 2.0f, 0.0f); + if(i < 200) + mlx_put_transformed_image_to_window(mlx->mlx, mlx->win, mlx->logo_jpg, 210, 150, 0.5f, 2.0f, 0.0f); + else + mlx_put_transformed_image_to_window(mlx->mlx, mlx->win, mlx->logo_jpg, 210, 150, fabs(sin(i / 100.0f)), fabs(cos(i / 100.0f) * 2.0f), 0.0f); mlx_set_font_scale(mlx->mlx, "default", 8.f); mlx_string_put(mlx->mlx, mlx->win, 210, 175, 0xFFAF2BFF, "hidden"); diff --git a/includes/mlx.h b/includes/mlx.h index 0d4e2f5..e39da89 100644 --- a/includes/mlx.h +++ b/includes/mlx.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 16:56:35 by maldavid #+# #+# */ -/* Updated: 2024/12/15 01:58:12 by maldavid ### ########.fr */ +/* Updated: 2024/12/15 13:59:00 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -78,7 +78,6 @@ MLX_API void mlx_destroy_context(mlx_context mlx); */ typedef struct mlx_window_create_info { - void* mlx_extension; const char* title; int width; int height; diff --git a/includes/mlx_extended.h b/includes/mlx_extended.h index 64d7357..f324d06 100644 --- a/includes/mlx_extended.h +++ b/includes/mlx_extended.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/12/14 16:17:10 by maldavid #+# #+# */ -/* Updated: 2024/12/14 17:42:06 by maldavid ### ########.fr */ +/* Updated: 2024/12/15 13:58:58 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,16 +26,6 @@ extern "C" { /* Window related functions */ -typedef struct mlx_window_create_info_extension -{ - int position_x; - int position_y; - int max_width; - int max_height; - int min_width; - int min_height; -} mlx_window_create_info_extension; - /** * @brief Sets maximum window size * diff --git a/runtime/Includes/Core/Application.h b/runtime/Includes/Core/Application.h index 5814218..4dff74f 100644 --- a/runtime/Includes/Core/Application.h +++ b/runtime/Includes/Core/Application.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace mlx { @@ -47,6 +48,7 @@ namespace mlx Inputs m_in; FontRegistry m_font_registry; ImageRegistry m_image_registry; + MeshRegistry m_mesh_registry; std::vector> m_graphics; std::shared_ptr p_last_font_bound; std::function f_loop_hook; diff --git a/runtime/Includes/Core/Graphics.h b/runtime/Includes/Core/Graphics.h index 8d69a91..eeb2820 100644 --- a/runtime/Includes/Core/Graphics.h +++ b/runtime/Includes/Core/Graphics.h @@ -26,7 +26,7 @@ namespace mlx inline void PixelPut(int x, int y, int color) noexcept; inline void StringPut(int x, int y, int, std::string str); - inline void TexturePut(NonOwningPtr texture, int x, int y, float scale, float angle); + inline void TexturePut(NonOwningPtr texture, int x, int y, float scale_x, float scale_y, float angle); inline void TryEraseSpritesInScene(NonOwningPtr texture) noexcept; diff --git a/runtime/Includes/Core/Graphics.inl b/runtime/Includes/Core/Graphics.inl index 13a33eb..f6fa842 100644 --- a/runtime/Includes/Core/Graphics.inl +++ b/runtime/Includes/Core/Graphics.inl @@ -59,10 +59,10 @@ namespace mlx p_scene->BringToDrawLayer(text.Get(), m_draw_layer); } - void GraphicsSupport::TexturePut(NonOwningPtr texture, int x, int y, float scale, float angle) + void GraphicsSupport::TexturePut(NonOwningPtr texture, int x, int y, float scale_x, float scale_y, float angle) { MLX_PROFILE_FUNCTION(); - NonOwningPtr sprite = p_scene->GetSpriteFromTexturePositionScaleRotation(texture, Vec2f{ static_cast(x), static_cast(y) }, scale, angle); + NonOwningPtr sprite = p_scene->GetSpriteFromTexturePositionScaleRotation(texture, Vec2f{ static_cast(x), static_cast(y) }, scale_x, scale_y, angle); if(!sprite) { if(m_pixelput_called) @@ -73,7 +73,7 @@ namespace mlx Sprite& new_sprite = p_scene->CreateSprite(texture); new_sprite.SetCenter(Vec2f{ texture->GetWidth() / 2.0f, texture->GetHeight() / 2.0f }); new_sprite.SetPosition(Vec2f{ static_cast(x), static_cast(y) }); - new_sprite.SetScale(Vec2f{ scale, scale }); + new_sprite.SetScale(Vec2f{ scale_x, scale_y }); new_sprite.SetRotation(angle); } else if(!p_scene->IsTextureAtGivenDrawLayer(texture, m_draw_layer)) diff --git a/runtime/Includes/Core/SDLManager.h b/runtime/Includes/Core/SDLManager.h index 952ccc4..6ed1c57 100644 --- a/runtime/Includes/Core/SDLManager.h +++ b/runtime/Includes/Core/SDLManager.h @@ -25,6 +25,12 @@ namespace mlx void SetWindowSize(Handle window, int x, int y) const noexcept; void SetWindowTitle(Handle window, std::string_view title) const noexcept; void SetWindowFullscreen(Handle window, bool enable) const noexcept; + void SetWindowMaxSize(Handle window, int x, int y) const noexcept; + void SetWindowMinSize(Handle window, int x, int y) const noexcept; + void MaximizeWindow(Handle window) const noexcept; + void MinimizeWindow(Handle window) const noexcept; + void RestoreWindow(Handle window) const noexcept; + void GetWindowPosition(Handle window, int* x, int* y) const noexcept; void GetWindowSize(Handle window, int* x, int* y) const noexcept; diff --git a/runtime/Includes/Graphics/Mesh.h b/runtime/Includes/Graphics/Mesh.h index 627b808..c0f59a9 100644 --- a/runtime/Includes/Graphics/Mesh.h +++ b/runtime/Includes/Graphics/Mesh.h @@ -12,11 +12,16 @@ namespace mlx public: struct SubMesh { + struct NoBuild {}; + VertexBuffer vbo; IndexBuffer ibo; + std::vector vertex_data; + std::vector index_data; std::size_t triangle_count = 0; inline SubMesh(const std::vector& vertices, const std::vector& indices); + inline SubMesh(const std::vector& vertices, const std::vector& indices, NoBuild); }; public: @@ -35,6 +40,27 @@ namespace mlx private: std::vector m_sub_meshes; }; + + // A registry just to avoid destroying meshes when clearing a window + class MeshRegistry + { + public: + inline MeshRegistry(); + + inline void RegisterMesh(std::shared_ptr mesh); + inline std::shared_ptr FindMesh(const std::vector& sub_meshes); + inline void UnregisterMesh(std::shared_ptr mesh); + inline void Reset(); + + inline static bool IsInit() noexcept { return s_instance != nullptr; } + inline static MeshRegistry& Get() noexcept { return *s_instance; } + + inline ~MeshRegistry(); + + private: + inline static MeshRegistry* s_instance = nullptr; + std::unordered_set> m_meshes_registry; + }; } #include diff --git a/runtime/Includes/Graphics/Mesh.inl b/runtime/Includes/Graphics/Mesh.inl index 2713ff0..5677f6f 100644 --- a/runtime/Includes/Graphics/Mesh.inl +++ b/runtime/Includes/Graphics/Mesh.inl @@ -3,7 +3,7 @@ namespace mlx { - Mesh::SubMesh::SubMesh(const std::vector& vertices, const std::vector& indices) + Mesh::SubMesh::SubMesh(const std::vector& vertices, const std::vector& indices) : vertex_data(vertices), index_data(indices) { CPUBuffer vb(vertices.size() * sizeof(Vertex)); std::memcpy(vb.GetData(), vertices.data(), vb.GetSize()); @@ -17,4 +17,61 @@ namespace mlx triangle_count = vertices.size() / 3; } + + Mesh::SubMesh::SubMesh(const std::vector& vertices, const std::vector& indices, NoBuild) : vertex_data(vertices), index_data(indices) {} + + MeshRegistry::MeshRegistry() + { + s_instance = this; + } + + void MeshRegistry::RegisterMesh(std::shared_ptr mesh) + { + m_meshes_registry.insert(mesh); + } + + std::shared_ptr MeshRegistry::FindMesh(const std::vector& sub_meshes) + { + for(const std::shared_ptr& mesh : m_meshes_registry) + { + if(mesh->GetSubMeshCount() != sub_meshes.size()) // If the number of submeshes is different than the one we want to find no need to test + continue; + bool found = true; + for(std::size_t i = 0; i < sub_meshes.size(); i++) + { + try + { + const Mesh::SubMesh& registered_sub_mesh = mesh->GetSubMesh(i); + if(registered_sub_mesh.vertex_data != sub_meshes[i].vertex_data || registered_sub_mesh.index_data != sub_meshes[i].index_data) + { + found = false; + break; + } + } + catch(...) + { + found = false; + break; + } + } + if(found) + return mesh; + } + return nullptr; + } + + void MeshRegistry::UnregisterMesh(std::shared_ptr mesh) + { + m_meshes_registry.erase(mesh); + } + + void MeshRegistry::Reset() + { + m_meshes_registry.clear(); + } + + MeshRegistry::~MeshRegistry() + { + s_instance = nullptr; + } } diff --git a/runtime/Includes/Graphics/PutPixelManager.h b/runtime/Includes/Graphics/PutPixelManager.h index 9bd14be..e630b4c 100644 --- a/runtime/Includes/Graphics/PutPixelManager.h +++ b/runtime/Includes/Graphics/PutPixelManager.h @@ -10,15 +10,17 @@ namespace mlx public: PutPixelManager(NonOwningPtr renderer) : p_renderer(renderer) {} - // Return a valid pointer when a new texture has been created + // Returns a valid pointer when a new texture has been created NonOwningPtr DrawPixel(int x, int y, std::uint64_t draw_layer, int color); void ResetRenderData(); - ~PutPixelManager(); + ~PutPixelManager() = default; private: - std::unordered_map m_textures; + std::unordered_map> m_placements; + std::vector> m_textures; NonOwningPtr p_renderer; + std::size_t m_current_texture_index = 0; }; } diff --git a/runtime/Includes/Graphics/Scene.h b/runtime/Includes/Graphics/Scene.h index 843d2b0..69d7fdc 100644 --- a/runtime/Includes/Graphics/Scene.h +++ b/runtime/Includes/Graphics/Scene.h @@ -17,7 +17,7 @@ namespace mlx Scene() = default; Sprite& CreateSprite(NonOwningPtr texture) noexcept; - NonOwningPtr GetSpriteFromTexturePositionScaleRotation(NonOwningPtr texture, const Vec2f& position, float scale, float rotation) const; + NonOwningPtr GetSpriteFromTexturePositionScaleRotation(NonOwningPtr texture, const Vec2f& position, float scale_x, float scale_y, float rotation) const; void TryEraseSpriteFromTexture(NonOwningPtr texture); bool IsTextureAtGivenDrawLayer(NonOwningPtr texture, std::uint64_t draw_layer) const; diff --git a/runtime/Includes/Platform/Window.h b/runtime/Includes/Platform/Window.h index b837820..a3a28d5 100644 --- a/runtime/Includes/Platform/Window.h +++ b/runtime/Includes/Platform/Window.h @@ -12,26 +12,31 @@ namespace mlx public: Window(const mlx_window_create_info* info, bool hidden = false); - inline Handle GetWindowHandle() const noexcept { return p_window; } - inline int GetWidth() noexcept { SDLManager::Get().GetWindowSize(p_window, &m_width, &m_height); return m_width; } - inline int GetHeight() noexcept { SDLManager::Get().GetWindowSize(p_window, &m_width, &m_height); return m_height; } - inline std::uint32_t GetID() const noexcept { return m_id; } - inline const std::string& GetName() const { return m_name; } + MLX_FORCEINLINE Handle GetWindowHandle() const noexcept { return p_window; } + MLX_FORCEINLINE int GetWidth() noexcept { SDLManager::Get().GetWindowSize(p_window, &m_width, &m_height); return m_width; } + MLX_FORCEINLINE int GetHeight() noexcept { SDLManager::Get().GetWindowSize(p_window, &m_width, &m_height); return m_height; } + MLX_FORCEINLINE std::uint32_t GetID() const noexcept { return m_id; } + MLX_FORCEINLINE const std::string& GetName() const { return m_name; } - inline void MoveMouse(int x, int y) { SDLManager::Get().MoveMouseOnWindow(p_window, x, y); } - inline void GetScreenSizeWindowIsOn(int* x, int* y) { SDLManager::Get().GetScreenSizeWindowIsOn(p_window, x, y); } + MLX_FORCEINLINE void MoveMouse(int x, int y) { SDLManager::Get().MoveMouseOnWindow(p_window, x, y); } + MLX_FORCEINLINE void GetScreenSizeWindowIsOn(int* x, int* y) { SDLManager::Get().GetScreenSizeWindowIsOn(p_window, x, y); } - inline void SetPosition(int x, int y) { SDLManager::Get().SetWindowPosition(p_window, x, y); } - inline void SetSize(int x, int y) { SDLManager::Get().SetWindowSize(p_window, x, y); m_width = x; m_height = y; } - inline void SetTitle(std::string title) { SDLManager::Get().SetWindowTitle(p_window, title); m_name = std::move(title); } - inline void SetFullscreen(bool enable) { SDLManager::Get().SetWindowFullscreen(p_window, enable); } + MLX_FORCEINLINE void SetPosition(int x, int y) { SDLManager::Get().SetWindowPosition(p_window, x, y); } + MLX_FORCEINLINE void SetSize(int x, int y) { SDLManager::Get().SetWindowSize(p_window, x, y); m_width = x; m_height = y; } + MLX_FORCEINLINE void SetTitle(std::string title) { SDLManager::Get().SetWindowTitle(p_window, title); m_name = std::move(title); } + MLX_FORCEINLINE void SetFullscreen(bool enable) { SDLManager::Get().SetWindowFullscreen(p_window, enable); } + MLX_FORCEINLINE void SetMaxSize(int x, int y) { SDLManager::Get().SetWindowMaxSize(p_window, x, y); } + MLX_FORCEINLINE void SetMinSize(int x, int y) { SDLManager::Get().SetWindowMinSize(p_window, x, y); } + MLX_FORCEINLINE void Maximize() { SDLManager::Get().MaximizeWindow(p_window); } + MLX_FORCEINLINE void Minimize() { SDLManager::Get().MinimizeWindow(p_window); } + MLX_FORCEINLINE void Restore() { SDLManager::Get().RestoreWindow(p_window); } - inline void GetPosition(int* x, int* y) { SDLManager::Get().GetWindowPosition(p_window, x, y); } - inline void GetSize(int* x, int* y) { *x = GetWidth(); *y = GetHeight(); } + MLX_FORCEINLINE void GetPosition(int* x, int* y) { SDLManager::Get().GetWindowPosition(p_window, x, y); } + MLX_FORCEINLINE void GetSize(int* x, int* y) { *x = GetWidth(); *y = GetHeight(); } - inline VkSurfaceKHR CreateVulkanSurface(VkInstance instance) const noexcept { return SDLManager::Get().CreateVulkanSurface(p_window, instance); } - inline std::vector GetRequiredVulkanInstanceExtentions() const noexcept { return SDLManager::Get().GetRequiredVulkanInstanceExtentions(p_window); } - inline Vec2ui GetVulkanDrawableSize() const noexcept { return SDLManager::Get().GetVulkanDrawableSize(p_window); } + MLX_FORCEINLINE VkSurfaceKHR CreateVulkanSurface(VkInstance instance) const noexcept { return SDLManager::Get().CreateVulkanSurface(p_window, instance); } + MLX_FORCEINLINE std::vector GetRequiredVulkanInstanceExtentions() const noexcept { return SDLManager::Get().GetRequiredVulkanInstanceExtentions(p_window); } + MLX_FORCEINLINE Vec2ui GetVulkanDrawableSize() const noexcept { return SDLManager::Get().GetVulkanDrawableSize(p_window); } void Destroy() noexcept; diff --git a/runtime/Includes/Renderer/Vertex.h b/runtime/Includes/Renderer/Vertex.h index d815a3e..f2c11d0 100644 --- a/runtime/Includes/Renderer/Vertex.h +++ b/runtime/Includes/Renderer/Vertex.h @@ -12,7 +12,9 @@ namespace mlx alignas(16) Vec2f uv = Vec2f{ 0.0f, 0.0f }; Vertex() = default; - Vertex(Vec4f p, Vec2f u) : position(std::move(p)), uv(std::move(u)) {} + inline Vertex(Vec4f p, Vec2f u) : position(std::move(p)), uv(std::move(u)) {} + + [[nodiscard]] inline bool operator==(const Vertex& rhs) const noexcept; [[nodiscard]] inline static VkVertexInputBindingDescription GetBindingDescription(); [[nodiscard]] inline static std::array GetAttributeDescriptions(); diff --git a/runtime/Includes/Renderer/Vertex.inl b/runtime/Includes/Renderer/Vertex.inl index fb09f95..e52ced8 100644 --- a/runtime/Includes/Renderer/Vertex.inl +++ b/runtime/Includes/Renderer/Vertex.inl @@ -3,6 +3,11 @@ namespace mlx { + bool Vertex::operator==(const Vertex& rhs) const noexcept + { + return position == rhs.position && uv == rhs.uv; + } + VkVertexInputBindingDescription Vertex::GetBindingDescription() { VkVertexInputBindingDescription binding_description{}; diff --git a/runtime/Sources/Core/Application.cpp b/runtime/Sources/Core/Application.cpp index 52d5583..daf35c0 100644 --- a/runtime/Sources/Core/Application.cpp +++ b/runtime/Sources/Core/Application.cpp @@ -109,12 +109,7 @@ namespace mlx Application::~Application() { - for(auto& window : m_graphics) - { - if(window && window->GetWindow()->GetName() == "让我们在月光下做爱吧") - window.reset(); - } - + m_mesh_registry.Reset(); m_font_registry.Reset(); p_render_core.reset(); p_sdl_manager.reset(); diff --git a/runtime/Sources/Core/Bridge.cpp b/runtime/Sources/Core/Bridge.cpp index a178420..2202705 100644 --- a/runtime/Sources/Core/Bridge.cpp +++ b/runtime/Sources/Core/Bridge.cpp @@ -1,3 +1,4 @@ +#include "mlx_extended.h" #include #include @@ -274,7 +275,7 @@ extern "C" mlx::NonOwningPtr texture = mlx->app->GetTexture(image); if(!texture) return; - gs->TexturePut(texture, x, y, 1.0f, 0.0f); + gs->TexturePut(texture, x, y, 1.0f, 1.0f, 0.0f); } void mlx_string_put(mlx_context mlx, mlx_window win, int x, int y, int color, char* str) @@ -299,7 +300,7 @@ extern "C" void mlx_set_font(mlx_context mlx, char* filepath) { MLX_CHECK_APPLICATION_POINTER(mlx); - if (filepath == nullptr) + if(filepath == nullptr) { mlx::Error("Font loader: filepath is NULL"); return; @@ -319,7 +320,7 @@ extern "C" void mlx_set_font_scale(mlx_context mlx, char* filepath, float scale) { MLX_CHECK_APPLICATION_POINTER(mlx); - if (filepath == nullptr) + if(filepath == nullptr) { mlx::Error("Font loader: filepath is NULL"); return; @@ -332,4 +333,87 @@ extern "C" } mlx->app->LoadFont(file, scale); } + + // Extended + + void mlx_set_window_max_size(mlx_context mlx, mlx_window win, int x, int y) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr gs = mlx->app->GetGraphicsSupport(win); + if(!gs) + return; + gs->GetWindow()->SetMaxSize(x, y); + } + + void mlx_set_window_min_size(mlx_context mlx, mlx_window win, int x, int y) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr gs = mlx->app->GetGraphicsSupport(win); + if(!gs) + return; + gs->GetWindow()->SetMinSize(x, y); + } + + void mlx_maximise_window(mlx_context mlx, mlx_window win) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr gs = mlx->app->GetGraphicsSupport(win); + if(!gs) + return; + gs->GetWindow()->Maximize(); + } + + void mlx_minimize_window(mlx_context mlx, mlx_window win) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr gs = mlx->app->GetGraphicsSupport(win); + if(!gs) + return; + gs->GetWindow()->Minimize(); + } + + void mlx_restore_window(mlx_context mlx, mlx_window win) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr gs = mlx->app->GetGraphicsSupport(win); + if(!gs) + return; + gs->GetWindow()->Restore(); + } + + void mlx_pixel_put_array(mlx_context mlx, mlx_window win, int x, int y, int* pixels) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr gs = mlx->app->GetGraphicsSupport(win); + if(!gs) + return; + } + + void mlx_get_image_region(mlx_context mlx, mlx_image image, int x, int y, int w, int h, int* dst) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr texture = mlx->app->GetTexture(image); + if(!texture) + return; + } + + void mlx_set_image_region(mlx_context mlx, mlx_image image, int x, int y, int w, int h, int* pixels) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr texture = mlx->app->GetTexture(image); + if(!texture) + return; + } + + void mlx_put_transformed_image_to_window(mlx_context mlx, mlx_window win, mlx_image image, int x, int y, float scale_x, float scale_y, float angle) + { + MLX_CHECK_APPLICATION_POINTER(mlx); + mlx::NonOwningPtr gs = mlx->app->GetGraphicsSupport(win); + if(!gs) + return; + mlx::NonOwningPtr texture = mlx->app->GetTexture(image); + if(!texture) + return; + gs->TexturePut(texture, x, y, scale_x, scale_y, angle); + } } diff --git a/runtime/Sources/Core/Memory.cpp b/runtime/Sources/Core/Memory.cpp index 1dcb660..690814b 100644 --- a/runtime/Sources/Core/Memory.cpp +++ b/runtime/Sources/Core/Memory.cpp @@ -68,15 +68,16 @@ namespace mlx #ifdef MLX_COMPILER_MSVC void* ptr2 = _aligned_realloc(ptr, alignment, size); + if(it != s_blocks.end()) + s_blocks.erase(it); #else void* ptr2 = AlignedMalloc(alignment, size); if(it != s_blocks.end()) + { std::memcpy(ptr2, ptr, it->size); + Free(ptr); + } #endif - - if(it != s_blocks.end()) - s_blocks.erase(it); - if(ptr2 != nullptr) s_blocks.emplace_back(ptr, size, true); return ptr2; diff --git a/runtime/Sources/Core/SDLManager.cpp b/runtime/Sources/Core/SDLManager.cpp index cd66caa..5fa5ce6 100644 --- a/runtime/Sources/Core/SDLManager.cpp +++ b/runtime/Sources/Core/SDLManager.cpp @@ -59,6 +59,8 @@ namespace mlx flags |= SDL_WINDOW_SHOWN; if(info->is_resizable) flags |= SDL_WINDOW_RESIZABLE; + if(info->is_fullscreen) + flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; infos->window = SDL_CreateWindow(info->title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, info->width, info->height, flags); if(!infos->window) @@ -148,6 +150,31 @@ namespace mlx SDL_SetWindowFullscreen(static_cast(window)->window, (enable ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); } + void SDLManager::SetWindowMaxSize(Handle window, int x, int y) const noexcept + { + SDL_SetWindowMaximumSize(static_cast(window)->window, x, y); + } + + void SDLManager::SetWindowMinSize(Handle window, int x, int y) const noexcept + { + SDL_SetWindowMinimumSize(static_cast(window)->window, x, y); + } + + void SDLManager::MaximizeWindow(Handle window) const noexcept + { + SDL_MaximizeWindow(static_cast(window)->window); + } + + void SDLManager::MinimizeWindow(Handle window) const noexcept + { + SDL_MinimizeWindow(static_cast(window)->window); + } + + void SDLManager::RestoreWindow(Handle window) const noexcept + { + SDL_RestoreWindow(static_cast(window)->window); + } + void SDLManager::GetWindowPosition(Handle window, int* x, int* y) const noexcept { SDL_GetWindowPosition(static_cast(window)->window, x, y); diff --git a/runtime/Sources/Graphics/PutPixelManager.cpp b/runtime/Sources/Graphics/PutPixelManager.cpp index 0993afc..1c99b65 100644 --- a/runtime/Sources/Graphics/PutPixelManager.cpp +++ b/runtime/Sources/Graphics/PutPixelManager.cpp @@ -17,24 +17,43 @@ namespace mlx else FatalError("a renderer was created without window nor render target attached (wtf)"); - #ifdef DEBUG - auto res = m_textures.try_emplace(draw_layer, CPUBuffer{}, extent.width, 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{}, extent.width, 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); + auto it = m_placements.find(draw_layer); + if(it != m_placements.end()) + { + it->second->SetPixel(x, y, color); + return nullptr; + } + + bool adjusment = false; + if(m_current_texture_index >= m_textures.size()) + { + #ifdef DEBUG + m_textures.push_back(std::make_unique(CPUBuffer{}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_put_pixel_layer_" + std::to_string(draw_layer))); + #else + m_textures.push_back(std::make_unique(CPUBuffer{}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, std::string_view{})); + #endif + m_current_texture_index++; + adjusment = true; + } + try + { + m_placements[draw_layer] = m_textures.at(m_current_texture_index - adjusment).get(); + m_textures.at(m_current_texture_index - adjusment)->Clear(VK_NULL_HANDLE, Vec4f{ 0.0f }); + m_textures.at(m_current_texture_index - adjusment)->SetPixel(x, y, color); + return m_textures.at(m_current_texture_index - adjusment).get(); + } + catch(...) + { + Error("PutPixelManager: invalid texture index; % is not in range of 0-% (internal mlx issue, please report to devs)", m_current_texture_index - 1, m_textures.size()); + return nullptr; + } } void PutPixelManager::ResetRenderData() { - m_textures.clear(); - } - - PutPixelManager::~PutPixelManager() - { - ResetRenderData(); + m_placements.clear(); + for(auto& texture : m_textures) + texture->Clear(VK_NULL_HANDLE, Vec4f{ 0.0f }); + m_current_texture_index = 0; } } diff --git a/runtime/Sources/Graphics/Scene.cpp b/runtime/Sources/Graphics/Scene.cpp index c070e64..d849d91 100644 --- a/runtime/Sources/Graphics/Scene.cpp +++ b/runtime/Sources/Graphics/Scene.cpp @@ -27,16 +27,16 @@ namespace mlx return *sprite; } - NonOwningPtr Scene::GetSpriteFromTexturePositionScaleRotation(NonOwningPtr texture, const Vec2f& position, float scale, float rotation) const + NonOwningPtr Scene::GetSpriteFromTexturePositionScaleRotation(NonOwningPtr texture, const Vec2f& position, float scale_x, float scale_y, float rotation) const { MLX_PROFILE_FUNCTION(); - auto it = std::find_if(m_drawables.begin(), m_drawables.end(), [&texture, &position, scale, rotation](std::shared_ptr drawable) + auto it = std::find_if(m_drawables.begin(), m_drawables.end(), [&texture, &position, scale_x, scale_y, rotation](std::shared_ptr drawable) { if(!drawable || drawable->GetType() != DrawableType::Sprite) return false; return static_cast(drawable.get())->GetTexture() == texture && drawable->GetPosition() == position && - drawable->GetScale() == Vec2f{ scale, scale } && + drawable->GetScale() == Vec2f{ scale_x, scale_y } && drawable->GetRotation().ToEulerAngles() == EulerAnglesf{ 0.0f, 0.0f, rotation }; }); return static_cast(it != m_drawables.end() ? it->get() : nullptr); diff --git a/runtime/Sources/Graphics/Sprite.cpp b/runtime/Sources/Graphics/Sprite.cpp index 3fd9ae0..5e1b616 100644 --- a/runtime/Sources/Graphics/Sprite.cpp +++ b/runtime/Sources/Graphics/Sprite.cpp @@ -32,7 +32,10 @@ namespace mlx 0, }; - std::shared_ptr mesh = std::make_shared(); + std::shared_ptr mesh = MeshRegistry::Get().FindMesh({ Mesh::SubMesh{ data, indices, Mesh::SubMesh::NoBuild{} } }); + if(mesh) + return mesh; + mesh = std::make_shared(); mesh->AddSubMesh({ std::move(data), std::move(indices) }); return mesh; } @@ -42,6 +45,7 @@ namespace mlx MLX_PROFILE_FUNCTION(); Verify((bool)texture, "Sprite: invalid texture (internal mlx issue, please report to devs)"); p_mesh = CreateQuad(0, 0, texture->GetWidth(), texture->GetHeight()); + MeshRegistry::Get().RegisterMesh(p_mesh); p_texture = texture; } diff --git a/runtime/Sources/Graphics/Text.cpp b/runtime/Sources/Graphics/Text.cpp index 90033d5..9498411 100644 --- a/runtime/Sources/Graphics/Text.cpp +++ b/runtime/Sources/Graphics/Text.cpp @@ -40,8 +40,13 @@ namespace mlx index_data.emplace_back(index + 0); } - std::shared_ptr mesh = std::make_shared(); - mesh->AddSubMesh({ std::move(vertex_data), std::move(index_data) }); + std::shared_ptr mesh = MeshRegistry::Get().FindMesh({ Mesh::SubMesh{ vertex_data, index_data, Mesh::SubMesh::NoBuild{} } }); + if(!mesh) + { + mesh = std::make_shared(); + mesh->AddSubMesh({ std::move(vertex_data), std::move(index_data) }); + MeshRegistry::Get().RegisterMesh(mesh); + } Init(text, font, mesh); } diff --git a/runtime/Sources/Renderer/Swapchain.cpp b/runtime/Sources/Renderer/Swapchain.cpp index bc414bb..b4b3117 100644 --- a/runtime/Sources/Renderer/Swapchain.cpp +++ b/runtime/Sources/Renderer/Swapchain.cpp @@ -79,7 +79,7 @@ namespace mlx m_surface = p_window->CreateVulkanSurface(RenderCore::Get().GetInstance()); DebugLog("Vulkan: surface created"); - m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, VK_NULL_HANDLE, false); + m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, m_swapchain, false); m_images_count = kvfGetSwapchainImagesCount(m_swapchain); m_min_images_count = kvfGetSwapchainMinImagesCount(m_swapchain);