Skip to content

Commit

Permalink
Refactor metal backend: add PrepareBackendCallbacksCommon()
Browse files Browse the repository at this point in the history
  • Loading branch information
pthom committed Dec 20, 2023
1 parent 55cc1bb commit f3e2617
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 128 deletions.
8 changes: 4 additions & 4 deletions src/hello_imgui/internal/backend_impls/abstract_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ void AbstractRunner::CreateFramesAndRender()
if (params.callbacks.PreNewFrame)
params.callbacks.PreNewFrame();

mRenderingBackendCallbacks.Impl_NewFrame_3D();
mRenderingBackendCallbacks->Impl_NewFrame_3D();
Impl_NewFrame_Backend();
{
// Workaround against SDL clock that sometimes leads to io.DeltaTime=0.f on emscripten
Expand Down Expand Up @@ -646,7 +646,7 @@ void AbstractRunner::CreateFramesAndRender()
if (params.callbacks.CustomBackground)
params.callbacks.CustomBackground();
else
mRenderingBackendCallbacks.Impl_Frame_3D_ClearColor(params.imGuiWindowParams.backgroundColor);
mRenderingBackendCallbacks->Impl_Frame_3D_ClearColor(params.imGuiWindowParams.backgroundColor);

// iii/ At the end of the second frame, we measure the size of the widgets and use it as the application window size, if the user required auto size
// ==> Note: RenderGui() may measure the size of the window and resize it if mIdxFrame==1
Expand All @@ -656,7 +656,7 @@ void AbstractRunner::CreateFramesAndRender()
params.callbacks.BeforeImGuiRender();

ImGui::Render();
mRenderingBackendCallbacks. Impl_RenderDrawData_To_3D();
mRenderingBackendCallbacks->Impl_RenderDrawData_To_3D();

if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
Impl_UpdateAndRenderAdditionalPlatformWindows();
Expand Down Expand Up @@ -802,7 +802,7 @@ void AbstractRunner::TearDown(bool gotException)
TestEngineCallbacks::TearDown_ImGuiContextAlive();
#endif

mRenderingBackendCallbacks.Impl_Shutdown_3D();
mRenderingBackendCallbacks->Impl_Shutdown_3D();
Impl_Cleanup();


Expand Down
4 changes: 2 additions & 2 deletions src/hello_imgui/internal/backend_impls/abstract_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class AbstractRunner
void OnLowMemory();

// For jupyter notebook, which displays a screenshot post execution
ImageBuffer ScreenshotRgb() { return mRenderingBackendCallbacks.Impl_ScreenshotRgb_3D(); }
ImageBuffer ScreenshotRgb() { return mRenderingBackendCallbacks->Impl_ScreenshotRgb_3D(); }

//
// Dpi related methods
Expand Down Expand Up @@ -92,7 +92,7 @@ class AbstractRunner
//
// Wish should be filled by Impl_InitRenderBackendCallbacks
virtual void Impl_InitRenderBackendCallbacks() = 0;
RenderingCallbacks mRenderingBackendCallbacks;
RenderingCallbacksPtr mRenderingBackendCallbacks;

private:
void PrepareWindowGeometry();
Expand Down
9 changes: 7 additions & 2 deletions src/hello_imgui/internal/backend_impls/rendering_callbacks.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#pragma once
#include "hello_imgui/hello_imgui_error.h"
#include "hello_imgui/screen_bounds.h"
#include "hello_imgui/hello_imgui_screenshot.h"

#include <functional>
#include <memory>


namespace HelloImGui
Expand All @@ -16,10 +18,13 @@ namespace HelloImGui
// As a consequence, it is implemented in the Rendering Backend, with #ifdefs
struct RenderingCallbacks
{
VoidFunction Impl_NewFrame_3D = [] { HIMG_ERROR("Empty function"); };
std::function<void(ImVec4)> Impl_Frame_3D_ClearColor = [] (ImVec4) { HIMG_ERROR("Empty function"); };
VoidFunction Impl_NewFrame_3D = [] { HIMG_ERROR("Empty function"); };
std::function<void(ImVec4)> Impl_Frame_3D_ClearColor = [] (ImVec4) { HIMG_ERROR("Empty function"); };
VoidFunction Impl_RenderDrawData_To_3D = [] { HIMG_ERROR("Empty function"); };
VoidFunction Impl_Shutdown_3D = [] { HIMG_ERROR("Empty function"); };
std::function<ImageBuffer()> Impl_ScreenshotRgb_3D = [] { return ImageBuffer{}; };
std::function<ScreenSize()> Impl_GetFrameBufferSize; //= [] { return ScreenSize{0, 0}; };
};

using RenderingCallbacksPtr = std::shared_ptr<RenderingCallbacks>;
} // namespace HelloImGui
16 changes: 9 additions & 7 deletions src/hello_imgui/internal/backend_impls/rendering_metal.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#pragma once
#ifdef HELLOIMGUI_HAS_METAL

