Closed mlfarrell closed 5 years ago
So this API call (MTLCreateSystemDefaultDevice) on the apple supplied metal examples triggers the graphics switch to occur properly. I notice molten vk does not call this on mac os. Is there an easy way we can detect if the GPU is indeed the "system default" and route the call through MTLCreateSystemDefaultDevice to ensure the graphics switch occurs properly? See documentation from apple below
/*!
@brief Returns a reference to the preferred system default Metal device.
@discussion On Mac OS X systems that support automatic graphics switching, calling
this API to get a Metal device will cause the system to switch to the high power
GPU. On other systems that support more than one GPU it will return the GPU that
is associated with the main display.
*/
MTL_EXTERN id <MTLDevice> __nullable MTLCreateSystemDefaultDevice(void) API_AVAILABLE(macos(10.11), ios(8.0)) NS_RETURNS_RETAINED;
Fixed and tested on my fork. Haven't tested the integrated low power route. Will do that tomorrow.
This brings me back to my old school ObjC days. Manual retain/release in 2018 - you guys are sadists :p
@mlfarrell
Have you tried inspecting the GPU activity with Apple's tools?
With MoltenVK (without your patch)...if I run an app that requests the high-power GPU (like the MoltenVK Hologram demo app) on my MacBook Pro...Apple's GPU tool shows the discrete GPU (AMD Radeon) spool up and run hard while the demo is running...and then spool down once the Hologram app is closed.
So...as far as I can tell...MoltenVK GPU selection is behaving as expected.
At the same time...the integrated Intel GPU still shows some activity (I assume from other windows).
All the while...gfxCardStatus
shows i in the menu bar.
Are you using some special kind of GPU configuration (external, etc)?
No special configuration.
Let me be clear. The nvidia GPU is indeed being used when I select it, however the critical "graphics switching" step on macbook pros like mine, is not triggered when you use a device returned from MTLCopyAllDevices
, meaning the nvidia GPU is being somehow utilized to render offscreen, then the results are being transferred to the intel integrated GPU that is powering the display.
Let me paste the apple documentation below and you can see the critical verbiage regarding graphics switching.
/*!
@brief Returns all Metal devices in the system.
@discussion This API will not cause the system to switch devices and leaves the
decision about which GPU to use up to the application based on whatever criteria
it deems appropriate.
*/
MTL_EXTERN NSArray <id<MTLDevice>> *MTLCopyAllDevices(void) API_AVAILABLE(macos(10.11)) API_UNAVAILABLE(ios) NS_RETURNS_RETAINED;
Afaik, it is impossible to trigger the graphics switching step on a metal application without calling MTLCreateSystemDefaultDevice
When I run moltenvk without my fix, the macOS activity monitor on my mac shows "requires high performance graphics" field as "no". The 3rd party graphics switching utility called gfxCardStatus shows that my integrated card remains in use without switching.
With my above PR, the app startup delays a bit (as normal during a switch), gfxcardstatus utilty shows proper swicth to discrete, and the activity monitor field shows "yes" for the "requires high performance graphics" field for this application. More importantly, the performance of my application is drastically improved.
The above issue will affect everyone running molten VK applications on macs with dual GPUs.
Okay. I think I understand the point you're raising now.
The graphics switching ensures that the system itself is converted to the GPU that is selected by MoltenVK. And as a result, the final system BLIT from the GPU used by the app to the GPU used by the system is not required.
Is that correct?
I'm curious...are there any other benefits/costs to enforcing graphics switching? Agreed that graphics performance is critical...and that's what we want...and why Vulkan was invented. But since your proposed solution forces the entire system to flip to the discrete GPU...I want to make sure there are no downsides that might cause us to perhaps make this step configurable in the MoltenVK configuration API.
In essence...there would seem to be three levels of GPU-based performance (lowest to highest)...
...and are there reasons why we might want to retain the middle option somehow?
PS - What an oblique API Apple invented with this! Talk about setting up a non-obvious side effect!
The graphics switching ensures that the system itself is converted to the GPU that is selected by MoltenVK. And as a result, the final system BLIT from the GPU used by the app to the GPU used by the system is not required.
That's correct (or at least my understanding of how it works from an outside perspective)
The costs would be the slight delay on startup. In my experience, alongside the performance benefits, 99% of metal apps that aren't moltenvk (as it is today) and 99% OpenGL apps will behave this way, so it's good to follow the herd in this case.
2 is likely very useful for GPGPU computing and for other non-present non-graphics applications.
I do admit my solution my PR above isn't the most elegant (feel free to use it or some variant). My aim was to prevent the gfx switch from occurring for users who don't request that device.
Okay. Makes sense.
Thanks for all the low-level detective work on this...and for the subsequent PR.
I just posted a review question on the PR. Once you've answered that...I'll pull the PR in.
I'm going to leave this issue open...until we've added a config to optionally turn off this behaviour to permit behaviour 2 above.
I will take care of that part as part of an update to the config features.
No problem, glad to help!
PR #450 adds config setting for GPU switching and enables it by default
Noticed this last night and forgot to post.
No matter what I try, I simply cannot get my application to use the discrete (nvidia) GPU on my 2012 retina mac book pro. OpenGL would always just automatically switch. But with metal, it won't do it.
I'm creating the device with a physical device named "NVIDIA GeForce GT 650M", but can verify via gfxCardStatus (and the bad performance) that i'm on intel. It only works if I force discrete via the same gfxCardStatus utility.
I'm on macOS 10.13.6 To reproduce, build and run my repo's example project on a macbook with integrated+discrete GPU Note via gfxCardStatus that it doesn't switch to 'd'.
https://github.com/mlfarrell/VGL-Vulkan-Core
This one is critical for my application since on intel, its killing my performance (30 FPS).