mirror of
https://github.com/ocornut/imgui.git
synced 2026-07-11 03:49:45 +00:00
committed by
ocornut
parent
a23e9fb1b5
commit
df71e28084
@@ -6,9 +6,9 @@
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture.gpuResourceID' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Multi-viewport support (multiple windows).
|
||||
// Missing features or Issues:
|
||||
// [ ] Texture view pool support? Reevaluate which type to use for ImtextureID.
|
||||
// [ ] Renderer: Multi-viewport support (multiple windows).
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Multi-viewport support (multiple windows).
|
||||
|
||||
// Missing features or Issues:
|
||||
// [ ] Texture view pool support? Reevaluate which type to use for ImtextureID.
|
||||
// [ ] Renderer: Multi-viewport support (multiple windows).
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -33,11 +34,21 @@
|
||||
#include <Metal/Metal.hpp>
|
||||
#endif
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplMetal_InitMultiViewportSupport();
|
||||
static void ImGui_ImplMetal_ShutdownMultiViewportSupport();
|
||||
static void ImGui_ImplMetal_CreateDeviceObjectsForPlatformWindows();
|
||||
static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows();
|
||||
|
||||
#pragma mark - Support classes and structs
|
||||
|
||||
#define METAL_IMGUI_VIEWPORTS_PER_CHUNK 64
|
||||
|
||||
struct ImGui_Metal4_ConstantData
|
||||
{
|
||||
float ModelViewProjectionMatrix[4][4];
|
||||
// 1 projection matrix is encoded as 4x4 float.
|
||||
// Store up to 64 of them in same constant buffer, so multiple viewports can use same constant buffer.
|
||||
float ModelViewProjectionMatrix[METAL_IMGUI_VIEWPORTS_PER_CHUNK][4][4];
|
||||
};
|
||||
|
||||
@interface MetalBuffer : NSObject
|
||||
@@ -76,13 +87,15 @@ struct ImGui_Metal4_ConstantData
|
||||
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache;
|
||||
@property (nonatomic, assign) NSUInteger framesInFlight;
|
||||
@property (nonatomic, assign) NSUInteger currentFrameSlot;
|
||||
@property (nonatomic, strong) NSArray<id<MTLBuffer>>* constantBuffers;
|
||||
@property (nonatomic, assign) ImGui_Metal4_ConstantData** constantBufferContentsArray;
|
||||
@property (nonatomic, strong) NSMutableArray<NSMutableArray<MetalBuffer*>*>* bufferCaches;
|
||||
@property (nonatomic, strong) NSObject* bufferCacheLock;
|
||||
@property (nonatomic, assign) double lastBufferCachePurge;
|
||||
- (id<MTLBuffer>)currentConstantBuffer;
|
||||
- (ImGui_Metal4_ConstantData*)currentConstantBufferContents;
|
||||
@property (nonatomic, strong) NSArray<id<MTLSharedEvent>>* events; // for tracking when a commands are complete to reset allocator
|
||||
@property (nonatomic) uint64_t eventValue;
|
||||
@property (nonatomic, strong) NSArray<id<MTL4CommandAllocator>>* commandAllocators;
|
||||
@property (nonatomic, strong) NSMutableArray<NSMutableArray<id<MTLBuffer>>*>* constantBuffers;
|
||||
@property (nonatomic) uint64_t constantBufferChunkCount;
|
||||
@property (nonatomic) uint64_t currentConstantBufferIndex;
|
||||
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
|
||||
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device;
|
||||
@end
|
||||
@@ -145,6 +158,10 @@ void ImGui_ImplMetal4_NewFrame(MTL4RenderPassDescriptor* renderPassDescriptor, i
|
||||
bd->SharedMetalContext.currentFrameSlot = (NSUInteger)frameInFlightIndex;
|
||||
if (bd->SharedMetalContext.depthStencilState == nil)
|
||||
ImGui_ImplMetal4_CreateDeviceObjects(bd->SharedMetalContext.device);
|
||||
|
||||
bd->SharedMetalContext.currentConstantBufferIndex = 0;
|
||||
[bd->SharedMetalContext.events[frameInFlightIndex] waitUntilSignaledValue:bd->SharedMetalContext.eventValue timeoutMS:UINT64_MAX];
|
||||
[bd->SharedMetalContext.commandAllocators[frameInFlightIndex] reset];
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal4_SetupRenderState(ImDrawData* draw_data, id<MTL4CommandBuffer> commandBuffer,
|
||||
@@ -183,11 +200,18 @@ static void ImGui_ImplMetal4_SetupRenderState(ImDrawData* draw_data, id<MTL4Comm
|
||||
{ 0.0f, 0.0f, 1/(F-N), 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f },
|
||||
};
|
||||
ImGui_Metal4_ConstantData* constantBufferContents = [bd->SharedMetalContext currentConstantBufferContents];
|
||||
memcpy(constantBufferContents->ModelViewProjectionMatrix, ortho_projection, sizeof(ortho_projection));
|
||||
|
||||
|
||||
int currentChunk = (int)((float)bd->SharedMetalContext.currentConstantBufferIndex / (float)METAL_IMGUI_VIEWPORTS_PER_CHUNK);
|
||||
int currentIndex = bd->SharedMetalContext.currentConstantBufferIndex % METAL_IMGUI_VIEWPORTS_PER_CHUNK;
|
||||
|
||||
int currentFrameIndex = (int)bd->SharedMetalContext.currentFrameSlot;
|
||||
id<MTLBuffer> constantBuffer = bd->SharedMetalContext.constantBuffers[currentFrameIndex][currentChunk];
|
||||
ImGui_Metal4_ConstantData* constantBufferContents = (ImGui_Metal4_ConstantData*)constantBuffer.contents;
|
||||
|
||||
memcpy(&constantBufferContents->ModelViewProjectionMatrix[currentIndex], ortho_projection, sizeof(ortho_projection));
|
||||
|
||||
id<MTL4ArgumentTable> argumentTable = bd->SharedMetalContext.argumentTable;
|
||||
[argumentTable setAddress:[bd->SharedMetalContext currentConstantBuffer].gpuAddress atIndex:1];
|
||||
[argumentTable setAddress:constantBuffer.gpuAddress+(uint64_t)currentIndex * sizeof(constantBufferContents->ModelViewProjectionMatrix[0]) atIndex:1];
|
||||
[argumentTable setAddress:(vertexBuffer.buffer.gpuAddress + vertexBufferOffset) attributeStride:sizeof(ImDrawVert) atIndex:0];
|
||||
[argumentTable setSamplerState:bd->SharedMetalContext.samplerStateLinear.gpuResourceID atIndex:0];
|
||||
[commandEncoder setArgumentTable:argumentTable atStages:MTLRenderStageVertex | MTLRenderStageFragment];
|
||||
@@ -234,8 +258,23 @@ void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, id<MTL4CommandBuffer
|
||||
MetalBuffer* indexBuffer = [ctx dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
|
||||
|
||||
bd->RenderCommandEncoder = commandEncoder;
|
||||
|
||||
// check if more chunks are required
|
||||
const int chunksRequired = 1 + (int)((float)bd->SharedMetalContext.currentConstantBufferIndex / (float)METAL_IMGUI_VIEWPORTS_PER_CHUNK);
|
||||
if (chunksRequired > bd->SharedMetalContext.constantBufferChunkCount)
|
||||
{
|
||||
for (NSUInteger i = 0; i < bd->SharedMetalContext.framesInFlight; i++)
|
||||
{
|
||||
id<MTLBuffer> buffer = [bd->SharedMetalContext.device newBufferWithLength:sizeof(ImGui_Metal4_ConstantData) options:MTLResourceStorageModeShared];
|
||||
[bd->SharedMetalContext.constantBuffers[i] addObject:buffer];
|
||||
[bd->SharedMetalContext.residencySet addAllocation:buffer];
|
||||
}
|
||||
bd->SharedMetalContext.constantBufferChunkCount++;
|
||||
}
|
||||
|
||||
ImGui_ImplMetal4_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, 0);
|
||||
|
||||
bd->SharedMetalContext.currentConstantBufferIndex++;
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
@@ -415,27 +454,33 @@ bool ImGui_ImplMetal4_CreateDeviceObjects(id<MTLDevice> device)
|
||||
samplerDescriptor.mipFilter = MTLSamplerMipFilterNearest;
|
||||
bd->SharedMetalContext.samplerStateNearest = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
|
||||
NSMutableArray<id<MTLBuffer>>* constantBuffers = [NSMutableArray array];
|
||||
ImGui_Metal4_ConstantData** constantBufferContentsArray = (ImGui_Metal4_ConstantData**)malloc(sizeof(ImGui_Metal4_ConstantData*) * bd->SharedMetalContext.framesInFlight);
|
||||
NSMutableArray<id<MTL4CommandAllocator>>* commandAllocators = [NSMutableArray array];
|
||||
NSMutableArray<id<MTLSharedEvent>>* events = [NSMutableArray array];
|
||||
bd->SharedMetalContext.constantBuffers = [NSMutableArray array];
|
||||
for (NSUInteger i = 0; i < bd->SharedMetalContext.framesInFlight; i++)
|
||||
{
|
||||
id<MTLBuffer> constantBuffer = [device newBufferWithLength:sizeof(ImGui_Metal4_ConstantData) options:MTLResourceStorageModeShared];
|
||||
[constantBuffers addObject:constantBuffer];
|
||||
constantBufferContentsArray[i] = (ImGui_Metal4_ConstantData*)constantBuffer.contents;
|
||||
[bd->SharedMetalContext.residencySet addAllocation:constantBuffer];
|
||||
events[i] = [device newSharedEvent];
|
||||
commandAllocators[i] = [device newCommandAllocator];
|
||||
bd->SharedMetalContext.constantBuffers[i] = [NSMutableArray array];
|
||||
id<MTLBuffer> buffer = [device newBufferWithLength:sizeof(ImGui_Metal4_ConstantData) options:MTLResourceStorageModeShared];
|
||||
[bd->SharedMetalContext.constantBuffers[i] addObject:buffer];
|
||||
[bd->SharedMetalContext.residencySet addAllocation:buffer];
|
||||
}
|
||||
bd->SharedMetalContext.constantBuffers = constantBuffers;
|
||||
bd->SharedMetalContext.constantBufferContentsArray = constantBufferContentsArray;
|
||||
bd->SharedMetalContext.constantBufferChunkCount = 1;
|
||||
bd->SharedMetalContext.events = events;
|
||||
|
||||
MTL4ArgumentTableDescriptor* argumentTableDescriptor = [[MTL4ArgumentTableDescriptor alloc] init];
|
||||
argumentTableDescriptor.maxBufferBindCount = 8;
|
||||
argumentTableDescriptor.maxTextureBindCount = 8;
|
||||
argumentTableDescriptor.maxSamplerStateBindCount = 8;
|
||||
argumentTableDescriptor.maxBufferBindCount = 2; // vertex buffer + constant buffer
|
||||
argumentTableDescriptor.maxTextureBindCount = 1; // font atlas or user texture
|
||||
argumentTableDescriptor.maxSamplerStateBindCount = 2;
|
||||
argumentTableDescriptor.supportAttributeStrides = YES; // required: vertex buffer is bound via setAddress:stride:atIndex: for stage_in fetch
|
||||
|
||||
bd->SharedMetalContext.commandAllocators = commandAllocators;
|
||||
|
||||
bd->SharedMetalContext.argumentTable = [device newArgumentTableWithDescriptor:argumentTableDescriptor error:&error];
|
||||
IM_ASSERT(bd->SharedMetalContext.argumentTable != nil && error == nil);
|
||||
|
||||
ImGui_ImplMetal_CreateDeviceObjectsForPlatformWindows();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -451,6 +496,8 @@ void ImGui_ImplMetal4_DestroyDeviceObjects()
|
||||
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
|
||||
bd->SharedMetalContext.samplerStateLinear = nil;
|
||||
bd->SharedMetalContext.samplerStateNearest = nil;
|
||||
ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows();
|
||||
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal4_Init(id<MTLDevice> device, id<MTL4CommandQueue> commandQueue, int framesInFlight)
|
||||
@@ -465,6 +512,7 @@ bool ImGui_ImplMetal4_Init(id<MTLDevice> device, id<MTL4CommandQueue> commandQue
|
||||
io.BackendRendererName = "imgui_impl_metal4";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal4_DrawCallback_ResetRenderState;
|
||||
@@ -479,6 +527,8 @@ bool ImGui_ImplMetal4_Init(id<MTLDevice> device, id<MTL4CommandQueue> commandQue
|
||||
for (NSUInteger i = 0; i < framesInFlight; i++)
|
||||
[bufferCaches addObject:[NSMutableArray array]];
|
||||
bd->SharedMetalContext.bufferCaches = bufferCaches;
|
||||
|
||||
ImGui_ImplMetal_InitMultiViewportSupport();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -490,6 +540,7 @@ void ImGui_ImplMetal4_Shutdown()
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplMetal_ShutdownMultiViewportSupport();
|
||||
ImGui_ImplMetal4_DestroyDeviceObjects();
|
||||
ImGui_ImplMetal4_DestroyBackendData();
|
||||
|
||||
@@ -587,17 +638,6 @@ void ImGui_ImplMetal4_Shutdown()
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(_constantBufferContentsArray);
|
||||
}
|
||||
|
||||
- (id<MTLBuffer>)currentConstantBuffer
|
||||
{
|
||||
return self.constantBuffers[self.currentFrameSlot];
|
||||
}
|
||||
|
||||
- (ImGui_Metal4_ConstantData*)currentConstantBufferContents
|
||||
{
|
||||
return self.constantBufferContentsArray[self.currentFrameSlot];
|
||||
}
|
||||
|
||||
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
|
||||
@@ -739,6 +779,159 @@ fragment half4 fragment_main(VertexOut in [[stage_in]],
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - Multi-viewport support
|
||||
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
|
||||
// This is an _advanced_ and _optional_ feature, allowing the back-end to create and handle multiple viewports simultaneously.
|
||||
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct ImGuiViewportDataMetal
|
||||
{
|
||||
CAMetalLayer* MetalLayer;
|
||||
id<MTLCommandQueue> CommandQueue;
|
||||
MTL4RenderPassDescriptor* RenderPassDescriptor;
|
||||
void* Handle = nullptr;
|
||||
bool FirstFrame = true;
|
||||
};
|
||||
|
||||
static void ImGui_ImplMetal_CreateWindow(ImGuiViewport* viewport)
|
||||
{
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
ImGuiViewportDataMetal* data = IM_NEW(ImGuiViewportDataMetal)();
|
||||
viewport->RendererUserData = data;
|
||||
|
||||
// PlatformHandleRaw should always be a NSWindow*, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
|
||||
// Some back-ends will leave PlatformHandleRaw == 0, in which case we assume PlatformHandle will contain the NSWindow*.
|
||||
void* handle = viewport->PlatformHandleRaw ? viewport->PlatformHandleRaw : viewport->PlatformHandle;
|
||||
IM_ASSERT(handle != nullptr);
|
||||
|
||||
id<MTLDevice> device = bd->SharedMetalContext.device;
|
||||
CAMetalLayer* layer = [CAMetalLayer layer];
|
||||
layer.device = device;
|
||||
layer.framebufferOnly = YES;
|
||||
layer.pixelFormat = bd->SharedMetalContext.framebufferDescriptor.colorPixelFormat;
|
||||
#if TARGET_OS_OSX
|
||||
NSWindow* window = (__bridge NSWindow*)handle;
|
||||
NSView* view = window.contentView;
|
||||
view.layer = layer;
|
||||
view.wantsLayer = YES;
|
||||
#endif
|
||||
data->MetalLayer = layer;
|
||||
data->CommandQueue = [device newCommandQueue];
|
||||
data->RenderPassDescriptor = [[MTL4RenderPassDescriptor alloc] init];
|
||||
data->Handle = handle;
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_DestroyWindow(ImGuiViewport* viewport)
|
||||
{
|
||||
// The main viewport (owned by the application) will always have RendererUserData == 0 since we didn't create the data for it.
|
||||
if (ImGuiViewportDataMetal* data = (ImGuiViewportDataMetal*)viewport->RendererUserData)
|
||||
IM_DELETE(data);
|
||||
viewport->RendererUserData = nullptr;
|
||||
}
|
||||
|
||||
inline static CGSize MakeScaledSize(CGSize size, CGFloat scale)
|
||||
{
|
||||
return CGSizeMake(size.width * scale, size.height * scale);
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
|
||||
{
|
||||
ImGuiViewportDataMetal* data = (ImGuiViewportDataMetal*)viewport->RendererUserData;
|
||||
data->MetalLayer.drawableSize = MakeScaledSize(CGSizeMake(size.x, size.y), viewport->DpiScale);
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_RenderWindow(ImGuiViewport* viewport, void*)
|
||||
{
|
||||
ImGuiViewportDataMetal* data = (ImGuiViewportDataMetal*)viewport->RendererUserData;
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
void* handle = viewport->PlatformHandleRaw ? viewport->PlatformHandleRaw : viewport->PlatformHandle;
|
||||
NSWindow* window = (__bridge NSWindow*)handle;
|
||||
|
||||
// Always render the first frame, regardless of occlusionState, to avoid an initial flicker
|
||||
if ((window.occlusionState & NSWindowOcclusionStateVisible) == 0 && !data->FirstFrame)
|
||||
{
|
||||
// Do not render windows which are completely occluded. Calling -[CAMetalLayer nextDrawable] will hang for
|
||||
// approximately 1 second if the Metal layer is completely occluded.
|
||||
return;
|
||||
}
|
||||
data->FirstFrame = false;
|
||||
|
||||
float fb_scale = (float)window.backingScaleFactor;
|
||||
if (data->MetalLayer.contentsScale != fb_scale)
|
||||
{
|
||||
data->MetalLayer.contentsScale = fb_scale;
|
||||
data->MetalLayer.drawableSize = MakeScaledSize(window.frame.size, fb_scale);
|
||||
}
|
||||
#endif
|
||||
|
||||
id <CAMetalDrawable> drawable = [data->MetalLayer nextDrawable];
|
||||
if (drawable == nil)
|
||||
return;
|
||||
|
||||
MTL4RenderPassDescriptor* renderPassDescriptor = data->RenderPassDescriptor;
|
||||
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
|
||||
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 0);
|
||||
if ((viewport->Flags & ImGuiViewportFlags_NoRendererClear) == 0)
|
||||
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
id <MTL4CommandBuffer> commandBuffer = [bd->SharedMetalContext.device newCommandBuffer];
|
||||
[commandBuffer beginCommandBufferWithAllocator:bd->SharedMetalContext.commandAllocators[bd->SharedMetalContext.currentFrameSlot]];
|
||||
|
||||
id <MTL4RenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||
ImGui_ImplMetal4_RenderDrawData(viewport->DrawData, commandBuffer, renderEncoder);
|
||||
[renderEncoder endEncoding];
|
||||
[commandBuffer endCommandBuffer];
|
||||
|
||||
[bd->SharedMetalContext.commandQueue waitForDrawable:drawable];
|
||||
[bd->SharedMetalContext.commandQueue commit:&commandBuffer count:1];
|
||||
[bd->SharedMetalContext.commandQueue signalDrawable:drawable];
|
||||
[drawable present];
|
||||
[bd->SharedMetalContext.commandQueue signalEvent:bd->SharedMetalContext.events[bd->SharedMetalContext.currentFrameSlot] value:++(bd->SharedMetalContext.eventValue)];
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_InitMultiViewportSupport()
|
||||
{
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_CreateWindow = ImGui_ImplMetal_CreateWindow;
|
||||
platform_io.Renderer_DestroyWindow = ImGui_ImplMetal_DestroyWindow;
|
||||
platform_io.Renderer_SetWindowSize = ImGui_ImplMetal_SetWindowSize;
|
||||
platform_io.Renderer_RenderWindow = ImGui_ImplMetal_RenderWindow;
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_ShutdownMultiViewportSupport()
|
||||
{
|
||||
ImGui::DestroyPlatformWindows();
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_CreateDeviceObjectsForPlatformWindows()
|
||||
{
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
for (int i = 1; i < platform_io.Viewports.Size; i++)
|
||||
if (!platform_io.Viewports[i]->RendererUserData)
|
||||
ImGui_ImplMetal_CreateWindow(platform_io.Viewports[i]);
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows()
|
||||
{
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
for (int i = 1; i < platform_io.Viewports.Size; i++)
|
||||
if (platform_io.Viewports[i]->RendererUserData)
|
||||
ImGui_ImplMetal_DestroyWindow(platform_io.Viewports[i]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -177,6 +177,8 @@ Docking+Viewports Branch:
|
||||
- Fixed behavior change/regression in 1.92.8 where a window using the
|
||||
ImGuiWindowFlags_AlwaysAutoResize flag would have ItemWidth default
|
||||
change when docked. (#9355, #9443) [@reybits]
|
||||
- Backends:
|
||||
- Metal4: added multi-viewport support. (#9465, #9451) [@hoffstadt]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user