Skip to content

Metal backend: optional sampler-aware user textures #9371

@ssh4net

Description

@ssh4net

Version/Branch of Dear ImGui:

Version 1.92, Branch: docking

Back-ends:

Metal

Compiler, OS:

MacOS

Details:

One thing that came up while integrating Dear ImGui's Metal backend in OpenImageIO imiv is that the current backend assumes a user texture is just an MTLTexture* sampled with a backend-defined linear sampler. That works for the usual UI case, but it becomes awkward in image tools where filtering mode is part of the view state. In imiv, the same image may be shown in two places with different expectations: the main view may follow a linear or nearest interpolation toggle, while the close-up view wants nearest sampling so individual pixels stay readable. Right now that means carrying a local fork of imgui_impl_metal, because the Metal shader hardcodes linear sampling.

What would help here is a small opt-in path that lets the Metal backend accept a user texture ID built from a (texture, sampler) pair, while leaving the current raw-MTLTexture* path alone. Existing code would keep working exactly as it does now. Plain MTLTexture* IDs would still use the backend default sampler, and only callers that need it would opt into a sampler-aware wrapper. A possible API shape is:

IMGUI_IMPL_API ImTextureID ImGui_ImplMetal_CreateUserTextureID(id<MTLTexture> texture,
                                                               id<MTLSamplerState> sampler_state);
IMGUI_IMPL_API void ImGui_ImplMetal_DestroyUserTextureID(ImTextureID tex_id);

On the render side, the backend would accept either a plain texture or a small backend-owned wrapper, bind the attached sampler when present, fall back to the default sampler otherwise, and change the Metal shader to take sampler [[sampler(0)]] instead of baking linear filtering into the shader source. That is a small change, but it removes a real fork point for Metal applications that care about how images are sampled.

This also seems like a better fit than draw callbacks. Callbacks can change sampler state, but the need here is not really custom rendering. It is just normal image presentation where different widgets need different filtering in the same frame. In imiv, the requirement is simple: the main image follows the interpolation setting, and the close-up view stays nearest. Having that travel with the texture ID is simpler to use and easier to reason about than pushing ordinary image widgets through callback-driven render-state changes.

I have a working workaround in https://github.com/ssh4net/OpenImageIO/blob/_imgui/src/imiv/external/imgui_impl_metal_imiv.mm
but maybe there are better way for this.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions