Skip to content

Commit a7b85d6

Browse files
committed
Metal Capture improvements
- Default to capturing with MTLCaptureScope - Test improvments - Spinlock until capture is over in `stopCapture`
1 parent 822abde commit a7b85d6

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

lib/mtl/capture.jl

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ Use [`beginScope()`](@ref) and [`endScope()`](@ref) to set the boundaries for a
1212
"""
1313
MTLCaptureScope
1414

15+
function MTLCaptureScope(queue::MTLDevice, manager=MTLCaptureManager())
16+
handle = @objc [manager::id{MTLCaptureManager} newCaptureScopeWithDevice:queue::id{MTLDevice}]::id{MTLCaptureScope}
17+
MTLCaptureScope(handle)
18+
end
19+
function MTLCaptureScope(queue::MTLCommandQueue, manager=MTLCaptureManager())
20+
handle = @objc [manager::id{MTLCaptureManager} newCaptureScopeWithCommandQueue:queue::id{MTLCommandQueue}]::id{MTLCaptureScope}
21+
MTLCaptureScope(handle)
22+
end
23+
1524
# @objcwrapper MTLCaptureScope <: NSObject
1625

1726
"""
@@ -59,7 +68,7 @@ function MTLCaptureDescriptor()
5968
end
6069

6170
# TODO: Add capture state
62-
function MTLCaptureDescriptor(obj::Union{MTLDevice,MTLCommandQueue, MTLCaptureScope},
71+
function MTLCaptureDescriptor(obj::Union{MTLDevice, MTLCommandQueue, MTLCaptureScope},
6372
destination::MTLCaptureDestination;
6473
folder::String=nothing)
6574
desc = MTLCaptureDescriptor()
@@ -110,7 +119,7 @@ end
110119
111120
Start GPU frame capture using the default capture object and specifying capture descriptor parameters directly.
112121
"""
113-
function startCapture(obj::Union{MTLDevice,MTLCommandQueue, MTLCaptureScope},
122+
function startCapture(obj::Union{MTLDevice, MTLCommandQueue, MTLCaptureScope},
114123
destination::MTLCaptureDestination=MTLCaptureDestinationGPUTraceDocument;
115124
folder::String=nothing)
116125
if destination == MTLCaptureDestinationGPUTraceDocument && folder === nothing
@@ -141,8 +150,17 @@ Stop GPU frame capture.
141150
"""
142151
function stopCapture(manager::MTLCaptureManager=MTLCaptureManager())
143152
@objc [manager::id{MTLCaptureManager} stopCapture]::Nothing
153+
# Spinlock until capture is fully complete. Otherwise, `stopCapture`
154+
# sometimes returns while the capture manager is still capturing,
155+
# causing test failures and potentially corrupted captures.
156+
while manager.isCapturing
157+
end
144158
end
145159

160+
"""
161+
supports_destination(manager::MTLCaptureManager, destination::MTLCaptureDestination)
162+
Checks if a given capture destination is supported.
163+
"""
146164
function supports_destination(manager::MTLCaptureManager, destination::MTLCaptureDestination)
147165
@objc [manager::id{MTLCaptureManager} supportsDestination:destination::MTLCaptureDestination]::Bool
148166
end

src/utilities.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,13 @@ function captured(f; dest=MTL.MTLCaptureDestinationGPUTraceDocument,
137137
end
138138

139139
folder = capture_dir()
140-
startCapture(object, dest; folder)
140+
scope = MTLCaptureScope(object)
141+
startCapture(scope, dest; folder)
141142
try
142-
f()
143-
synchronize()
143+
beginScope(scope)
144+
f()
145+
endScope(scope)
146+
synchronize()
144147
finally
145148
@info "GPU frame capture saved to $folder; open the resulting trace in Xcode"
146149
stopCapture()

test/capturing.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ else
77
# Verify Metal capture is enabled via environment variable
88
@test capturing
99

10-
@testset "capturing" begin
11-
1210
mktempdir() do tmpdir
1311
cd(tmpdir) do
1412

@@ -38,6 +36,10 @@ desc.captureObject = dev
3836
desc.destination = MTL.MTLCaptureDestinationGPUTraceDocument
3937
@test desc.destination == MTL.MTLCaptureDestinationGPUTraceDocument
4038

39+
# Capture Manager supports destination
40+
@test !supports_destination(manager, MTL.MTLCaptureDestinationDeveloperTools)
41+
@test supports_destination(manager, MTL.MTLCaptureDestinationGPUTraceDocument)
42+
4143
# Output URL
4244
@test desc.outputURL === nothing
4345
path = joinpath(tmpdir, "test.gputrace")
@@ -67,7 +69,7 @@ bufferA = MtlArray{Float32,1,SharedStorage}(undef, tuple(4))
6769
@test manager.isCapturing == false
6870
startCapture(manager, desc)
6971
@test manager.isCapturing
70-
@test_throws ErrorException startCapture(manager, desc)
72+
@test_throws "Capture manager is already capturing." startCapture(manager, desc)
7173
Metal.@sync @metal threads=4 tester(bufferA)
7274
stopCapture(manager)
7375
@test manager.isCapturing == false
@@ -85,5 +87,4 @@ end
8587
end # cd(tmpdir) do
8688
end # mktempdir() do tmpdir
8789

88-
end # @testset "capturing" begin
8990
end # if shader_validation (else branch)

0 commit comments

Comments
 (0)