Is this normal?
I only see that issue on real iOS devices. If I run the same Metal code on macOS (or with iOS simulator on macOS) there is no measurable CPU load at all.
The heaviest Metal API calls are, in this order:
renderCommandEncoderWithDescriptor: (40%)
[commandBuffer commit]; (22%)
[self nextDrawable]; (17%)
Code Block - (void)renderFrame:(CADisplayLink*)dlink { // semaphore previously initialized with 3 dispatch_semaphore_wait(semaphoreRenderFrame, DISPATCH_TIME_FOREVER); @autoreleasepool { id<MTLCommandBuffer> commandBuffer = commandQueue.commandBuffer; // 8% id<CAMetalDrawable> drawable = [self nextDrawable]; // 17% if (!drawable) return; renderPass.colorAttachments[0].texture = drawable.texture; id<MTLRenderCommandEncoder> commander = [commandBuffer renderCommandEncoderWithDescriptor:renderPass]; // 40! [commander setRenderPipelineState:renderPipeline]; [commander drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:nVertices instanceCount:1]; [commander endEncoding]; [commandBuffer presentDrawable:drawable]; __block dispatch_semaphore_t semaphore = semaphoreRenderFrame; [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) { dispatch_semaphore_signal(semaphore); }]; [commandBuffer commit]; // 22% } }
So there is no data transferred between CPU and GPU, no work on the shaders. Simply nothing.
Configuration:
Frame capturing disabled.
Metal API validation disabled.
Metal fast math enabled.
Compiled in release mode.
All sanitizers disabled.
The widget class derives directly from CAMetalLayer, so this is not using MTKView.
iPad Pro 4 (iOS 14.2).
Xcode 12.2.