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_spatial = false; /**< If true, Metal FX spatial functions are supported. */
|
||||||
bool metal_fx_temporal = false; /**< If true, Metal FX temporal 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_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_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. */
|
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 {
|
struct MetalLimits {
|
||||||
|
|||||||
@ -122,10 +122,12 @@ void MetalDeviceProperties::init_features(id<MTLDevice> p_device) {
|
|||||||
features.simdReduction = [p_device supportsFamily:MTLGPUFamilyApple7];
|
features.simdReduction = [p_device supportsFamily:MTLGPUFamilyApple7];
|
||||||
features.argument_buffers_tier = p_device.argumentBuffersSupport;
|
features.argument_buffers_tier = p_device.argumentBuffersSupport;
|
||||||
features.supports_image_atomic_32_bit = [p_device supportsFamily:MTLGPUFamilyApple6];
|
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") {
|
if (OS::get_singleton()->get_environment("GODOT_MTL_DISABLE_IMAGE_ATOMICS") == "1") {
|
||||||
features.supports_image_atomic_32_bit = false;
|
features.supports_native_image_atomics = false;
|
||||||
features.supports_image_atomic_64_bit = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (@available(macOS 13.0, iOS 16.0, tvOS 16.0, *)) {
|
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) {
|
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 (@available(macOS 14.0, iOS 17.0, tvOS 17.0, *)) {
|
||||||
if (format_caps & kMTLFmtCapsAtomic) {
|
desc.usage |= MTLTextureUsageShaderAtomic;
|
||||||
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.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,34 +365,8 @@ RDD::TextureID RenderingDeviceDriverMetal::texture_create(const TextureFormat &p
|
|||||||
is_linear = std::get<bool>(is_linear_or_err);
|
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;
|
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.
|
// Linear textures are restricted to 2D textures, a single mipmap level and a single array layer.
|
||||||
MTLPixelFormat pixel_format = desc.pixelFormat;
|
MTLPixelFormat pixel_format = desc.pixelFormat;
|
||||||
size_t row_alignment = get_texel_buffer_alignment_for_format(p_format.format);
|
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:
|
case SUPPORTS_METALFX_TEMPORAL:
|
||||||
return device_properties->features.metal_fx_temporal;
|
return device_properties->features.metal_fx_temporal;
|
||||||
case SUPPORTS_IMAGE_ATOMIC_32_BIT:
|
case SUPPORTS_IMAGE_ATOMIC_32_BIT:
|
||||||
return device_properties->features.supports_image_atomic_32_bit;
|
return device_properties->features.supports_native_image_atomics;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user