diff --git a/Makefile b/Makefile index 7617caa..2ade2ba 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ SHADERS_SRCS = $(wildcard $(addsuffix /*.nzsl, $(SHADERS_DIR))) SPVS = $(SHADERS_SRCS:.nzsl=.spv.h) CXX = clang++ -CXXFLAGS = -std=c++20 -O3 -fPIC -Wall -Wextra -DSDL_MAIN_HANDLED +CXXFLAGS = -std=c++20 -fPIC -Wall -Wextra -DSDL_MAIN_HANDLED INCLUDES = -I./includes -I./runtime/Includes -I./runtime/Sources -I./third_party NZSLC = nzslc @@ -49,6 +49,8 @@ endif ifeq ($(DEBUG), true) CXXFLAGS += -g3 -D DEBUG LDFLAGS += -rdynamic +else + CXXFLAGS += -O3 endif ifeq ($(FORCE_INTEGRATED_GPU), true) diff --git a/runtime/Includes/Core/Logs.inl b/runtime/Includes/Core/Logs.inl index 744fbaa..54983cf 100644 --- a/runtime/Includes/Core/Logs.inl +++ b/runtime/Includes/Core/Logs.inl @@ -16,7 +16,7 @@ namespace mlx } catch(const std::exception& e) { - Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what()); + Logs::Report(LogType::Error, line, file, function, "formatter exception catched in the log printer: "s + e.what()); } } @@ -32,7 +32,7 @@ namespace mlx } catch(const std::exception& e) { - Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what()); + Logs::Report(LogType::Error, line, file, function, "formatter exception catched in the log printer: "s + e.what()); } } @@ -48,7 +48,7 @@ namespace mlx } catch(const std::exception& e) { - Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what()); + Logs::Report(LogType::Error, line, file, function, "formatter exception catched in the log printer: "s + e.what()); } } @@ -64,7 +64,7 @@ namespace mlx } catch(const std::exception& e) { - Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what()); + Logs::Report(LogType::Error, line, file, function, "formatter exception catched in the log printer: "s + e.what()); } } @@ -80,7 +80,7 @@ namespace mlx } catch(const std::exception& e) { - Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what()); + Logs::Report(LogType::FatalError, line, file, function, "formatter exception catched in the log printer: "s + e.what()); } } @@ -98,7 +98,7 @@ namespace mlx } catch(const std::exception& e) { - Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what()); + Logs::Report(LogType::FatalError, line, file, function, "formatter exception catched in the log printer: "s + e.what()); } } @@ -117,7 +117,7 @@ namespace mlx } catch(const std::exception& e) { - Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what()); + Logs::Report(LogType::FatalError, line, file, function, "formatter exception catched in the log printer: "s + e.what()); } } #endif diff --git a/runtime/Includes/Renderer/RenderPasses/Passes.h b/runtime/Includes/Renderer/RenderPasses/Passes.h index 45f084e..a24bcc2 100644 --- a/runtime/Includes/Renderer/RenderPasses/Passes.h +++ b/runtime/Includes/Renderer/RenderPasses/Passes.h @@ -12,7 +12,7 @@ namespace mlx public: RenderPasses() = default; - void Init(class Renderer& renderer); + void Init(); void Pass(class Scene& scene, class Renderer& renderer, const Vec4f& clear_color); void Destroy(); diff --git a/runtime/Includes/Renderer/ScenesRenderer.h b/runtime/Includes/Renderer/ScenesRenderer.h index 36dcdad..03c391e 100644 --- a/runtime/Includes/Renderer/ScenesRenderer.h +++ b/runtime/Includes/Renderer/ScenesRenderer.h @@ -9,7 +9,7 @@ namespace mlx { public: SceneRenderer() = default; - void Init(class Renderer& renderer); + void Init(); void Render(class Scene& scene, class Renderer& renderer); // TODO : add RTT support void Destroy(); ~SceneRenderer() = default; diff --git a/runtime/Sources/Core/Graphics.cpp b/runtime/Sources/Core/Graphics.cpp index 9769bbf..66a70ed 100644 --- a/runtime/Sources/Core/Graphics.cpp +++ b/runtime/Sources/Core/Graphics.cpp @@ -12,7 +12,7 @@ namespace mlx MLX_PROFILE_FUNCTION(); // TODO : re-enable render targets m_renderer.Init(nullptr); - m_scene_renderer.Init(m_renderer); + m_scene_renderer.Init(); p_scene = std::make_unique(); } @@ -24,7 +24,7 @@ namespace mlx { MLX_PROFILE_FUNCTION(); m_renderer.Init(p_window.get()); - m_scene_renderer.Init(m_renderer); + m_scene_renderer.Init(); p_scene = std::make_unique(); } diff --git a/runtime/Sources/Core/Memory.cpp b/runtime/Sources/Core/Memory.cpp index 197a458..3a69d32 100644 --- a/runtime/Sources/Core/Memory.cpp +++ b/runtime/Sources/Core/Memory.cpp @@ -40,6 +40,8 @@ namespace mlx void MemManager::Free(void* ptr) { + if(ptr == nullptr) + return; auto it = std::find(s_blocks.begin(), s_blocks.end(), ptr); if(it == s_blocks.end()) { diff --git a/runtime/Sources/Graphics/Mesh.cpp b/runtime/Sources/Graphics/Mesh.cpp index cebfe54..751d12e 100644 --- a/runtime/Sources/Graphics/Mesh.cpp +++ b/runtime/Sources/Graphics/Mesh.cpp @@ -7,7 +7,6 @@ namespace mlx void Mesh::Draw(VkCommandBuffer cmd, std::size_t& drawcalls, std::size_t& polygondrawn) const noexcept { MLX_PROFILE_FUNCTION(); - #pragma omp parallel for for(std::size_t i = 0; i < m_sub_meshes.size(); i++) Draw(cmd, drawcalls, polygondrawn, i); } @@ -26,7 +25,6 @@ namespace mlx Mesh::~Mesh() { MLX_PROFILE_FUNCTION(); - #pragma omp parallel for for(auto& mesh : m_sub_meshes) { mesh.vbo.Destroy(); diff --git a/runtime/Sources/Renderer/Image.cpp b/runtime/Sources/Renderer/Image.cpp index 7280831..f4f1276 100644 --- a/runtime/Sources/Renderer/Image.cpp +++ b/runtime/Sources/Renderer/Image.cpp @@ -8,7 +8,7 @@ #define STB_IMAGE_IMPLEMENTATION -#define STBI_ASSERT(x) mlx::Assert(x, "internal stb assertion " #x) +#define STBI_ASSERT(x) (mlx::Assert(x, "internal stb assertion " #x)) #define STBI_MALLOC(x) (mlx::MemManager::Get().Malloc(x)) #define STBI_REALLOC(p, x) (mlx::MemManager::Get().Realloc(p, x)) #define STBI_FREE(x) (mlx::MemManager::Get().Free(x)) @@ -162,6 +162,10 @@ namespace mlx #endif } m_image = VK_NULL_HANDLE; + m_layout = VK_IMAGE_LAYOUT_UNDEFINED; + m_width = 0; + m_height = 0; + m_is_multisampled = false; } void Texture::Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format, bool is_multisampled, [[maybe_unused]] std::string_view debug_name) @@ -269,6 +273,7 @@ namespace mlx Texture* StbTextureLoad(const std::filesystem::path& file, int* w, int* h) { + using namespace std::literals; MLX_PROFILE_FUNCTION(); std::string filename = file.string(); @@ -289,11 +294,9 @@ namespace mlx Vec2i size; int channels; - std::uint8_t* data = stbi_load(filename.c_str(), &size.x, &size.y, &channels, STBI_rgb_alpha); + std::uint8_t* data = stbi_load(filename.c_str(), &size.x, &size.y, &channels, 4); CallOnExit defer([=]() { stbi_image_free(data); }); - Verify(channels == 4, "invalid channels number in image loaded (should be 4, was %)", channels); - CPUBuffer buffer(size.x * size.y * 4); std::memcpy(buffer.GetData(), data, buffer.GetSize()); diff --git a/runtime/Sources/Renderer/Pipelines/Graphics.cpp b/runtime/Sources/Renderer/Pipelines/Graphics.cpp index 52950f1..3a7e51d 100644 --- a/runtime/Sources/Renderer/Pipelines/Graphics.cpp +++ b/runtime/Sources/Renderer/Pipelines/Graphics.cpp @@ -103,7 +103,6 @@ namespace mlx scissor.extent = fb_extent; RenderCore::Get().vkCmdSetScissor(command_buffer, 0, 1, &scissor); - #pragma omp parallel for for(std::size_t i = 0; i < m_clears.size(); i++) { m_clears[i].color.float32[0] = clear[0]; @@ -128,7 +127,6 @@ namespace mlx MLX_PROFILE_FUNCTION(); p_vertex_shader.reset(); p_fragment_shader.reset(); - #pragma omp parallel for for(auto& fb : m_framebuffers) { kvfDestroyFramebuffer(RenderCore::Get().GetDevice(), fb); @@ -144,6 +142,9 @@ namespace mlx kvfDestroyPipeline(RenderCore::Get().GetDevice(), m_pipeline); m_pipeline = VK_NULL_HANDLE; DebugLog("Vulkan: graphics pipeline destroyed"); + p_renderer = nullptr; + m_clears.clear(); + m_attachments.clear(); } void GraphicPipeline::CreateFramebuffers(const std::vector>& render_targets, bool clear_attachments) @@ -157,7 +158,6 @@ namespace mlx attachment_views.push_back(p_renderer->GetSwapchain().GetSwapchainImages()[0].GetImageView()); } - #pragma omp parallel for for(NonOwningPtr image : render_targets) { attachments.push_back(kvfBuildAttachmentDescription((kvfIsDepthFormat(image->GetFormat()) ? KVF_IMAGE_DEPTH : KVF_IMAGE_COLOR), image->GetFormat(), image->GetLayout(), image->GetLayout(), clear_attachments, VK_SAMPLE_COUNT_1_BIT)); @@ -178,7 +178,6 @@ namespace mlx DebugLog("Vulkan: framebuffer created"); } } - #pragma omp parallel for for(NonOwningPtr image : render_targets) { m_framebuffers.push_back(kvfCreateFramebuffer(RenderCore::Get().GetDevice(), m_renderpass, attachment_views.data(), attachment_views.size(), { .width = image->GetWidth(), .height = image->GetHeight() })); diff --git a/runtime/Sources/Renderer/RenderCore.cpp b/runtime/Sources/Renderer/RenderCore.cpp index 3ea7461..e4abfaf 100644 --- a/runtime/Sources/Renderer/RenderCore.cpp +++ b/runtime/Sources/Renderer/RenderCore.cpp @@ -1,12 +1,16 @@ #include #include +#include #define KVF_IMPLEMENTATION #ifdef DEBUG #define KVF_ENABLE_VALIDATION_LAYERS #endif -#define KVF_ASSERT(x) mlx::Assert(x, #x) +#define KVF_ASSERT(x) (mlx::Assert(x, "internal kvf assertion " #x)) +#define KVF_MALLOC(x) (mlx::MemManager::Get().Malloc(x)) +#define KVF_REALLOC(p, x) (mlx::MemManager::Get().Realloc(p, x)) +#define KVF_FREE(x) (mlx::MemManager::Get().Free(x)) #if defined(MLX_COMPILER_GCC) || defined(MLX_COMPILER_CLANG) #pragma clang diagnostic push diff --git a/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp b/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp index 5775187..e59bb5e 100644 --- a/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp +++ b/runtime/Sources/Renderer/RenderPasses/FinalPass.cpp @@ -20,7 +20,7 @@ namespace mlx ShaderLayout fragment_shader_layout( { { 0, - ShaderSetLayout({ + ShaderSetLayout({ { 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER } }) } diff --git a/runtime/Sources/Renderer/RenderPasses/Passes.cpp b/runtime/Sources/Renderer/RenderPasses/Passes.cpp index c094f84..f1ea588 100644 --- a/runtime/Sources/Renderer/RenderPasses/Passes.cpp +++ b/runtime/Sources/Renderer/RenderPasses/Passes.cpp @@ -5,37 +5,30 @@ namespace mlx { - void RenderPasses::Init(Renderer& renderer) + void RenderPasses::Init() { m_2Dpass.Init(); m_final.Init(); - func::function functor = [this, &renderer](const EventBase& event) + func::function functor = [this](const EventBase& event) { if(event.What() == Event::ResizeEventCode) - { m_main_render_texture.Destroy(); - auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain().Get()); - #ifdef DEBUG - m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_renderpasses_target"); - #else - m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, {}); - #endif - m_main_render_texture.TransitionLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } }; EventBus::RegisterListener({ functor, "__MlxRenderPasses" }); - auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain().Get()); - - #ifdef DEBUG - m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_renderpasses_target"); - #else - m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, {}); - #endif - m_main_render_texture.TransitionLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } void RenderPasses::Pass(Scene& scene, Renderer& renderer, const Vec4f& clear_color) { + if(!m_main_render_texture.IsInit()) + { + auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain().Get()); + #ifdef DEBUG + m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_renderpasses_target"); + #else + m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, {}); + #endif + m_main_render_texture.TransitionLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } m_main_render_texture.Clear(renderer.GetActiveCommandBuffer(), clear_color); m_2Dpass.Pass(scene, renderer, m_main_render_texture); diff --git a/runtime/Sources/Renderer/SceneRenderer.cpp b/runtime/Sources/Renderer/SceneRenderer.cpp index 2b5bcaa..98fa750 100644 --- a/runtime/Sources/Renderer/SceneRenderer.cpp +++ b/runtime/Sources/Renderer/SceneRenderer.cpp @@ -6,10 +6,10 @@ namespace mlx { - void SceneRenderer::Init(Renderer& renderer) + void SceneRenderer::Init() { MLX_PROFILE_FUNCTION(); - m_passes.Init(renderer); + m_passes.Init(); } void SceneRenderer::Render(Scene& scene, Renderer& renderer) diff --git a/third_party/kvf.h b/third_party/kvf.h index 7080ab6..fa6a1bd 100755 --- a/third_party/kvf.h +++ b/third_party/kvf.h @@ -40,7 +40,7 @@ * by using #define KVF_NO_EXIT_ON_FAILURE * * If you are using Volk or any other meta loader you must define KVF_IMPL_VK_NO_PROTOTYPES - * or VK_NO_PROTOTYPES before including this file to avoid conflicts with Vulkan prototypes. + * before including this file to avoid conflicts with Vulkan prototypes. * You will also need to pass the function pointers to kvf using dedicated functions. * * You can also #define KVF_ENABLE_VALIDATION_LAYERS to enable validation layers. @@ -236,7 +236,7 @@ void kvfCheckVk(VkResult result); #ifdef KVF_IMPL_VK_NO_PROTOTYPES #ifdef KVF_DEFINE_VULKAN_FUNCTION_PROTOTYPE - #undef KVF_DEFINE_VULKAN_FUNCTION_PROTOTYPE + #undef KVF_DEFINE_VULKAN_FUNCTION_PROTOTYPE #endif #define KVF_DEFINE_VULKAN_FUNCTION_PROTOTYPE(fn) PFN_##fn fn @@ -2122,6 +2122,7 @@ void kvfDestroyImageView(VkDevice device, VkImageView image_view) void kvfTransitionImageLayout(VkDevice device, VkImage image, KvfImageType type, VkCommandBuffer cmd, VkFormat format, VkImageLayout old_layout, VkImageLayout new_layout, bool is_single_time_cmd_buffer) { KVF_ASSERT(device != VK_NULL_HANDLE); + KVF_ASSERT(cmd != VK_NULL_HANDLE); if(new_layout == old_layout) return;