Backends: Metal: add sampler states and DrawCallback_SetSamplerLinear / DrawCallback_SetSamplerNearest callbacks. (#9381, #9371, #9378)
This commit is contained in:
@@ -5,8 +5,6 @@
|
|||||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
// [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: 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: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||||
// Missing features or Issues:
|
|
||||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks.
|
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// 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.
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
// [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: 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: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||||
// Missing features or Issues:
|
|
||||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks.
|
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// 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.
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
@@ -18,6 +16,7 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381)
|
||||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378)
|
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378)
|
||||||
// 2026-04-14: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for @synchronize(). (#9367)
|
// 2026-04-14: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for @synchronize(). (#9367)
|
||||||
// 2026-04-03: Metal: avoid redundant vertex buffer bind in SetupRenderState. (#9343)
|
// 2026-04-03: Metal: avoid redundant vertex buffer bind in SetupRenderState. (#9343)
|
||||||
@@ -79,6 +78,8 @@
|
|||||||
@interface MetalContext : NSObject
|
@interface MetalContext : NSObject
|
||||||
@property (nonatomic, strong) id<MTLDevice> device;
|
@property (nonatomic, strong) id<MTLDevice> device;
|
||||||
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
|
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
|
||||||
|
@property (nonatomic, strong) id<MTLSamplerState> samplerStateLinear;
|
||||||
|
@property (nonatomic, strong) id<MTLSamplerState> samplerStateNearest;
|
||||||
@property (nonatomic, strong) FramebufferDescriptor* framebufferDescriptor; // framebuffer descriptor for current frame; transient
|
@property (nonatomic, strong) FramebufferDescriptor* framebufferDescriptor; // framebuffer descriptor for current frame; transient
|
||||||
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
|
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
|
||||||
@property (nonatomic, strong) NSMutableArray<MetalBuffer*>* bufferCache;
|
@property (nonatomic, strong) NSMutableArray<MetalBuffer*>* bufferCache;
|
||||||
@@ -91,6 +92,7 @@
|
|||||||
struct ImGui_ImplMetal_Data
|
struct ImGui_ImplMetal_Data
|
||||||
{
|
{
|
||||||
MetalContext* SharedMetalContext;
|
MetalContext* SharedMetalContext;
|
||||||
|
id<MTLRenderCommandEncoder> RenderCommandEncoder;
|
||||||
|
|
||||||
ImGui_ImplMetal_Data() { memset((void*)this, 0, sizeof(*this)); }
|
ImGui_ImplMetal_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
};
|
};
|
||||||
@@ -185,12 +187,15 @@ static void ImGui_ImplMetal_SetupRenderState(ImDrawData* draw_data, id<MTLComman
|
|||||||
[commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
|
[commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
|
||||||
|
|
||||||
[commandEncoder setRenderPipelineState:renderPipelineState];
|
[commandEncoder setRenderPipelineState:renderPipelineState];
|
||||||
|
[commandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateLinear atIndex:0];
|
||||||
|
|
||||||
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:vertexBufferOffset atIndex:0];
|
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:vertexBufferOffset atIndex:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw callbacks
|
// Draw callbacks
|
||||||
static void ImGui_ImplMetal_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
static void ImGui_ImplMetal_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||||
|
static void ImGui_ImplMetal_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [bd->RenderCommandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateLinear atIndex:0]; }
|
||||||
|
static void ImGui_ImplMetal_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [bd->RenderCommandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateNearest atIndex:0]; }
|
||||||
|
|
||||||
// Metal Render function.
|
// Metal Render function.
|
||||||
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
|
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
|
||||||
@@ -228,6 +233,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
|
|||||||
MetalBuffer* vertexBuffer = [ctx dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
|
MetalBuffer* vertexBuffer = [ctx dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
|
||||||
MetalBuffer* indexBuffer = [ctx dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
|
MetalBuffer* indexBuffer = [ctx dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
|
||||||
|
|
||||||
|
bd->RenderCommandEncoder = commandEncoder;
|
||||||
ImGui_ImplMetal_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, 0);
|
ImGui_ImplMetal_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, 0);
|
||||||
|
|
||||||
// Will project scissor/clipping rectangles into framebuffer space
|
// Will project scissor/clipping rectangles into framebuffer space
|
||||||
@@ -306,6 +312,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
|
|||||||
[sharedMetalContext.bufferCache addObject:indexBuffer];
|
[sharedMetalContext.bufferCache addObject:indexBuffer];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
bd->RenderCommandEncoder = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
|
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
|
||||||
@@ -382,7 +389,17 @@ bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
|
|||||||
depthStencilDescriptor.depthWriteEnabled = NO;
|
depthStencilDescriptor.depthWriteEnabled = NO;
|
||||||
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
||||||
bd->SharedMetalContext.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
|
bd->SharedMetalContext.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
|
||||||
|
MTLSamplerDescriptor* samplerDescriptor = [[MTLSamplerDescriptor alloc] init];
|
||||||
|
samplerDescriptor.minFilter = MTLSamplerMinMagFilterLinear;
|
||||||
|
samplerDescriptor.magFilter = MTLSamplerMinMagFilterLinear;
|
||||||
|
samplerDescriptor.mipFilter = MTLSamplerMipFilterLinear;
|
||||||
|
bd->SharedMetalContext.samplerStateLinear = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||||
|
samplerDescriptor.minFilter = MTLSamplerMinMagFilterNearest;
|
||||||
|
samplerDescriptor.magFilter = MTLSamplerMinMagFilterNearest;
|
||||||
|
samplerDescriptor.mipFilter = MTLSamplerMipFilterNearest;
|
||||||
|
bd->SharedMetalContext.samplerStateNearest = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||||
#ifdef IMGUI_IMPL_METAL_CPP
|
#ifdef IMGUI_IMPL_METAL_CPP
|
||||||
|
[samplerDescriptor release];
|
||||||
[depthStencilDescriptor release];
|
[depthStencilDescriptor release];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -399,6 +416,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
|||||||
ImGui_ImplMetal_DestroyTexture(tex);
|
ImGui_ImplMetal_DestroyTexture(tex);
|
||||||
|
|
||||||
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
|
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
|
||||||
|
bd->SharedMetalContext.samplerStateLinear = nil;
|
||||||
|
bd->SharedMetalContext.samplerStateNearest = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
||||||
@@ -415,6 +434,8 @@ bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
|||||||
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal_DrawCallback_ResetRenderState;
|
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal_DrawCallback_ResetRenderState;
|
||||||
|
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplMetal_DrawCallback_SetSamplerLinear;
|
||||||
|
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplMetal_DrawCallback_SetSamplerNearest;
|
||||||
|
|
||||||
bd->SharedMetalContext = [[MetalContext alloc] init];
|
bd->SharedMetalContext = [[MetalContext alloc] init];
|
||||||
bd->SharedMetalContext.device = device;
|
bd->SharedMetalContext.device = device;
|
||||||
@@ -599,9 +620,9 @@ void ImGui_ImplMetal_Shutdown()
|
|||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"fragment half4 fragment_main(VertexOut in [[stage_in]],\n"
|
"fragment half4 fragment_main(VertexOut in [[stage_in]],\n"
|
||||||
" texture2d<half, access::sample> texture [[texture(0)]]) {\n"
|
" texture2d<half, access::sample> texture [[texture(0)]],\n"
|
||||||
" constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear, mip_filter::linear);\n"
|
" sampler textureSampler [[sampler(0)]]) {\n"
|
||||||
" half4 texColor = texture.sample(linearSampler, in.texCoords);\n"
|
" half4 texColor = texture.sample(textureSampler, in.texCoords);\n"
|
||||||
" return half4(in.color) * texColor;\n"
|
" return half4(in.color) * texColor;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -149,7 +149,7 @@ Other Changes:
|
|||||||
- DX10: Reset SetSamplerLinear SetSamplerNearest
|
- DX10: Reset SetSamplerLinear SetSamplerNearest
|
||||||
- DX11: Reset SetSamplerLinear SetSamplerNearest
|
- DX11: Reset SetSamplerLinear SetSamplerNearest
|
||||||
- DX12: Reset SetSamplerLinear SetSamplerNearest
|
- DX12: Reset SetSamplerLinear SetSamplerNearest
|
||||||
- Metal: Reset *missing* *missing*
|
- Metal: Reset SetSamplerLinear SetSamplerNearest
|
||||||
- OpenGL2: Reset SetSamplerLinear SetSamplerNearest
|
- OpenGL2: Reset SetSamplerLinear SetSamplerNearest
|
||||||
- OpenGL3+: Reset SetSamplerLinear SetSamplerNearest
|
- OpenGL3+: Reset SetSamplerLinear SetSamplerNearest
|
||||||
- SDLGPU3: Reset SetSamplerLinear SetSamplerNearest
|
- SDLGPU3: Reset SetSamplerLinear SetSamplerNearest
|
||||||
@@ -157,7 +157,7 @@ Other Changes:
|
|||||||
- SDLRenderer3: Reset SetSamplerLinear SetSamplerNearest
|
- SDLRenderer3: Reset SetSamplerLinear SetSamplerNearest
|
||||||
- Vulkan: Reset SetSamplerLinear SetSamplerNearest
|
- Vulkan: Reset SetSamplerLinear SetSamplerNearest
|
||||||
- WebGPU: Reset SetSamplerLinear SetSamplerNearest
|
- WebGPU: Reset SetSamplerLinear SetSamplerNearest
|
||||||
(Vulkan backend by @yaz0r, others by @ocornut)
|
(Vulkan backend by @yaz0r, Metal by @ssh4net, others by @ocornut)
|
||||||
- GLFW: added a Win32-specific implementation of `ImGui_ImplGlfw_GetContentScaleXXXX`
|
- GLFW: added a Win32-specific implementation of `ImGui_ImplGlfw_GetContentScaleXXXX`
|
||||||
functions for legacy GLFW 3.2. (#9003)
|
functions for legacy GLFW 3.2. (#9003)
|
||||||
- Metal: avoid redundant vertex buffer bind in `SetupRenderState()`, which leads
|
- Metal: avoid redundant vertex buffer bind in `SetupRenderState()`, which leads
|
||||||
|
|||||||
@@ -4018,11 +4018,11 @@ struct ImGuiPlatformIO
|
|||||||
// Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure.
|
// Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure.
|
||||||
void* Renderer_RenderState;
|
void* Renderer_RenderState;
|
||||||
|
|
||||||
// Standard draw callbacks
|
// Standard draw callbacks provided by renderer backend.
|
||||||
ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
|
ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
|
||||||
ImDrawCallback DrawCallback_SetSamplerLinear; // Request to set current texture sampling to Linear
|
ImDrawCallback DrawCallback_SetSamplerLinear; // Request backend to set texture sampling to Linear.
|
||||||
ImDrawCallback DrawCallback_SetSamplerNearest; // Request to set current texture sampling to Nearest/Point
|
ImDrawCallback DrawCallback_SetSamplerNearest; // Request backend to set texture sampling to Nearest/Point.
|
||||||
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request to set current texture sampling using Backend Specific data.
|
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request backend to set texture sampling using Backend Specific data.
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Output
|
// Output
|
||||||
|
|||||||
Reference in New Issue
Block a user