blade icon indicating copy to clipboard operation
blade copied to clipboard

Ability to save metal capture to file?

Open EriKWDev opened this issue 1 year ago • 8 comments

Saw that upon drop of the Context, a metal capture is finished if capturing was enabled.

What would be a clean API for describing an optional location to save this capture? Could the ContextDesc include a capture_location: Option<std::path::PathBuf>?

https://developer.apple.com/documentation/xcode/capturing-a-metal-workload-programmatically#Save-the-capture-to-your-computer

Would ofc be even more nice to be able to manually start and finish a capture regardless of frame and operation boundaries

https://developer.apple.com/documentation/xcode/capturing-a-metal-workload-programmatically#Capture-specific-commands-with-a-capture-scope

EriKWDev avatar Dec 10 '24 14:12 EriKWDev

(Using renderdoc/RadeonGpuProfiler for vulkan backend works good as is, just don't know how to get the rust application running in xcode to use the metal debugger without a bit of fiffling about with how the application starts, so a capture file would be nice)

EriKWDev avatar Dec 10 '24 14:12 EriKWDev

Welp, that is unfortunate

[2024-12-11T07:24:13Z ERROR blade_graphics::hal] A capture location was specified but metal device doesn't support saving a gpu trace
[2024-12-11T07:24:13Z ERROR blade_graphics::hal] Error during metal capture start: Capturing is not supported.
DeviceInformation { is_software_emulated: false, device_name: "Apple M4", driver_name: "Metal", driver_info: "" }
metal/mod.rs

                let capture_desc = metal::CaptureDescriptor::new();
                capture_desc.set_capture_device(&device);
                capture_desc.set_capture_scope(&default_capture_scope);

                if let Some(capture_location) = desc.metal_capture_location.as_ref() {
                    if capture_manager
                        .supports_destination(metal::MTLCaptureDestination::GpuTraceDocument)
                    {
                        capture_desc
                            .set_destination(metal::MTLCaptureDestination::GpuTraceDocument);
                        capture_desc.set_output_url(capture_location);
                    } else {
                        log::error!("A capture location was specified but metal device doesn't support saving a gpu trace")
                    }
                }
                let res = capture_manager.start_capture(capture_desc.as_ref());
                if let Err(res) = res {
                    log::error!("Error during metal capture start: {res}");
                }

edit: wth, the environment variable MTL_CAPTURE_ENABLED=1 must be set https://developer.apple.com/documentation/xcode/capturing-a-metal-workload-programmatically#Enable-capturing-programmatically edit: and the file path has to end with 'gputrace' or else it won't be allowed edit: the path seems to need to be absolute. Undocumented?

EriKWDev avatar Dec 11 '24 07:12 EriKWDev

Successfully captured bunnymark to a gputrace file:

Screenshot 2024-12-11 at 09 54 58

As suspected though, the file gets infeasibly large very quickly since everything is captured. Being able to specify a specific start and end scope or a specific frame would be better

https://github.com/EriKWDev/blade/tree/ErikWDev/metal-capture

EriKWDev avatar Dec 11 '24 08:12 EriKWDev

The original purpose of the "capture" was to (indeed) capture the whole execution of a compute-like workload. That's useful because the capturing tools would often be oriented towards frame-based captures, and those aren't present in compute workloads. If you have frames, you should just load the app in the capturing program as usual and capture manually, instead of using the built-in "capture" facilities.

kvark avatar Dec 13 '24 06:12 kvark

Makes sense!

The reasoning was that, to my knowledge, getting the app to run from Xcode/metal debugger requires a bit of a different main function and making the rust binary application into a lib that is loaded from the apple-side and all the fun with making an Xcode project understand cargo :/

Creating capture files programmatically allows debugging on macOS without this hassle

EriKWDev avatar Dec 15 '24 08:12 EriKWDev

getting the app to run from Xcode/metal debugger requires a bit of a different main function and making the rust binary application into a lib that is loaded from the apple-side and all the fun with making an Xcode project understand cargo :/

Oh, no, not at all! You can load the program directly in XCode and debug. Very similar to how you'd do that from Microsoft Visual Studio.

See instructions in https://github.com/gfx-rs/wgpu/wiki/Debugging-with-Xcode Basically, create a simple project, point it to the executable, then run

kvark avatar Dec 15 '24 19:12 kvark

That is very helpful :')

EriKWDev avatar Dec 16 '24 07:12 EriKWDev

When it is possible to capture that way I don't think it's too bad

Though, it could ofc be even nicer!

The kind of integration I would ideally like to have is to from the in-game dev menu hit a 'capture' button which captures the frame and opens it in renderdoc on appropriate platforms and then in xcode on apple, so I might still look into this in the future, and given what I managed to implement above I don't think it would be too far away

I might be able to implement it as a util lib though

EriKWDev avatar Dec 16 '24 07:12 EriKWDev