begenning the refactor

This commit is contained in:
2024-03-27 23:03:54 +01:00
parent e5ff232065
commit 6bbf1e196d
131 changed files with 2135 additions and 1192 deletions

71
runtime/Includes/Core/Application.h git.filemode.normal_file
View File

@@ -0,0 +1,71 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Application.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 21:49:46 by maldavid #+# #+# */
/* Updated: 2024/03/27 21:00:53 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_APPLICATION__
#define __MLX_APPLICATION__
#include <Core/Graphics.h>
#include <Platform/Inputs.h>
#include <Core/Fps.h>
namespace mlx
{
class Application
{
public:
Application();
inline void GetMousePos(int* x, int* y) noexcept;
inline void MouseMove(void* win, int x, int y) noexcept;
inline void OnEvent(void* win, int event, int (*funct_ptr)(int, void*), void* param) noexcept;
inline void GetScreenSize(void* win, int* w, int* h) noexcept;
inline void SetFPSCap(std::uint32_t fps) noexcept;
inline void* NewGraphicsSuport(std::size_t w, std::size_t h, const char* title);
inline void ClearGraphicsSupport(void* win);
inline void DestroyGraphicsSupport(void* win);
inline void PixelPut(void* win, int x, int y, std::uint32_t color) const noexcept;
inline void StringPut(void* win, int x, int y, std::uint32_t color, char* str);
void* NewTexture(int w, int h);
void* NewStbTexture(char* file, int* w, int* h); // stb textures are image files (png, jpg, bpm, ...)
inline void TexturePut(void* win, void* img, int x, int y);
inline int GetTexturePixel(void* img, int x, int y);
inline void SetTexturePixel(void* img, int x, int y, std::uint32_t color);
void DestroyTexture(void* ptr);
inline void LoopHook(int (*f)(void*), void* param);
inline void LoopEnd() noexcept;
inline void LoadFont(void* win, const std::filesystem::path& filepath, float scale);
void Run() noexcept;
~Application();
private:
FpsManager m_fps;
std::list<Texture> m_textures;
std::vector<std::unique_ptr<GraphicsSupport>> m_graphics;
std::function<int(void*)> f_loop_hook;
std::unique_ptr<Input> p_in;
void* p_param = nullptr;
};
}
#include <core/application.inl>
#endif // __MLX_APPLICATION__

196
runtime/Includes/Core/Application.inl git.filemode.normal_file
View File

@@ -0,0 +1,196 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* application.inl :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 21:49:46 by maldavid #+# #+# */
/* Updated: 2023/04/02 14:56:27 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <Core/Application.h>
#define CHECK_WINDOW_PTR(win) \
if(win == nullptr) \
{ \
Error("invalid window ptr (NULL)"); \
return; \
} \
else if(*static_cast<int*>(win) < 0 || *static_cast<int*>(win) > static_cast<int>(_graphics.size()))\
{ \
Error("invalid window ptr"); \
return; \
} else {}
#define CHECK_IMAGE_PTR(img, retval) \
if(img == nullptr) \
{ \
Error("invalid image ptr (NULL)"); \
retval; \
} \
else if(std::find_if(_textures.begin(), _textures.end(), [=](const Texture& texture) \
{ \
return &texture == img; \
}) == _textures.end()) \
{ \
Error(e_kind::error, "invalid image ptr"); \
retval; \
} else {}
namespace mlx
{
void Application::GetMousePos(int* x, int* y) noexcept
{
*x = p_in->GetX();
*y = p_in->GetY();
}
void Application::MouseMove(void* win, int x, int y) noexcept
{
CHECK_WINDOW_PTR(win);
if(!m_graphics[*static_cast<int*>(win)]->HasWindow())
{
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;
}
}
void Application::OnEvent(void* win, int event, int (*funct_ptr)(int, void*), void* param) noexcept
{
CHECK_WINDOW_PTR(win);
if(!m_graphics[*static_cast<int*>(win)]->HasWindow())
{
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;
}
p_in->OnEvent(m_graphics[*static_cast<int*>(win)]->GetWindow()->GetID(), event, funct_ptr, param);
}
void Application::GetScreenSize(void* win, int* w, int* h) noexcept
{
CHECK_WINDOW_PTR(win);
*w = 0;
*h = 0;
}
void Application::SetFPSCap(std::uint32_t fps) noexcept
{
m_fps.SetMaxFPS(fps);
}
void* Application::NewGraphicsSuport(std::size_t w, std::size_t h, const char* title)
{
MLX_PROFILE_FUNCTION();
auto it = std::find_if(m_textures.begin(), m_textures.end(), [=](const Texture& texture)
{
return &texture == reinterpret_cast<Texture*>(const_cast<char*>(title));
});
if(it != _textures.end())
m_graphics.emplace_back(std::make_unique<GraphicsSupport>(w, h, reinterpret_cast<Texture*>(const_cast<char*>(title)), m_graphics.size()));
else
{
if(title == NULL)
{
FatalError("invalid window title (NULL)");
return nullptr;
}
m_graphics.emplace_back(std::make_unique<GraphicsSupport>(w, h, title, m_graphics.size()));
p_in->RegisterWindow(m_graphics.back()->GetWindow());
}
return static_cast<void*>(&m_graphics.back()->GetID());
}
void Application::ClearGraphicsSupport(void* win)
{
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
m_graphics[*static_cast<int*>(win)]->ClearRenderData();
}
void Application::DestroyGraphicsSupport(void* win)
{
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
m_graphics[*static_cast<int*>(win)].reset();
}
void Application::PixelPut(void* win, int x, int y, std::uint32_t color) const noexcept
{
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
m_graphics[*static_cast<int*>(win)]->PixelPut(x, y, color);
}
void Application::StringPut(void* win, int x, int y, std::uint32_t color, char* str)
{
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
if(str == nullptr)
{
Error("wrong text (NULL)");
return;
}
if(std::strlen(str) == 0)
{
Warning("trying to put an empty text");
return;
}
m_graphics[*static_cast<int*>(win)]->StringPut(x, y, color, str);
}
void Application::LoadFont(void* win, const std::filesystem::path& filepath, float scale)
{
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
m_graphics[*static_cast<int*>(win)]->LoadFont(filepath, scale);
}
void Application::TexturePut(void* win, void* img, int x, int y)
{
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
CHECK_IMAGE_PTR(img, return);
NonOwningPtr<Texture> texture = static_cast<Texture*>(img);
if(!texture->IsInit())
Error("trying to put a texture that has been destroyed");
else
m_graphics[*static_cast<int*>(win)]->TexturePut(texture, x, y);
}
int Application::GetTexturePixel(void* img, int x, int y)
{
MLX_PROFILE_FUNCTION();
CHECK_IMAGE_PTR(img, return 0);
NonOwningPtr<Texture> texture = static_cast<Texture*>(img);
if(!texture->IsInit())
{
Error("trying to get a pixel from texture that has been destroyed");
return 0;
}
return texture->GetPixel(x, y);
}
void Application::setTexturePixel(void* img, int x, int y, std::uint32_t color)
{
MLX_PROFILE_FUNCTION();
CHECK_IMAGE_PTR(img, return);
NonOwningPtr<Texture> texture = static_cast<Texture*>(img);
if(!texture->IsInit())
Error("trying to set a pixel on texture that has been destroyed");
else
texture->SetPixel(x, y, color);
}
void Application::LoopHook(int (*f)(void*), void* param)
{
f_loop_hook = f;
p_param = param;
}
void Application::LoopEnd() noexcept
{
p_in->Finish();
}
}

33
runtime/Includes/Core/Enums.h git.filemode.normal_file
View File

@@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Enums.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/27 17:15:24 by maldavid #+# #+# */
/* Updated: 2024/03/27 17:16:03 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_CORE_ENUMS__
#define __MLX_CORE_ENUMS__
#include <cstddef>
namespace mlx
{
enum class LogType
{
Message = 0,
Warning,
Error,
FatalError,
EndEnum
};
constexpr std::size_t LogTypeCount = static_cast<std::size_t>(LogType::EndEnum) + 1;
}
#endif

24
runtime/Includes/Core/EventBase.h git.filemode.normal_file
View File

@@ -0,0 +1,24 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* EventBase.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/27 17:27:22 by maldavid #+# #+# */
/* Updated: 2024/03/27 17:31:16 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_BASE_EVENT__
#define __MLX_BASE_EVENT__
namespace mlx
{
struct EventBase
{
virtual std::uint32_t What() const = 0;
};
}
#endif

35
runtime/Includes/Core/EventBus.h git.filemode.normal_file
View File

@@ -0,0 +1,35 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* EventBus.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/27 17:30:36 by maldavid #+# #+# */
/* Updated: 2024/03/27 17:31:41 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_EVENT_BUS__
#define __MLX_EVENT_BUS__
#include <Core/EventBase.h>
#include <Core/EventListener.h>
namespace mlx
{
class EventBus
{
public:
EventBus() = delete;
static void Send(const std::string& listener_name, const EventBase& event);
static void SendBroadcast(const EventBase& event);
inline static void RegisterListener(const EventListener& listener) { s_listeners.push_back(listener); }
~EventBus() = delete;
private:
inline static std::vector<EventListener> s_listeners;
};
}
#endif

37
runtime/Includes/Core/EventListener.h git.filemode.normal_file
View File

@@ -0,0 +1,37 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* EventListener.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/27 17:28:17 by maldavid #+# #+# */
/* Updated: 2024/03/27 17:37:53 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_EVENT_LISTENER__
#define __MLX_EVENT_LISTENER__
#include <Core/EventBase.h>
namespace mlx
{
class EventListener
{
public:
EventListener() = delete;
EventListener(func::function<void(const EventBase&)> functor, std::string name);
inline const std::string& GetName() const { return m_name; }
inline void Call(const EventBase& event) const noexcept { m_listen_functor(event); }
~EventListener() = default;
private:
func::function<void(const EventBase&)> m_listen_functor;
std::string m_name;
};
}
#endif

33
runtime/Includes/Core/Format.h git.filemode.normal_file
View File

@@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Format.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/27 17:11:09 by maldavid #+# #+# */
/* Updated: 2024/03/27 17:12:03 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_FORMAT__
#define __MLX_FORMAT__
#include <type_traits>
#include <string_view>
namespace mlx
{
template<typename T, typename = void>
struct IsOstreamable : std::false_type {};
template<typename T>
struct IsOstreamable<T, std::void_t<decltype(std::declval<std::ostream>() << std::declval<T>())>> : std::true_type {};
template<typename... Args, std::enable_if_t<std::conjunction_v<IsOstreamable<Args>...>, int> = 0>
auto Format(std::string_view format, const Args&... args);
}
#include <Core/Format.inl>
#endif

146
runtime/Includes/Core/Format.inl git.filemode.normal_file
View File

@@ -0,0 +1,146 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Format.inl :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/27 17:11:09 by maldavid #+# #+# */
/* Updated: 2024/03/27 17:12:03 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <Core/Format.h>
#include <sstream>
#include <ostream>
namespace mlx
{
namespace Internal
{
template<typename It>
void Format(std::stringstream& ss, It first, It last)
{
for(auto it = first; it != last; ++it)
{
switch(*it)
{
case '%':
throw std::invalid_argument{"too few arguments"};
case '/':
++it;
if(it == last)
throw std::invalid_argument{"stray '/'"};
[[fallthrough]];
default: ss << *it;
}
}
}
template<typename It, typename T, typename... Args>
void Format(std::stringstream& ss, It first, It last, const T& arg, const Args&... args)
{
for(auto it = first; it != last; ++it)
{
switch(*it)
{
case '%':
ss << arg;
return Format(ss, ++it, last, args...);
case '/':
++it;
if(it == last)
throw std::invalid_argument{"stray '/'"};
[[fallthrough]];
default: ss << *it;
}
}
throw std::invalid_argument{"too many arguments"};
}
template<typename It>
void Format(std::ostream& os, It first, It last)
{
for(auto it = first; it != last; ++it)
{
switch(*it)
{
case '%':
throw std::invalid_argument{"too few arguments"};
case '/':
++it;
if(it == last)
throw std::invalid_argument{"stray '/'"};
[[fallthrough]];
default: os << *it;
}
}
}
template<typename It, typename T, typename... Args>
void Format(std::ostream& os, It first, It last, const T& arg, const Args&... args)
{
for(auto it = first; it != last; ++it)
{
switch(*it)
{
case '%':
os << arg;
return Format(os, ++it, last, args...);
case '/':
++it;
if(it == last)
throw std::invalid_argument{"stray '/'"};
[[fallthrough]];
default: os << *it;
}
}
throw std::invalid_argument{"too many arguments"};
}
template<typename... Args>
struct Formatter
{
std::string_view format;
std::tuple<const Args&...> args;
};
template<typename... Args, std::size_t... Is>
void FormatHelper(std::stringstream& ss, const Formatter<Args...>& formatter, std::index_sequence<Is...>)
{
Format(ss, formatter.format.begin(), formatter.format.end(),
std::get<Is>(formatter.args)...);
}
template<typename... Args>
std::stringstream& operator<<(std::stringstream& ss, const Formatter<Args...>& printer)
{
FormatHelper(ss, printer, std::index_sequence_for<Args...>{});
return ss;
}
template<typename... Args, std::size_t... Is>
void FormatHelper(std::ostream& os, const Formatter<Args...>& formatter, std::index_sequence<Is...>)
{
Format(os, formatter.format.begin(), formatter.format.end(),
std::get<Is>(formatter.args)...);
}
template<typename... Args>
std::ostream& operator<<(std::ostream& os, const Formatter<Args...>& printer)
{
FormatHelper(os, printer, std::index_sequence_for<Args...>{});
return os;
}
}
template<typename... Args, std::enable_if_t<std::conjunction_v<IsOstreamable<Args>...>, int>>
auto Format(std::string_view format, const Args&... args)
{
return Internal::Formatter<Args...>{format, std::forward_as_tuple(args...)};
}
}

39
runtime/Includes/Core/Fps.h git.filemode.normal_file
View File

@@ -0,0 +1,39 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Fps.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/18 14:53:30 by maldavid #+# #+# */
/* Updated: 2024/03/27 20:52:06 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_FPS__
#define __MLX_FPS__
namespace mlx
{
class FpsManager
{
public:
FpsManager() = default;
void Init();
bool Update();
inline void SetMaxFPS(std::uint32_t fps) noexcept { m_max_fps = fps; m_ns = 1000000000.0 / fps; }
~FpsManager() = default;
private:
double m_ns = 1000000000.0 / 1'337'000.0;
std::int64_t m_fps_before = 0;
std::int64_t m_fps_now = 0;
std::int64_t m_timer = 0;
std::uint32_t m_max_fps = 1'337'000;
std::uint32_t m_fps_elapsed_time = 0;
};
}
#endif

75
runtime/Includes/Core/Graphics.h git.filemode.normal_file
View File

@@ -0,0 +1,75 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Graphics.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 14:49:49 by maldavid #+# #+# */
/* Updated: 2024/03/27 21:16:11 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_GRAPHICS__
#define __MLX_GRAPHICS__
#include <Platform/Window.h>
#include <Renderer/Renderer.h>
#include <Renderer/PixelPut.h>
#include <Renderer/Core/DrawableResource.h>
#include <Renderer/Images/TextureManager.h>
#include <Renderer/Texts/TextManager.h>
#include <Utils/NonCopyable.h>
#include <Renderer/Images/Texture.h>
namespace mlx
{
class GraphicsSupport : public NonCopyable
{
public:
GraphicsSupport(std::size_t w, std::size_t h, NonOwningPtr<Texture> render_target, int id);
GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id);
inline int& GetID() noexcept;
inline std::shared_ptr<Window> GetWindow();
void Render() noexcept;
inline void ClearRenderData() noexcept;
inline void PixelPut(int x, int y, std::uint32_t color) noexcept;
inline void StringPut(int x, int y, std::uint32_t color, std::string str);
inline void TexturePut(NonOwningPtr<class Texture> texture, int x, int y);
inline void LoadFont(const std::filesystem::path& filepath, float scale);
inline void TryEraseTextureFromManager(NonOwningPtr<Texture> texture) noexcept;
inline bool HasWindow() const noexcept { return _has_window; }
inline Renderer& GetRenderer() { return *_renderer; }
~GraphicsSupport();
private:
PixelPutPipeline m_pixel_put_pipeline;
std::vector<NonOwningPtr<DrawableResource>> m_drawlist;
TextManager m_text_manager;
TextureManager m_texture_manager;
glm::mat4 m_proj = glm::mat4(1.0);
std::shared_ptr<Window> p_window;
std::unique_ptr<Renderer> p_renderer;
std::size_t m_width = 0;
std::size_t m_height = 0;
int m_id;
bool m_has_window;
};
}
#include <core/graphics.inl>
#endif

79
runtime/Includes/Core/Graphics.inl git.filemode.normal_file
View File

@@ -0,0 +1,79 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* graphics.inl :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 15:13:55 by maldavid #+# #+# */
/* Updated: 2023/04/02 15:26:16 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <Core/Graphics.h>
namespace mlx
{
int& GraphicsSupport::GetID() noexcept { return m_id; }
std::shared_ptr<Window> GraphicsSupport::GetWindow() { return p_window; }
void GraphicsSupport::ClearRenderData() noexcept
{
MLX_PROFILE_FUNCTION();
m_drawlist.clear();
m_pixel_put_pipeline.Clear();
m_text_manager.Clear();
m_texture_manager.Clear();
}
void GraphicsSupport::PixelPut(int x, int y, std::uint32_t color) noexcept
{
MLX_PROFILE_FUNCTION();
m_pixel_put_pipeline.SetPixel(x, y, color);
}
void GraphicsSupport::StringPut(int x, int y, std::uint32_t color, std::string str)
{
MLX_PROFILE_FUNCTION();
std::pair<NonOwningPtr<DrawableResource>, bool> res = m_text_manager.RegisterText(x, y, color, str);
if(!res.second) // if this is not a completly new text draw
{
auto it = std::find(m_drawlist.begin(), m_drawlist.end(), res.first);
if(it != m_drawlist.end())
m_drawlist.erase(it);
}
m_drawlist.push_back(res.first);
}
void GraphicsSupport::TexturePut(NonOwningPtr<Texture> texture, int x, int y)
{
MLX_PROFILE_FUNCTION();
auto res = m_texture_manager.RegisterTexture(texture, x, y);
if(!res.second) // if this is not a completly new texture draw
{
auto it = std::find(m_drawlist.begin(), m_drawlist.end(), res.first);
if(it != m_drawlist.end())
m_drawlist.erase(it);
}
m_drawlist.push_back(res.first);
}
void GraphicsSupport::LoadFont(const std::filesystem::path& filepath, float scale)
{
MLX_PROFILE_FUNCTION();
m_text_manager.LoadFont(*_renderer, filepath, scale);
}
void GraphicsSupport::TryEraseTextureFromManager(NonOwningPtr<Texture> texture) noexcept
{
MLX_PROFILE_FUNCTION();
for(auto it = m_drawlist.begin(); it != m_drawlist.end();)
{
if(m_texture_manager.IsTextureKnown(texture))
it = m_drawlist.erase(it);
else
++it;
}
m_texture_manager.EraseTextures(texture);
}
}

84
runtime/Includes/Core/Logs.h git.filemode.normal_file
View File

@@ -0,0 +1,84 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Logs.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/27 17:14:10 by maldavid #+# #+# */
/* Updated: 2024/03/27 17:19:23 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_LOGS__
#define __MLX_LOGS__
#include <Core/Enums.h>
namespace mlx
{
template<typename... Args>
void DebugLog(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
template<typename... Args>
void Error(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
template<typename... Args>
void Warning(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
template<typename... Args>
void Message(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
template<typename... Args>
void FatalError(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
template<typename... Args>
void Verify(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
class Logs
{
public:
Logs() = delete;
static void Report(LogType type, std::string message);
static void Report(LogType type, unsigned int line, std::string_view file, std::string_view function, std::string message);
~Logs() = delete;
};
#if defined(DEBUG)
template<typename... Args>
void Assert(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
#else
template<typename... Args>
void Assert(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args) {}
#endif
}
#include <Core/Logs.inl>
namespace mlx
{
#undef DebugLog
#define DebugLog(...) DebugLog(__LINE__, __FILE__, AK_FUNC_SIG, __VA_ARGS__)
#undef Message
#define Message(...) Message(__LINE__, __FILE__, __func__, __VA_ARGS__)
#undef Warning
#define Warning(...) Warning(__LINE__, __FILE__, __func__, __VA_ARGS__)
#undef Error
#define Error(...) Error(__LINE__, __FILE__, __func__, __VA_ARGS__)
#undef FatalError
#define FatalError(...) FatalError(__LINE__, __FILE__, __func__, __VA_ARGS__)
#undef Verify
#define Verify(cond, ...) Verify(cond, __LINE__, __FILE__, __func__, __VA_ARGS__)
#undef Assert
#define Assert(cond, ...) Assert(cond, __LINE__, __FILE__, __func__, __VA_ARGS__)
}
#endif

135
runtime/Includes/Core/Logs.inl git.filemode.normal_file
View File

@@ -0,0 +1,135 @@
/* **************************************************************************** */
/* */
/* ::: :::::::: */
/* Logs.inl :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/27 17:19:47 by maldavid #+# #+# */
/* Updated: 2024/03/27 17:19:47 by maldavid ### ########.fr */
/* */
/* **************************************************************************** */
#include <Core/Logs.h>
#include <Core/Format.h>
namespace mlx
{
template<typename... Args>
void DebugLog(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
{
using namespace std::literals;
try
{
std::stringstream ss;
ss << Format(message, args...);
Logs::Report(LogType::Debug, line, file, function, ss.str());
}
catch(const std::exception& e)
{
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
}
}
template<typename... Args>
void Error(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
{
using namespace std::literals;
try
{
std::stringstream ss;
ss << Format(message, args...);
Logs::Report(LogType::Error, line, file, function, ss.str());
}
catch(const std::exception& e)
{
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
}
}
template<typename... Args>
void Warning(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
{
using namespace std::literals;
try
{
std::stringstream ss;
ss << Format(message, args...);
Logs::Report(LogType::Warning, line, file, function, ss.str());
}
catch(const std::exception& e)
{
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
}
}
template<typename... Args>
void Message(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
{
using namespace std::literals;
try
{
std::stringstream ss;
ss << Format(message, args...);
Logs::Report(LogType::Message, line, file, function, ss.str());
}
catch(const std::exception& e)
{
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
}
}
template<typename... Args>
void FatalError(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
{
using namespace std::literals;
try
{
std::stringstream ss;
ss << Format(message, args...);
Logs::Report(LogType::FatalError, line, file, function, ss.str());
}
catch(const std::exception& e)
{
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
}
}
template<typename... Args>
void Verify(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
{
using namespace std::literals;
if(cond)
return;
try
{
std::stringstream ss;
ss << Format("Verification failed : %", message, args...);
Logs::Report(LogType::FatalError, line, file, function, ss.str());
}
catch(const std::exception& e)
{
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
}
}
#if defined(DEBUG)
template<typename... Args>
void Assert(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
{
using namespace std::literals;
if(cond)
return;
try
{
std::stringstream ss;
ss << Format("Assertion failed : %", message, args...);
Logs::Report(LogType::FatalError, line, file, function, ss.str());
}
catch(const std::exception& e)
{
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
}
}
#endif
}

39
runtime/Includes/Core/Memory.h git.filemode.normal_file
View File

@@ -0,0 +1,39 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Memory.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/07 16:31:51 by kbz_8 #+# #+# */
/* Updated: 2024/03/27 21:16:44 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_MEMORY__
#define __MLX_MEMORY__
#include <Utils/Singleton.h>
namespace mlx
{
class MemManager : public Singleton<MemManager>
{
friend class Singleton<MemManager>;
public:
static void* Malloc(std::size_t size);
static void* Calloc(std::size_t n, std::size_t size);
static void* Realloc(void* ptr, std::size_t size);
static void Free(void* ptr);
private:
MemManager() = default;
~MemManager();
private:
inline static std::list<void*> s_blocks;
};
}
#endif

137
runtime/Includes/Core/Profiler.h git.filemode.normal_file
View File

@@ -0,0 +1,137 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Profiler.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/10 13:35:45 by maldavid #+# #+# */
/* Updated: 2024/03/27 21:19:01 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_PROFILER__
#define __MLX_PROFILER__
#include <Utils/Singleton.h>
namespace mlx
{
using FloatingPointMilliseconds = std::chrono::duration<double, std::milli>;
struct ProfileResult
{
std::string name;
FloatingPointMilliseconds elapsed_time;
std::thread::id thread_id;
};
class Profiler : public Singleton<Profiler>
{
friend class Singleton<Profiler>;
public:
Profiler(const Profiler&) = delete;
Profiler(Profiler&&) = delete;
void AppendProfileData(ProfileResult&& result);
private:
Profiler() { BeginRuntimeSession(); }
~Profiler();
void BeginRuntimeSession();
void WriteProfile(const ProfileResult& result);
void EndRuntimeSession();
inline void WriteHeader()
{
m_output_stream << "{\"profileData\":[{}";
m_output_stream.flush();
}
inline void WriteFooter()
{
m_output_stream << "]}";
m_output_stream.flush();
}
private:
std::unordered_map<std::string, std::pair<std::size_t, ProfileResult>> m_profile_data;
std::ofstream m_output_stream;
std::mutex m_mutex;
bool m_runtime_session_began = false;
};
class ProfilerTimer
{
public:
ProfilerTimer(const char* name) : m_name(name)
{
m_start_timepoint = std::chrono::steady_clock::now();
}
inline void Stop()
{
auto end_timepoint = std::chrono::steady_clock::now();
auto high_res_start = FloatingPointMilliseconds{ m_start_timepoint.time_since_epoch() };
auto elapsed_time = std::chrono::time_point_cast<std::chrono::milliseconds>(end_timepoint).time_since_epoch() - std::chrono::time_point_cast<std::chrono::milliseconds>(m_start_timepoint).time_since_epoch();
Profiler::get().appendProfileData({ m_name, elapsed_time, std::this_thread::get_id() });
m_stopped = true;
}
~ProfilerTimer()
{
if(!m_stopped)
stop();
}
private:
std::chrono::time_point<std::chrono::steady_clock> m_start_timepoint;
const char* m_name;
bool m_stopped = false;
};
namespace ProfilerUtils
{
template <std::size_t N>
struct ChangeResult
{
char data[N];
};
template <std::size_t N, std::size_t K>
constexpr auto CleanupOutputString(const char(&expr)[N], const char(&remove)[K])
{
ChangeResult<N> result = {};
std::size_t src_index = 0;
std::size_t dst_index = 0;
while(src_index < N)
{
std::size_t match_index = 0;
while(match_index < K - 1 && src_index + match_index < N - 1 && expr[src_index + match_index] == remove[match_index])
match_index++;
if(match_index == K - 1)
src_index += match_index;
result.data[dst_index++] = expr[src_index] == '"' ? '\'' : expr[src_index];
src_index++;
}
return result;
}
}
}
#ifdef PROFILER
#define MLX_PROFILE_SCOPE_LINE2(name, line) constexpr auto fixed_name_##line = ::mlx::ProfilerUtils::CleanupOutputString(name, "__cdecl ");\
::mlx::ProfilerTimer timer##line(fixed_name_##line.data)
#define MLX_PROFILE_SCOPE_LINE(name, line) MLX_PROFILE_SCOPE_LINE2(name, line)
#define MLX_PROFILE_SCOPE(name) MLX_PROFILE_SCOPE_LINE(name, __LINE__)
#define MLX_PROFILE_FUNCTION() MLX_PROFILE_SCOPE(MLX_FUNC_SIG)
#else
#define MLX_PROFILE_SCOPE(name)
#define MLX_PROFILE_FUNCTION()
#endif
#endif

31
runtime/Includes/Core/UUID.h git.filemode.normal_file
View File

@@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* UUID.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/06 11:13:23 by maldavid #+# #+# */
/* Updated: 2024/03/27 21:19:18 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_UUID__
#define __MLX_UUID__
namespace mlx
{
class UUID
{
public:
UUID();
UUID(std::uint64_t uuid);
inline operator std::uint64_t() const { return m_uuid; }
private:
std::uint64_t m_uuid;
};
}
#endif