addPresentedHandler not being triggered in Metal on iOS

白昼怎懂夜的黑 提交于 2021-01-28 07:54:39

问题


I've been trying to set up a addPresentedHandler for some time now, but without luck.

I've got a addCompletedHandler working on the command buffers that contain the rendering work to be executed every frame. I've verified that the addCompletedHandler is working by seeing setting breakpoints within the code block. These are triggered when running the app. For the addPresentedHandler however, no breakpoint within the code block is triggered (I've also verified through modifying variables from the code block, and inserting printfs into the block).

My rendering loop is currently very simple, and looks like this (hopefully I've provided enough):

NOTE: I'm using a strong combination of C++ and Objective-C++. The code presented below is therefore not a direct representation of the actual code.

dispatch_semaphore_wait(m_inFlightFramesSemaphore, DISPATCH_TIME_FOREVER);
m_drawables[m_currentFrameIndex] = [m_swapChain nextDrawable];
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor new];
renderPassDescriptor.colorAttachments[0].texture = m_drawables[m_currentFrameIndex].texture;
renderPassDescriptor.colorAttachments[0].level = 0;
renderPassDescriptor.colorAttachments[0].slice = 0;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0, 1.0, 1.0, 1.0);

id<MTLCommandBuffer> commandBuffer = [m_commandQueue commandBuffer];
id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor: renderPassDescriptor];
[renderEncoder setRenderPipelineState: m_pipelineState];
[renderEncoder setTriangleFillMode: MTLTriangleFillModeFill];
[renderEncoder setFrontFacingWinding: MTLWindingCounterClockwise];
[renderEncoder setCullMode: MTLCullModeBack];
/* set viewport and scissor (omitted here) */
[renderEncoder useResource: m_vertexBuffer usage: MTLResourceUsageRead stages: MTLRenderStageVertex];
[renderEncoder setVertexBuffer: m_vertexBuffer offset: 0 atIndex: 0];
[renderEncoder useResource: m_indexBuffer usage: MTLResourceUsageRead stages: MTLRenderStageVertex];
[renderEncoder drawIndexedPrimitives: MTLPrimitiveTypeTriangle indexCount: 6
  indexType: MTLIndexTypeUInt32 indexBuffer: m_indexBuffer indexBufferOffset: 0
  instanceCount: 1];
[renderEncoder endEncoding];
PresentDrawable(commandBuffer, m_drawables[m_currentFrameIndex]);
CommitFinalCommandBufferInFrame(commandBuffer);

The two final function calls are implemented as follows:

void PresentDrawable(id<MTLCommandBuffer> commandBuffer, id<CAMetalDrawable> drawable)
{
    [drawable addPresentedHandler:^(id<MTLDrawable> dr) {
        m_framesPresented++;
        if (m_framesPresented == m_maxFrames)
        {
            dispatch_semaphore_signal(m_lastFramePresentedSemaphore);
        }
    }];

    [commandBuffer presentDrawable:drawable];
}

void CommitFinalCommandBufferInFrame(id<MTLCommandBuffer> commandBuffer)
{
    [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> cb) {
        dispatch_semaphore_signal(m_inFlightFramesSemaphore);
    }];

    [commandBuffer commit];
    m_framesSubmitted++;
    m_currentFrameIndex = (m_currentFrameIndex + 1) % m_maximumDrawableCount;
}

I don't see why the addPresentedHandler code block isn't be triggered, while the addCompletedHandler block is...am I missing something obvious?

Thanks!


回答1:


I don't see any problems with your code, I've checked it works.

void PresentDrawable(id<MTLCommandBuffer> commandBuffer, id<CAMetalDrawable> drawable)
{
    [drawable addPresentedHandler:^(id<MTLDrawable> dr) {

        printf("Handler \n");
        m_framesPresented++;
        if (m_framesPresented == m_maxFrames)
        {
            dispatch_semaphore_signal(m_lastFramePresentedSemaphore);
        }
    }];

    [commandBuffer presentDrawable:drawable];
}



回答2:


In my question, I did not mention that I was running on the iPhone 11 Pro Max (v13.3) Simulator. Upon trying on an actual iPhone 11 (v13.3.1) the addPresentHandler as implemented in my question triggers successfully. I've tried to determine if this limitation in functionality on the simulator is documented anywhere, but have come up empty.

As specified in the docs, addPresentedHandler requires version iOS version 10.3. This is also reflected in it's definition in MTLDrawable.h:

- (void)addPresentedHandler:(MTLDrawablePresentedHandler)block
                             API_AVAILABLE(ios(10.3))
                             API_UNAVAILABLE(macos, macCatalyst);

Nowhere can I find any mention of limitations for the simulator version.



来源:https://stackoverflow.com/questions/60774782/addpresentedhandler-not-being-triggered-in-metal-on-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!