From 62bd63c364c7afc18826afcc66579744171b64df Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Tue, 17 Dec 2024 02:33:04 +0100 Subject: [PATCH] adding multiple hooks supports for events and loop --- .github/workflows/windows.yml | 4 ---- Makefile | 21 +++++++++++--------- example/main.c | 11 ++++------ includes/mlx.h | 6 +++--- runtime/Includes/Core/Application.h | 16 +++++++++++---- runtime/Includes/Core/Application.inl | 9 ++++----- runtime/Includes/Core/Logs.inl | 4 ++-- runtime/Includes/Platform/Inputs.h | 11 +++++----- runtime/Sources/Core/Application.cpp | 7 +++++-- runtime/Sources/Core/Bridge.cpp | 19 +++++++++--------- runtime/Sources/Graphics/PutPixelManager.cpp | 3 ++- runtime/Sources/Platform/Inputs.cpp | 8 ++++++-- runtime/Sources/Renderer/Descriptor.cpp | 2 +- runtime/Sources/Renderer/Image.cpp | 13 +++++++----- xmake.lua | 2 ++ 15 files changed, 77 insertions(+), 59 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ad4d479..6e3abd5 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -50,7 +50,3 @@ jobs: # Build the mlx - name: Build MacroLibX run: xmake --yes - - # Build the example - - name: Build Example - run: xmake build --yes Test diff --git a/Makefile b/Makefile index 5a5c659..7dd2529 100644 --- a/Makefile +++ b/Makefile @@ -33,17 +33,19 @@ INCLUDES = -I./includes -I./runtime/Includes -I./runtime/Sources -I./third_party CXXPCHFLAGS = -xc++-header -PCH = runtime/Includes/PreCompiled.h -GCH = +PCH_SOURCE = runtime/Includes/PreCompiled.h +GCH = runtime/Includes/PreCompiled.h.gch +CCH = runtime/Includes/PreCompiled.h.pch +PCH = -NZRRC = nzslc +NZRRC ?= nzslc ifeq ($(TOOLCHAIN), gcc) CXX = g++ - GCH = runtime/Includes/PreCompiled.h.gch + PCH = $(GCH) CXXFLAGS += -Wno-error=cpp else - GCH = runtime/Includes/PreCompiled.h.pch + PCH = $(CCH) CXXFLAGS += -Wno-error=#warning -include-pch $(GCH) endif @@ -115,7 +117,7 @@ ifeq ($(OBJS_TOTAL), 0) # To avoid division per 0 endif CURR_OBJ = 0 -$(OBJ_DIR)/%.o: %.cpp $(GCH) +$(OBJ_DIR)/%.o: %.cpp $(PCH) @mkdir -p $(dir $@) @$(eval CURR_OBJ=$(shell echo $$(( $(CURR_OBJ) + 1 )))) @$(eval PERCENT=$(shell echo $$(( $(CURR_OBJ) * 100 / $(OBJS_TOTAL) )))) @@ -139,9 +141,9 @@ CURR_SPV = 0 all: _printbuildinfos @$(MAKE) $(NAME) -$(GCH): +$(PCH): @printf "$(COLOR)($(_BOLD)%3s%%$(_RESET)$(COLOR)) $(_RESET)Compiling $(_BOLD)PreCompiled header$(_RESET)\n" "0" - @$(CXX) $(CXXPCHFLAGS) $(INCLUDES) $(PCH) -o $(GCH) + @$(CXX) $(CXXPCHFLAGS) $(INCLUDES) $(PCH_SOURCE) -o $(PCH) $(NAME): $(OBJS) @printf "Linking $(_BOLD)$(NAME)$(_RESET)\n" @@ -163,7 +165,8 @@ clean: @$(RM) $(OBJ_DIR) @printf "Cleaned $(_BOLD)$(OBJ_DIR)$(_RESET)\n" @$(RM) $(GCH) - @printf "Cleaned $(_BOLD)$(GCH)$(_RESET)\n" + @$(RM) $(CCH) + @printf "Cleaned pre compiled header\n" fclean: clean @$(RM) $(NAME) diff --git a/example/main.c b/example/main.c index a06fc0e..8868be8 100644 --- a/example/main.c +++ b/example/main.c @@ -18,7 +18,7 @@ typedef struct static mlx_color pixels_circle[CIRCLE_DIAMETER * CIRCLE_DIAMETER] = { 0 }; -int update(void* param) +void update(void* param) { static int i = 0; mlx_t* mlx = (mlx_t*)param; @@ -60,7 +60,6 @@ int update(void* param) mlx_pixel_put_region(mlx->mlx, mlx->win, 200, 170, CIRCLE_DIAMETER, CIRCLE_DIAMETER, pixels_circle); i++; - return 0; } mlx_image create_image(mlx_t* mlx) @@ -87,7 +86,7 @@ mlx_image create_image(mlx_t* mlx) return img; } -int key_hook(int key, void* param) +void key_hook(int key, void* param) { int x; int y; @@ -123,14 +122,12 @@ int key_hook(int key, void* param) default : break; } - return 0; } -int window_hook(int event, void* param) +void window_hook(int event, void* param) { if(event == 0) mlx_loop_end(((mlx_t*)param)->mlx); - return 0; } int main(void) @@ -179,7 +176,7 @@ int main(void) mlx_set_font_scale(mlx.mlx, "font.ttf", 16.f); mlx_string_put(mlx.mlx, mlx.win, 20, 20, (mlx_color){ .rgba = 0x0020FFFF }, "that text will disappear"); - mlx_loop_hook(mlx.mlx, update, &mlx); + mlx_add_loop_hook(mlx.mlx, update, &mlx); mlx_loop(mlx.mlx); mlx_destroy_image(mlx.mlx, mlx.logo_png); diff --git a/includes/mlx.h b/includes/mlx.h index f41edf2..56f461e 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/17 00:27:35 by maldavid ### ########.fr */ +/* Updated: 2024/12/17 02:23:40 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -213,7 +213,7 @@ MLX_API void mlx_get_screen_size(mlx_context mlx, mlx_window win, int* w, int* h * @param f The function * @param param Param to give to the function passed */ -MLX_API void mlx_loop_hook(mlx_context mlx, int (*f)(void*), void* param); +MLX_API void mlx_add_loop_hook(mlx_context mlx, void(*f)(void*), void* param); /** * @brief Starts the internal main loop @@ -289,7 +289,7 @@ typedef enum mlx_event_type * @param f Function to be executed * @param param Parameter given to the function */ -MLX_API void mlx_on_event(mlx_context mlx, mlx_window win, mlx_event_type event, int (*f)(int, void*), void* param); +MLX_API void mlx_on_event(mlx_context mlx, mlx_window win, mlx_event_type event, void(*f)(int, void*), void* param); diff --git a/runtime/Includes/Core/Application.h b/runtime/Includes/Core/Application.h index 4dff74f..3cc30ee 100644 --- a/runtime/Includes/Core/Application.h +++ b/runtime/Includes/Core/Application.h @@ -21,7 +21,7 @@ namespace mlx inline void GetScreenSize(mlx_window win, int* w, int* h) noexcept; inline void SetFPSCap(std::uint32_t fps) noexcept; - inline void OnEvent(mlx_window win, int event, int (*funct_ptr)(int, void*), void* param) noexcept; + inline void OnEvent(mlx_window win, int event, void(*f)(int, void*), void* param) noexcept; inline mlx_window NewGraphicsSuport(const mlx_window_create_info* info); inline NonOwningPtr GetGraphicsSupport(mlx_window win); @@ -32,7 +32,7 @@ namespace mlx inline NonOwningPtr GetTexture(mlx_image image); void DestroyTexture(mlx_image img); - inline void LoopHook(int (*f)(void*), void* param); + inline void AddLoopHook(void(*f)(void*), void* param); inline void LoopEnd() noexcept; inline void LoadFont(const std::filesystem::path& filepath, float scale); @@ -41,6 +41,15 @@ namespace mlx ~Application(); + private: + struct Hook + { + func::function fn; + void* param; + + Hook(func::function fn, void* param) : fn(fn), param(param) {} + }; + private: std::unique_ptr p_mem_manager; // Putting ptr here to initialise them before inputs, even if it f*cks the padding std::unique_ptr p_sdl_manager; @@ -50,13 +59,12 @@ namespace mlx ImageRegistry m_image_registry; MeshRegistry m_mesh_registry; std::vector> m_graphics; + std::vector m_hooks; std::shared_ptr p_last_font_bound; - std::function f_loop_hook; std::unique_ptr p_render_core; #ifdef PROFILER std::unique_ptr p_profiler; #endif - Handle p_param = nullptr; }; } diff --git a/runtime/Includes/Core/Application.inl b/runtime/Includes/Core/Application.inl index 822c4d9..cbdbbb2 100644 --- a/runtime/Includes/Core/Application.inl +++ b/runtime/Includes/Core/Application.inl @@ -40,12 +40,12 @@ namespace mlx *y = m_in.GetY(); } - void Application::OnEvent(mlx_window win, int event, int (*funct_ptr)(int, void*), void* param) noexcept + void Application::OnEvent(mlx_window win, int event, void(*f)(int, void*), void* param) noexcept { CHECK_WINDOW_PTR(win, ); if(!m_graphics[win->id]->HasWindow()) return; - m_in.OnEvent(m_graphics[win->id]->GetWindow()->GetID(), event, funct_ptr, param); + m_in.OnEvent(m_graphics[win->id]->GetWindow()->GetID(), event, f, param); } void Application::SetFPSCap(std::uint32_t fps) noexcept @@ -122,10 +122,9 @@ namespace mlx return texture; } - void Application::LoopHook(int (*f)(void*), void* param) + void Application::AddLoopHook(void(*f)(void*), void* param) { - f_loop_hook = f; - p_param = param; + m_hooks.emplace_back(f, param); } void Application::LoopEnd() noexcept diff --git a/runtime/Includes/Core/Logs.inl b/runtime/Includes/Core/Logs.inl index 1275383..b9f66e4 100644 --- a/runtime/Includes/Core/Logs.inl +++ b/runtime/Includes/Core/Logs.inl @@ -93,7 +93,7 @@ namespace mlx try { std::stringstream ss; - ss << Format("Verification failed : %", message, args...); + ss << Format("Verification failed: %", message, args...); Logs::Report(LogType::FatalError, line, file, function, ss.str()); } catch(const std::exception& e) @@ -112,7 +112,7 @@ namespace mlx try { std::stringstream ss; - ss << Format("Assertion failed : %", message, args...); + ss << Format("Assertion failed: %", message, args...); Logs::Report(LogType::FatalError, line, file, function, ss.str()); } catch(const std::exception& e) diff --git a/runtime/Includes/Platform/Inputs.h b/runtime/Includes/Platform/Inputs.h index 3ac5b90..e2b7c9a 100644 --- a/runtime/Includes/Platform/Inputs.h +++ b/runtime/Includes/Platform/Inputs.h @@ -12,8 +12,10 @@ namespace mlx public: struct Hook { - func::function hook; + func::function fn; void* param = nullptr; + + Hook(func::function fn, void* param) : fn(fn), param(param) {} }; public: @@ -33,17 +35,16 @@ namespace mlx MLX_FORCEINLINE constexpr void Finish() noexcept { m_run = false; } MLX_FORCEINLINE constexpr void Run() noexcept { m_run = true; } - inline void OnEvent(std::uint32_t id, int event, int (*funct_ptr)(int, void*), void* param) noexcept + inline void OnEvent(std::uint32_t id, int event, void(*f)(int, void*), void* param) noexcept { - m_events_hooks[id][event].hook = funct_ptr; - m_events_hooks[id][event].param = param; + m_events_hooks[id][event].emplace_back(f, param); } ~Inputs() = default; private: std::unordered_map> m_windows; - std::unordered_map> m_events_hooks; + std::unordered_map, 6>> m_events_hooks; bool m_run = false; }; } diff --git a/runtime/Sources/Core/Application.cpp b/runtime/Sources/Core/Application.cpp index daf35c0..b3cf579 100644 --- a/runtime/Sources/Core/Application.cpp +++ b/runtime/Sources/Core/Application.cpp @@ -38,8 +38,11 @@ namespace mlx m_in.FetchInputs(); - if(f_loop_hook) - f_loop_hook(p_param); + for(const auto& hook : m_hooks) + { + if(hook.fn) + hook.fn(hook.param); + } for(auto& gs : m_graphics) { diff --git a/runtime/Sources/Core/Bridge.cpp b/runtime/Sources/Core/Bridge.cpp index eff5d65..835dce2 100644 --- a/runtime/Sources/Core/Bridge.cpp +++ b/runtime/Sources/Core/Bridge.cpp @@ -31,12 +31,13 @@ extern "C" mlx::MemManager::Get(); // just to initialize the C garbage collector - try { __internal_application_ptr = new mlx::Application; } - catch(...) { mlx::FatalError("internal application memory allocation failed"); } + __internal_application_ptr = new mlx::Application; + if(__internal_application_ptr == nullptr) + mlx::FatalError("internal application memory allocation failed"); - mlx_context_handler* context; - try { context = new mlx_context_handler; } - catch(...) { mlx::FatalError("mlx_context memory allocation failed"); } + mlx_context_handler* context = new mlx_context_handler; + if(context == nullptr) + mlx::FatalError("mlx_context memory allocation failed"); context->app = __internal_application_ptr; return context; } @@ -150,10 +151,10 @@ extern "C" gs->GetWindow()->GetScreenSizeWindowIsOn(w, h); } - void mlx_loop_hook(mlx_context mlx, int (*f)(void*), void* param) + void mlx_add_loop_hook(mlx_context mlx, void(*f)(void*), void* param) { MLX_CHECK_APPLICATION_POINTER(mlx); - mlx->app->LoopHook(f, param); + mlx->app->AddLoopHook(f, param); } void mlx_loop(mlx_context mlx) @@ -195,10 +196,10 @@ extern "C" mlx->app->GetMousePos(x, y); } - void mlx_on_event(mlx_context mlx, mlx_window win, mlx_event_type event, int (*funct_ptr)(int, void*), void* param) + void mlx_on_event(mlx_context mlx, mlx_window win, mlx_event_type event, void(*f)(int, void*), void* param) { MLX_CHECK_APPLICATION_POINTER(mlx); - mlx->app->OnEvent(win, static_cast(event), funct_ptr, param); + mlx->app->OnEvent(win, static_cast(event), f, param); } void mlx_pixel_put(mlx_context mlx, mlx_window win, int x, int y, mlx_color color) diff --git a/runtime/Sources/Graphics/PutPixelManager.cpp b/runtime/Sources/Graphics/PutPixelManager.cpp index 1adc0a6..41ba4de 100644 --- a/runtime/Sources/Graphics/PutPixelManager.cpp +++ b/runtime/Sources/Graphics/PutPixelManager.cpp @@ -54,13 +54,14 @@ namespace mlx if(m_current_texture_index >= m_textures.size()) { - VkExtent2D extent; + VkExtent2D extent{ .width = 0, .height = 0 }; if(p_renderer->GetWindow()) extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain().Get()); else if(p_renderer->GetRenderTarget()) extent = VkExtent2D{ .width = p_renderer->GetRenderTarget()->GetWidth(), .height = p_renderer->GetRenderTarget()->GetHeight() }; else FatalError("a renderer was created without window nor render target attached (wtf)"); + #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(m_current_texture_index))); #else diff --git a/runtime/Sources/Platform/Inputs.cpp b/runtime/Sources/Platform/Inputs.cpp index 25ea36f..dd4c905 100644 --- a/runtime/Sources/Platform/Inputs.cpp +++ b/runtime/Sources/Platform/Inputs.cpp @@ -12,9 +12,13 @@ namespace mlx { if(!m_windows.contains(window_id)) return; - if(!m_events_hooks.contains(window_id) || !m_events_hooks[window_id][event].hook) + if(!m_events_hooks.contains(window_id) || m_events_hooks[window_id][event].empty()) return; - m_events_hooks[window_id][event].hook(code, m_events_hooks[window_id][event].param); + for(const auto& hook : m_events_hooks[window_id][event]) + { + if(hook.fn) + hook.fn(code, hook.param); + } }); } diff --git a/runtime/Sources/Renderer/Descriptor.cpp b/runtime/Sources/Renderer/Descriptor.cpp index 6436770..8d7afca 100644 --- a/runtime/Sources/Renderer/Descriptor.cpp +++ b/runtime/Sources/Renderer/Descriptor.cpp @@ -80,7 +80,7 @@ namespace mlx case ShaderType::Vertex: vulkan_shader_stage = VK_SHADER_STAGE_VERTEX_BIT; break; case ShaderType::Fragment: vulkan_shader_stage = VK_SHADER_STAGE_FRAGMENT_BIT; break; - default : FatalError("wtf"); break; + default: FatalError("wtf"); vulkan_shader_stage = VK_SHADER_STAGE_VERTEX_BIT; /* Just to shut up warnings */ break; } std::vector bindings(layout.binds.size()); diff --git a/runtime/Sources/Renderer/Image.cpp b/runtime/Sources/Renderer/Image.cpp index af34d74..9757ace 100644 --- a/runtime/Sources/Renderer/Image.cpp +++ b/runtime/Sources/Renderer/Image.cpp @@ -43,6 +43,8 @@ namespace mlx void Image::Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, bool is_multisampled, [[maybe_unused]] std::string_view debug_name) { MLX_PROFILE_FUNCTION(); + Verify(width > 0 && height > 0, "width or height cannot be null"); + m_type = type; m_width = width; m_height = height; @@ -387,6 +389,11 @@ namespace mlx int channels; std::uint8_t* data = stbi_load(filename.c_str(), &size.x, &size.y, &channels, 4); + if(data == nullptr) + { + Error("Image loader: could not load % due to %", file, stbi_failure_reason()); + return nullptr; + } CallOnExit defer([&]() { stbi_image_free(data); }); CPUBuffer buffer(size.x * size.y * 4); @@ -396,10 +403,6 @@ namespace mlx *w = size.x; if(h != nullptr) *h = size.y; - - Texture* texture; - try { texture = new Texture(std::move(buffer), size.x, size.y, VK_FORMAT_R8G8B8A8_SRGB, false, std::move(filename)); } - catch(...) { return nullptr; } - return texture; + return new Texture(std::move(buffer), size.x, size.y, VK_FORMAT_R8G8B8A8_SRGB, false, std::move(filename)); } } diff --git a/xmake.lua b/xmake.lua index c145724..1ffbc7e 100644 --- a/xmake.lua +++ b/xmake.lua @@ -85,6 +85,7 @@ target("mlx") end) target_end() +--[[ target("Test") set_default(false) set_kind("binary") @@ -100,3 +101,4 @@ target("Test") add_packages("libsdl") target_end() +]]--