#import <Metal/Metal.h>
#import <QuartzCore/QuartzCore.h>

#ifdef HELLOIMGUI_USE_SDL2
struct SDL_Renderer;
struct SDL_Window;
Expand All @@ -15,6 +12,10 @@ struct GLFWwindow;

#include "hello_imgui/internal/backend_impls/rendering_callbacks.h"

#import <Metal/Metal.h>
#import <QuartzCore/QuartzCore.h>


namespace HelloImGui
{
struct MetalGlobals
Expand All @@ -28,12 +29,14 @@ namespace HelloImGui
};
MetalGlobals& GetMetalGlobals();

void SwapMetalBuffers();
RenderingCallbacksPtr PrepareBackendCallbacksCommon();

#ifdef HELLOIMGUI_USE_SDL2
RenderingCallbacks CreateBackendCallbacks_SdlMetal();
RenderingCallbacksPtr CreateBackendCallbacks_SdlMetal();

void PrepareSdlForMetal_WithWindow_PreImGuiInit(SDL_Window* window);
void PrepareSdlForMetal_PosImGuiInit();
void SwapSdlMetalBuffers();

struct SdlMetalGlobals
{
Expand All @@ -44,11 +47,10 @@ namespace HelloImGui
#endif

#ifdef HELLOIMGUI_USE_GLFW3
RenderingCallbacks CreateBackendCallbacks_GlfwMetal();
RenderingCallbacksPtr CreateBackendCallbacks_GlfwMetal();

void PrepareGlfwForMetal_WithWindow_PreImGuiInit(GLFWwindow* window);
void PrepareGlfwForMetal_PosImGuiInit();
void SwapGlfwMetalBuffers();

struct GlfwMetalGlobals
{
Expand Down
67 changes: 67 additions & 0 deletions src/hello_imgui/internal/backend_impls/rendering_metal.mm
Original file line number Diff line number Diff line change
@@ -1,13 +1,80 @@
#ifdef HELLOIMGUI_HAS_METAL
#include "rendering_metal.h"

#include <backends/imgui_impl_metal.h>
#include "hello_imgui/hello_imgui.h"


namespace HelloImGui
{
MetalGlobals& GetMetalGlobals()
{
static MetalGlobals sMetalGlobals;
return sMetalGlobals;
}

void SwapMetalBuffers()
{
auto& gMetalGlobals = GetMetalGlobals();

[gMetalGlobals.mtlRenderCommandEncoder popDebugGroup];
[gMetalGlobals.mtlRenderCommandEncoder endEncoding];

[gMetalGlobals.mtlCommandBuffer presentDrawable:gMetalGlobals.caMetalDrawable];
[gMetalGlobals.mtlCommandBuffer commit];
}

RenderingCallbacksPtr PrepareBackendCallbacksCommon()
{
auto callbacks = std::make_shared<RenderingCallbacks>();

callbacks->Impl_NewFrame_3D = [callbacks] // Capture by value required, since we are using the callbacks shared_ptr
{
auto& gMetalGlobals = GetMetalGlobals();

auto Vec4_To_Array = [](ImVec4 v) { return std::array<float, 4>{ v.x, v.y, v.z, v.w }; };

//
// New Frame + Clear color
//
ScreenSize frameBufferSize = callbacks->Impl_GetFrameBufferSize();
gMetalGlobals.caMetalLayer.drawableSize = CGSizeMake(frameBufferSize[0], frameBufferSize[1]);
gMetalGlobals.caMetalDrawable = [gMetalGlobals.caMetalLayer nextDrawable];

gMetalGlobals.mtlCommandBuffer = [gMetalGlobals.mtlCommandQueue commandBuffer];
auto clearColor = Vec4_To_Array(HelloImGui::GetRunnerParams()->imGuiWindowParams.backgroundColor);
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clearColor[0] * clearColor[3], clearColor[1] * clearColor[3], clearColor[2] * clearColor[3], clearColor[3]);
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].texture = gMetalGlobals.caMetalDrawable.texture;
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
gMetalGlobals.mtlRenderCommandEncoder = [
gMetalGlobals.mtlCommandBuffer renderCommandEncoderWithDescriptor:gMetalGlobals.mtlRenderPassDescriptor];
[gMetalGlobals.mtlRenderCommandEncoder pushDebugGroup:@"ImGui demo"];

// Start the Dear ImGui frame
ImGui_ImplMetal_NewFrame(gMetalGlobals.mtlRenderPassDescriptor);
};

callbacks->Impl_RenderDrawData_To_3D = []
{
auto& gMetalGlobals = GetMetalGlobals();
ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), gMetalGlobals.mtlCommandBuffer, gMetalGlobals.mtlRenderCommandEncoder);
};

