metal: Add hint to select low power device instead of the default one (#8182)

On some system like MacBook Pro Intel with AMD card, asking for the default device will always return the AMD GPU.
This is not an issue for 99% of the case when the renderer context is here to provide the maximum performance level like for game.
However, for video application using GPU for 1 quad and 1 texture, using the discrete GPU for that lead to an important power consumption (4 to 8W), heat increase, and fan noise.
With this patch, I successfully amend ffplay to only use the integrated GPU (i.e. the Intel one), instead of the discrete GPU (i.e. the AMD one).

(cherry picked from commit aa7ba62978)
This commit is contained in:
Jeremy Demeule 2023-08-31 10:23:45 +02:00 committed by Sam Lantinga
parent d46fdfa3ee
commit c25a49c406
2 changed files with 27 additions and 2 deletions

View File

@ -1474,6 +1474,17 @@ extern "C" {
*/
#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC"
/**
* \brief A variable controlling whether the Metal render driver select low power device over default one
*
* This variable can be set to the following values:
* "0" - Use the prefered OS device
* "1" - Select a low power one
*
* By default the prefered OS device is used.
*/
#define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE"
/**
* \brief A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS
*

View File

@ -1654,8 +1654,22 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
return NULL;
}
// !!! FIXME: MTLCopyAllDevices() can find other GPUs on macOS...
mtldevice = MTLCreateSystemDefaultDevice();
#ifdef __MACOSX__
if (SDL_GetHintBoolean(SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE, SDL_TRUE)) {
NSArray<id<MTLDevice>> *devices = MTLCopyAllDevices();
for (id<MTLDevice> device in devices) {
if (device.isLowPower) {
mtldevice = device;
break;
}
}
}
#endif
if (mtldevice == nil) {
mtldevice = MTLCreateSystemDefaultDevice();
}
if (mtldevice == nil) {
SDL_free(renderer);