Merge pull request #108452 from stuartcarnie/108445/fix_atomic_check

Metal: Remove invalid assumption for image atomic operations
This commit is contained in:
Thaddeus Crews
2025-07-10 11:39:22 -05:00
3 changed files with 14 additions and 40 deletions

View File

@ -94,8 +94,9 @@ struct API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) MetalFeatures {
bool metal_fx_spatial = false; /**< If true, Metal FX spatial functions are supported. */
bool metal_fx_temporal = false; /**< If true, Metal FX temporal functions are supported. */
bool supports_gpu_address = false; /**< If true, referencing a GPU address in a shader is supported. */
bool supports_image_atomic_32_bit = false; /**< If true, 32-bit atomic operations on images are supported. */
bool supports_image_atomic_64_bit = false; /**< If true, 64-bit atomic operations on images are supported. */
bool supports_image_atomic_32_bit = false; /**< If true, 32-bit atomic operations on images are supported by the GPU. */
bool supports_image_atomic_64_bit = false; /**< If true, 64-bit atomic operations on images are supported by the GPU. */
bool supports_native_image_atomics = false; /**< If true, native image atomic operations are supported by the OS. */
};
struct MetalLimits {

View File

@ -122,10 +122,12 @@ void MetalDeviceProperties::init_features(id<MTLDevice> p_device) {
features.simdReduction = [p_device supportsFamily:MTLGPUFamilyApple7];
features.argument_buffers_tier = p_device.argumentBuffersSupport;
features.supports_image_atomic_32_bit = [p_device supportsFamily:MTLGPUFamilyApple6];
features.supports_image_atomic_64_bit = [p_device supportsFamily:MTLGPUFamilyApple8];
features.supports_image_atomic_64_bit = [p_device supportsFamily:MTLGPUFamilyApple9] || ([p_device supportsFamily:MTLGPUFamilyApple8] && [p_device supportsFamily:MTLGPUFamilyMac2]);
if (@available(macOS 14.0, iOS 17.0, tvOS 17.0, visionOS 1.0, *)) {
features.supports_native_image_atomics = true;
}
if (OS::get_singleton()->get_environment("GODOT_MTL_DISABLE_IMAGE_ATOMICS") == "1") {
features.supports_image_atomic_32_bit = false;
features.supports_image_atomic_64_bit = false;
features.supports_native_image_atomics = false;
}
if (@available(macOS 13.0, iOS 16.0, tvOS 16.0, *)) {

View File

@ -330,14 +330,11 @@ RDD::TextureID RenderingDeviceDriverMetal::texture_create(const TextureFormat &p
}
if (p_format.usage_bits & TEXTURE_USAGE_STORAGE_ATOMIC_BIT) {
ERR_FAIL_COND_V_MSG((format_caps & kMTLFmtCapsAtomic) == 0, RDD::TextureID(), "Atomic operations on this texture format are not supported.");
ERR_FAIL_COND_V_MSG(!device_properties->features.supports_native_image_atomics, RDD::TextureID(), "Atomic operations on textures are not supported on this OS version. Check SUPPORTS_IMAGE_ATOMIC_32_BIT.");
// If supports_native_image_atomics is true, this condition should always succeed, as it is set the same.
if (@available(macOS 14.0, iOS 17.0, tvOS 17.0, *)) {
if (format_caps & kMTLFmtCapsAtomic) {
desc.usage |= MTLTextureUsageShaderAtomic;
} else {
ERR_FAIL_V_MSG(RDD::TextureID(), "Atomic operations on this texture format are not supported.");
}
} else {
ERR_FAIL_V_MSG(RDD::TextureID(), "Atomic texture operations not supported on this OS version.");
desc.usage |= MTLTextureUsageShaderAtomic;
}
}
@ -368,34 +365,8 @@ RDD::TextureID RenderingDeviceDriverMetal::texture_create(const TextureFormat &p
is_linear = std::get<bool>(is_linear_or_err);
}
// Check if it is a linear format for atomic operations and therefore needs a buffer,
// as generally Metal does not support atomic operations on textures.
bool needs_buffer = is_linear;
// Check for atomic requirements.
if (flags::any(p_format.usage_bits, TEXTURE_USAGE_STORAGE_BIT) && p_format.array_layers == 1 && p_format.mipmaps == 1 && p_format.texture_type == TEXTURE_TYPE_2D) {
switch (p_format.format) {
case RenderingDeviceCommons::DATA_FORMAT_R32_SINT:
case RenderingDeviceCommons::DATA_FORMAT_R32_UINT: {
if (!device_properties->features.supports_image_atomic_32_bit) {
// We can emulate 32-bit atomic operations on textures.
needs_buffer = true;
}
} break;
case RenderingDeviceCommons::DATA_FORMAT_R32G32_SINT:
case RenderingDeviceCommons::DATA_FORMAT_R32G32_UINT: {
if (!device_properties->features.supports_image_atomic_64_bit) {
// No emulation for 64-bit atomics.
ERR_FAIL_V_MSG(TextureID(), "64-bit atomic operations are not supported.");
}
} break;
default:
break;
}
}
id<MTLTexture> obj = nil;
if (needs_buffer) {
if (is_linear) {
// Linear textures are restricted to 2D textures, a single mipmap level and a single array layer.
MTLPixelFormat pixel_format = desc.pixelFormat;
size_t row_alignment = get_texel_buffer_alignment_for_format(p_format.format);
@ -2771,7 +2742,7 @@ bool RenderingDeviceDriverMetal::has_feature(Features p_feature) {
case SUPPORTS_METALFX_TEMPORAL:
return device_properties->features.metal_fx_temporal;
case SUPPORTS_IMAGE_ATOMIC_32_BIT:
return device_properties->features.supports_image_atomic_32_bit;
return device_properties->features.supports_native_image_atomics;
default:
return false;
}