Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to save metal capture to file? #221

Open
EriKWDev opened this issue Dec 10, 2024 · 8 comments
Open

Ability to save metal capture to file? #221

EriKWDev opened this issue Dec 10, 2024 · 8 comments

Comments

@EriKWDev
Copy link
Contributor

EriKWDev commented Dec 10, 2024

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

This comment was marked as off-topic.

@EriKWDev
Copy link
Contributor Author

EriKWDev commented Dec 11, 2024

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
Copy link
Contributor Author

EriKWDev commented Dec 11, 2024

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

@kvark
Copy link
Owner

kvark commented Dec 13, 2024

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.

@EriKWDev
Copy link
Contributor Author

EriKWDev commented Dec 15, 2024

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

@kvark
Copy link
Owner

kvark commented Dec 15, 2024

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

@EriKWDev
Copy link
Contributor Author

That is very helpful :')

@EriKWDev
Copy link
Contributor Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants