diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h index 5a1317fc..a1cba32e 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h @@ -44,12 +44,13 @@ typedef enum : uint16_t { kMVKMTLFmtCapsRead = (1<<0), kMVKMTLFmtCapsFilter = (1<<1), kMVKMTLFmtCapsWrite = (1<<2), - kMVKMTLFmtCapsColorAtt = (1<<3), - kMVKMTLFmtCapsDSAtt = (1<<4), - kMVKMTLFmtCapsBlend = (1<<5), - kMVKMTLFmtCapsMSAA = (1<<6), - kMVKMTLFmtCapsResolve = (1<<7), - kMVKMTLFmtCapsVertex = (1<<8), + kMVKMTLFmtCapsAtomic = (1<<3), + kMVKMTLFmtCapsColorAtt = (1<<4), + kMVKMTLFmtCapsDSAtt = (1<<5), + kMVKMTLFmtCapsBlend = (1<<6), + kMVKMTLFmtCapsMSAA = (1<<7), + kMVKMTLFmtCapsResolve = (1<<8), + kMVKMTLFmtCapsVertex = (1<<9), kMVKMTLFmtCapsRF = (kMVKMTLFmtCapsRead | kMVKMTLFmtCapsFilter), kMVKMTLFmtCapsRC = (kMVKMTLFmtCapsRead | kMVKMTLFmtCapsColorAtt), @@ -291,14 +292,12 @@ protected: MVKMTLFormatDesc& getMTLPixelFormatDesc(MTLPixelFormat mtlFormat); MVKMTLFormatDesc& getMTLVertexFormatDesc(VkFormat vkFormat); MVKMTLFormatDesc& getMTLVertexFormatDesc(MTLVertexFormat mtlFormat); - VkFormatFeatureFlags getOptimalTilingFeatures(VkFormat vkFormat, MVKMTLFmtCaps mtlFmtCaps); - VkFormatFeatureFlags getLinearTilingFeatures(VkFormat vkFormat, MVKMTLFmtCaps mtlFmtCaps, MVKFormatType mvkFmtType); - VkFormatFeatureFlags getBufferFeatures(VkFormat vkFormat, MVKMTLFmtCaps mtlFmtTexCaps, MVKMTLFmtCaps mtlFmtVtxCaps, MVKFormatType mvkFmtType); void initVkFormatCapabilities(); void initMTLPixelFormatCapabilities(); void initMTLVertexFormatCapabilities(); void buildMTLFormatMaps(); void buildVkFormatMaps(); + void setFormatProperties(MVKVkFormatDesc& vkDesc); void modifyMTLFormatCapabilities(); void modifyMTLFormatCapabilities(id mtlDevice); void addMTLPixelFormatCapabilities(id mtlDevice, diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm index 927af4b4..5197c4d7 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm @@ -1072,6 +1072,10 @@ void MVKPixelFormats::modifyMTLFormatCapabilities() { // Modifies the format capability tables based on the capabilities of the specific MTLDevice #if MVK_MACOS void MVKPixelFormats::modifyMTLFormatCapabilities(id mtlDevice) { + + addMTLPixelFormatCapabilities( macOS_GPUFamily1_v1, R32Uint, Atomic ); + addMTLPixelFormatCapabilities( macOS_GPUFamily1_v1, R32Sint, Atomic ); + if (mtlDevice.isDepth24Stencil8PixelFormatSupported) { addMTLPixelFormatCapabilities( macOS_GPUFamily1_v1, Depth24Unorm_Stencil8, DRFMR ); } @@ -1105,7 +1109,9 @@ void MVKPixelFormats::modifyMTLFormatCapabilities(id mtlDevice) { addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, RG8Snorm, All ); addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Uint, RWC ); + addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Uint, Atomic ); addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Sint, RWC ); + addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Sint, Atomic ); addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Float, RWCMB ); @@ -1227,13 +1233,8 @@ void MVKPixelFormats::buildVkFormatMaps() { if ( !mtlDesc.isSupported() ) { vkDesc.mtlVertexFormatSubstitute = MTLVertexFormatInvalid; } } - // Vulkan format features - MVKFormatType fmtType = vkDesc.formatType; - MVKMTLFmtCaps mtlPixFmtCaps = getMTLPixelFormatDesc(vkFmt).mtlFmtCaps; - MVKMTLFmtCaps mtlVtxFmtCaps = getMTLVertexFormatDesc(vkFmt).mtlFmtCaps; - vkDesc.properties = { getLinearTilingFeatures(vkFmt, mtlPixFmtCaps, fmtType), - getOptimalTilingFeatures(vkFmt, mtlPixFmtCaps), - getBufferFeatures(vkFmt, mtlPixFmtCaps, mtlVtxFmtCaps, fmtType) }; + // Set Vulkan format properties + setFormatProperties(vkDesc); } } } @@ -1246,87 +1247,65 @@ typedef enum : VkFormatFeatureFlags { VK_FORMAT_FEATURE_TRANSFER_DST_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT), kMVKVkFormatFeatureFlagsTexFilter = (VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT), - kMVKVkFormatFeatureFlagsTexWrite = (VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | - VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT), + kMVKVkFormatFeatureFlagsTexWrite = (VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT), + kMVKVkFormatFeatureFlagsTexAtomic = (VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT), kMVKVkFormatFeatureFlagsTexColorAtt = (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT), kMVKVkFormatFeatureFlagsTexDSAtt = (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT), kMVKVkFormatFeatureFlagsTexBlend = (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT), kMVKVkFormatFeatureFlagsBufRead = (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT), - kMVKVkFormatFeatureFlagsBufWrite = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | - VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT), + kMVKVkFormatFeatureFlagsBufWrite = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT), + kMVKVkFormatFeatureFlagsBufAtomic = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT), kMVKVkFormatFeatureFlagsBufVertex = (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT), } MVKVkFormatFeatureFlags; -#define enableTexFormatFeatures(CAP) \ - if (mvkAreAllFlagsEnabled(mtlFmtCaps, kMVKMTLFmtCaps ##CAP)) { \ - vkFeatures |= kMVKVkFormatFeatureFlagsTex ##CAP; \ - } -VkFormatFeatureFlags MVKPixelFormats::getOptimalTilingFeatures(VkFormat vkFormat, - MVKMTLFmtCaps mtlFmtCaps) { - VkFormatFeatureFlags vkFeatures = kMVKVkFormatFeatureFlagsTexNone; - enableTexFormatFeatures(Read); - enableTexFormatFeatures(Filter); - enableTexFormatFeatures(Write); - enableTexFormatFeatures(ColorAtt); - enableTexFormatFeatures(DSAtt); - enableTexFormatFeatures(Blend); - // Only support atomics on R32UI/R32I images for now. Until Metal supports this - // for real, we need to use the underlying buffer to support image atomics. - if (vkFormat != VK_FORMAT_R32_UINT && vkFormat != VK_FORMAT_R32_SINT) { - mvkDisableFlags(vkFeatures, VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT); - } - return vkFeatures; -} +// Sets the VkFormatProperties (optimal/linear/buffer) for the Vulkan format. +void MVKPixelFormats::setFormatProperties(MVKVkFormatDesc& vkDesc) { -VkFormatFeatureFlags MVKPixelFormats::getLinearTilingFeatures(VkFormat vkFormat, - MVKMTLFmtCaps mtlFmtCaps, - MVKFormatType mvkFmtType) { - - // Depth-stencil or compressed formats cannot be used for linear textures. - if (mvkFmtType == kMVKFormatDepthStencil || mvkFmtType == kMVKFormatCompressed) { - return kMVKVkFormatFeatureFlagsTexNone; +# define enableFormatFeatures(CAP, TYPE, MTL_FMT_CAPS, VK_FEATS) \ + if (mvkAreAllFlagsEnabled(MTL_FMT_CAPS, kMVKMTLFmtCaps ##CAP)) { \ + mvkEnableFlags(VK_FEATS, kMVKVkFormatFeatureFlags ##TYPE ##CAP); \ } - // Start with the optimal features. - VkFormatFeatureFlags vkFeatures = getOptimalTilingFeatures(vkFormat, mtlFmtCaps); + VkFormat vkFmt = vkDesc.vkFormat; + VkFormatProperties& vkProps = vkDesc.properties; + MVKMTLFmtCaps mtlPixFmtCaps = getMTLPixelFormatDesc(vkFmt).mtlFmtCaps; + + // Set optimal tiling features first + vkProps.optimalTilingFeatures = kMVKVkFormatFeatureFlagsTexNone; + enableFormatFeatures(Read, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures); + enableFormatFeatures(Filter, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures); + enableFormatFeatures(Write, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures); + enableFormatFeatures(ColorAtt, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures); + enableFormatFeatures(DSAtt, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures); + enableFormatFeatures(Blend, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures); + + // Linear tiling is not available to depth/stencil or compressed formats. + vkProps.linearTilingFeatures = kMVKVkFormatFeatureFlagsTexNone; + if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed) ) { + + // Start with optimal tiling features, and modify. + vkProps.linearTilingFeatures = vkProps.optimalTilingFeatures; + + // Linear tiling can support atomic writing for some formats, even though optimal tiling does not. + enableFormatFeatures(Atomic, Tex, mtlPixFmtCaps, vkProps.linearTilingFeatures); #if MVK_MACOS - // On macOS, linear textures cannot be used as attachments, so disable those features. - mvkDisableFlags(vkFeatures, (kMVKVkFormatFeatureFlagsTexColorAtt | - kMVKVkFormatFeatureFlagsTexDSAtt | - kMVKVkFormatFeatureFlagsTexBlend)); + // On macOS, linear textures cannot be used as attachments, so disable those features. + mvkDisableFlags(vkProps.linearTilingFeatures, (kMVKVkFormatFeatureFlagsTexColorAtt | + kMVKVkFormatFeatureFlagsTexDSAtt | + kMVKVkFormatFeatureFlagsTexBlend)); #endif - - return vkFeatures; -} - -VkFormatFeatureFlags MVKPixelFormats::getBufferFeatures(VkFormat vkFormat, - MVKMTLFmtCaps mtlPixFmtCaps, - MVKMTLFmtCaps mtlVtxFmtCaps, - MVKFormatType mvkFmtType) { - - // Depth-stencil or compressed formats cannot be used for texel buffers. - if (mvkFmtType == kMVKFormatDepthStencil || mvkFmtType == kMVKFormatCompressed) { - return kMVKVkFormatFeatureFlagsTexNone; } - VkFormatFeatureFlags vkFeatures = kMVKVkFormatFeatureFlagsTexNone; - if (mvkAreAllFlagsEnabled(mtlPixFmtCaps, kMVKMTLFmtCapsRead)) { - vkFeatures |= kMVKVkFormatFeatureFlagsBufRead; + // Texel buffers are not available to depth/stencil or compressed formats. + vkProps.bufferFeatures = kMVKVkFormatFeatureFlagsTexNone; + if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed) ) { + enableFormatFeatures(Read, Buf, mtlPixFmtCaps, vkProps.bufferFeatures); + enableFormatFeatures(Write, Buf, mtlPixFmtCaps, vkProps.bufferFeatures); + enableFormatFeatures(Atomic, Buf, mtlPixFmtCaps, vkProps.bufferFeatures); + enableFormatFeatures(Vertex, Buf, getMTLVertexFormatDesc(vkFmt).mtlFmtCaps, vkProps.bufferFeatures); } - if (mvkAreAllFlagsEnabled(mtlPixFmtCaps, kMVKMTLFmtCapsWrite)) { - vkFeatures |= kMVKVkFormatFeatureFlagsBufWrite; - } - if (mvkAreAllFlagsEnabled(mtlVtxFmtCaps, kMVKMTLFmtCapsVertex)) { - vkFeatures |= kMVKVkFormatFeatureFlagsBufVertex; - } - // Only support atomics on R32UI/R32I images for now. Until Metal supports this - // for real, we need to use the underlying buffer to support image atomics. - if (vkFormat != VK_FORMAT_R32_UINT && vkFormat != VK_FORMAT_R32_SINT) { - mvkDisableFlags(vkFeatures, VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT); - } - return vkFeatures; }