Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Bug Metal C++ graphics plugin - Unity returns nil for MTLCommandEncoder

Discussion in 'General Graphics' started by williamih-resolve, Feb 26, 2024.

  1. williamih-resolve


    Feb 4, 2021
    Hi all,

    We're looking into a Metal version of our Unity app that uses a native C++ plugin that performs custom Metal rendering, but we're blocked because Unity is returning a nil result for MTLCommandEncoder.

    To render into Unity's scene with Metal, it's necessary to have an id<MTLCommandEncoder> representing the current rendering pass. This is provided by the CurrentCommandEncoder member of the IUnityGraphicsMetal interface here.

    However, CurrentCommandEncoder returns nil at several points where we need to perform custom rendering. Specifically, using Camera.AddCommandBuffer() and CommandBuffer.IssuePluginEvent() to register a native callback gives a nil result for CurrentCommandEncoder when using either CameraEvent.BeforeForwardOpaque or CameraEvent.AfterForwardOpaque.

    The official example here uses a coroutine with WaitForEndOfFrame() and then issues a plugin event to perform custom rendering. This gives a non-nil MTLCommandEncoder, but it is very limiting: it only allows rendering at the very end of a frame. This breaks correct rendering of transparent objects. To correctly use custom rendering supporting both opaque and transparent objects, it's necessary to add the custom rendering commands to an earlier point in the frame, e.g. using CameraEvent.BeforeForwardOpaque and CameraEvent.BeforeForwardAlpha.

    The approach we're using here works correctly on two other platforms (D3D11 and Vulkan), but does not work for Metal because of the nil result.

    Does anyone know of a solution to this? One possibility could be to create our own MTLCommandEncoder, but to do this we'd need access to the Metal texture objects for the framebuffer (color and depth buffer). I haven't seen a way to access these from Unity.