// Not implemented for Metal
//callbacks.Impl_ScreenshotRgb = []() { ...;};

// This is done at Impl_NewFrame_3D
callbacks->Impl_Frame_3D_ClearColor = [](ImVec4 clearColor) { };

callbacks->Impl_Shutdown_3D = []
{
ImGui_ImplMetal_Shutdown();
};

return callbacks;
}

}

#endif // HELLOIMGUI_HAS_METAL
54 changes: 4 additions & 50 deletions src/hello_imgui/internal/backend_impls/rendering_metal_glfw.mm
Original file line number Diff line number Diff line change
Expand Up @@ -54,64 +54,18 @@ void PrepareGlfwForMetal_PosImGuiInit()
gMetalGlobals.mtlRenderPassDescriptor = [MTLRenderPassDescriptor new];
}

void SwapGlfwMetalBuffers()
RenderingCallbacksPtr CreateBackendCallbacks_GlfwMetal()
{
auto& gMetalGlobals = GetMetalGlobals();

[gMetalGlobals.mtlRenderCommandEncoder popDebugGroup];
[gMetalGlobals.mtlRenderCommandEncoder endEncoding];

[gMetalGlobals.mtlCommandBuffer presentDrawable:gMetalGlobals.caMetalDrawable];
[gMetalGlobals.mtlCommandBuffer commit];
}
auto callbacks = PrepareBackendCallbacksCommon();

RenderingCallbacks CreateBackendCallbacks_GlfwMetal()
{
RenderingCallbacks callbacks;

callbacks.Impl_NewFrame_3D = []
callbacks->Impl_GetFrameBufferSize = []
{
auto& gMetalGlobals = GetMetalGlobals();
auto& gGlfwMetalGlobals = GetGlfwMetalGlobals();

auto Vec4_To_Array = [](ImVec4 v) { return std::array<float, 4>{ v.x, v.y, v.z, v.w }; };

int width, height;
glfwGetFramebufferSize(gGlfwMetalGlobals.glfwWindow, &width, &height);
gMetalGlobals.caMetalLayer.drawableSize = CGSizeMake(width, height);
gMetalGlobals.caMetalDrawable = [gMetalGlobals.caMetalLayer nextDrawable];

gMetalGlobals.mtlCommandBuffer = [gMetalGlobals.mtlCommandQueue commandBuffer];
auto clearColor = Vec4_To_Array(HelloImGui::GetRunnerParams()->imGuiWindowParams.backgroundColor);
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clearColor[0] * clearColor[3], clearColor[1] * clearColor[3], clearColor[2] * clearColor[3], clearColor[3]);
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].texture = gMetalGlobals.caMetalDrawable.texture;
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
gMetalGlobals.mtlRenderCommandEncoder = [
gMetalGlobals.mtlCommandBuffer renderCommandEncoderWithDescriptor:gMetalGlobals.mtlRenderPassDescriptor];
[gMetalGlobals.mtlRenderCommandEncoder pushDebugGroup:@"ImGui demo"];

// Start the Dear ImGui frame
ImGui_ImplMetal_NewFrame(gMetalGlobals.mtlRenderPassDescriptor);
ImGui_ImplGlfw_NewFrame();
return ScreenSize{width, height};
};

