[ad_1]
I’m attempting to make use of MTLSharedEvent together with MTLSharedEventListener to synchronize computation between GPU and CPU, as in instance supplied by Apple (https://developer.apple.com/documentation/metallic/synchronization/synchronizing_events_between_a_gpu_and_the_cpu). Mainly what I need to obtain is have work break up into 3 elements executed so as, like so:
- GPU computation half 1
- CPU computation based mostly on outcomes from GPU computation half 1
- GPU computation half 2 after CPU computation
My downside is that eventListener block is all the time known as earlier than command buffer is being scheduled for execution, which make my CPU job execute first so as.
To simplify the case, let’s use easy instructions that fill MTLBuffer with sure values (my unique use case is extra sophisticated, as utilizing compute encoders with customized shaders, however behaves the identical):
let gadget = MTLCreateSystemDefaultDevice()!
let queue = gadget.makeCommandQueue()!
let occasion = gadget.makeSharedEvent()!
let dispatchQueue = DispatchQueue(label: "myqueue")
let eventListener = MTLSharedEventListener(dispatchQueue: dispatchQueue)
let metalBuffer = gadget.makeBuffer(size: 2048, choices: MTLResourceOptions.storageModeShared)!
let buffer = queue.makeCommandBuffer()!
NSLog("Begin - signaled worth: (occasion.signaledValue)")
occasion.notify(eventListener, atValue: 1) { occasion, worth in
// CPU work
let pointer = metalBuffer.contents().assumingMemoryBound(to: UInt8.self)
for i in 0..<512 {
(pointer + i).pointee = (pointer + i).pointee + 1;
}
NSLog("Occasion notification - signaled worth: (worth), buffer standing: (buffer.standing.rawValue)")
occasion.signaledValue = 2
}
// GPU work half 1
let encoder1 = buffer.makeBlitCommandEncoder()!
encoder1.fill(buffer: metalBuffer, vary: .init(0...127), worth: 22)
encoder1.endEncoding()
// sign with 1 to start out CPU job
buffer.encodeSignalEvent(occasion, worth: 1)
// look ahead to worth >= 2 to proceed
buffer.encodeWaitForEvent(occasion, worth: 2)
// GPU work half 2
let encoder2 = buffer.makeBlitCommandEncoder()!
encoder2.fill(buffer: metalBuffer, vary: .init(128...511), worth: 255)
encoder2.endEncoding()
buffer.addScheduledHandler { buffer in
NSLog("Buffer scheduled - signaled worth: (occasion.signaledValue)")
}
buffer.addCompletedHandler { buffer in
NSLog("Buffer accomplished - signaled worth: (occasion.signaledValue)")
}
buffer.commit()
buffer.waitUntilCompleted()
Output:
2022-01-09 23:46:08.774 Sync[76882:3531755] Steel GPU Body Seize Enabled
2022-01-09 23:46:08.805 Sync[76882:3531755] Begin - signaled worth: 0
2022-01-09 23:46:08.808 Sync[76882:3531764] Occasion notification - signaled worth: 1, buffer standing: 2 (Commited)
2022-01-09 23:46:08.809 Sync[76882:3531763] Buffer scheduled - signaled worth: 2
2022-01-09 23:46:08.809 Sync[76882:3531763] Buffer accomplished - signaled worth: 2
As you possibly can see eventListener logs buffer standing as .commited.
What’s the matter right here? Am I lacking one thing?
System: macOS 12.0.1, Apple M1 Professional, Xcode 13.2.1
[ad_2]
