问题
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 printf
s 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