metal: check success of device creation (#11367)

When macOS runs under a virtual environment, it is possible that
MTLCreateSystemDefaultDevice() does not succeed.
Not checking this failure results in a crash down the road.
This change allows to skip GPU renderer and use an adequate fallback.

Co-authored-by: D.musique <d-musique@users.noreply.github.com>
This commit is contained in:
d-musique
2024-10-29 17:35:13 +01:00
committed by GitHub
parent feb10434a1
commit 35e53f76a9

View File

@@ -4166,33 +4166,40 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
{ {
@autoreleasepool { @autoreleasepool {
MetalRenderer *renderer; MetalRenderer *renderer;
id<MTLDevice> device = NULL;
// Allocate and zero out the renderer
renderer = (MetalRenderer *)SDL_calloc(1, sizeof(MetalRenderer));
// Create the Metal device and command queue // Create the Metal device and command queue
#ifdef SDL_PLATFORM_MACOS #ifdef SDL_PLATFORM_MACOS
if (preferLowPower) { if (preferLowPower) {
NSArray<id<MTLDevice>> *devices = MTLCopyAllDevices(); NSArray<id<MTLDevice>> *devices = MTLCopyAllDevices();
for (id<MTLDevice> device in devices) { for (id<MTLDevice> candidate in devices) {
if (device.isLowPower) { if (candidate.isLowPower) {
renderer->device = device; device = candidate;
break; break;
} }
} }
} }
#endif #endif
if (renderer->device == NULL) { if (device == NULL) {
renderer->device = MTLCreateSystemDefaultDevice(); device = MTLCreateSystemDefaultDevice();
if (device == NULL) {
SDL_SetError("Failed to create Metal device");
return NULL;
}
} }
renderer->queue = [renderer->device newCommandQueue];
// Allocate and zero out the renderer
renderer = (MetalRenderer *)SDL_calloc(1, sizeof(MetalRenderer));
renderer->device = device;
renderer->queue = [device newCommandQueue];
// Print driver info // Print driver info
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Metal"); SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Metal");
SDL_LogInfo( SDL_LogInfo(
SDL_LOG_CATEGORY_GPU, SDL_LOG_CATEGORY_GPU,
"Metal Device: %s", "Metal Device: %s",
[renderer->device.name UTF8String]); [device.name UTF8String]);
// Remember debug mode // Remember debug mode
renderer->debugMode = debugMode; renderer->debugMode = debugMode;