callbacks.Impl_RenderDrawData_To_3D = []
{
auto& gMetalGlobals = GetMetalGlobals();
ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), gMetalGlobals.mtlCommandBuffer, gMetalGlobals.mtlRenderCommandEncoder);
};

// Not implemented for Metal
//callbacks.Impl_ScreenshotRgb = []() { ...;};

// This is done at Impl_NewFrame_3D
callbacks.Impl_Frame_3D_ClearColor = [](ImVec4 clearColor) { };

callbacks.Impl_Shutdown_3D = []
{
ImGui_ImplMetal_Shutdown();
};
return callbacks;
}

Expand Down
59 changes: 7 additions & 52 deletions src/hello_imgui/internal/backend_impls/rendering_metal_sdl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <SDL.h>
#include <backends/imgui_impl_sdl2.h>

#include <tuple>


namespace HelloImGui
{
Expand Down Expand Up @@ -51,64 +53,17 @@ void PrepareSdlForMetal_PosImGuiInit()
gMetalGlobals.mtlRenderPassDescriptor = [MTLRenderPassDescriptor new];
}

void SwapSdlMetalBuffers()
{
auto& gMetalGlobals = GetMetalGlobals();
[gMetalGlobals.mtlRenderCommandEncoder popDebugGroup];
[gMetalGlobals.mtlRenderCommandEncoder endEncoding];

[gMetalGlobals.mtlCommandBuffer presentDrawable:gMetalGlobals.caMetalDrawable];
[gMetalGlobals.mtlCommandBuffer commit];
}

RenderingCallbacks CreateBackendCallbacks_SdlMetal()
RenderingCallbacksPtr CreateBackendCallbacks_SdlMetal()
{
RenderingCallbacks callbacks;
auto callbacks = PrepareBackendCallbacksCommon();

callbacks.Impl_NewFrame_3D = []
callbacks->Impl_GetFrameBufferSize = []
{
auto& gMetalGlobals = GetMetalGlobals();
auto& gSdlMetalGlobals = GetSdlMetalGlobals();

auto Vec4_To_Array = [](ImVec4 v) { return std::array<float, 4>{ v.x, v.y, v.z, v.w }; };

//
// New Frame + Clear color
//
int width, height;
SDL_GetRendererOutputSize(gSdlMetalGlobals.sdlRenderer, &width, &height);
gMetalGlobals.caMetalLayer.drawableSize = CGSizeMake(width, height);
gMetalGlobals.caMetalDrawable = [gMetalGlobals.caMetalLayer nextDrawable];

gMetalGlobals.mtlCommandBuffer = [gMetalGlobals.mtlCommandQueue commandBuffer];
auto clearColor = Vec4_To_Array(HelloImGui::GetRunnerParams()->imGuiWindowParams.backgroundColor);
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clearColor[0] * clearColor[3], clearColor[1] * clearColor[3], clearColor[2] * clearColor[3], clearColor[3]);
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].texture = gMetalGlobals.caMetalDrawable.texture;
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
gMetalGlobals.mtlRenderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
gMetalGlobals.mtlRenderCommandEncoder = [gMetalGlobals.mtlCommandBuffer renderCommandEncoderWithDescriptor:gMetalGlobals.mtlRenderPassDescriptor];
[gMetalGlobals.mtlRenderCommandEncoder pushDebugGroup:@"ImGui demo"];

// Start the Dear ImGui frame
ImGui_ImplMetal_NewFrame(gMetalGlobals.mtlRenderPassDescriptor);
SDL_GetRendererOutputSize(GetSdlMetalGlobals().sdlRenderer, &width, &height);
return ScreenSize{width, height};
};

callbacks.Impl_RenderDrawData_To_3D = []
{
auto& gMetalGlobals = GetMetalGlobals();
ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), gMetalGlobals.mtlCommandBuffer, gMetalGlobals.mtlRenderCommandEncoder);
};

// Not implemented for Metal
//callbacks.Impl_ScreenshotRgb = []() { ...;};

// This is done at Impl_NewFrame_3D
callbacks.Impl_Frame_3D_ClearColor = [](ImVec4 clearColor) { };

callbacks.Impl_Shutdown_3D = []
{
ImGui_ImplMetal_Shutdown();
};
return callbacks;
}

Expand Down
Loading

0 comments on commit f3e2617

Please sign in to comment.