From 5afeaa41da9f71d1f2f3bf94048b327a91b8caca Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Tue, 13 Aug 2024 16:09:04 -0400 Subject: [PATCH] Refactor defining MTLPixelFormat and GPU capabilities. - Add MVKMTLDeviceCapabilities to encapsulate Metal GPU family capabilities, and use it in MVKPhysicalDevice and MVKPixelFormats to identify GPU capabilities. - Remove all references to MTLGPUFamily and MTLFeatureSet outside MVKMTLDeviceCapabilities. - Blend or select AppleGPU and MacGPU format capabilities. - Simplify MVKPixelFormats::modifyMTLFormatCapabilities() based on MVKMTLDeviceCapabilities. - Add guard code to ensure MTLPixelFormatInvalid & MTLVertexFormatInvalid capabilities are not overwritten by other formats that don't exist on some platforms. - Update MTLPixelFormat capabilities based on latest Metal docs. - Remove some variations tied to very older OS versions, or MTLFeatureSets that have the same GPU family, including setting MSL 2.0 as the earliest supported version. - Enable VkPhysicalDeviceFeatures::vertexPipelineStoresAndAtomics & fragmentStoresAndAtomics on all platforms. - During startup, only log the highest GPU family. --- Docs/Whats_New.md | 1 + MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 55 +- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 536 ++++---- .../MoltenVK/GPUObjects/MVKFramebuffer.mm | 8 +- .../MoltenVK/GPUObjects/MVKPixelFormats.h | 39 +- .../MoltenVK/GPUObjects/MVKPixelFormats.mm | 1126 +++++------------ 6 files changed, 610 insertions(+), 1155 deletions(-) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 168635786..ccb915218 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -25,6 +25,7 @@ Released TBD return `VK_ERROR_FRAGMENTED_POOL` if failure was due to pool fragmentation. - `vkUpdateDescriptorSets()`: Per Vulkan spec, allow write or copy beyond the end of a descriptor binding count, including inline uniform block descriptors. +- Update `VkFormat` capabilities based on latest Metal docs. - Fix rendering issue with render pass that immediately follows a kernel dispatch. - Ensure all MoltenVK config info set by `VK_EXT_layer_settings` is used. - Move primitive-restart-disabled warning from renderpass to pipeline creation, to reduce voluminous log noise. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 606410902..54452b824 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -93,6 +93,37 @@ static constexpr VkExtent2D kMVKSampleLocationPixelGridSizeNotSupported = { 0, 0 typedef NSUInteger MTLTimestamp; #endif + +#pragma mark - +#pragma mark MVKMTLDeviceCapabilities + +typedef struct MVKMTLDeviceCapabilities { + bool supportsApple1; + bool supportsApple2; + bool supportsApple3; + bool supportsApple4; + bool supportsApple5; + bool supportsApple6; + bool supportsApple7; + bool supportsApple8; + bool supportsApple9; + bool supportsMac1; + bool supportsMac2; + bool supportsMetal3; + + bool isAppleGPU; + bool supportsBCTextureCompression; + bool supportsDepth24Stencil8; + bool supports32BitFloatFiltering; + bool supports32BitMSAA; + + uint8_t getHighestAppleGPU() const; + uint8_t getHighestMacGPU() const; + + MVKMTLDeviceCapabilities(id mtlDev); +} MVKMTLDeviceCapabilities; + + #pragma mark - #pragma mark MVKPhysicalDevice @@ -355,6 +386,9 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { /** Returns the MTLStorageMode that matches the Vulkan memory property flags. */ MTLStorageMode getMTLStorageModeFromVkMemoryPropertyFlags(VkMemoryPropertyFlags vkFlags); + /** Returns the MTLDevice capabilities. */ + const MVKMTLDeviceCapabilities getMTLDeviceCapabilities() { return _gpuCapabilities; } + #pragma mark Construction @@ -413,9 +447,11 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { void populateHostImageCopyProperties(VkPhysicalDeviceHostImageCopyPropertiesEXT* pHostImageCopyProps); void logGPUInfo(); - id _mtlDevice; MVKInstance* _mvkInstance; + id _mtlDevice; + const MVKMTLDeviceCapabilities _gpuCapabilities; const MVKExtensionList _supportedExtensions; + MVKPixelFormats _pixelFormats; VkPhysicalDeviceFeatures _features; MVKPhysicalDeviceVulkan12FeaturesNoExt _vulkan12FeaturesNoExt; MVKPhysicalDeviceMetalFeatures _metalFeatures; @@ -423,7 +459,6 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT _texelBuffAlignProperties; VkPhysicalDeviceMemoryProperties _memoryProperties; MVKSmallVector _queueFamilies; - MVKPixelFormats _pixelFormats; VkExternalMemoryProperties _hostPointerExternalMemoryProperties; VkExternalMemoryProperties _mtlBufferExternalMemoryProperties; VkExternalMemoryProperties _mtlTextureExternalMemoryProperties; @@ -437,7 +472,6 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { uint32_t _privateMemoryTypes; uint32_t _lazilyAllocatedMemoryTypes; bool _hasUnifiedMemory = true; - bool _isAppleGPU = true; bool _isUsingMetalArgumentBuffers = true; }; @@ -896,7 +930,7 @@ class MVKDeviceTrackingMixin { bool isUnifiedMemoryGPU() { return _device->_physicalDevice->_hasUnifiedMemory; } /** Returns whether the GPU is Apple Silicon. */ - bool isAppleGPU() { return _device->_physicalDevice->_isAppleGPU; } + bool isAppleGPU() { return _device->_physicalDevice->_gpuCapabilities.isAppleGPU; } /** Returns whether this device is using one Metal argument buffer for each descriptor set, on multiple pipeline and pipeline stages. */ virtual bool isUsingMetalArgumentBuffers() { return _device->_physicalDevice->_isUsingMetalArgumentBuffers; }; @@ -1068,16 +1102,3 @@ uint64_t mvkGetRegistryID(id mtlDevice); * the returned value will be zero. */ uint64_t mvkGetLocationID(id mtlDevice); - -/** Returns whether the MTLDevice supports BC texture compression. */ -bool mvkSupportsBCTextureCompression(id mtlDevice); - -/** Redefinitions because Mac Catalyst doesn't support feature sets. */ -#if MVK_MACCAT -#define MTLFeatureSet_macOS_GPUFamily1_v1 MTLGPUFamilyMacCatalyst1 -#define MTLFeatureSet_macOS_GPUFamily1_v2 MTLGPUFamilyMacCatalyst1 -#define MTLFeatureSet_macOS_GPUFamily1_v3 MTLGPUFamilyMacCatalyst1 -#define MTLFeatureSet_macOS_GPUFamily1_v4 MTLGPUFamilyMacCatalyst1 - -#define MTLFeatureSet_macOS_GPUFamily2_v1 MTLGPUFamilyMacCatalyst2 -#endif diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 11db0e2bf..5b43ea0de 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -52,15 +52,6 @@ # define MVKViewClass NSView #endif -// Mac Catalyst does not support feature sets, so we redefine them to GPU families in MVKDevice.h. -#if MVK_MACCAT -#define supportsMTLFeatureSet(MFS) [_mtlDevice supportsFamily: MTLFeatureSet_ ##MFS] -#else -#define supportsMTLFeatureSet(MFS) [_mtlDevice supportsFeatureSet: MTLFeatureSet_ ##MFS] -#endif - -#define supportsMTLGPUFamily(GPUF) ([_mtlDevice respondsToSelector: @selector(supportsFamily:)] && [_mtlDevice supportsFamily: MTLGPUFamily ##GPUF]) - // Suppress unused variable warnings to allow us to define these all in one place, // but use them in platform-conditional code blocks. #pragma clang diagnostic push @@ -82,9 +73,95 @@ #pragma clang diagnostic pop +#pragma mark - +#pragma mark MVKMTLDeviceCapabilities + +#define supportsGPUFam(gpuFam, mtlDev) ([mtlDev respondsToSelector: @selector(supportsFamily:)] && [mtlDev supportsFamily: MTLGPUFamily ##gpuFam]) + +#if MVK_IOS +#define supportsIOSGPU(gpuIdx, mtlDev) [mtlDev supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily ##gpuIdx ##_v1] +#else +#define supportsIOSGPU(gpuIdx, mtlDev) false +#endif + +#if MVK_TVOS +#define supportsTVOSGPU(gpuIdx, mtlDev) [mtlDev supportsFeatureSet: MTLFeatureSet_tvOS_GPUFamily ##gpuIdx ##_v1] +#else +#define supportsTVOSGPU(gpuIdx, mtlDev) false +#endif + +#define returnGPUValIf(gpuType, gpuIdx) if (supports ##gpuType ##gpuIdx) { return gpuIdx; } + +uint8_t MVKMTLDeviceCapabilities::getHighestAppleGPU() const { + returnGPUValIf(Apple, 9); + returnGPUValIf(Apple, 8); + returnGPUValIf(Apple, 7); + returnGPUValIf(Apple, 6); + returnGPUValIf(Apple, 5); + returnGPUValIf(Apple, 4); + returnGPUValIf(Apple, 3); + returnGPUValIf(Apple, 2); + returnGPUValIf(Apple, 1); + return 0; +} + +uint8_t MVKMTLDeviceCapabilities::getHighestMacGPU() const { + returnGPUValIf(Mac, 2); + returnGPUValIf(Mac, 1); + return 0; +} + +MVKMTLDeviceCapabilities::MVKMTLDeviceCapabilities(id mtlDev) { + mvkClear(this); + supportsApple1 = supportsGPUFam(Apple1, mtlDev) || supportsIOSGPU(1, mtlDev) || supportsTVOSGPU(1, mtlDev); + supportsApple2 = supportsGPUFam(Apple2, mtlDev) || supportsIOSGPU(2, mtlDev) || supportsTVOSGPU(1, mtlDev); + supportsApple3 = supportsGPUFam(Apple3, mtlDev) || supportsIOSGPU(3, mtlDev) || supportsTVOSGPU(2, mtlDev); + supportsApple4 = supportsGPUFam(Apple4, mtlDev) || supportsIOSGPU(4, mtlDev); + supportsApple5 = supportsGPUFam(Apple5, mtlDev) || supportsIOSGPU(5, mtlDev); +#if MVK_XCODE_12 + supportsApple6 = supportsGPUFam(Apple6, mtlDev); +#endif +#if MVK_XCODE_13 + supportsApple7 = supportsGPUFam(Apple7, mtlDev); +#endif +#if MVK_XCODE_14 + supportsApple8 = supportsGPUFam(Apple8, mtlDev); + supportsMetal3 = supportsGPUFam(Metal3, mtlDev); +#endif +#if MVK_XCODE_15 && !MVK_TVOS + supportsApple9 = supportsGPUFam(Apple9, mtlDev); +#endif + supportsMac1 = MVK_MACOS; // Incl Mac1 & MacCatalyst1 + supportsMac2 = MVK_MACOS; // Incl Mac2 & MacCatalyst2 + + isAppleGPU = supportsApple1; + +#if MVK_XCODE_14_3 || (MVK_XCODE_12 && MVK_MACOS && !MVK_MACCAT) + if ([mtlDev respondsToSelector: @selector(supportsBCTextureCompression)]) { + supportsBCTextureCompression = mtlDev.supportsBCTextureCompression; + } +#else + supportsBCTextureCompression = supportsMac1; +#endif +#if MVK_MACOS + supportsDepth24Stencil8 = mtlDev.isDepth24Stencil8PixelFormatSupported; +#endif +#if MVK_XCODE_14 || (MVK_XCODE_12 && !MVK_TVOS) + if ([mtlDev respondsToSelector: @selector(supports32BitFloatFiltering)]) { + supports32BitFloatFiltering = mtlDev.supports32BitFloatFiltering; + } + if ([mtlDev respondsToSelector: @selector(supports32BitMSAA)]) { + supports32BitMSAA = mtlDev.supports32BitMSAA; + } +#endif +} + + #pragma mark - #pragma mark MVKPhysicalDevice +#define supportsMTLGPUFamily(gpuFam) _gpuCapabilities.supports ##gpuFam + VkResult MVKPhysicalDevice::getExtensionProperties(const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties) { return _supportedExtensions.getProperties(pCount, pProperties); } @@ -1767,7 +1844,7 @@ // wild temporary changes, particularly during initial queries before much GPU activity has occurred. // On Apple GPUs, CPU & GPU timestamps are the same, and timestamp period never changes. void MVKPhysicalDevice::updateTimestampPeriod() { - if ( !_isAppleGPU && [_mtlDevice respondsToSelector: @selector(sampleTimestamps:gpuTimestamp:)]) { + if ( !_gpuCapabilities.isAppleGPU && [_mtlDevice respondsToSelector: @selector(sampleTimestamps:gpuTimestamp:)]) { MTLTimestamp earlierCPUTs = _prevCPUTimestamp; MTLTimestamp earlierGPUTs = _prevGPUTimestamp; [_mtlDevice sampleTimestamps: &_prevCPUTimestamp gpuTimestamp: &_prevGPUTimestamp]; @@ -1828,10 +1905,11 @@ #pragma mark Construction MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id mtlDevice) : - _mtlDevice([mtlDevice retain]), // Set first _mvkInstance(mvkInstance), + _mtlDevice([mtlDevice retain]), + _gpuCapabilities(mtlDevice), _supportedExtensions(this, true), - _pixelFormats(this) { // Set after _mtlDevice + _pixelFormats(this) { // Set after _mtlDevice & _gpuCapabilities initMTLDevice(); // Call first. initProperties(); // Call second. @@ -1848,8 +1926,6 @@ void MVKPhysicalDevice::initMTLDevice() { #if MVK_MACOS - _isAppleGPU = supportsMTLGPUFamily(Apple1); - // Apple Silicon will respond false to isLowPower, but never hits it. _hasUnifiedMemory = ([_mtlDevice respondsToSelector: @selector(hasUnifiedMemory)] ? _mtlDevice.hasUnifiedMemory : _mtlDevice.isLowPower); @@ -1932,7 +2008,7 @@ } #if MVK_TVOS - _metalFeatures.mslVersionEnum = MTLLanguageVersion1_1; + _metalFeatures.mslVersionEnum = MTLLanguageVersion2_0; _metalFeatures.mtlBufferAlignment = 64; _metalFeatures.mtlCopyBufferAlignment = 1; _metalFeatures.texelBuffers = true; @@ -1942,28 +2018,16 @@ _metalFeatures.maxPerStageDynamicMTLBufferCount = _metalFeatures.maxPerStageBufferCount; _metalFeatures.renderLinearTextures = true; _metalFeatures.tileBasedDeferredRendering = true; - - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v2)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion1_2; - _metalFeatures.shaderSpecialization = true; - _metalFeatures.stencilViews = true; - _metalFeatures.fences = true; - _metalFeatures.deferredStoreActions = true; - } - - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v3)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion2_0; - _metalFeatures.renderWithoutAttachments = true; - _metalFeatures.argumentBuffers = true; - } - - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v4)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion2_1; - _metalFeatures.events = true; - _metalFeatures.textureBuffers = true; - } - - if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) { + _metalFeatures.shaderSpecialization = true; + _metalFeatures.stencilViews = true; + _metalFeatures.fences = true; + _metalFeatures.deferredStoreActions = true; + _metalFeatures.renderWithoutAttachments = true; + _metalFeatures.argumentBuffers = true; + _metalFeatures.events = true; + _metalFeatures.textureBuffers = true; + + if (supportsMTLGPUFamily(Apple3)) { _metalFeatures.indirectDrawing = true; _metalFeatures.baseVertexInstanceDrawing = true; _metalFeatures.combinedStoreResolveAction = true; @@ -1975,6 +2039,10 @@ _metalFeatures.depthResolve = true; } + if ( mvkOSVersionIsAtLeast(12.0) ) { + _metalFeatures.mslVersionEnum = MTLLanguageVersion2_1; + } + if ( mvkOSVersionIsAtLeast(13.0) ) { _metalFeatures.mslVersionEnum = MTLLanguageVersion2_2; _metalFeatures.placementHeaps = getMVKConfig().useMTLHeap; @@ -2024,7 +2092,7 @@ #endif #if MVK_IOS - _metalFeatures.mslVersionEnum = MTLLanguageVersion1_0; + _metalFeatures.mslVersionEnum = MTLLanguageVersion2_0; _metalFeatures.mtlBufferAlignment = 64; _metalFeatures.mtlCopyBufferAlignment = 1; _metalFeatures.texelBuffers = true; @@ -2032,35 +2100,19 @@ _metalFeatures.sharedLinearTextures = true; _metalFeatures.renderLinearTextures = true; _metalFeatures.tileBasedDeferredRendering = true; - - if (supportsMTLFeatureSet(iOS_GPUFamily1_v2)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion1_1; - _metalFeatures.dynamicMTLBufferSize = (4 * KIBI); - _metalFeatures.maxTextureDimension = (8 * KIBI); - _metalFeatures.maxPerStageDynamicMTLBufferCount = _metalFeatures.maxPerStageBufferCount; - } - - if (supportsMTLFeatureSet(iOS_GPUFamily1_v3)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion1_2; - _metalFeatures.shaderSpecialization = true; - _metalFeatures.stencilViews = true; - _metalFeatures.fences = true; - _metalFeatures.deferredStoreActions = true; - } - - if (supportsMTLFeatureSet(iOS_GPUFamily1_v4)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion2_0; - _metalFeatures.renderWithoutAttachments = true; - _metalFeatures.argumentBuffers = true; - } - - if (supportsMTLFeatureSet(iOS_GPUFamily1_v5)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion2_1; - _metalFeatures.events = true; - _metalFeatures.textureBuffers = true; - } - - if (supportsMTLFeatureSet(iOS_GPUFamily3_v1)) { + _metalFeatures.dynamicMTLBufferSize = (4 * KIBI); + _metalFeatures.maxTextureDimension = (8 * KIBI); + _metalFeatures.maxPerStageDynamicMTLBufferCount = _metalFeatures.maxPerStageBufferCount; + _metalFeatures.shaderSpecialization = true; + _metalFeatures.stencilViews = true; + _metalFeatures.fences = true; + _metalFeatures.deferredStoreActions = true; + _metalFeatures.renderWithoutAttachments = true; + _metalFeatures.argumentBuffers = true; + _metalFeatures.events = true; + _metalFeatures.textureBuffers = true; + + if (supportsMTLGPUFamily(Apple3)) { _metalFeatures.indirectDrawing = true; _metalFeatures.baseVertexInstanceDrawing = true; _metalFeatures.combinedStoreResolveAction = true; @@ -2070,25 +2122,29 @@ _metalFeatures.depthResolve = true; } - if (supportsMTLFeatureSet(iOS_GPUFamily3_v2)) { + if (supportsMTLGPUFamily(Apple3)) { _metalFeatures.arrayOfTextures = true; } - if (supportsMTLFeatureSet(iOS_GPUFamily3_v3)) { + if (supportsMTLGPUFamily(Apple3)) { _metalFeatures.arrayOfSamplers = true; } - if (supportsMTLFeatureSet(iOS_GPUFamily4_v1)) { + if (supportsMTLGPUFamily(Apple4)) { _metalFeatures.postDepthCoverage = true; _metalFeatures.nonUniformThreadgroups = true; } - if (supportsMTLFeatureSet(iOS_GPUFamily5_v1)) { + if (supportsMTLGPUFamily(Apple5)) { _metalFeatures.layeredRendering = true; _metalFeatures.stencilFeedback = true; _metalFeatures.indirectTessellationDrawing = true; _metalFeatures.stencilResolve = true; } + if ( mvkOSVersionIsAtLeast(12.0) ) { + _metalFeatures.mslVersionEnum = MTLLanguageVersion2_1; + } + if ( mvkOSVersionIsAtLeast(13.0) ) { _metalFeatures.mslVersionEnum = MTLLanguageVersion2_2; _metalFeatures.placementHeaps = getMVKConfig().useMTLHeap; @@ -2152,7 +2208,7 @@ #endif #if MVK_MACOS - _metalFeatures.mslVersionEnum = MTLLanguageVersion1_1; + _metalFeatures.mslVersionEnum = MTLLanguageVersion2_0; _metalFeatures.maxPerStageTextureCount = 128; _metalFeatures.mtlBufferAlignment = 256; _metalFeatures.mtlCopyBufferAlignment = 4; @@ -2161,40 +2217,28 @@ _metalFeatures.maxTextureDimension = (16 * KIBI); _metalFeatures.depthSampleCompare = true; _metalFeatures.samplerMirrorClampToEdge = true; - - if (supportsMTLFeatureSet(macOS_GPUFamily1_v2)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion1_2; - _metalFeatures.indirectDrawing = true; - _metalFeatures.indirectTessellationDrawing = true; - _metalFeatures.dynamicMTLBufferSize = (4 * KIBI); - _metalFeatures.shaderSpecialization = true; - _metalFeatures.stencilViews = true; - _metalFeatures.samplerClampToBorder = true; - _metalFeatures.combinedStoreResolveAction = true; - _metalFeatures.deferredStoreActions = true; - _metalFeatures.maxMTLBufferSize = (1 * GIBI); - _metalFeatures.maxPerStageDynamicMTLBufferCount = 14; - } - - if (supportsMTLFeatureSet(macOS_GPUFamily1_v3)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion2_0; - _metalFeatures.texelBuffers = true; - _metalFeatures.arrayOfTextures = true; - _metalFeatures.arrayOfSamplers = true; - _metalFeatures.presentModeImmediate = true; - _metalFeatures.fences = true; - _metalFeatures.nonUniformThreadgroups = true; - _metalFeatures.argumentBuffers = true; - } - - if (supportsMTLFeatureSet(macOS_GPUFamily1_v4)) { - _metalFeatures.mslVersionEnum = MTLLanguageVersion2_1; - _metalFeatures.multisampleArrayTextures = true; - _metalFeatures.events = true; - _metalFeatures.textureBuffers = true; - } - - if (supportsMTLFeatureSet(macOS_GPUFamily2_v1)) { + _metalFeatures.indirectDrawing = true; + _metalFeatures.indirectTessellationDrawing = true; + _metalFeatures.dynamicMTLBufferSize = (4 * KIBI); + _metalFeatures.shaderSpecialization = true; + _metalFeatures.stencilViews = true; + _metalFeatures.samplerClampToBorder = true; + _metalFeatures.combinedStoreResolveAction = true; + _metalFeatures.deferredStoreActions = true; + _metalFeatures.maxMTLBufferSize = (1 * GIBI); + _metalFeatures.maxPerStageDynamicMTLBufferCount = 14; + _metalFeatures.texelBuffers = true; + _metalFeatures.arrayOfTextures = true; + _metalFeatures.arrayOfSamplers = true; + _metalFeatures.presentModeImmediate = true; + _metalFeatures.fences = true; + _metalFeatures.nonUniformThreadgroups = true; + _metalFeatures.argumentBuffers = true; + _metalFeatures.multisampleArrayTextures = true; + _metalFeatures.events = true; + _metalFeatures.textureBuffers = true; + + if (supportsMTLGPUFamily(Mac2)) { _metalFeatures.multisampleLayeredRendering = _metalFeatures.layeredRendering; _metalFeatures.stencilFeedback = true; _metalFeatures.depthResolve = true; @@ -2204,6 +2248,10 @@ _metalFeatures.simdReduction = true; } + if ( mvkOSVersionIsAtLeast(10.14) ) { + _metalFeatures.mslVersionEnum = MTLLanguageVersion2_1; + } + if ( mvkOSVersionIsAtLeast(10.15) ) { _metalFeatures.mslVersionEnum = MTLLanguageVersion2_2; _metalFeatures.maxQueryBufferSize = (256 * KIBI); @@ -2267,11 +2315,7 @@ // Don't use barriers in render passes on Apple GPUs. Apple GPUs don't support them, // and in fact Metal's validation layer will complain if you try to use them. // Texture barriers deprecated as of macOS 10.14. - if ( !supportsMTLGPUFamily(Apple1) ) { - if (supportsMTLFeatureSet(macOS_GPUFamily1_v4)) { - _metalFeatures.memoryBarriers = true; - } - } + _metalFeatures.memoryBarriers = !_gpuCapabilities.isAppleGPU; #endif @@ -2484,72 +2528,64 @@ _features.shaderInt16 = true; _features.multiDrawIndirect = true; _features.inheritedQueries = true; + _features.vertexPipelineStoresAndAtomics = true; + _features.fragmentStoresAndAtomics = true; _features.shaderSampledImageArrayDynamicIndexing = _metalFeatures.arrayOfTextures; - _features.textureCompressionBC = mvkSupportsBCTextureCompression(_mtlDevice); + _features.textureCompressionBC = _gpuCapabilities.supportsBCTextureCompression; _features.drawIndirectFirstInstance = _metalFeatures.indirectDrawing && _metalFeatures.baseVertexInstanceDrawing; +#if MVK_XCODE_12 + _features.shaderInt64 = mslVersionIsAtLeast(MTLLanguageVersion2_3) && (supportsMTLGPUFamily(Apple3) || supportsMTLGPUFamily(Mac1)); +#endif + #if MVK_TVOS _features.textureCompressionETC2 = true; _features.textureCompressionASTC_LDR = true; -#if MVK_XCODE_12 - _features.shaderInt64 = mslVersionIsAtLeast(MTLLanguageVersion2_3) && supportsMTLGPUFamily(Apple3); -#else - _features.shaderInt64 = false; -#endif - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v3)) { - _features.dualSrcBlend = true; - } + _features.dualSrcBlend = true; - if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) { + if (supportsMTLGPUFamily(Apple3)) { _features.occlusionQueryPrecise = true; } - if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) { + if (supportsMTLGPUFamily(Apple3)) { _features.tessellationShader = true; } #endif #if MVK_IOS _features.textureCompressionETC2 = true; -#if MVK_XCODE_12 - _features.shaderInt64 = mslVersionIsAtLeast(MTLLanguageVersion2_3) && supportsMTLGPUFamily(Apple3); -#else - _features.shaderInt64 = false; -#endif - if (supportsMTLFeatureSet(iOS_GPUFamily2_v1)) { + if (supportsMTLGPUFamily(Apple2)) { _features.textureCompressionASTC_LDR = true; } - if (supportsMTLFeatureSet(iOS_GPUFamily3_v1)) { + if (supportsMTLGPUFamily(Apple3)) { _features.occlusionQueryPrecise = true; } - if (supportsMTLFeatureSet(iOS_GPUFamily1_v4)) { - _features.dualSrcBlend = true; - } + _features.dualSrcBlend = true; #if MVK_OS_SIMULATOR _features.depthClamp = false; #else - if (supportsMTLFeatureSet(iOS_GPUFamily2_v4)) { + if (supportsMTLGPUFamily(Apple2)) { _features.depthClamp = true; } #endif - if (supportsMTLFeatureSet(iOS_GPUFamily3_v2)) { + if (supportsMTLGPUFamily(Apple3)) { _features.tessellationShader = true; _features.shaderTessellationAndGeometryPointSize = true; } - if (supportsMTLFeatureSet(iOS_GPUFamily4_v1)) { + if (supportsMTLGPUFamily(Apple4)) { _features.imageCubeArray = true; } - if (supportsMTLFeatureSet(iOS_GPUFamily5_v1)) { + if (supportsMTLGPUFamily(Apple5)) { _features.multiViewport = true; } @@ -2562,14 +2598,6 @@ _features.occlusionQueryPrecise = true; _features.imageCubeArray = true; _features.depthClamp = true; - _features.vertexPipelineStoresAndAtomics = true; - _features.fragmentStoresAndAtomics = true; -#if MVK_XCODE_12 - _features.shaderInt64 = mslVersionIsAtLeast(MTLLanguageVersion2_3); -#else - _features.shaderInt64 = false; -#endif - _features.shaderStorageImageArrayDynamicIndexing = _metalFeatures.arrayOfTextures; #if MVK_USE_METAL_PRIVATE_API @@ -2579,15 +2607,10 @@ } #endif - if (supportsMTLFeatureSet(macOS_GPUFamily1_v2)) { - _features.tessellationShader = true; - _features.dualSrcBlend = true; - _features.shaderTessellationAndGeometryPointSize = true; - } - - if (supportsMTLFeatureSet(macOS_GPUFamily1_v3)) { - _features.multiViewport = true; - } + _features.tessellationShader = true; + _features.dualSrcBlend = true; + _features.shaderTessellationAndGeometryPointSize = true; + _features.multiViewport = true; if ( mvkOSVersionIsAtLeast(10.15) ) { _features.shaderResourceMinLod = true; @@ -2618,7 +2641,7 @@ _properties.limits.maxColorAttachments = kMVKMaxColorAttachmentCount; #endif #if MVK_IOS - if (supportsMTLFeatureSet(iOS_GPUFamily2_v1)) { + if (supportsMTLGPUFamily(Apple2)) { _properties.limits.maxColorAttachments = kMVKMaxColorAttachmentCount; } else { _properties.limits.maxColorAttachments = 4; // < kMVKMaxColorAttachmentCount @@ -2785,7 +2808,7 @@ _properties.limits.minTexelBufferOffsetAlignment = 64; #endif #if MVK_IOS - if (supportsMTLFeatureSet(iOS_GPUFamily3_v1)) { + if (supportsMTLGPUFamily(Apple3)) { _properties.limits.minTexelBufferOffsetAlignment = 16; } else { _properties.limits.minTexelBufferOffsetAlignment = 64; @@ -2810,7 +2833,7 @@ _properties.limits.maxFragmentInputComponents = 60; } - if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) { + if (supportsMTLGPUFamily(Apple3)) { _properties.limits.optimalBufferCopyOffsetAlignment = 16; } else { _properties.limits.optimalBufferCopyOffsetAlignment = 64; @@ -2826,16 +2849,16 @@ _properties.limits.maxFragmentInputComponents = 60; } - if (supportsMTLFeatureSet(iOS_GPUFamily3_v1)) { + if (supportsMTLGPUFamily(Apple3)) { _properties.limits.optimalBufferCopyOffsetAlignment = 16; } else { _properties.limits.optimalBufferCopyOffsetAlignment = 64; } - if (supportsMTLFeatureSet(iOS_GPUFamily5_v1)) { + if (supportsMTLGPUFamily(Apple5)) { _properties.limits.maxTessellationGenerationLevel = 64; _properties.limits.maxTessellationPatchSize = 32; - } else if (supportsMTLFeatureSet(iOS_GPUFamily3_v2)) { + } else if (supportsMTLGPUFamily(Apple3)) { _properties.limits.maxTessellationGenerationLevel = 16; _properties.limits.maxTessellationPatchSize = 32; } else { @@ -2850,13 +2873,8 @@ _properties.limits.optimalBufferCopyOffsetAlignment = 16; } - if (supportsMTLFeatureSet(macOS_GPUFamily1_v2)) { - _properties.limits.maxTessellationGenerationLevel = 64; - _properties.limits.maxTessellationPatchSize = 32; - } else { - _properties.limits.maxTessellationGenerationLevel = 0; - _properties.limits.maxTessellationPatchSize = 0; - } + _properties.limits.maxTessellationGenerationLevel = 64; + _properties.limits.maxTessellationPatchSize = 32; #endif _properties.limits.maxVertexOutputComponents = _properties.limits.maxFragmentInputComponents; @@ -2919,16 +2937,16 @@ _properties.limits.maxComputeSharedMemorySize = (uint32_t)_mtlDevice.maxThreadgroupMemoryLength; } else { #if MVK_TVOS - if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) { + if (supportsMTLGPUFamily(Apple3)) { _properties.limits.maxComputeSharedMemorySize = (16 * KIBI); } else { _properties.limits.maxComputeSharedMemorySize = ((16 * KIBI) - 32); } #endif #if MVK_IOS - if (supportsMTLFeatureSet(iOS_GPUFamily4_v1)) { + if (supportsMTLGPUFamily(Apple4)) { _properties.limits.maxComputeSharedMemorySize = (32 * KIBI); - } else if (supportsMTLFeatureSet(iOS_GPUFamily3_v1)) { + } else if (supportsMTLGPUFamily(Apple3)) { _properties.limits.maxComputeSharedMemorySize = (16 * KIBI); } else { _properties.limits.maxComputeSharedMemorySize = ((16 * KIBI) - 32); @@ -3013,7 +3031,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope // GPU capability, which is a combination of OS version and GPU type. // We determine Apple Silicon directly from the GPU, instead // of from the build, in case we are running Rosetta2. - if (_isAppleGPU) { + if (_gpuCapabilities.isAppleGPU) { _properties.vendorID = kAppleVendorId; _properties.deviceID = getHighestGPUCapability(); return; @@ -3103,62 +3121,16 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope uuidComponentOffset += sizeof(mtlFeatures); } +// Combine OS major (8 bits), OS minor (8 bits), Mac GPU family (8 bits), and +// Apple GPU family (8 bits) into one 32-bit value summarizing highest GPU capability. uint32_t MVKPhysicalDevice::getHighestGPUCapability() { - - // On newer OS's, combine OS version with highest GPU family. - // On macOS, Apple GPU fam takes precedence over others. - MTLGPUFamily gpuFam = MTLGPUFamily(0); - if (supportsMTLGPUFamily(Mac1)) { gpuFam = MTLGPUFamilyMac1; } - if (supportsMTLGPUFamily(Mac2)) { gpuFam = MTLGPUFamilyMac2; } - - if (supportsMTLGPUFamily(Apple1)) { gpuFam = MTLGPUFamilyApple1; } - if (supportsMTLGPUFamily(Apple2)) { gpuFam = MTLGPUFamilyApple2; } - if (supportsMTLGPUFamily(Apple3)) { gpuFam = MTLGPUFamilyApple3; } - if (supportsMTLGPUFamily(Apple4)) { gpuFam = MTLGPUFamilyApple4; } - if (supportsMTLGPUFamily(Apple5)) { gpuFam = MTLGPUFamilyApple5; } -#if MVK_IOS || (MVK_MACOS && MVK_XCODE_12) - if (supportsMTLGPUFamily(Apple6)) { gpuFam = MTLGPUFamilyApple6; } -#endif -#if (MVK_IOS || MVK_MACOS) && MVK_XCODE_12 - if (supportsMTLGPUFamily(Apple7)) { gpuFam = MTLGPUFamilyApple7; } -#endif -#if MVK_XCODE_14 || (MVK_IOS && MVK_XCODE_13) - if (supportsMTLGPUFamily(Apple8)) { gpuFam = MTLGPUFamilyApple8; } -#endif -#if MVK_XCODE_15 && (MVK_IOS || MVK_MACOS) - if (supportsMTLGPUFamily(Apple9)) { gpuFam = MTLGPUFamilyApple9; } -#endif - - // Combine OS major (8 bits), OS minor (8 bits), and GPU family (16 bits) - // into one 32-bit value summarizing highest GPU capability. - if (gpuFam) { - float fosMaj, fosMin; - fosMin = modf(mvkOSVersion(), &fosMaj); - uint8_t osMaj = (uint8_t)fosMaj; - uint8_t osMin = (uint8_t)(fosMin * 100); - return (osMaj << 24) + (osMin << 16) + (uint16_t)gpuFam; - } - - // Fall back to legacy feature sets on older OS's -#if MVK_IOS_OR_VISIONOS - uint32_t maxFS = (uint32_t)MTLFeatureSet_iOS_GPUFamily5_v1; - uint32_t minFS = (uint32_t)MTLFeatureSet_iOS_GPUFamily1_v1; -#endif - -#if MVK_TVOS - uint32_t maxFS = (uint32_t)MTLFeatureSet_tvOS_GPUFamily2_v2; - uint32_t minFS = (uint32_t)MTLFeatureSet_tvOS_GPUFamily1_v1; -#endif - -#if MVK_MACOS - uint32_t maxFS = (uint32_t)MTLFeatureSet_macOS_GPUFamily2_v1; - uint32_t minFS = (uint32_t)MTLFeatureSet_macOS_GPUFamily1_v1; -#endif - - for (uint32_t fs = maxFS; fs > minFS; fs--) { - if ( [_mtlDevice supportsFeatureSet: (MTLFeatureSet)fs] ) { return fs; } - } - return minFS; + float fosMaj; + float fosMin = modf(mvkOSVersion(), &fosMaj); + uint8_t osMaj = (uint8_t)fosMaj; + uint8_t osMin = (uint8_t)(fosMin * 100); + uint8_t gpuM = _gpuCapabilities.getHighestMacGPU(); + uint8_t gpuA = _gpuCapabilities.getHighestAppleGPU(); + return (osMaj << 24) + (osMin << 16) + (gpuM << 8) + gpuA; } // Retrieve the SPIRV-Cross Git revision hash from a derived header file, @@ -3233,7 +3205,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope // Managed storage. On all Apple Silicon, use Shared instead. uint32_t managedBit = 0; #if MVK_MACOS - if ( !_isAppleGPU ) { + if ( !_gpuCapabilities.isAppleGPU ) { managedBit = 1 << typeIdx; setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MANAGED); typeIdx++; @@ -3250,18 +3222,14 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope } #endif #if MVK_IOS - if (supportsMTLFeatureSet(iOS_GPUFamily1_v3)) { - memlessBit = 1 << typeIdx; - setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS); - typeIdx++; - } + memlessBit = 1 << typeIdx; + setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS); + typeIdx++; #endif #if MVK_TVOS - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v2)) { - memlessBit = 1 << typeIdx; - setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS); - typeIdx++; - } + memlessBit = 1 << typeIdx; + setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS); + typeIdx++; #endif _memoryProperties.memoryTypeCount = typeIdx; @@ -3292,7 +3260,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope // If visible to the host, but not coherent: Shared on Apple Silicon, Managed on other GPUs. #if MVK_MACOS - return _isAppleGPU ? MTLStorageModeShared : MTLStorageModeManaged; + return _gpuCapabilities.isAppleGPU ? MTLStorageModeShared : MTLStorageModeManaged; #else return MTLStorageModeShared; #endif @@ -3462,7 +3430,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope switch (getMVKConfig().semaphoreSupportStyle) { case MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE: { bool isNVIDIA = _properties.vendorID == kNVVendorId; - bool isRosetta2 = _isAppleGPU && !MVK_APPLE_SILICON; + bool isRosetta2 = _gpuCapabilities.isAppleGPU && !MVK_APPLE_SILICON; if (_metalFeatures.events && !(isRosetta2 || isNVIDIA)) { _vkSemaphoreStyle = MVKSemaphoreStyleUseMTLEvent; } break; } @@ -3517,86 +3485,29 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope if (supportsMTLGPUFamily(Metal3)) { logMsg += "\n\t\tGPU Family Metal 3"; } #endif #if MVK_XCODE_15 && (MVK_IOS || MVK_MACOS) - if (supportsMTLGPUFamily(Apple9)) { logMsg += "\n\t\tGPU Family Apple 9"; } + if (supportsMTLGPUFamily(Apple9)) { logMsg += "\n\t\tGPU Family Apple 9"; } else #endif #if MVK_XCODE_14 || (MVK_IOS && MVK_XCODE_13) - if (supportsMTLGPUFamily(Apple8)) { logMsg += "\n\t\tGPU Family Apple 8"; } + if (supportsMTLGPUFamily(Apple8)) { logMsg += "\n\t\tGPU Family Apple 8"; } else #endif #if (MVK_IOS || MVK_MACOS) && MVK_XCODE_12 - if (supportsMTLGPUFamily(Apple7)) { logMsg += "\n\t\tGPU Family Apple 7"; } + if (supportsMTLGPUFamily(Apple7)) { logMsg += "\n\t\tGPU Family Apple 7"; } else #endif #if MVK_IOS || (MVK_MACOS && MVK_XCODE_12) - if (supportsMTLGPUFamily(Apple6)) { logMsg += "\n\t\tGPU Family Apple 6"; } + if (supportsMTLGPUFamily(Apple6)) { logMsg += "\n\t\tGPU Family Apple 6"; } else #endif - if (supportsMTLGPUFamily(Apple5)) { logMsg += "\n\t\tGPU Family Apple 5"; } - if (supportsMTLGPUFamily(Apple4)) { logMsg += "\n\t\tGPU Family Apple 4"; } - if (supportsMTLGPUFamily(Apple3)) { logMsg += "\n\t\tGPU Family Apple 3"; } - if (supportsMTLGPUFamily(Apple2)) { logMsg += "\n\t\tGPU Family Apple 2"; } + if (supportsMTLGPUFamily(Apple5)) { logMsg += "\n\t\tGPU Family Apple 5"; } else + if (supportsMTLGPUFamily(Apple4)) { logMsg += "\n\t\tGPU Family Apple 4"; } else + if (supportsMTLGPUFamily(Apple3)) { logMsg += "\n\t\tGPU Family Apple 3"; } else + if (supportsMTLGPUFamily(Apple2)) { logMsg += "\n\t\tGPU Family Apple 2"; } else if (supportsMTLGPUFamily(Apple1)) { logMsg += "\n\t\tGPU Family Apple 1"; } - if (supportsMTLGPUFamily(Mac2)) { logMsg += "\n\t\tGPU Family Mac 2"; } + if (supportsMTLGPUFamily(Mac2)) { logMsg += "\n\t\tGPU Family Mac 2"; } else if (supportsMTLGPUFamily(Mac1)) { logMsg += "\n\t\tGPU Family Mac 1"; } - if (supportsMTLGPUFamily(Common3)) { logMsg += "\n\t\tGPU Family Common 3"; } - if (supportsMTLGPUFamily(Common2)) { logMsg += "\n\t\tGPU Family Common 2"; } - if (supportsMTLGPUFamily(Common1)) { logMsg += "\n\t\tGPU Family Common 1"; } - - if (supportsMTLGPUFamily(MacCatalyst2)) { logMsg += "\n\t\tGPU Family Mac Catalyst 2"; } - if (supportsMTLGPUFamily(MacCatalyst1)) { logMsg += "\n\t\tGPU Family Mac Catalyst 1"; } - -#if MVK_IOS - if (supportsMTLFeatureSet(iOS_GPUFamily5_v1)) { logMsg += "\n\t\tiOS GPU Family 5 v1"; } - - if (supportsMTLFeatureSet(iOS_GPUFamily4_v2)) { logMsg += "\n\t\tiOS GPU Family 4 v2"; } - if (supportsMTLFeatureSet(iOS_GPUFamily4_v1)) { logMsg += "\n\t\tiOS GPU Family 4 v1"; } - - if (supportsMTLFeatureSet(iOS_GPUFamily3_v4)) { logMsg += "\n\t\tiOS GPU Family 3 v4"; } - if (supportsMTLFeatureSet(iOS_GPUFamily3_v3)) { logMsg += "\n\t\tiOS GPU Family 3 v3"; } - if (supportsMTLFeatureSet(iOS_GPUFamily3_v2)) { logMsg += "\n\t\tiOS GPU Family 3 v2"; } - if (supportsMTLFeatureSet(iOS_GPUFamily3_v1)) { logMsg += "\n\t\tiOS GPU Family 3 v1"; } - - if (supportsMTLFeatureSet(iOS_GPUFamily2_v5)) { logMsg += "\n\t\tiOS GPU Family 2 v5"; } - if (supportsMTLFeatureSet(iOS_GPUFamily2_v4)) { logMsg += "\n\t\tiOS GPU Family 2 v4"; } - if (supportsMTLFeatureSet(iOS_GPUFamily2_v3)) { logMsg += "\n\t\tiOS GPU Family 2 v3"; } - if (supportsMTLFeatureSet(iOS_GPUFamily2_v2)) { logMsg += "\n\t\tiOS GPU Family 2 v2"; } - if (supportsMTLFeatureSet(iOS_GPUFamily2_v1)) { logMsg += "\n\t\tiOS GPU Family 2 v1"; } - - if (supportsMTLFeatureSet(iOS_GPUFamily1_v5)) { logMsg += "\n\t\tiOS GPU Family 1 v5"; } - if (supportsMTLFeatureSet(iOS_GPUFamily1_v4)) { logMsg += "\n\t\tiOS GPU Family 1 v4"; } - if (supportsMTLFeatureSet(iOS_GPUFamily1_v3)) { logMsg += "\n\t\tiOS GPU Family 1 v3"; } - if (supportsMTLFeatureSet(iOS_GPUFamily1_v2)) { logMsg += "\n\t\tiOS GPU Family 1 v2"; } - if (supportsMTLFeatureSet(iOS_GPUFamily1_v1)) { logMsg += "\n\t\tiOS GPU Family 1 v1"; } -#endif - -#if MVK_TVOS - if (supportsMTLFeatureSet(tvOS_GPUFamily2_v2)) { logMsg += "\n\t\ttvOS GPU Family 2 v2"; } - if (supportsMTLFeatureSet(tvOS_GPUFamily2_v1)) { logMsg += "\n\t\ttvOS GPU Family 2 v1"; } - - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v4)) { logMsg += "\n\t\ttvOS GPU Family 1 v4"; } - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v3)) { logMsg += "\n\t\ttvOS GPU Family 1 v3"; } - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v2)) { logMsg += "\n\t\ttvOS GPU Family 1 v2"; } - if (supportsMTLFeatureSet(tvOS_GPUFamily1_v1)) { logMsg += "\n\t\ttvOS GPU Family 1 v1"; } -#endif - -#if MVK_MACOS - if (supportsMTLFeatureSet(macOS_GPUFamily2_v1)) { logMsg += "\n\t\tmacOS GPU Family 2 v1"; } - - if (supportsMTLFeatureSet(macOS_GPUFamily1_v4)) { logMsg += "\n\t\tmacOS GPU Family 1 v4"; } - if (supportsMTLFeatureSet(macOS_GPUFamily1_v3)) { logMsg += "\n\t\tmacOS GPU Family 1 v3"; } - if (supportsMTLFeatureSet(macOS_GPUFamily1_v2)) { logMsg += "\n\t\tmacOS GPU Family 1 v2"; } - if (supportsMTLFeatureSet(macOS_GPUFamily1_v1)) { logMsg += "\n\t\tmacOS GPU Family 1 v1"; } - -#if !MVK_MACCAT - if (supportsMTLFeatureSet(macOS_ReadWriteTextureTier2)) { logMsg += "\n\t\tmacOS Read-Write Texture Tier 2"; } -#endif -#endif - -#if MVK_MACCAT - if ([_mtlDevice respondsToSelector: @selector(readWriteTextureSupport)] && - _mtlDevice.readWriteTextureSupport == MTLReadWriteTextureTier2) { - logMsg += "\n\t\tmacOS Read-Write Texture Tier 2"; - } -#endif + logMsg += "\n\t\tRead-Write Texture Tier "; + logMsg += ([_mtlDevice respondsToSelector: @selector(readWriteTextureSupport)] && + _mtlDevice.readWriteTextureSupport == MTLReadWriteTextureTier2) ? "2" : "1"; string devTypeStr; switch (_properties.deviceType) { @@ -5347,14 +5258,3 @@ uint64_t mvkGetLocationID(id mtlDevice) { return hash; } - -// If the supportsBCTextureCompression query is available, use it. -// Otherwise only macOS supports BC compression. -bool mvkSupportsBCTextureCompression(id mtlDevice) { -#if MVK_XCODE_14_3 || (MVK_XCODE_12 && MVK_MACOS && !MVK_MACCAT) - if ([mtlDevice respondsToSelector: @selector(supportsBCTextureCompression)]) { - return mtlDevice.supportsBCTextureCompression; - } -#endif - return MVK_MACOS && !MVK_MACCAT; -} diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm index 688c01bb2..7200bd8d0 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm @@ -63,12 +63,8 @@ mtlTexDesc.textureType = MTLTextureType2DMultisample; mtlTexDesc.sampleCount = sampleCount; } -#if MVK_IOS - if ([getMTLDevice() supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily1_v3]) { - mtlTexDesc.storageMode = MTLStorageModeMemoryless; - } else { - mtlTexDesc.storageMode = MTLStorageModePrivate; - } +#if !MVK_MACOS || MVK_XCODE_12 + mtlTexDesc.storageMode = MTLStorageModeMemoryless; #else mtlTexDesc.storageMode = MTLStorageModePrivate; #endif diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h index 59bf29e34..66ae774fd 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h @@ -28,6 +28,7 @@ #import class MVKPhysicalDevice; +struct MVKMTLDeviceCapabilities; #pragma mark - @@ -409,35 +410,21 @@ class MVKPixelFormats : public MVKBaseObject { MVKVkFormatDesc& getVkFormatDesc(VkFormat vkFormat); MVKVkFormatDesc& getVkFormatDesc(MTLPixelFormat mtlFormat); MVKMTLFormatDesc& getMTLPixelFormatDesc(MTLPixelFormat mtlFormat); + MVKMTLFmtCaps& getMTLPixelFormatCapsIf(MTLPixelFormat mtlPixFmt, bool cond); MVKMTLFormatDesc& getMTLVertexFormatDesc(MTLVertexFormat mtlFormat); id getMTLDevice(); void initVkFormatCapabilities(); - void initMTLPixelFormatCapabilities(); - void initMTLVertexFormatCapabilities(); - void buildVkFormatMaps(id mtlDevice); - void setFormatProperties(id mtlDevice, MVKVkFormatDesc& vkDesc); - void modifyMTLFormatCapabilities(id mtlDevice); - void addMTLPixelFormatCapabilities(id mtlDevice, - MTLFeatureSet mtlFeatSet, - MTLPixelFormat mtlPixFmt, - MVKMTLFmtCaps mtlFmtCaps); - void addMTLPixelFormatCapabilities(id mtlDevice, - MTLGPUFamily gpuFamily, - MVKOSVersion minOSVer, - MTLPixelFormat mtlPixFmt, - MVKMTLFmtCaps mtlFmtCaps); - void disableMTLPixelFormatCapabilities(MTLPixelFormat mtlPixFmt, - MVKMTLFmtCaps mtlFmtCaps); - void disableAllMTLPixelFormatCapabilities(MTLPixelFormat mtlPixFmt); - void addMTLVertexFormatCapabilities(id mtlDevice, - MTLFeatureSet mtlFeatSet, - MTLVertexFormat mtlVtxFmt, - MVKMTLFmtCaps mtlFmtCaps); - void addMTLVertexFormatCapabilities(id mtlDevice, - MTLGPUFamily gpuFamily, - MVKOSVersion minOSVer, - MTLVertexFormat mtlVtxFmt, - MVKMTLFmtCaps mtlFmtCaps); + void initMTLPixelFormatCapabilities(const MVKMTLDeviceCapabilities& gpuCaps); + void initMTLVertexFormatCapabilities(const MVKMTLDeviceCapabilities& gpuCaps); + void modifyMTLFormatCapabilities(const MVKMTLDeviceCapabilities& gpuCaps); + void buildVkFormatMaps(const MVKMTLDeviceCapabilities& gpuCaps); + void setFormatProperties(MVKVkFormatDesc& vkDesc, const MVKMTLDeviceCapabilities& gpuCaps); + void addMTLPixelFormatDescImpl(MTLPixelFormat mtlPixFmt, MTLPixelFormat mtlPixFmtLinear, + MVKMTLViewClass viewClass, MVKMTLFmtCaps fmtCaps, const char* name); + void addValidatedMTLPixelFormatDesc(MTLPixelFormat mtlPixFmt, MTLPixelFormat mtlPixFmtLinear, + MVKMTLViewClass viewClass, MVKMTLFmtCaps appleGPUCaps, MVKMTLFmtCaps macGPUCaps, + const MVKMTLDeviceCapabilities& mtlDevCaps, const char* name); + void addMTLVertexFormatDescImpl(MTLVertexFormat mtlVtxFmt, MVKMTLFmtCaps vtxCap, const char* name); MVKPhysicalDevice* _physicalDevice; MVKInflectionMap _vkFormatDescriptions; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm index 02a1461da..6adc31a86 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm @@ -137,7 +137,6 @@ # define MTLPixelFormatX24_Stencil8 MTLPixelFormatInvalid #endif - #if MVK_TVOS # define MTLPixelFormatASTC_4x4_HDR MTLPixelFormatInvalid # define MTLPixelFormatASTC_5x4_HDR MTLPixelFormatInvalid @@ -642,24 +641,24 @@ case kMVKFormatColorUInt8: case kMVKFormatColorUInt16: case kMVKFormatColorUInt32: - mtlClr.red = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 0, inverseMap.r); - mtlClr.green = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 1, inverseMap.g); - mtlClr.blue = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 2, inverseMap.b); - mtlClr.alpha = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 3, inverseMap.a); + mtlClr.red = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 0, inverseMap.r); + mtlClr.green = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 1, inverseMap.g); + mtlClr.blue = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 2, inverseMap.b); + mtlClr.alpha = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 3, inverseMap.a); break; case kMVKFormatColorInt8: case kMVKFormatColorInt16: case kMVKFormatColorInt32: - mtlClr.red = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 0, inverseMap.r); - mtlClr.green = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 1, inverseMap.g); - mtlClr.blue = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 2, inverseMap.b); - mtlClr.alpha = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 3, inverseMap.a); + mtlClr.red = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 0, inverseMap.r); + mtlClr.green = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 1, inverseMap.g); + mtlClr.blue = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 2, inverseMap.b); + mtlClr.alpha = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 3, inverseMap.a); break; default: - mtlClr.red = 0.0; - mtlClr.green = 0.0; - mtlClr.blue = 0.0; - mtlClr.alpha = 1.0; + mtlClr.red = 0.0; + mtlClr.green = 0.0; + mtlClr.blue = 0.0; + mtlClr.alpha = 1.0; break; } return mtlClr; @@ -819,16 +818,16 @@ MVKPixelFormats::MVKPixelFormats(MVKPhysicalDevice* physicalDevice) : _physicalDevice(physicalDevice) { - auto* mtlDev = getMTLDevice(); + const auto& gpuCaps = _physicalDevice ? _physicalDevice->getMTLDeviceCapabilities() : MVKMTLDeviceCapabilities(getMTLDevice()); // Build and update the Metal formats - initMTLPixelFormatCapabilities(); - initMTLVertexFormatCapabilities(); - modifyMTLFormatCapabilities(mtlDev); + initMTLPixelFormatCapabilities(gpuCaps); + initMTLVertexFormatCapabilities(gpuCaps); + modifyMTLFormatCapabilities(gpuCaps); // Build the Vulkan formats and link them to the Metal formats initVkFormatCapabilities(); - buildVkFormatMaps(mtlDev); + buildVkFormatMaps(gpuCaps); } // Call this sparsely. If there is no physical device, this operation may be costly. @@ -862,7 +861,7 @@ void MVKPixelFormats::initVkFormatCapabilities() { VkFormat vkFmt; - _vkFormatDescriptions.reserve(512); // High estimate to future-proof against allocations as elements are added. shrink_to_fit() below will collapse. + _vkFormatDescriptions.reserve(KIBI); // High estimate to future-proof against allocations as elements are added. shrink_to_fit() below will collapse. // UNDEFINED must come first. addVkFormatDesc( UNDEFINED, Invalid, Invalid, Invalid, Invalid, 1, 1, 0, None ); @@ -1156,31 +1155,49 @@ _vkFormatDescriptions.shrink_to_fit(); } -#define addMTLPixelFormatDescFull(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS, MTL_FMT_LINEAR) \ - mtlPixFmt = MTLPixelFormat ##MTL_FMT; \ - _mtlPixelFormatDescriptions[mtlPixFmt] = { .mtlPixelFormat = mtlPixFmt, VK_FORMAT_UNDEFINED, \ - mvkSelectPlatformValue(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS), \ - MVKMTLViewClass:: VIEW_CLASS, MTLPixelFormat ##MTL_FMT_LINEAR, "MTLPixelFormat" #MTL_FMT } +void MVKPixelFormats::addMTLPixelFormatDescImpl(MTLPixelFormat mtlPixFmt, MTLPixelFormat mtlPixFmtLinear, + MVKMTLViewClass viewClass, MVKMTLFmtCaps fmtCaps, const char* name) { + _mtlPixelFormatDescriptions[mtlPixFmt] = { .mtlPixelFormat = mtlPixFmt, VK_FORMAT_UNDEFINED, fmtCaps, viewClass, mtlPixFmtLinear, name }; +} + +// Verify mtlFmt exists on platform, to avoid overwriting the MTLPixelFormatInvalid entry. +// Select the appropriate capabilities for the GPU. Apple Silicon on Mac is a blend of both Apple and Mac caps. +void MVKPixelFormats::addValidatedMTLPixelFormatDesc(MTLPixelFormat mtlPixFmt, MTLPixelFormat mtlPixFmtLinear, + MVKMTLViewClass viewClass, MVKMTLFmtCaps appleGPUCaps, MVKMTLFmtCaps macGPUCaps, + const MVKMTLDeviceCapabilities& mtlDevCaps, const char* name) { + if ( !mtlPixFmt) { return; } + + MVKMTLFmtCaps fmtCaps = kMVKMTLFmtCapsNone; + if (mtlDevCaps.isAppleGPU && mtlDevCaps.supportsMac1) { + mvkEnableFlags(fmtCaps, appleGPUCaps); + mvkEnableFlags(fmtCaps, macGPUCaps); + } else { + fmtCaps = mtlDevCaps.isAppleGPU ? appleGPUCaps : macGPUCaps; + } + addMTLPixelFormatDescImpl(mtlPixFmt, mtlPixFmtLinear, viewClass, fmtCaps, name); +} -#define addMTLPixelFormatDesc(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS) \ - addMTLPixelFormatDescFull(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS, MTL_FMT) +#define addMTLPixelFormatDescFull(mtlFmt, mtlFmtLinear, viewClass, appleGPUCaps, macGPUCaps) \ + addValidatedMTLPixelFormatDesc(MTLPixelFormat ##mtlFmt, MTLPixelFormat ##mtlFmtLinear, MVKMTLViewClass:: viewClass, \ + kMVKMTLFmtCaps ##appleGPUCaps, kMVKMTLFmtCaps ##macGPUCaps, gpuCaps, "MTLPixelFormat" #mtlFmt) -#define addMTLPixelFormatDescSRGB(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS, MTL_FMT_LINEAR) \ - addMTLPixelFormatDescFull(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS, MTL_FMT_LINEAR) +#define addMTLPixelFormatDesc(mtlFmt, viewClass, appleGPUCaps, macGPUCaps) \ + addMTLPixelFormatDescFull(mtlFmt, mtlFmt, viewClass, appleGPUCaps, macGPUCaps) +#define addMTLPixelFormatDescSRGB(mtlFmt, viewClass, appleGPUCaps, macGPUCaps, mtlFmtLinear) \ + addMTLPixelFormatDescFull(mtlFmt, mtlFmtLinear, viewClass, appleGPUCaps, macGPUCaps) -void MVKPixelFormats::initMTLPixelFormatCapabilities() { - MTLPixelFormat mtlPixFmt; - _mtlPixelFormatDescriptions.reserve(512); // High estimate to future-proof against allocations as elements are added. shrink_to_fit() below will collapse. +void MVKPixelFormats::initMTLPixelFormatCapabilities(const MVKMTLDeviceCapabilities& gpuCaps) { + _mtlPixelFormatDescriptions.reserve(KIBI); // High estimate to future-proof against allocations as elements are added. shrink_to_fit() below will collapse. - // MTLPixelFormatInvalid must come first. - addMTLPixelFormatDesc ( Invalid, None, None, None ); + // MTLPixelFormatInvalid must come first. Use addMTLPixelFormatDescImpl to avoid guard code. + addMTLPixelFormatDescImpl( MTLPixelFormatInvalid, MTLPixelFormatInvalid, MVKMTLViewClass::None, kMVKMTLFmtCapsNone, "MTLPixelFormatInvalid" ); // Ordinary 8-bit pixel formats - addMTLPixelFormatDesc ( A8Unorm, Color8, RF, RF ); + addMTLPixelFormatDesc ( A8Unorm, Color8, All, All ); addMTLPixelFormatDesc ( R8Unorm, Color8, All, All ); - addMTLPixelFormatDescSRGB( R8Unorm_sRGB, Color8, RFCMRB, None, R8Unorm ); - addMTLPixelFormatDesc ( R8Snorm, Color8, RFWCMB, All ); + addMTLPixelFormatDescSRGB( R8Unorm_sRGB, Color8, All, None, R8Unorm ); + addMTLPixelFormatDesc ( R8Snorm, Color8, All, All ); addMTLPixelFormatDesc ( R8Uint, Color8, RWCM, RWCM ); addMTLPixelFormatDesc ( R8Sint, Color8, RWCM, RWCM ); @@ -1192,8 +1209,8 @@ addMTLPixelFormatDesc ( R16Float, Color16, All, All ); addMTLPixelFormatDesc ( RG8Unorm, Color16, All, All ); - addMTLPixelFormatDescSRGB( RG8Unorm_sRGB, Color16, RFCMRB, None, RG8Unorm ); - addMTLPixelFormatDesc ( RG8Snorm, Color16, RFWCMB, All ); + addMTLPixelFormatDescSRGB( RG8Unorm_sRGB, Color16, All, None, RG8Unorm ); + addMTLPixelFormatDesc ( RG8Snorm, Color16, All, All ); addMTLPixelFormatDesc ( RG8Uint, Color16, RWCM, RWCM ); addMTLPixelFormatDesc ( RG8Sint, Color16, RWCM, RWCM ); @@ -1204,9 +1221,9 @@ addMTLPixelFormatDesc ( BGR5A1Unorm, Color16, RFCMRB, None ); // Ordinary 32-bit pixel formats - addMTLPixelFormatDesc ( R32Uint, Color32, RC, RWCM ); - addMTLPixelFormatDesc ( R32Sint, Color32, RC, RWCM ); - addMTLPixelFormatDesc ( R32Float, Color32, RCMB, All ); + addMTLPixelFormatDesc ( R32Uint, Color32, RWC, RWCM ); + addMTLPixelFormatDesc ( R32Sint, Color32, RWC, RWCM ); + addMTLPixelFormatDesc ( R32Float, Color32, All, All ); addMTLPixelFormatDesc ( RG16Unorm, Color32, RFWCMB, All ); addMTLPixelFormatDesc ( RG16Snorm, Color32, RFWCMB, All ); @@ -1215,24 +1232,25 @@ addMTLPixelFormatDesc ( RG16Float, Color32, All, All ); addMTLPixelFormatDesc ( RGBA8Unorm, Color32, All, All ); - addMTLPixelFormatDescSRGB( RGBA8Unorm_sRGB, Color32, RFCMRB, RFCMRB, RGBA8Unorm ); - addMTLPixelFormatDesc ( RGBA8Snorm, Color32, RFWCMB, All ); + addMTLPixelFormatDescSRGB( RGBA8Unorm_sRGB, Color32, All, RFCMRB, RGBA8Unorm ); + addMTLPixelFormatDesc ( RGBA8Snorm, Color32, All, All ); addMTLPixelFormatDesc ( RGBA8Uint, Color32, RWCM, RWCM ); addMTLPixelFormatDesc ( RGBA8Sint, Color32, RWCM, RWCM ); addMTLPixelFormatDesc ( BGRA8Unorm, Color32, All, All ); - addMTLPixelFormatDescSRGB( BGRA8Unorm_sRGB, Color32, RFCMRB, RFCMRB, BGRA8Unorm ); + addMTLPixelFormatDescSRGB( BGRA8Unorm_sRGB, Color32, All, RFCMRB, BGRA8Unorm ); // Packed 32-bit pixel formats - addMTLPixelFormatDesc ( RGB10A2Unorm, Color32, RFCMRB, All ); - addMTLPixelFormatDesc ( RGB10A2Uint, Color32, RCM, RWCM ); - addMTLPixelFormatDesc ( RG11B10Float, Color32, RFCMRB, All ); - addMTLPixelFormatDesc ( RGB9E5Float, Color32, RFCMRB, RF ); + addMTLPixelFormatDesc ( RGB10A2Unorm, Color32, All, All ); + addMTLPixelFormatDesc ( BGR10A2Unorm, Color32, All, All ); + addMTLPixelFormatDesc ( RGB10A2Uint, Color32, RWCM, RWCM ); + addMTLPixelFormatDesc ( RG11B10Float, Color32, All, All ); + addMTLPixelFormatDesc ( RGB9E5Float, Color32, All, RF ); // Ordinary 64-bit pixel formats - addMTLPixelFormatDesc ( RG32Uint, Color64, RC, RWCM ); - addMTLPixelFormatDesc ( RG32Sint, Color64, RC, RWCM ); - addMTLPixelFormatDesc ( RG32Float, Color64, RCB, All ); + addMTLPixelFormatDesc ( RG32Uint, Color64, RWCM, RWCM ); + addMTLPixelFormatDesc ( RG32Sint, Color64, RWCM, RWCM ); + addMTLPixelFormatDesc ( RG32Float, Color64, All, All ); addMTLPixelFormatDesc ( RGBA16Unorm, Color64, RFWCMB, All ); addMTLPixelFormatDesc ( RGBA16Snorm, Color64, RFWCMB, All ); @@ -1241,9 +1259,9 @@ addMTLPixelFormatDesc ( RGBA16Float, Color64, All, All ); // Ordinary 128-bit pixel formats - addMTLPixelFormatDesc ( RGBA32Uint, Color128, RC, RWCM ); - addMTLPixelFormatDesc ( RGBA32Sint, Color128, RC, RWCM ); - addMTLPixelFormatDesc ( RGBA32Float, Color128, RC, All ); + addMTLPixelFormatDesc ( RGBA32Uint, Color128, RWC, RWCM ); + addMTLPixelFormatDesc ( RGBA32Sint, Color128, RWC, RWCM ); + addMTLPixelFormatDesc ( RGBA32Float, Color128, All, All ); // Compressed pixel formats addMTLPixelFormatDesc ( PVRTC_RGBA_2BPP, PVRTC_RGBA_2BPP, RF, None ); @@ -1262,48 +1280,48 @@ addMTLPixelFormatDesc ( EAC_RG11Unorm, EAC_RG11, RF, None ); addMTLPixelFormatDesc ( EAC_RG11Snorm, EAC_RG11, RF, None ); - addMTLPixelFormatDesc ( ASTC_4x4_LDR, ASTC_4x4, None, None ); - addMTLPixelFormatDescSRGB( ASTC_4x4_sRGB, ASTC_4x4, None, None, ASTC_4x4_LDR ); - addMTLPixelFormatDesc ( ASTC_4x4_HDR, ASTC_4x4, None, None ); - addMTLPixelFormatDesc ( ASTC_5x4_LDR, ASTC_5x4, None, None ); - addMTLPixelFormatDescSRGB( ASTC_5x4_sRGB, ASTC_5x4, None, None, ASTC_5x4_LDR ); - addMTLPixelFormatDesc ( ASTC_5x4_HDR, ASTC_5x4, None, None ); - addMTLPixelFormatDesc ( ASTC_5x5_LDR, ASTC_5x5, None, None ); - addMTLPixelFormatDescSRGB( ASTC_5x5_sRGB, ASTC_5x5, None, None, ASTC_5x5_LDR ); - addMTLPixelFormatDesc ( ASTC_5x5_HDR, ASTC_5x5, None, None ); - addMTLPixelFormatDesc ( ASTC_6x5_LDR, ASTC_6x5, None, None ); - addMTLPixelFormatDescSRGB( ASTC_6x5_sRGB, ASTC_6x5, None, None, ASTC_6x5_LDR ); - addMTLPixelFormatDesc ( ASTC_6x5_HDR, ASTC_6x5, None, None ); - addMTLPixelFormatDesc ( ASTC_6x6_LDR, ASTC_6x6, None, None ); - addMTLPixelFormatDescSRGB( ASTC_6x6_sRGB, ASTC_6x6, None, None, ASTC_6x6_LDR ); - addMTLPixelFormatDesc ( ASTC_6x6_HDR, ASTC_6x6, None, None ); - addMTLPixelFormatDesc ( ASTC_8x5_LDR, ASTC_8x5, None, None ); - addMTLPixelFormatDescSRGB( ASTC_8x5_sRGB, ASTC_8x5, None, None, ASTC_8x5_LDR ); - addMTLPixelFormatDesc ( ASTC_8x5_HDR, ASTC_8x5, None, None ); - addMTLPixelFormatDesc ( ASTC_8x6_LDR, ASTC_8x6, None, None ); - addMTLPixelFormatDescSRGB( ASTC_8x6_sRGB, ASTC_8x6, None, None, ASTC_8x6_LDR ); - addMTLPixelFormatDesc ( ASTC_8x6_HDR, ASTC_8x6, None, None ); - addMTLPixelFormatDesc ( ASTC_8x8_LDR, ASTC_8x8, None, None ); - addMTLPixelFormatDescSRGB( ASTC_8x8_sRGB, ASTC_8x8, None, None, ASTC_8x8_LDR ); - addMTLPixelFormatDesc ( ASTC_8x8_HDR, ASTC_8x8, None, None ); - addMTLPixelFormatDesc ( ASTC_10x5_LDR, ASTC_10x5, None, None ); - addMTLPixelFormatDescSRGB( ASTC_10x5_sRGB, ASTC_10x5, None, None, ASTC_10x5_LDR ); - addMTLPixelFormatDesc ( ASTC_10x5_HDR, ASTC_10x5, None, None ); - addMTLPixelFormatDesc ( ASTC_10x6_LDR, ASTC_10x6, None, None ); - addMTLPixelFormatDescSRGB( ASTC_10x6_sRGB, ASTC_10x6, None, None, ASTC_10x6_LDR ); - addMTLPixelFormatDesc ( ASTC_10x6_HDR, ASTC_10x6, None, None ); - addMTLPixelFormatDesc ( ASTC_10x8_LDR, ASTC_10x8, None, None ); - addMTLPixelFormatDescSRGB( ASTC_10x8_sRGB, ASTC_10x8, None, None, ASTC_10x8_LDR ); - addMTLPixelFormatDesc ( ASTC_10x8_HDR, ASTC_10x8, None, None ); - addMTLPixelFormatDesc ( ASTC_10x10_LDR, ASTC_10x10, None, None ); - addMTLPixelFormatDescSRGB( ASTC_10x10_sRGB, ASTC_10x10, None, None, ASTC_10x10_LDR ); - addMTLPixelFormatDesc ( ASTC_10x10_HDR, ASTC_10x10, None, None ); - addMTLPixelFormatDesc ( ASTC_12x10_LDR, ASTC_12x10, None, None ); - addMTLPixelFormatDescSRGB( ASTC_12x10_sRGB, ASTC_12x10, None, None, ASTC_12x10_LDR ); - addMTLPixelFormatDesc ( ASTC_12x10_HDR, ASTC_12x10, None, None ); - addMTLPixelFormatDesc ( ASTC_12x12_LDR, ASTC_12x12, None, None ); - addMTLPixelFormatDescSRGB( ASTC_12x12_sRGB, ASTC_12x12, None, None, ASTC_12x12_LDR ); - addMTLPixelFormatDesc ( ASTC_12x12_HDR, ASTC_12x12, None, None ); + addMTLPixelFormatDesc ( ASTC_4x4_LDR, ASTC_4x4, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_4x4_sRGB, ASTC_4x4, RF, None, ASTC_4x4_LDR ); + addMTLPixelFormatDesc ( ASTC_4x4_HDR, ASTC_4x4, RF, None ); + addMTLPixelFormatDesc ( ASTC_5x4_LDR, ASTC_5x4, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_5x4_sRGB, ASTC_5x4, RF, None, ASTC_5x4_LDR ); + addMTLPixelFormatDesc ( ASTC_5x4_HDR, ASTC_5x4, RF, None ); + addMTLPixelFormatDesc ( ASTC_5x5_LDR, ASTC_5x5, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_5x5_sRGB, ASTC_5x5, RF, None, ASTC_5x5_LDR ); + addMTLPixelFormatDesc ( ASTC_5x5_HDR, ASTC_5x5, RF, None ); + addMTLPixelFormatDesc ( ASTC_6x5_LDR, ASTC_6x5, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_6x5_sRGB, ASTC_6x5, RF, None, ASTC_6x5_LDR ); + addMTLPixelFormatDesc ( ASTC_6x5_HDR, ASTC_6x5, RF, None ); + addMTLPixelFormatDesc ( ASTC_6x6_LDR, ASTC_6x6, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_6x6_sRGB, ASTC_6x6, RF, None, ASTC_6x6_LDR ); + addMTLPixelFormatDesc ( ASTC_6x6_HDR, ASTC_6x6, RF, None ); + addMTLPixelFormatDesc ( ASTC_8x5_LDR, ASTC_8x5, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_8x5_sRGB, ASTC_8x5, RF, None, ASTC_8x5_LDR ); + addMTLPixelFormatDesc ( ASTC_8x5_HDR, ASTC_8x5, RF, None ); + addMTLPixelFormatDesc ( ASTC_8x6_LDR, ASTC_8x6, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_8x6_sRGB, ASTC_8x6, RF, None, ASTC_8x6_LDR ); + addMTLPixelFormatDesc ( ASTC_8x6_HDR, ASTC_8x6, RF, None ); + addMTLPixelFormatDesc ( ASTC_8x8_LDR, ASTC_8x8, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_8x8_sRGB, ASTC_8x8, RF, None, ASTC_8x8_LDR ); + addMTLPixelFormatDesc ( ASTC_8x8_HDR, ASTC_8x8, RF, None ); + addMTLPixelFormatDesc ( ASTC_10x5_LDR, ASTC_10x5, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_10x5_sRGB, ASTC_10x5, RF, None, ASTC_10x5_LDR ); + addMTLPixelFormatDesc ( ASTC_10x5_HDR, ASTC_10x5, RF, None ); + addMTLPixelFormatDesc ( ASTC_10x6_LDR, ASTC_10x6, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_10x6_sRGB, ASTC_10x6, RF, None, ASTC_10x6_LDR ); + addMTLPixelFormatDesc ( ASTC_10x6_HDR, ASTC_10x6, RF, None ); + addMTLPixelFormatDesc ( ASTC_10x8_LDR, ASTC_10x8, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_10x8_sRGB, ASTC_10x8, RF, None, ASTC_10x8_LDR ); + addMTLPixelFormatDesc ( ASTC_10x8_HDR, ASTC_10x8, RF, None ); + addMTLPixelFormatDesc ( ASTC_10x10_LDR, ASTC_10x10, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_10x10_sRGB, ASTC_10x10, RF, None, ASTC_10x10_LDR ); + addMTLPixelFormatDesc ( ASTC_10x10_HDR, ASTC_10x10, RF, None ); + addMTLPixelFormatDesc ( ASTC_12x10_LDR, ASTC_12x10, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_12x10_sRGB, ASTC_12x10, RF, None, ASTC_12x10_LDR ); + addMTLPixelFormatDesc ( ASTC_12x10_HDR, ASTC_12x10, RF, None ); + addMTLPixelFormatDesc ( ASTC_12x12_LDR, ASTC_12x12, RF, None ); + addMTLPixelFormatDescSRGB( ASTC_12x12_sRGB, ASTC_12x12, RF, None, ASTC_12x12_LDR ); + addMTLPixelFormatDesc ( ASTC_12x12_HDR, ASTC_12x12, RF, None ); addMTLPixelFormatDesc ( BC1_RGBA, BC1_RGBA, RF, RF ); addMTLPixelFormatDescSRGB( BC1_RGBA_sRGB, BC1_RGBA, RF, RF, BC1_RGBA ); @@ -1325,704 +1343,253 @@ addMTLPixelFormatDesc ( BGRG422, None, RF, RF ); // Extended range and wide color pixel formats - addMTLPixelFormatDesc ( BGRA10_XR, BGRA10_XR, None, None ); - addMTLPixelFormatDescSRGB( BGRA10_XR_sRGB, BGRA10_XR, None, None, BGRA10_XR ); - addMTLPixelFormatDesc ( BGR10_XR, BGR10_XR, None, None ); - addMTLPixelFormatDescSRGB( BGR10_XR_sRGB, BGR10_XR, None, None, BGR10_XR ); - addMTLPixelFormatDesc ( BGR10A2Unorm, Color32, None, None ); + addMTLPixelFormatDesc ( BGRA10_XR, BGRA10_XR, All, None ); + addMTLPixelFormatDescSRGB( BGRA10_XR_sRGB, BGRA10_XR, All, None, BGRA10_XR ); + addMTLPixelFormatDesc ( BGR10_XR, BGR10_XR, All, None ); + addMTLPixelFormatDescSRGB( BGR10_XR_sRGB, BGR10_XR, All, None, BGR10_XR ); // Depth and stencil pixel formats - addMTLPixelFormatDesc ( Depth16Unorm, None, None, None ); - addMTLPixelFormatDesc ( Depth32Float, None, DRM, DRFMR ); - addMTLPixelFormatDesc ( Stencil8, None, DRM, DRMR ); - addMTLPixelFormatDesc ( Depth24Unorm_Stencil8, Depth24_Stencil8, None, None ); - addMTLPixelFormatDesc ( Depth32Float_Stencil8, Depth32_Stencil8, DRM, DRFMR ); - addMTLPixelFormatDesc ( X24_Stencil8, Depth24_Stencil8, None, DRMR ); - addMTLPixelFormatDesc ( X32_Stencil8, Depth32_Stencil8, DRM, DRMR ); + addMTLPixelFormatDesc ( Depth16Unorm, None, DRFMR, DRFMR ); + addMTLPixelFormatDesc ( Depth32Float, None, DRMR, DRFMR ); + addMTLPixelFormatDesc ( Stencil8, None, DRM, DRM ); + addMTLPixelFormatDesc ( Depth24Unorm_Stencil8, Depth24_Stencil8, None, DRFMR ); + addMTLPixelFormatDesc ( Depth32Float_Stencil8, Depth32_Stencil8, DRMR, DRFMR ); + addMTLPixelFormatDesc ( X24_Stencil8, Depth24_Stencil8, None, DRM ); + addMTLPixelFormatDesc ( X32_Stencil8, Depth32_Stencil8, DRM, DRM ); _mtlPixelFormatDescriptions.shrink_to_fit(); } // If necessary, resize vector with empty elements -#define addMTLVertexFormatDesc(MTL_VTX_FMT, IOS_CAPS, MACOS_CAPS) \ - mtlVtxFmt = MTLVertexFormat ##MTL_VTX_FMT; \ - if (mtlVtxFmt >= _mtlVertexFormatDescriptions.size()) { _mtlVertexFormatDescriptions.resize(mtlVtxFmt + 1, {}); } \ - _mtlVertexFormatDescriptions[mtlVtxFmt] = { .mtlVertexFormat = mtlVtxFmt, VK_FORMAT_UNDEFINED, \ - mvkSelectPlatformValue(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS), \ - MVKMTLViewClass::None, MTLPixelFormatInvalid, "MTLVertexFormat" #MTL_VTX_FMT }; - -void MVKPixelFormats::initMTLVertexFormatCapabilities() { - MTLVertexFormat mtlVtxFmt; - _mtlVertexFormatDescriptions.resize(MTLVertexFormatHalf + 3, {}); - - addMTLVertexFormatDesc( Invalid, None, None ); // MTLVertexFormatInvalid must come first. - - addMTLVertexFormatDesc( UChar2Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( Char2Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( UChar2, Vertex, Vertex ); - addMTLVertexFormatDesc( Char2, Vertex, Vertex ); - - addMTLVertexFormatDesc( UChar3Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( Char3Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( UChar3, Vertex, Vertex ); - addMTLVertexFormatDesc( Char3, Vertex, Vertex ); - - addMTLVertexFormatDesc( UChar4Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( Char4Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( UChar4, Vertex, Vertex ); - addMTLVertexFormatDesc( Char4, Vertex, Vertex ); - - addMTLVertexFormatDesc( UInt1010102Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( Int1010102Normalized, Vertex, Vertex ); - - addMTLVertexFormatDesc( UShort2Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( Short2Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( UShort2, Vertex, Vertex ); - addMTLVertexFormatDesc( Short2, Vertex, Vertex ); - addMTLVertexFormatDesc( Half2, Vertex, Vertex ); - - addMTLVertexFormatDesc( UShort3Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( Short3Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( UShort3, Vertex, Vertex ); - addMTLVertexFormatDesc( Short3, Vertex, Vertex ); - addMTLVertexFormatDesc( Half3, Vertex, Vertex ); - - addMTLVertexFormatDesc( UShort4Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( Short4Normalized, Vertex, Vertex ); - addMTLVertexFormatDesc( UShort4, Vertex, Vertex ); - addMTLVertexFormatDesc( Short4, Vertex, Vertex ); - addMTLVertexFormatDesc( Half4, Vertex, Vertex ); - - addMTLVertexFormatDesc( UInt, Vertex, Vertex ); - addMTLVertexFormatDesc( Int, Vertex, Vertex ); - addMTLVertexFormatDesc( Float, Vertex, Vertex ); - - addMTLVertexFormatDesc( UInt2, Vertex, Vertex ); - addMTLVertexFormatDesc( Int2, Vertex, Vertex ); - addMTLVertexFormatDesc( Float2, Vertex, Vertex ); - - addMTLVertexFormatDesc( UInt3, Vertex, Vertex ); - addMTLVertexFormatDesc( Int3, Vertex, Vertex ); - addMTLVertexFormatDesc( Float3, Vertex, Vertex ); - - addMTLVertexFormatDesc( UInt4, Vertex, Vertex ); - addMTLVertexFormatDesc( Int4, Vertex, Vertex ); - addMTLVertexFormatDesc( Float4, Vertex, Vertex ); - - addMTLVertexFormatDesc( UCharNormalized, None, None ); - addMTLVertexFormatDesc( CharNormalized, None, None ); - addMTLVertexFormatDesc( UChar, None, None ); - addMTLVertexFormatDesc( Char, None, None ); - - addMTLVertexFormatDesc( UShortNormalized, None, None ); - addMTLVertexFormatDesc( ShortNormalized, None, None ); - addMTLVertexFormatDesc( UShort, None, None ); - addMTLVertexFormatDesc( Short, None, None ); - addMTLVertexFormatDesc( Half, None, None ); - - addMTLVertexFormatDesc( UChar4Normalized_BGRA, None, None ); - -#if MVK_XCODE_15 - addMTLVertexFormatDesc( FloatRG11B10, None, None ); - addMTLVertexFormatDesc( FloatRGB9E5, None, None ); -#endif - - _mtlVertexFormatDescriptions.shrink_to_fit(); +void MVKPixelFormats::addMTLVertexFormatDescImpl(MTLVertexFormat mtlVtxFmt, MVKMTLFmtCaps vtxCap, const char* name) { + if (mtlVtxFmt >= _mtlVertexFormatDescriptions.size()) { _mtlVertexFormatDescriptions.resize(mtlVtxFmt + 1, {}); } + _mtlVertexFormatDescriptions[mtlVtxFmt] = { .mtlVertexFormat = mtlVtxFmt, VK_FORMAT_UNDEFINED, vtxCap, MVKMTLViewClass::None, MTLPixelFormatInvalid, name }; } -// If the device supports the feature set, add additional capabilities to a MTLPixelFormat -void MVKPixelFormats::addMTLPixelFormatCapabilities(id mtlDevice, - MTLFeatureSet mtlFeatSet, - MTLPixelFormat mtlPixFmt, - MVKMTLFmtCaps mtlFmtCaps) { - if ( [mtlDevice supportsFeatureSet: mtlFeatSet] ) { - mvkEnableFlags(getMTLPixelFormatDesc(mtlPixFmt).mtlFmtCaps, mtlFmtCaps); - } -} +// Check mtlVtx exists on platform, to avoid overwriting the MTLVertexFormatInvalid entry. +#define addMTLVertexFormatDesc(mtlVtx) if (MTLVertexFormat ##mtlVtx) { addMTLVertexFormatDescImpl(MTLVertexFormat ##mtlVtx, kMVKMTLFmtCapsVertex, "MTLVertexFormat" #mtlVtx); } -// If the device supports the GPU family, add additional capabilities to a MTLPixelFormat -void MVKPixelFormats::addMTLPixelFormatCapabilities(id mtlDevice, - MTLGPUFamily gpuFamily, - MVKOSVersion minOSVer, - MTLPixelFormat mtlPixFmt, - MVKMTLFmtCaps mtlFmtCaps) { - if (mvkOSVersionIsAtLeast(minOSVer) && - [mtlDevice respondsToSelector: @selector(supportsFamily:)] && - [mtlDevice supportsFamily: gpuFamily]) { - - mvkEnableFlags(getMTLPixelFormatDesc(mtlPixFmt).mtlFmtCaps, mtlFmtCaps); - } -} - - -// Disable capability flags in the Metal pixel format. -void MVKPixelFormats::disableMTLPixelFormatCapabilities(MTLPixelFormat mtlPixFmt, - MVKMTLFmtCaps mtlFmtCaps) { - mvkDisableFlags(getMTLPixelFormatDesc(mtlPixFmt).mtlFmtCaps, mtlFmtCaps); -} - -void MVKPixelFormats::disableAllMTLPixelFormatCapabilities(MTLPixelFormat mtlPixFmt) { - getMTLPixelFormatDesc(mtlPixFmt).mtlFmtCaps = kMVKMTLFmtCapsNone; -} +void MVKPixelFormats::initMTLVertexFormatCapabilities(const MVKMTLDeviceCapabilities& gpuCaps) { + _mtlVertexFormatDescriptions.resize(MTLVertexFormatHalf + 3, {}); -// If the device supports the feature set, add additional capabilities to a MTLVertexFormat -void MVKPixelFormats::addMTLVertexFormatCapabilities(id mtlDevice, - MTLFeatureSet mtlFeatSet, - MTLVertexFormat mtlVtxFmt, - MVKMTLFmtCaps mtlFmtCaps) { - if ( [mtlDevice supportsFeatureSet: mtlFeatSet] ) { - mvkEnableFlags(getMTLVertexFormatDesc(mtlVtxFmt).mtlFmtCaps, mtlFmtCaps); + // MTLVertexFormatInvalid must come first. Use addMTLVertexFormatDescImpl to avoid guard code. + addMTLVertexFormatDescImpl(MTLVertexFormatInvalid, kMVKMTLFmtCapsNone, "MTLVertexFormatInvalid"); + + addMTLVertexFormatDesc( UChar2Normalized ); + addMTLVertexFormatDesc( Char2Normalized ); + addMTLVertexFormatDesc( UChar2 ); + addMTLVertexFormatDesc( Char2 ); + + addMTLVertexFormatDesc( UChar3Normalized ); + addMTLVertexFormatDesc( Char3Normalized ); + addMTLVertexFormatDesc( UChar3 ); + addMTLVertexFormatDesc( Char3 ); + + addMTLVertexFormatDesc( UChar4Normalized ); + addMTLVertexFormatDesc( Char4Normalized ); + addMTLVertexFormatDesc( UChar4 ); + addMTLVertexFormatDesc( Char4 ); + + addMTLVertexFormatDesc( UInt1010102Normalized ); + addMTLVertexFormatDesc( Int1010102Normalized ); + + addMTLVertexFormatDesc( UShort2Normalized ); + addMTLVertexFormatDesc( Short2Normalized ); + addMTLVertexFormatDesc( UShort2 ); + addMTLVertexFormatDesc( Short2 ); + addMTLVertexFormatDesc( Half2 ); + + addMTLVertexFormatDesc( UShort3Normalized ); + addMTLVertexFormatDesc( Short3Normalized ); + addMTLVertexFormatDesc( UShort3 ); + addMTLVertexFormatDesc( Short3 ); + addMTLVertexFormatDesc( Half3 ); + + addMTLVertexFormatDesc( UShort4Normalized ); + addMTLVertexFormatDesc( Short4Normalized ); + addMTLVertexFormatDesc( UShort4 ); + addMTLVertexFormatDesc( Short4 ); + addMTLVertexFormatDesc( Half4 ); + + addMTLVertexFormatDesc( UInt ); + addMTLVertexFormatDesc( Int ); + addMTLVertexFormatDesc( Float ); + + addMTLVertexFormatDesc( UInt2 ); + addMTLVertexFormatDesc( Int2 ); + addMTLVertexFormatDesc( Float2 ); + + addMTLVertexFormatDesc( UInt3 ); + addMTLVertexFormatDesc( Int3 ); + addMTLVertexFormatDesc( Float3 ); + + addMTLVertexFormatDesc( UInt4 ); + addMTLVertexFormatDesc( Int4 ); + addMTLVertexFormatDesc( Float4 ); + + addMTLVertexFormatDesc( UCharNormalized ); + addMTLVertexFormatDesc( CharNormalized ); + addMTLVertexFormatDesc( UChar ); + addMTLVertexFormatDesc( Char ); + + addMTLVertexFormatDesc( UShortNormalized ); + addMTLVertexFormatDesc( ShortNormalized ); + addMTLVertexFormatDesc( UShort ); + addMTLVertexFormatDesc( Short ); + addMTLVertexFormatDesc( Half ); + + addMTLVertexFormatDesc( UChar4Normalized_BGRA ); + + if (gpuCaps.supportsApple5 || gpuCaps.supportsMac2) { + addMTLVertexFormatDesc( FloatRG11B10 ); + addMTLVertexFormatDesc( FloatRGB9E5 ); } + + _mtlVertexFormatDescriptions.shrink_to_fit(); } -// If the device supports the GPU family, add additional capabilities to a MTLVertexFormat -void MVKPixelFormats::addMTLVertexFormatCapabilities(id mtlDevice, - MTLGPUFamily gpuFamily, - MVKOSVersion minOSVer, - MTLVertexFormat mtlVtxFmt, - MVKMTLFmtCaps mtlFmtCaps) { - if (mvkOSVersionIsAtLeast(minOSVer) && - [mtlDevice respondsToSelector: @selector(supportsFamily:)] && - [mtlDevice supportsFamily: gpuFamily]) { - - mvkEnableFlags(getMTLVertexFormatDesc(mtlVtxFmt).mtlFmtCaps, mtlFmtCaps); +// Return a reference to the format capabilities, so the caller can manipulate them. +// Check mtlPixFmt exists on platform, to avoid overwriting the MTLPixelFormatInvalid entry. +// When returning the dummy, reset it on each access because it can be written to by caller. +MVKMTLFmtCaps& MVKPixelFormats::getMTLPixelFormatCapsIf(MTLPixelFormat mtlPixFmt, bool cond) { + static MVKMTLFmtCaps dummyFmtCaps; + if (mtlPixFmt && cond) { + return getMTLPixelFormatDesc(mtlPixFmt).mtlFmtCaps; + } else { + dummyFmtCaps = kMVKMTLFmtCapsNone; + return dummyFmtCaps; } } -// Mac Catalyst does not support feature sets, so we redefine them to GPU families in MVKDevice.h. -#if MVK_MACCAT -#define addFeatSetMTLPixFmtCaps(FEAT_SET, MTL_FMT, CAPS) \ - addMTLPixelFormatCapabilities(mtlDevice, MTLFeatureSet_ ##FEAT_SET, 11.0, MTLPixelFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) - -#define addFeatSetMTLVtxFmtCaps(FEAT_SET, MTL_FMT, CAPS) \ - addMTLVertexFormatCapabilities(mtlDevice, MTLFeatureSet_ ##FEAT_SET, 11.0, MTLVertexFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) - -#else -#define addFeatSetMTLPixFmtCaps(FEAT_SET, MTL_FMT, CAPS) \ - addMTLPixelFormatCapabilities(mtlDevice, MTLFeatureSet_ ##FEAT_SET, MTLPixelFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) - -#define addFeatSetMTLVtxFmtCaps(FEAT_SET, MTL_FMT, CAPS) \ - addMTLVertexFormatCapabilities(mtlDevice, MTLFeatureSet_ ##FEAT_SET, MTLVertexFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) - -#endif - -#define addGPUOSMTLPixFmtCaps(GPU_FAM, OS_VER, MTL_FMT, CAPS) \ - addMTLPixelFormatCapabilities(mtlDevice, MTLGPUFamily ##GPU_FAM, OS_VER, MTLPixelFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) +#define setMTLPixFmtCapsIf(cond, mtlFmt, caps) getMTLPixelFormatCapsIf(MTLPixelFormat ##mtlFmt, cond) = kMVKMTLFmtCaps ##caps; +#define setMTLPixFmtCapsIfGPU(gpuFam, mtlFmt, caps) setMTLPixFmtCapsIf(gpuCaps.supports ##gpuFam, mtlFmt, caps) -#define disableAllMTLPixFmtCaps(MTL_FMT) \ - disableAllMTLPixelFormatCapabilities(MTLPixelFormat ##MTL_FMT) +#define enableMTLPixFmtCapsIf(cond, mtlFmt, caps) mvkEnableFlags(getMTLPixelFormatCapsIf(MTLPixelFormat ##mtlFmt, cond), kMVKMTLFmtCaps ##caps); +#define enableMTLPixFmtCapsIfGPU(gpuFam, mtlFmt, caps) enableMTLPixFmtCapsIf(gpuCaps.supports ##gpuFam, mtlFmt, caps) -#define disableMTLPixFmtCaps(MTL_FMT, CAPS) \ - disableMTLPixelFormatCapabilities(MTLPixelFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) - -#define addGPUOSMTLVtxFmtCaps(GPU_FAM, OS_VER, MTL_FMT, CAPS) \ - addMTLVertexFormatCapabilities(mtlDevice, MTLGPUFamily ##GPU_FAM, OS_VER, MTLVertexFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) +#define disableMTLPixFmtCapsIf(cond, mtlFmt, caps) mvkDisableFlags(getMTLPixelFormatCapsIf(MTLPixelFormat ##mtlFmt, cond), kMVKMTLFmtCaps ##caps); +#define disableMTLPixFmtCapsIfGPU(gpuFam, mtlFmt, caps) disableMTLPixFmtCapsIf(gpuCaps.supports ##gpuFam, mtlFmt, caps) // Modifies the format capability tables based on the capabilities of the specific MTLDevice -void MVKPixelFormats::modifyMTLFormatCapabilities(id mtlDevice) { - if ( !mvkSupportsBCTextureCompression(mtlDevice) ) { - disableAllMTLPixFmtCaps( BC1_RGBA ); - disableAllMTLPixFmtCaps( BC1_RGBA_sRGB ); - disableAllMTLPixFmtCaps( BC2_RGBA ); - disableAllMTLPixFmtCaps( BC2_RGBA_sRGB ); - disableAllMTLPixFmtCaps( BC3_RGBA ); - disableAllMTLPixFmtCaps( BC3_RGBA_sRGB ); - disableAllMTLPixFmtCaps( BC4_RUnorm ); - disableAllMTLPixFmtCaps( BC4_RSnorm ); - disableAllMTLPixFmtCaps( BC5_RGUnorm ); - disableAllMTLPixFmtCaps( BC5_RGSnorm ); - disableAllMTLPixFmtCaps( BC6H_RGBUfloat ); - disableAllMTLPixFmtCaps( BC6H_RGBFloat ); - disableAllMTLPixFmtCaps( BC7_RGBAUnorm ); - disableAllMTLPixFmtCaps( BC7_RGBAUnorm_sRGB ); - } -#if MVK_XCODE_12 - if ([mtlDevice respondsToSelector: @selector(supports32BitMSAA)] && - !mtlDevice.supports32BitMSAA) { - - disableMTLPixFmtCaps( R32Uint, MSAA ); - disableMTLPixFmtCaps( R32Uint, Resolve ); - disableMTLPixFmtCaps( R32Sint, MSAA ); - disableMTLPixFmtCaps( R32Sint, Resolve ); - disableMTLPixFmtCaps( R32Float, MSAA ); - disableMTLPixFmtCaps( R32Float, Resolve ); - disableMTLPixFmtCaps( RG32Uint, MSAA ); - disableMTLPixFmtCaps( RG32Uint, Resolve ); - disableMTLPixFmtCaps( RG32Sint, MSAA ); - disableMTLPixFmtCaps( RG32Sint, Resolve ); - disableMTLPixFmtCaps( RG32Float, MSAA ); - disableMTLPixFmtCaps( RG32Float, Resolve ); - disableMTLPixFmtCaps( RGBA32Uint, MSAA ); - disableMTLPixFmtCaps( RGBA32Uint, Resolve ); - disableMTLPixFmtCaps( RGBA32Sint, MSAA ); - disableMTLPixFmtCaps( RGBA32Sint, Resolve ); - disableMTLPixFmtCaps( RGBA32Float, MSAA ); - disableMTLPixFmtCaps( RGBA32Float, Resolve ); - } - - if ([mtlDevice respondsToSelector: @selector(supports32BitFloatFiltering)] && - !mtlDevice.supports32BitFloatFiltering) { - - disableMTLPixFmtCaps( R32Float, Filter ); - disableMTLPixFmtCaps( RG32Float, Filter ); - disableMTLPixFmtCaps( RGBA32Float, Filter ); - } -#endif - -#if MVK_MACOS - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, R32Uint, Atomic ); - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, R32Sint, Atomic ); - - if (mtlDevice.isDepth24Stencil8PixelFormatSupported) { - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, Depth24Unorm_Stencil8, DRFMR ); - } - - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v2, Depth16Unorm, DRFMR ); - - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v3, BGR10A2Unorm, RFCMRB ); - -#if MVK_XCODE_12 - addGPUOSMTLPixFmtCaps( Apple5, 11.0, R8Unorm_sRGB, All ); - - addGPUOSMTLPixFmtCaps( Apple5, 11.0, RG8Unorm_sRGB, All ); - - addGPUOSMTLPixFmtCaps( Apple5, 11.0, B5G6R5Unorm, RFCMRB ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, A1BGR5Unorm, RFCMRB ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ABGR4Unorm, RFCMRB ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGR5A1Unorm, RFCMRB ); - - addGPUOSMTLPixFmtCaps( Apple5, 11.0, RGBA8Unorm_sRGB, All ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGRA8Unorm_sRGB, All ); - - // Blending is actually supported for this format, but format channels cannot be individually write-enabled during blending. - // Disabling blending is the least-intrusive way to handle this in a Vulkan-friendly way. - addGPUOSMTLPixFmtCaps( Apple5, 11.0, RGB9E5Float, All ); - disableMTLPixFmtCaps ( RGB9E5Float, Blend); - - addGPUOSMTLPixFmtCaps( Apple5, 11.0, PVRTC_RGBA_2BPP, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, PVRTC_RGBA_2BPP_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, PVRTC_RGBA_4BPP, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, PVRTC_RGBA_4BPP_sRGB, RF ); - - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ETC2_RGB8, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ETC2_RGB8_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ETC2_RGB8A1, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ETC2_RGB8A1_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_RGBA8, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_RGBA8_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_R11Unorm, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_R11Snorm, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_RG11Unorm, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_RG11Snorm, RF ); - - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_4x4_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_4x4_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_4x4_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_5x4_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_5x4_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_5x4_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_5x5_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_5x5_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_5x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_6x5_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_6x5_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_6x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_6x6_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_6x6_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_6x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x5_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x5_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_8x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x6_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x6_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_8x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x8_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x8_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_8x8_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x5_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x5_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_10x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x6_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x6_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_10x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x8_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x8_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_10x8_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x10_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x10_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_10x10_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_12x10_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_12x10_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_12x10_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_12x12_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_12x12_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_12x12_HDR, RF ); - - addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGRA10_XR, All ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGRA10_XR_sRGB, All ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGR10_XR, All ); - addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGR10_XR_sRGB, All ); -#endif - -#if MVK_XCODE_15 - addGPUOSMTLPixFmtCaps( Apple9, 14.0, R32Float, All ); - addGPUOSMTLPixFmtCaps( Apple9, 14.0, RG32Float, All ); - addGPUOSMTLPixFmtCaps( Apple9, 14.0, RGBA32Float, All ); -#endif - - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, UCharNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, CharNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, UChar, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, Char, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, UShortNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, ShortNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, UShort, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, Short, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, Half, Vertex ); - addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, UChar4Normalized_BGRA, Vertex ); - -#if MVK_XCODE_15 - addGPUOSMTLVtxFmtCaps( Apple5, 14.0, FloatRG11B10, Vertex ); - addGPUOSMTLVtxFmtCaps( Apple5, 14.0, FloatRGB9E5, Vertex ); -#endif -#endif - -#if MVK_TVOS - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v2, R8Unorm_sRGB, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, R8Unorm_sRGB, All ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v2, R8Snorm, All ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v2, RG8Unorm_sRGB, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, RG8Unorm_sRGB, All ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RG8Snorm, All ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RGBA8Snorm, All ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, R32Uint, RWC ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, R32Uint, Atomic ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, R32Sint, RWC ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, R32Sint, Atomic ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, R32Float, RWCMB ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v2, RGBA8Unorm_sRGB, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, RGBA8Unorm_sRGB, All ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v2, BGRA8Unorm_sRGB, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGRA8Unorm_sRGB, All ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, RGB10A2Unorm, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, RGB10A2Uint, RWCM ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, RG11B10Float, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, RGB9E5Float, All ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RG32Uint, RWC ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RG32Sint, RWC ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RG32Float, RWCB ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RGBA32Uint, RWC ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RGBA32Sint, RWC ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RGBA32Float, RWC ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_4x4_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_4x4_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_5x4_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_5x4_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_5x5_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_5x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_6x5_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_6x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_6x6_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_6x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x5_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x6_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x8_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x8_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x5_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x6_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x8_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x8_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x10_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x10_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_12x10_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_12x10_sRGB, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_12x12_LDR, RF ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_12x12_sRGB, RF ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, Depth32Float, DRMR ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, Depth32Float_Stencil8, DRMR ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, Stencil8, DRMR ); - - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGRA10_XR, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGRA10_XR_sRGB, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGR10_XR, All ); - addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGR10_XR_sRGB, All ); - - addGPUOSMTLPixFmtCaps( Apple1, 13.0, Depth16Unorm, DRFM ); - addGPUOSMTLPixFmtCaps( Apple3, 13.0, Depth16Unorm, DRFMR ); - - // Vertex formats - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, UCharNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, CharNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, UChar, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, Char, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, UShortNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, ShortNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, UShort, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, Short, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, Half, Vertex ); - addFeatSetMTLVtxFmtCaps( tvOS_GPUFamily1_v3, UChar4Normalized_BGRA, Vertex ); - -#if MVK_XCODE_15 - addGPUOSMTLVtxFmtCaps( Apple5, 17.0, FloatRG11B10, Vertex ); - addGPUOSMTLVtxFmtCaps( Apple5, 17.0, FloatRGB9E5, Vertex ); -#endif - - // Disable for tvOS simulator last. -#if MVK_OS_SIMULATOR - if (!([mtlDevice respondsToSelector: @selector(supportsFamily:)] && - [mtlDevice supportsFamily: MTLGPUFamilyApple5])) { - disableAllMTLPixFmtCaps( R8Unorm_sRGB ); - disableAllMTLPixFmtCaps( RG8Unorm_sRGB ); - disableAllMTLPixFmtCaps( B5G6R5Unorm ); - disableAllMTLPixFmtCaps( A1BGR5Unorm ); - disableAllMTLPixFmtCaps( ABGR4Unorm ); - disableAllMTLPixFmtCaps( BGR5A1Unorm ); - - disableAllMTLPixFmtCaps( BGRA10_XR ); - disableAllMTLPixFmtCaps( BGRA10_XR_sRGB ); - disableAllMTLPixFmtCaps( BGR10_XR ); - disableAllMTLPixFmtCaps( BGR10_XR_sRGB ); - - disableAllMTLPixFmtCaps( GBGR422 ); - disableAllMTLPixFmtCaps( BGRG422 ); - - disableMTLPixFmtCaps( RGB9E5Float, ColorAtt ); - - disableMTLPixFmtCaps( R8Unorm_sRGB, Write ); - disableMTLPixFmtCaps( RG8Unorm_sRGB, Write ); - disableMTLPixFmtCaps( RGBA8Unorm_sRGB, Write ); - disableMTLPixFmtCaps( BGRA8Unorm_sRGB, Write ); - disableMTLPixFmtCaps( PVRTC_RGBA_2BPP_sRGB, Write ); - disableMTLPixFmtCaps( PVRTC_RGBA_4BPP_sRGB, Write ); - disableMTLPixFmtCaps( ETC2_RGB8_sRGB, Write ); - disableMTLPixFmtCaps( ETC2_RGB8A1_sRGB, Write ); - disableMTLPixFmtCaps( EAC_RGBA8_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_4x4_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_5x4_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_5x5_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_6x5_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_6x6_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_8x5_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_8x6_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_8x8_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_10x5_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_10x6_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_10x8_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_10x10_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_12x10_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_12x12_sRGB, Write ); - } -#endif -#endif - -#if MVK_IOS - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v3, R8Unorm_sRGB, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, R8Unorm_sRGB, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, R8Snorm, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v3, RG8Unorm_sRGB, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, RG8Unorm_sRGB, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, RG8Snorm, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, R32Uint, RWC ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, R32Uint, Atomic ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, R32Sint, RWC ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, R32Sint, Atomic ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, R32Float, RWCMB ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v3, RGBA8Unorm_sRGB, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, RGBA8Unorm_sRGB, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, RGBA8Snorm, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v3, BGRA8Unorm_sRGB, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, BGRA8Unorm_sRGB, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, RGB10A2Unorm, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, RGB10A2Uint, RWCM ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, RG11B10Float, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, RGB9E5Float, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, RG32Uint, RWC ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, RG32Sint, RWC ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, RG32Float, RWCB ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, RGBA32Uint, RWC ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, RGBA32Sint, RWC ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v2, RGBA32Float, RWC ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_4x4_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_4x4_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_5x4_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_5x4_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_5x5_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_5x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_6x5_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_6x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_6x6_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_6x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_8x5_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_8x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_8x6_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_8x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_8x8_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_8x8_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_10x5_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_10x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_10x6_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_10x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_10x8_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_10x8_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_10x10_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_10x10_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_12x10_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_12x10_sRGB, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_12x12_LDR, RF ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v1, ASTC_12x12_sRGB, RF ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, Depth32Float, DRMR ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, Depth32Float_Stencil8, DRMR ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, Stencil8, DRMR ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v2, BGRA10_XR, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v2, BGRA10_XR_sRGB, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v2, BGR10_XR, All ); - addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v2, BGR10_XR_sRGB, All ); - - addFeatSetMTLPixFmtCaps( iOS_GPUFamily1_v4, BGR10A2Unorm, All ); - - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_4x4_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_5x4_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_5x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_6x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_6x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_8x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_8x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_8x8_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_10x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_10x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_10x8_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_10x10_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_12x10_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 13.0, ASTC_12x12_HDR, RF ); - - addGPUOSMTLPixFmtCaps( Apple1, 13.0, Depth16Unorm, DRFM ); - addGPUOSMTLPixFmtCaps( Apple3, 13.0, Depth16Unorm, DRFMR ); - -#if MVK_XCODE_15 - addGPUOSMTLPixFmtCaps( Apple9, 14.0, R32Float, All ); - addGPUOSMTLPixFmtCaps( Apple9, 14.0, RG32Float, All ); - addGPUOSMTLPixFmtCaps( Apple9, 14.0, RGBA32Float, All ); -#endif - - // Vertex formats - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, UCharNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, CharNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, UChar, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, Char, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, UShortNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, ShortNormalized, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, UShort, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, Short, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, Half, Vertex ); - addFeatSetMTLVtxFmtCaps( iOS_GPUFamily1_v4, UChar4Normalized_BGRA, Vertex ); - -#if MVK_XCODE_15 - addGPUOSMTLVtxFmtCaps( Apple5, 17.0, FloatRG11B10, Vertex ); - addGPUOSMTLVtxFmtCaps( Apple5, 17.0, FloatRGB9E5, Vertex ); -#endif - -// Disable for iOS simulator last. -#if MVK_OS_SIMULATOR - if (!([mtlDevice respondsToSelector: @selector(supportsFamily:)] && - [mtlDevice supportsFamily: MTLGPUFamilyApple5])) { - disableAllMTLPixFmtCaps( R8Unorm_sRGB ); - disableAllMTLPixFmtCaps( RG8Unorm_sRGB ); - disableAllMTLPixFmtCaps( B5G6R5Unorm ); - disableAllMTLPixFmtCaps( A1BGR5Unorm ); - disableAllMTLPixFmtCaps( ABGR4Unorm ); - disableAllMTLPixFmtCaps( BGR5A1Unorm ); - - disableAllMTLPixFmtCaps( BGRA10_XR ); - disableAllMTLPixFmtCaps( BGRA10_XR_sRGB ); - disableAllMTLPixFmtCaps( BGR10_XR ); - disableAllMTLPixFmtCaps( BGR10_XR_sRGB ); - - disableAllMTLPixFmtCaps( GBGR422 ); - disableAllMTLPixFmtCaps( BGRG422 ); - - disableMTLPixFmtCaps( RGB9E5Float, ColorAtt ); - - disableMTLPixFmtCaps( R8Unorm_sRGB, Write ); - disableMTLPixFmtCaps( RG8Unorm_sRGB, Write ); - disableMTLPixFmtCaps( RGBA8Unorm_sRGB, Write ); - disableMTLPixFmtCaps( BGRA8Unorm_sRGB, Write ); - disableMTLPixFmtCaps( PVRTC_RGBA_2BPP_sRGB, Write ); - disableMTLPixFmtCaps( PVRTC_RGBA_4BPP_sRGB, Write ); - disableMTLPixFmtCaps( ETC2_RGB8_sRGB, Write ); - disableMTLPixFmtCaps( ETC2_RGB8A1_sRGB, Write ); - disableMTLPixFmtCaps( EAC_RGBA8_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_4x4_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_5x4_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_5x5_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_6x5_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_6x6_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_8x5_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_8x6_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_8x8_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_10x5_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_10x6_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_10x8_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_10x10_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_12x10_sRGB, Write ); - disableMTLPixFmtCaps( ASTC_12x12_sRGB, Write ); - } -#endif -#endif +void MVKPixelFormats::modifyMTLFormatCapabilities(const MVKMTLDeviceCapabilities& gpuCaps) { + + bool noVulkanSupport = false; // Indicated supported in Metal but not Vulkan or SPIR-V. + bool notMac = gpuCaps.isAppleGPU && !gpuCaps.supportsMac1; + bool iosOnly1 = notMac && !gpuCaps.supportsApple2; + bool iosOnly2 = notMac && !gpuCaps.supportsApple3; + bool iosOnly6 = notMac && !gpuCaps.supportsApple7; + bool iosOnly8 = notMac && !gpuCaps.supportsApple9; + + setMTLPixFmtCapsIf( iosOnly2, A8Unorm, RF ); + setMTLPixFmtCapsIf( iosOnly1, R8Unorm_sRGB, RFCMRB ); + setMTLPixFmtCapsIf( iosOnly1, R8Snorm, RFWCMB ); + + setMTLPixFmtCapsIf( iosOnly1, RG8Unorm_sRGB, RFCMRB ); + setMTLPixFmtCapsIf( iosOnly1, RG8Snorm, RFWCMB ); + + enableMTLPixFmtCapsIfGPU( Apple6, R32Uint, Atomic ); + enableMTLPixFmtCapsIfGPU( Mac2, R32Uint, Atomic ); + enableMTLPixFmtCapsIfGPU( Apple6, R32Sint, Atomic ); + enableMTLPixFmtCapsIfGPU( Mac2, R32Sint, Atomic ); + + setMTLPixFmtCapsIf( iosOnly8, R32Float, RWCMB ); + + setMTLPixFmtCapsIf( iosOnly1, RGBA8Unorm_sRGB, RFCMRB ); + setMTLPixFmtCapsIf( iosOnly1, RGBA8Snorm, RFWCMB ); + setMTLPixFmtCapsIf( iosOnly1, BGRA8Unorm_sRGB, RFCMRB ); + + setMTLPixFmtCapsIf( iosOnly2, RGB10A2Unorm, RFCMRB ); + setMTLPixFmtCapsIf( iosOnly2, RGB10A2Uint, RCM ); + setMTLPixFmtCapsIf( iosOnly2, RG11B10Float, RFCMRB ); + setMTLPixFmtCapsIf( iosOnly2, RGB9E5Float, RFCMRB ); + + // Blending is actually supported for RGB9E5Float, but format channels cannot + // be individually write-enabled during blending on macOS. Disabling blending + // on macOS is the least-intrusive way to handle this in a Vulkan-friendly way. + disableMTLPixFmtCapsIfGPU( Mac1, RGB9E5Float, Blend); + + setMTLPixFmtCapsIf( iosOnly6, RG32Uint, RWC ); + setMTLPixFmtCapsIf( iosOnly6, RG32Sint, RWC ); + + // Metal supports reading both R&G into as one 64-bit atomic operation, but Vulkan and SPIR-V do not. + // Including this here so we remember to update this if support is added to Vulkan in the future. + bool atomic64 = noVulkanSupport && (gpuCaps.supportsApple9 || (gpuCaps.supportsApple8 && gpuCaps.supportsMac2)); + enableMTLPixFmtCapsIf( atomic64, RG32Uint, Atomic ); + enableMTLPixFmtCapsIf( atomic64, RG32Sint, Atomic ); + + setMTLPixFmtCapsIf( iosOnly8, RG32Float, RWCMB ); + setMTLPixFmtCapsIf( iosOnly6, RG32Float, RWCB ); + + setMTLPixFmtCapsIf( iosOnly8, RGBA32Float, RWCM ); + setMTLPixFmtCapsIf( iosOnly6, RGBA32Float, RWC ); + + bool msaa32 = gpuCaps.supports32BitMSAA; + enableMTLPixFmtCapsIf(msaa32, R32Uint, MSAA ); + enableMTLPixFmtCapsIf(msaa32, R32Sint, MSAA ); + enableMTLPixFmtCapsIf(msaa32, R32Float, Resolve ); + enableMTLPixFmtCapsIf(msaa32, RG32Uint, MSAA ); + enableMTLPixFmtCapsIf(msaa32, RG32Sint, MSAA ); + enableMTLPixFmtCapsIf(msaa32, RG32Float, Resolve ); + enableMTLPixFmtCapsIf(msaa32, RGBA32Uint, MSAA ); + enableMTLPixFmtCapsIf(msaa32, RGBA32Sint, MSAA ); + enableMTLPixFmtCapsIf(msaa32, RGBA32Float, Resolve ); + + bool floatFB = gpuCaps.supports32BitFloatFiltering; + enableMTLPixFmtCapsIf( floatFB, R32Float, Filter ); + enableMTLPixFmtCapsIf( floatFB, RG32Float, Filter ); + enableMTLPixFmtCapsIf( floatFB, RGBA32Float, Filter ); + enableMTLPixFmtCapsIf( floatFB, RGBA32Float, Blend ); // Undocumented by confirmed through testing + + bool noHDR_ASTC = !gpuCaps.supportsApple6; + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_4x4_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_5x4_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_5x5_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_6x5_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_6x6_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_8x5_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_8x6_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_8x8_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_10x5_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_10x6_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_10x8_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_10x10_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_12x10_HDR, None ); + setMTLPixFmtCapsIf( noHDR_ASTC, ASTC_12x12_HDR, None ); + + bool noBC = !gpuCaps.supportsBCTextureCompression; + setMTLPixFmtCapsIf( noBC, BC1_RGBA, None ); + setMTLPixFmtCapsIf( noBC, BC1_RGBA_sRGB, None ); + setMTLPixFmtCapsIf( noBC, BC2_RGBA, None ); + setMTLPixFmtCapsIf( noBC, BC2_RGBA_sRGB, None ); + setMTLPixFmtCapsIf( noBC, BC3_RGBA, None ); + setMTLPixFmtCapsIf( noBC, BC3_RGBA_sRGB, None ); + setMTLPixFmtCapsIf( noBC, BC4_RUnorm, None ); + setMTLPixFmtCapsIf( noBC, BC4_RSnorm, None ); + setMTLPixFmtCapsIf( noBC, BC5_RGUnorm, None ); + setMTLPixFmtCapsIf( noBC, BC5_RGSnorm, None ); + setMTLPixFmtCapsIf( noBC, BC6H_RGBUfloat, None ); + setMTLPixFmtCapsIf( noBC, BC6H_RGBFloat, None ); + setMTLPixFmtCapsIf( noBC, BC7_RGBAUnorm, None ); + setMTLPixFmtCapsIf( noBC, BC7_RGBAUnorm_sRGB, None ); + + setMTLPixFmtCapsIf( iosOnly2, BGRA10_XR, None ); + setMTLPixFmtCapsIf( iosOnly2, BGRA10_XR_sRGB, None ); + setMTLPixFmtCapsIf( iosOnly2, BGR10_XR, None ); + setMTLPixFmtCapsIf( iosOnly2, BGR10_XR_sRGB, None ); + + setMTLPixFmtCapsIf( iosOnly2, Depth16Unorm, DRFM ); + setMTLPixFmtCapsIf( iosOnly2, Depth32Float, DRM ); + + setMTLPixFmtCapsIf( !gpuCaps.supportsDepth24Stencil8, Depth24Unorm_Stencil8, None ); + setMTLPixFmtCapsIf( iosOnly2, Depth32Float_Stencil8, DRM ); } -#undef addFeatSetMTLPixFmtCaps -#undef addGPUOSMTLPixFmtCaps -#undef disableMTLPixFmtCaps -#undef disableAllMTLPixFmtCaps -#undef addFeatSetMTLVtxFmtCaps -#undef addGPUOSMTLVtxFmtCaps - // Connects Vulkan and Metal pixel formats to one-another. -void MVKPixelFormats::buildVkFormatMaps(id mtlDevice) { +void MVKPixelFormats::buildVkFormatMaps(const MVKMTLDeviceCapabilities& gpuCaps) { for (auto& vkDesc : _vkFormatDescriptions) { if (vkDesc.needsSwizzle()) { -#if MVK_MACCAT - bool supportsNativeTextureSwizzle = [mtlDevice supportsFamily: MTLGPUFamilyMacCatalyst2]; -#elif MVK_MACOS - bool supportsNativeTextureSwizzle = mvkOSVersionIsAtLeast(10.15) && [mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily2_v1]; -#endif -#if MVK_IOS || MVK_TVOS - bool supportsNativeTextureSwizzle = mtlDevice && mvkOSVersionIsAtLeast(13.0); -#endif -#if MVK_VISIONOS - bool supportsNativeTextureSwizzle = mtlDevice; -#endif + bool supportsNativeTextureSwizzle = ((gpuCaps.isAppleGPU || gpuCaps.supportsMac2) + && mvkOSVersionIsAtLeast(10.15, 13.0, 1.0)); if (!supportsNativeTextureSwizzle && !getMVKConfig().fullImageViewSwizzle) { vkDesc.mtlPixelFormat = vkDesc.mtlPixelFormatSubstitute = MTLPixelFormatInvalid; } @@ -2051,7 +1618,7 @@ } // Set Vulkan format properties - setFormatProperties(mtlDevice, vkDesc); + setFormatProperties(vkDesc, gpuCaps); } } @@ -2087,7 +1654,7 @@ } MVKVkFormatFeatureFlags; // Sets the VkFormatProperties (optimal/linear/buffer) for the Vulkan format. -void MVKPixelFormats::setFormatProperties(id mtlDevice, MVKVkFormatDesc& vkDesc) { +void MVKPixelFormats::setFormatProperties(MVKVkFormatDesc& vkDesc, const MVKMTLDeviceCapabilities& gpuCaps) { # define enableFormatFeatures(CAP, TYPE, MTL_FMT_CAPS, VK_FEATS) \ if (mvkAreAllFlagsEnabled(MTL_FMT_CAPS, kMVKMTLFmtCaps ##CAP)) { \ @@ -2125,26 +1692,9 @@ vkProps.optimalTilingFeatures |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT; } - // We would really want to use the device's Metal features instead of duplicating - // the logic from MVKPhysicalDevice, but those may not have been initialized yet. -#if MVK_MACOS && !MVK_MACCAT - bool supportsStencilFeedback = [mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily2_v1]; -#endif -#if MVK_MACCAT - bool supportsStencilFeedback = [mtlDevice supportsFamily: MTLGPUFamilyMacCatalyst2]; -#endif -#if MVK_IOS - bool supportsStencilFeedback = [mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily5_v1]; -#endif -#if MVK_TVOS - bool supportsStencilFeedback = false; -#endif -#if MVK_VISIONOS - bool supportsStencilFeedback = [mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily5_v1]; -#endif - // Vulkan forbids blits between chroma-subsampled formats. // If we can't write the stencil reference from the shader, we can't blit stencil. + bool supportsStencilFeedback = gpuCaps.supportsApple5 || gpuCaps.supportsMac2; if (chromaSubsamplingComponentBits > 0 || (isStencilFormat(vkDesc.mtlPixelFormat) && !supportsStencilFeedback)) { mvkDisableFlags(vkProps.optimalTilingFeatures, (VK_FORMAT_FEATURE_2_BLIT_SRC_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT)); }