Merge pull request #108452 from stuartcarnie/108445/fix_atomic_check
Metal: Remove invalid assumption for image atomic operations
This commit is contained in:
@ -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 {
|
||||
|
||||
@ -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, *)) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user