- Problem with CAMetalLayer nextDrawable on OSX 10.11 Beta 2
Whenever I add CAMetalLayer
in NSView
, the method [CAMetalLayer nextDrawable]
will go through nil
after 3 successful ones id<CAMetalDrawable>
.
I tried two different setup methods. First, I used MTKView and used it CAMetalLayer
, it didn't work. Secondly, NSView
a new one is used and created CAMetalLayer
. It didn't work either. I was having strange problems.
I want to know if anyone else has this problem and if anyone knows a solution to solve this problem.
Additional Notes:
I don't want to use the MTKView paint system by overriding its methods (not yet). Also this is not a problem for iOS 8 and I have not tried my code with iOS 9 beta (not yet).
Update
I am redirecting my invitations to use a delegate MTKViewDelegate
. And from the delegate method drawInView
I was able to get the consistent available frameworks. However , I would still like to use the method nextDrawable
directly from CAMetalLayer
. Hope this helps someone else.
source to share
I forgot to come back to this.
It was fixed
with OSX Beta 4
. nextDrawable
works correctly and returns useful CAMetalDrawable
objects. Probably, I should have waited for the release version to be released before publishing it. I just wanted everyone else to be aware of this issue when the beta was first released.
source to share
I had the same problem and asked WWDC Developers Metal 15 .
How it MTKView
works : MTKView
Has a limited number of drawings (maybe 3), so when you code frames you can draw multiple links.
What are you doing . Your scene is probably pretty simple, so you can encode frames very quickly. It looks like when the CPU is 4 frames ahead of the GPU, you are asking for the next result, and since all (3) blueprints are in use, it fails.
Solution . You need to use semapthore to wait for drawable when there is no free.
Here's the code to use:
let inflightSemaphore = dispatch_semaphore_create(3)
func drawInView(view: MTKView) {
// use semaphore to encode 3 frames ahead
dispatch_semaphore_wait(inflightSemaphore, DISPATCH_TIME_FOREVER)
self.update()
let commandBuffer = commandQueue.commandBuffer()
let renderEncoder = commandBuffer.renderCommandEncoderWithDescriptor(view.currentRenderPassDescriptor!)
renderEncoder.drawPrimitives()
// use completion handler to signal the semaphore when this frame is completed allowing the encoding of the next frame to proceed
commandBuffer.addCompletedHandler{ [weak self] commandBuffer in
if let strongSelf = self {
dispatch_semaphore_signal(strongSelf.inflightSemaphore)
}
return
}
commandBuffer.presentDrawable(view.currentDrawable!)
commandBuffer.commit()
}
This is not documented anywhere! The only written mention of this is in the iOS project template (File -> New -> Project -> Game -> Pick Metal) in GameViewController
.
I have already completed the radar on this one (not answered yet) and it would be appreciated if you would do the same https://bugreport.apple.com
Also you can find my github repo helpful https://github.com/haawa799/RamOnMetal
source to share