update SDL3 from 3.2.20 to 3.4.2

This commit is contained in:
Sven Balzer
2026-04-01 18:25:03 +02:00
parent 1daf4d79f1
commit 05b19704f8
1626 changed files with 124218 additions and 191491 deletions
File diff suppressed because it is too large Load Diff
+158 -5
View File
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -35,7 +35,7 @@
#define UNIFORM_BUFFER_SIZE 32768
#define MAX_VERTEX_BUFFERS 16
#define MAX_VERTEX_ATTRIBUTES 16
#define MAX_COLOR_TARGET_BINDINGS 4
#define MAX_COLOR_TARGET_BINDINGS 8
#define MAX_PRESENT_COUNT 16
#define MAX_FRAMES_IN_FLIGHT 3
@@ -446,6 +446,154 @@ static inline bool IsIntegerFormat(
}
}
static inline bool IsCompressedFormat(
SDL_GPUTextureFormat format)
{
switch (format) {
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT:
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT:
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT:
return true;
default:
return false;
}
}
static inline bool FormatHasAlpha(
SDL_GPUTextureFormat format)
{
switch (format) {
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT:
// ASTC textures may or may not have alpha; return true as this is mainly intended for validation
return true;
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM:
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM:
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM:
case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM:
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM:
case SDL_GPU_TEXTUREFORMAT_A8_UNORM:
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM:
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM:
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT:
case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT:
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT:
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT:
case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_UINT:
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT:
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT:
case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_INT:
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB:
return true;
default:
return false;
}
}
static inline Uint32 IndexSize(SDL_GPUIndexElementSize size)
{
return (size == SDL_GPU_INDEXELEMENTSIZE_16BIT) ? 2 : 4;
@@ -517,10 +665,12 @@ typedef struct SDL_GPURenderer SDL_GPURenderer;
struct SDL_GPUDevice
{
// Quit
// Device
void (*DestroyDevice)(SDL_GPUDevice *device);
SDL_PropertiesID (*GetDeviceProperties)(SDL_GPUDevice *device);
// State Creation
SDL_GPUComputePipeline *(*CreateComputePipeline)(
@@ -946,12 +1096,16 @@ struct SDL_GPUDevice
// Store this for SDL_gpu.c's debug layer
bool debug_mode;
bool default_enable_depth_clip;
bool validate_feature_depth_clamp_disabled;
bool validate_feature_anisotropy_disabled;
};
#define ASSIGN_DRIVER_FUNC(func, name) \
result->func = name##_##func;
#define ASSIGN_DRIVER(name) \
ASSIGN_DRIVER_FUNC(DestroyDevice, name) \
ASSIGN_DRIVER_FUNC(GetDeviceProperties, name) \
ASSIGN_DRIVER_FUNC(CreateComputePipeline, name) \
ASSIGN_DRIVER_FUNC(CreateGraphicsPipeline, name) \
ASSIGN_DRIVER_FUNC(CreateSampler, name) \
@@ -1037,8 +1191,7 @@ struct SDL_GPUDevice
typedef struct SDL_GPUBootstrap
{
const char *name;
const SDL_GPUShaderFormat shader_formats;
bool (*PrepareDriver)(SDL_VideoDevice *_this);
bool (*PrepareDriver)(SDL_VideoDevice *_this, SDL_PropertiesID props);
SDL_GPUDevice *(*CreateDevice)(bool debug_mode, bool prefer_low_power, SDL_PropertiesID props);
} SDL_GPUBootstrap;
File diff suppressed because it is too large Load Diff
+116 -23
View File
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -31,7 +31,7 @@
// Defines
#define METAL_FIRST_VERTEX_BUFFER_SLOT 14
#define WINDOW_PROPERTY_DATA "SDL_GPUMetalWindowPropertyData"
#define WINDOW_PROPERTY_DATA "SDL.internal.gpu.metal.data"
#define SDL_GPU_SHADERSTAGE_COMPUTE 2
#define TRACK_RESOURCE(resource, type, array, count, capacity) \
@@ -423,6 +423,8 @@ static MTLDepthClipMode SDLToMetal_DepthClipMode(
// Structs
typedef struct MetalRenderer MetalRenderer;
typedef struct MetalTexture
{
id<MTLTexture> handle;
@@ -452,6 +454,8 @@ typedef struct MetalFence
typedef struct MetalWindowData
{
SDL_Window *window;
MetalRenderer *renderer;
int refcount;
SDL_MetalView view;
CAMetalLayer *layer;
SDL_GPUPresentMode presentMode;
@@ -523,8 +527,6 @@ typedef struct MetalUniformBuffer
Uint32 drawOffset;
} MetalUniformBuffer;
typedef struct MetalRenderer MetalRenderer;
typedef struct MetalCommandBuffer
{
CommandBufferCommonHeader common;
@@ -631,6 +633,7 @@ struct MetalRenderer
id<MTLCommandQueue> queue;
bool debugMode;
SDL_PropertiesID props;
Uint32 allowedFramesInFlight;
MetalWindowData **claimedWindows;
@@ -753,11 +756,20 @@ static void METAL_DestroyDevice(SDL_GPUDevice *device)
// Release the command queue
renderer->queue = nil;
// Release properties
SDL_DestroyProperties(renderer->props);
// Free the primary structures
SDL_free(renderer);
SDL_free(device);
}
static SDL_PropertiesID METAL_GetDeviceProperties(SDL_GPUDevice *device)
{
MetalRenderer *renderer = (MetalRenderer *)device->driverData;
return renderer->props;
}
// Resource tracking
static void METAL_INTERNAL_TrackBuffer(
@@ -814,6 +826,17 @@ typedef struct MetalLibraryFunction
id<MTLFunction> function;
} MetalLibraryFunction;
static bool METAL_INTERNAL_IsValidMetalLibrary(
const Uint8 *code,
size_t codeSize)
{
// Metal libraries have a 4 byte header containing `MTLB`.
if (codeSize < 4 || code == NULL) {
return false;
}
return SDL_memcmp(code, "MTLB", 4) == 0;
}
// This function assumes that it's called from within an autorelease pool
static MetalLibraryFunction METAL_INTERNAL_CompileShader(
MetalRenderer *renderer,
@@ -842,6 +865,11 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
options:nil
error:&error];
} else if (format == SDL_GPU_SHADERFORMAT_METALLIB) {
if (!METAL_INTERNAL_IsValidMetalLibrary(code, codeSize)) {
SET_STRING_ERROR_AND_RETURN(
"The provided shader code is not a valid Metal library!",
libraryFunction);
}
data = dispatch_data_create(
code,
codeSize,
@@ -1090,6 +1118,13 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
SDL_assert_release(!"CreateGraphicsPipeline was passed a vertex shader for the fragment stage");
}
}
#ifdef SDL_PLATFORM_VISIONOS
// The default is depth clipping enabled and it can't be changed
if (!createinfo->rasterizer_state.enable_depth_clip) {
SDL_assert_release(!"Rasterizer state enable_depth_clip must be true on this platform");
}
#endif
pipelineDescriptor = [MTLRenderPipelineDescriptor new];
// Blend
@@ -1114,6 +1149,7 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
// Multisample
pipelineDescriptor.rasterSampleCount = SDLToMetal_SampleCount[createinfo->multisample_state.sample_count];
pipelineDescriptor.alphaToCoverageEnabled = createinfo->multisample_state.enable_alpha_to_coverage;
// Depth Stencil
@@ -1778,7 +1814,8 @@ static void METAL_UploadToTexture(
copyFromBuffer:bufferContainer->activeBuffer->handle
sourceOffset:source->offset
sourceBytesPerRow:BytesPerRow(destination->w, textureContainer->header.info.format)
sourceBytesPerImage:SDL_CalculateGPUTextureFormatSize(textureContainer->header.info.format, destination->w, destination->h, destination->d)
// sourceBytesPerImage expects the stride between 2D images (slices) of a 3D texture, not the size of the entire region
sourceBytesPerImage:SDL_CalculateGPUTextureFormatSize(textureContainer->header.info.format, destination->w, destination->h, 1)
sourceSize:MTLSizeMake(destination->w, destination->h, destination->d)
toTexture:metalTexture->handle
destinationSlice:destination->layer
@@ -2292,6 +2329,8 @@ static void METAL_BeginRenderPass(
depthStencilTargetInfo->cycle);
passDescriptor.depthAttachment.texture = texture->handle;
passDescriptor.depthAttachment.level = depthStencilTargetInfo->mip_level;
passDescriptor.depthAttachment.slice = depthStencilTargetInfo->layer;
passDescriptor.depthAttachment.loadAction = SDLToMetal_LoadOp[depthStencilTargetInfo->load_op];
passDescriptor.depthAttachment.storeAction = SDLToMetal_StoreOp[depthStencilTargetInfo->store_op];
passDescriptor.depthAttachment.clearDepth = depthStencilTargetInfo->clear_depth;
@@ -2325,8 +2364,8 @@ static void METAL_BeginRenderPass(
if (depthStencilTargetInfo != NULL) {
MetalTextureContainer *container = (MetalTextureContainer *)depthStencilTargetInfo->texture;
Uint32 w = container->header.info.width;
Uint32 h = container->header.info.height;
Uint32 w = container->header.info.width >> depthStencilTargetInfo->mip_level;
Uint32 h = container->header.info.height >> depthStencilTargetInfo->mip_level;
if (w < vpWidth) {
vpWidth = w;
@@ -2372,6 +2411,7 @@ static void METAL_BindGraphicsPipeline(
{
@autoreleasepool {
MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
MetalGraphicsPipeline *previousPipeline = metalCommandBuffer->graphics_pipeline;
MetalGraphicsPipeline *pipeline = (MetalGraphicsPipeline *)graphicsPipeline;
SDL_GPURasterizerState *rast = &pipeline->rasterizerState;
Uint32 i;
@@ -2384,7 +2424,9 @@ static void METAL_BindGraphicsPipeline(
[metalCommandBuffer->renderEncoder setTriangleFillMode:SDLToMetal_PolygonMode[pipeline->rasterizerState.fill_mode]];
[metalCommandBuffer->renderEncoder setCullMode:SDLToMetal_CullMode[pipeline->rasterizerState.cull_mode]];
[metalCommandBuffer->renderEncoder setFrontFacingWinding:SDLToMetal_FrontFace[pipeline->rasterizerState.front_face]];
#ifndef SDL_PLATFORM_VISIONOS
[metalCommandBuffer->renderEncoder setDepthClipMode:SDLToMetal_DepthClipMode(pipeline->rasterizerState.enable_depth_clip)];
#endif
[metalCommandBuffer->renderEncoder
setDepthBias:((rast->enable_depth_bias) ? rast->depth_bias_constant_factor : 0)
slopeScale:((rast->enable_depth_bias) ? rast->depth_bias_slope_factor : 0)
@@ -2414,6 +2456,17 @@ static void METAL_BindGraphicsPipeline(
metalCommandBuffer);
}
}
if (previousPipeline && previousPipeline != pipeline) {
// if the number of uniform buffers has changed, the storage buffers will move as well
// and need a rebind at their new locations
if (previousPipeline->header.num_vertex_uniform_buffers != pipeline->header.num_vertex_uniform_buffers) {
metalCommandBuffer->needVertexStorageBufferBind = true;
}
if (previousPipeline->header.num_fragment_uniform_buffers != pipeline->header.num_fragment_uniform_buffers) {
metalCommandBuffer->needFragmentStorageBufferBind = true;
}
}
}
}
@@ -3594,7 +3647,7 @@ static bool METAL_SupportsSwapchainComposition(
}
// This function assumes that it's called from within an autorelease pool
static Uint8 METAL_INTERNAL_CreateSwapchain(
static bool METAL_INTERNAL_CreateSwapchain(
MetalRenderer *renderer,
MetalWindowData *windowData,
SDL_GPUSwapchainComposition swapchainComposition,
@@ -3666,7 +3719,7 @@ static Uint8 METAL_INTERNAL_CreateSwapchain(
windowData->textureContainer.header.info.width = (Uint32)drawableSize.width;
windowData->textureContainer.header.info.height = (Uint32)drawableSize.height;
return 1;
return true;
}
static bool METAL_SupportsPresentMode(
@@ -3696,6 +3749,8 @@ static bool METAL_ClaimWindow(
if (windowData == NULL) {
windowData = (MetalWindowData *)SDL_calloc(1, sizeof(MetalWindowData));
windowData->window = window;
windowData->renderer = renderer;
windowData->refcount = 1;
if (METAL_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
@@ -3716,10 +3771,13 @@ static bool METAL_ClaimWindow(
return true;
} else {
SDL_free(windowData);
SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window", false);
return false;
}
} else if (windowData->renderer == renderer) {
++windowData->refcount;
return true;
} else {
SET_ERROR_AND_RETURN("%s", "Window already claimed!", false);
SET_STRING_ERROR_AND_RETURN("Window already claimed", false);
}
}
}
@@ -3733,7 +3791,15 @@ static void METAL_ReleaseWindow(
MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
if (windowData == NULL) {
SET_STRING_ERROR_AND_RETURN("Window is not claimed by this SDL_GpuDevice", );
return;
}
if (windowData->renderer != renderer) {
SDL_SetError("Window not claimed by this device");
return;
}
if (windowData->refcount > 1) {
--windowData->refcount;
return;
}
METAL_Wait(driverData);
@@ -3812,7 +3878,7 @@ static bool METAL_INTERNAL_AcquireSwapchainTexture(
windowData = METAL_INTERNAL_FetchWindowData(window);
if (windowData == NULL) {
SET_STRING_ERROR_AND_RETURN("Window is not claimed by this SDL_GpuDevice", false);
SET_STRING_ERROR_AND_RETURN("Window is not claimed by this SDL_GPUDevice", false);
}
// Update the window size
@@ -4269,8 +4335,13 @@ static bool METAL_SupportsTextureFormat(
// Device Creation
static bool METAL_PrepareDriver(SDL_VideoDevice *this)
static bool METAL_PrepareDriver(SDL_VideoDevice *this, SDL_PropertiesID props)
{
if (!SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN, false) &&
!SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN, false)) {
return false;
}
if (@available(macOS 10.14, iOS 13.0, tvOS 13.0, *)) {
return (this->Metal_CreateView != NULL);
}
@@ -4435,6 +4506,11 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
id<MTLDevice> device = NULL;
bool hasHardwareSupport = false;
bool verboseLogs = SDL_GetBooleanProperty(
props,
SDL_PROP_GPU_DEVICE_CREATE_VERBOSE_BOOLEAN,
true);
if (debugMode) {
/* Due to a Metal driver quirk, once a MTLDevice has been created
* with this environment variable set, the Metal validation layers
@@ -4466,11 +4542,21 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
#ifdef SDL_PLATFORM_MACOS
hasHardwareSupport = true;
bool allowMacFamily1 = SDL_GetBooleanProperty(
props,
SDL_PROP_GPU_DEVICE_CREATE_METAL_ALLOW_MACFAMILY1_BOOLEAN,
false);
if (@available(macOS 10.15, *)) {
hasHardwareSupport = [device supportsFamily:MTLGPUFamilyMac2];
hasHardwareSupport = allowMacFamily1 ?
[device supportsFamily:MTLGPUFamilyMac1] :
[device supportsFamily:MTLGPUFamilyMac2];
} else if (@available(macOS 10.14, *)) {
hasHardwareSupport = [device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1];
hasHardwareSupport = allowMacFamily1 ?
[device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v4] :
[device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1];
}
#elif defined(SDL_PLATFORM_VISIONOS)
hasHardwareSupport = true;
#else
if (@available(iOS 13.0, tvOS 13.0, *)) {
hasHardwareSupport = [device supportsFamily:MTLGPUFamilyApple3];
@@ -4488,12 +4574,20 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
renderer->device = device;
renderer->queue = [device newCommandQueue];
// Print driver info
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Metal");
SDL_LogInfo(
SDL_LOG_CATEGORY_GPU,
"Metal Device: %s",
[device.name UTF8String]);
renderer->props = SDL_CreateProperties();
if (verboseLogs) {
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Metal");
}
// Record device name
const char *deviceName = [device.name UTF8String];
SDL_SetStringProperty(
renderer->props,
SDL_PROP_GPU_DEVICE_NAME_STRING,
deviceName);
if (verboseLogs) {
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Metal Device: %s", deviceName);
}
// Remember debug mode
renderer->debugMode = debugMode;
@@ -4568,7 +4662,6 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
SDL_GPUBootstrap MetalDriver = {
"metal",
SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_METALLIB,
METAL_PrepareDriver,
METAL_CreateDevice
};
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -51,6 +51,9 @@ VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties)
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties)
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties)
// Vulkan 1.1 (Needed for opt-in feature checks)
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2)
// VK_KHR_get_physical_device_properties2, needed for KHR_driver_properties
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2KHR)