diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index becec329..ba274735 100644 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -261,6 +261,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_KHR_bind_memory2` - `VK_KHR_create_renderpass2` - `VK_KHR_dedicated_allocation` +- `VK_KHR_depth_stencil_resolve` - `VK_KHR_descriptor_update_template` - `VK_KHR_device_group` - `VK_KHR_device_group_creation` diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 9eb11bf2..03b2cc56 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -27,6 +27,7 @@ Released 2020/09/28 - Add support for extensions: - `VK_KHR_portability_subset` - `VK_KHR_create_renderpass2` + - `VK_KHR_depth_stencil_resolve` - `VK_KHR_external_fence` (non-functional groundwork for future extensions, including support for GCD and Mach semaphores) - `VK_KHR_external_fence_capabilities` (non-functional groundwork for future diff --git a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj index a8dc7f26..ffdf19a9 100644 --- a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj +++ b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj @@ -124,6 +124,16 @@ 2FEA0AB424902F9F00EEF3AD /* MVKCmdDebug.mm in Sources */ = {isa = PBXBuildFile; fileRef = A99C90ED229455B300A061DA /* MVKCmdDebug.mm */; }; 45003E73214AD4E500E989CB /* MVKExtensions.def in Headers */ = {isa = PBXBuildFile; fileRef = 45003E6F214AD4C900E989CB /* MVKExtensions.def */; }; 45003E74214AD4E600E989CB /* MVKExtensions.def in Headers */ = {isa = PBXBuildFile; fileRef = 45003E6F214AD4C900E989CB /* MVKExtensions.def */; }; + 453638322508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 4536382D2508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h */; }; + 453638342508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 4536382D2508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h */; }; + 453638352508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 4536382F2508A4C6000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m */; }; + 453638362508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 4536382F2508A4C6000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m */; }; + 453638372508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 4536382F2508A4C6000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m */; }; + 453638382508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 453638302508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m */; }; + 4536383A2508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 453638302508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m */; }; + 4536383B2508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 453638312508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h */; }; + 4536383C2508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 453638312508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h */; }; + 4536383D2508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 453638312508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h */; }; 4553AEFB2251617100E8EBCD /* MVKBlockObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 4553AEF62251617100E8EBCD /* MVKBlockObserver.m */; }; 4553AEFC2251617100E8EBCD /* MVKBlockObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 4553AEF62251617100E8EBCD /* MVKBlockObserver.m */; }; 4553AEFD2251617100E8EBCD /* MVKBlockObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4553AEFA2251617100E8EBCD /* MVKBlockObserver.h */; }; @@ -451,6 +461,10 @@ /* Begin PBXFileReference section */ 2FEA0ABA24902F9F00EEF3AD /* libMoltenVK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMoltenVK.a; sourceTree = BUILT_PRODUCTS_DIR; }; 45003E6F214AD4C900E989CB /* MVKExtensions.def */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = MVKExtensions.def; sourceTree = ""; }; + 4536382D2508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h"; sourceTree = ""; }; + 4536382F2508A4C6000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m"; sourceTree = ""; }; + 453638302508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m"; sourceTree = ""; }; + 453638312508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h"; sourceTree = ""; }; 4553AEF62251617100E8EBCD /* MVKBlockObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVKBlockObserver.m; sourceTree = ""; }; 4553AEFA2251617100E8EBCD /* MVKBlockObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKBlockObserver.h; sourceTree = ""; }; 45557A4D21C9EFF3008868BD /* MVKCodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKCodec.cpp; sourceTree = ""; }; @@ -758,8 +772,12 @@ children = ( A9E53DD12100B197002781DD /* CAMetalLayer+MoltenVK.h */, A9E53DD62100B197002781DD /* CAMetalLayer+MoltenVK.m */, + 453638312508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h */, + 4536382F2508A4C6000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m */, A9E53DEE2100B302002781DD /* MTLRenderPassDescriptor+MoltenVK.h */, A9E53DF22100B302002781DD /* MTLRenderPassDescriptor+MoltenVK.m */, + 4536382D2508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h */, + 453638302508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m */, A9E53DFE21064F84002781DD /* MTLRenderPipelineDescriptor+MoltenVK.h */, A9E53DFA21064F84002781DD /* MTLRenderPipelineDescriptor+MoltenVK.m */, A9E53DD32100B197002781DD /* MTLSamplerDescriptor+MoltenVK.h */, @@ -871,6 +889,7 @@ 2FEA0A7524902F9F00EEF3AD /* MVKCmdDebug.h in Headers */, 2FEA0A7624902F9F00EEF3AD /* MVKWatermarkTextureContent.h in Headers */, 2FEA0A7724902F9F00EEF3AD /* MVKFoundation.h in Headers */, + 4536383C2508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h in Headers */, 2FEA0A7824902F9F00EEF3AD /* MVKDeviceMemory.h in Headers */, 2FEA0A7924902F9F00EEF3AD /* MVKMTLResourceBindings.h in Headers */, 2FEA0A7A24902F9F00EEF3AD /* MVKExtensions.def in Headers */, @@ -906,6 +925,7 @@ 45557A5421C9EFF3008868BD /* MVKCodec.h in Headers */, A94FB8041C7DFB4800632CA3 /* MVKRenderPass.h in Headers */, A9F042A61FB4CF83009FCCB8 /* MVKLogging.h in Headers */, + 453638322508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h in Headers */, A94FB8001C7DFB4800632CA3 /* MVKQueue.h in Headers */, A94FB7EC1C7DFB4800632CA3 /* MVKFramebuffer.h in Headers */, 83A4AD2C21BD75570006C935 /* MVKVectorAllocator.h in Headers */, @@ -949,6 +969,7 @@ A9CEAAD5227378D400FAF779 /* mvk_datatypes.hpp in Headers */, A90C8DEA1F45354D009CB32C /* MVKCommandEncodingPool.h in Headers */, A94FB8081C7DFB4800632CA3 /* MVKResource.h in Headers */, + 4536383B2508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h in Headers */, A9E53DDD2100B197002781DD /* MTLTextureDescriptor+MoltenVK.h in Headers */, A9653FBA24129C84005999D7 /* MVKPixelFormats.h in Headers */, A981496B1FB6A998005F00B4 /* MVKStrings.h in Headers */, @@ -978,6 +999,7 @@ 45557A5521C9EFF3008868BD /* MVKCodec.h in Headers */, A94FB8051C7DFB4800632CA3 /* MVKRenderPass.h in Headers */, A9F042A71FB4CF83009FCCB8 /* MVKLogging.h in Headers */, + 453638342508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h in Headers */, A94FB8011C7DFB4800632CA3 /* MVKQueue.h in Headers */, A94FB7ED1C7DFB4800632CA3 /* MVKFramebuffer.h in Headers */, 83A4AD2D21BD75570006C935 /* MVKVectorAllocator.h in Headers */, @@ -1021,6 +1043,7 @@ A9CEAAD6227378D400FAF779 /* mvk_datatypes.hpp in Headers */, A90C8DEB1F45354D009CB32C /* MVKCommandEncodingPool.h in Headers */, A94FB8091C7DFB4800632CA3 /* MVKResource.h in Headers */, + 4536383D2508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h in Headers */, A9E53DDE2100B197002781DD /* MTLTextureDescriptor+MoltenVK.h in Headers */, A9653FBB24129C84005999D7 /* MVKPixelFormats.h in Headers */, A981496C1FB6A998005F00B4 /* MVKStrings.h in Headers */, @@ -1413,6 +1436,7 @@ 2FEA0A9B24902F9F00EEF3AD /* MVKFoundation.cpp in Sources */, 2FEA0A9C24902F9F00EEF3AD /* MVKPixelFormats.mm in Sources */, 2FEA0A9D24902F9F00EEF3AD /* MVKDevice.mm in Sources */, + 453638362508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m in Sources */, 2FEA0A9E24902F9F00EEF3AD /* MTLRenderPassDescriptor+MoltenVK.m in Sources */, 2FEA0A9F24902F9F00EEF3AD /* MVKDescriptor.mm in Sources */, 2FEA0AA024902F9F00EEF3AD /* MVKPipeline.mm in Sources */, @@ -1455,6 +1479,7 @@ A981494D1FB6A3F7005F00B4 /* MVKBaseObject.mm in Sources */, A9E53DE52100B197002781DD /* NSString+MoltenVK.mm in Sources */, A94FB8321C7DFB4800632CA3 /* vulkan.mm in Sources */, + 453638352508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m in Sources */, A94FB8121C7DFB4800632CA3 /* MVKSurface.mm in Sources */, A94FB7FE1C7DFB4800632CA3 /* MVKQueryPool.mm in Sources */, A94FB7F61C7DFB4800632CA3 /* MVKInstance.mm in Sources */, @@ -1489,6 +1514,7 @@ A94FB7BE1C7DFB4800632CA3 /* MVKCmdPipeline.mm in Sources */, A94FB81E1C7DFB4800632CA3 /* MVKLayers.mm in Sources */, A94FB7EE1C7DFB4800632CA3 /* MVKFramebuffer.mm in Sources */, + 453638382508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m in Sources */, A9C96DD21DDC20C20053187F /* MVKMTLBufferAllocation.mm in Sources */, A9E53DE92100B197002781DD /* CAMetalLayer+MoltenVK.m in Sources */, A9096E5E1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */, @@ -1512,6 +1538,7 @@ A981494E1FB6A3F7005F00B4 /* MVKBaseObject.mm in Sources */, A9E53DE62100B197002781DD /* NSString+MoltenVK.mm in Sources */, A94FB8331C7DFB4800632CA3 /* vulkan.mm in Sources */, + 453638372508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m in Sources */, A94FB8131C7DFB4800632CA3 /* MVKSurface.mm in Sources */, A94FB7FF1C7DFB4800632CA3 /* MVKQueryPool.mm in Sources */, A94FB7F71C7DFB4800632CA3 /* MVKInstance.mm in Sources */, @@ -1546,6 +1573,7 @@ A94FB7BF1C7DFB4800632CA3 /* MVKCmdPipeline.mm in Sources */, A94FB81F1C7DFB4800632CA3 /* MVKLayers.mm in Sources */, A94FB7EF1C7DFB4800632CA3 /* MVKFramebuffer.mm in Sources */, + 4536383A2508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m in Sources */, A9C96DD31DDC20C20053187F /* MVKMTLBufferAllocation.mm in Sources */, A9E53DEA2100B197002781DD /* CAMetalLayer+MoltenVK.m in Sources */, A9096E5F1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */, diff --git a/MoltenVK/MoltenVK/API/mvk_datatypes.h b/MoltenVK/MoltenVK/API/mvk_datatypes.h index 3f9e601e..12628c52 100644 --- a/MoltenVK/MoltenVK/API/mvk_datatypes.h +++ b/MoltenVK/MoltenVK/API/mvk_datatypes.h @@ -362,6 +362,14 @@ MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp /** Returns the Metal MTLStoreAction corresponding to the specified Vulkan VkAttachmentStoreOp. */ MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment); +/** Returns the Metal MTLMultisampleDepthResolveFilter corresponding to the specified Vulkan VkResolveModeFlagBits. */ +MTLMultisampleDepthResolveFilter mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBits(VkResolveModeFlagBits vkResolveMode); + +#if MVK_MACOS_OR_IOS +/** Returns the Metal MTLMultisampleStencilResolveFilter corresponding to the specified Vulkan VkResolveModeFlagBits. */ +MTLMultisampleStencilResolveFilter mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBits(VkResolveModeFlagBits vkResolveMode); +#endif + /** Returns the Metal MTLViewport corresponding to the specified Vulkan VkViewport. */ MTLViewport mvkMTLViewportFromVkViewport(VkViewport vkViewport); diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index 3b67b4d5..d6025c45 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -618,6 +618,8 @@ typedef struct { VkBool32 renderWithoutAttachments; /**< If true, we don't have to create a dummy attachment for a render pass if there isn't one. */ VkBool32 deferredStoreActions; /**< If true, render pass store actions can be specified after the render encoder is created. */ VkBool32 sharedLinearTextures; /**< If true, linear textures and texture buffers can be created from buffers in Shared storage. */ + VkBool32 depthResolve; /**< If true, resolving depth textures with filters other than Sample0 is supported. */ + VkBool32 stencilResolve; /**< If true, resolving stencil textures with filters other than Sample0 is supported. */ } MVKPhysicalDeviceMetalFeatures; /** MoltenVK performance of a particular type of activity. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 04047b43..f7541235 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -210,6 +210,23 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) { properties->properties = _properties; for (auto* next = (VkBaseOutStructure*)properties->pNext; next; next = next->pNext) { switch ((uint32_t)next->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES: { + auto* depthStencilResolveProps = (VkPhysicalDeviceDepthStencilResolveProperties*)next; + + // We can always support resolve from sample zero. Other modes require additional capabilities. + depthStencilResolveProps->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; + if (_metalFeatures.depthResolve) { + depthStencilResolveProps->supportedDepthResolveModes |= VK_RESOLVE_MODE_MIN_BIT | VK_RESOLVE_MODE_MAX_BIT; + } + // Metal allows you to set the stencil resolve filter to either + // Sample0 or DepthResolvedSample--in other words, you can always use sample 0, + // but you can also use the sample chosen for depth resolve. This is impossible + // to express in Vulkan. + depthStencilResolveProps->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; + depthStencilResolveProps->independentResolveNone = true; + depthStencilResolveProps->independentResolve = true; + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES: { auto* physicalDeviceDriverProps = (VkPhysicalDeviceDriverPropertiesKHR*)next; strcpy(physicalDeviceDriverProps->driverName, "MoltenVK"); @@ -1027,6 +1044,7 @@ void MVKPhysicalDevice::initMetalFeatures() { _metalFeatures.depthSampleCompare = true; _metalFeatures.arrayOfTextures = true; _metalFeatures.arrayOfSamplers = true; + _metalFeatures.depthResolve = true; } if ( mvkOSVersionIsAtLeast(13.0) ) { @@ -1079,6 +1097,7 @@ void MVKPhysicalDevice::initMetalFeatures() { _metalFeatures.mtlBufferAlignment = 16; // Min float4 alignment for typical vertex buffers. MTLBuffer may go down to 4 bytes for other data. _metalFeatures.maxTextureDimension = (16 * KIBI); _metalFeatures.depthSampleCompare = true; + _metalFeatures.depthResolve = true; } if (supportsMTLFeatureSet(iOS_GPUFamily3_v2)) { @@ -1097,6 +1116,7 @@ void MVKPhysicalDevice::initMetalFeatures() { _metalFeatures.layeredRendering = true; _metalFeatures.stencilFeedback = true; _metalFeatures.indirectTessellationDrawing = true; + _metalFeatures.stencilResolve = true; } if ( mvkOSVersionIsAtLeast(13.0) ) { @@ -1153,6 +1173,8 @@ void MVKPhysicalDevice::initMetalFeatures() { if (supportsMTLFeatureSet(macOS_GPUFamily2_v1)) { _metalFeatures.multisampleLayeredRendering = _metalFeatures.layeredRendering; _metalFeatures.stencilFeedback = true; + _metalFeatures.depthResolve = true; + _metalFeatures.stencilResolve = true; } if ( mvkOSVersionIsAtLeast(10.15) ) { @@ -2236,6 +2258,11 @@ void MVKPhysicalDevice::initExtensions() { MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_supportedExtensions; pWritableExtns->disableAllButEnabledDeviceExtensions(); +#if MVK_IOS_OR_TVOS + if (!_metalFeatures.depthResolve) { + pWritableExtns->vk_KHR_depth_stencil_resolve.enabled = false; + } +#endif if (!_metalFeatures.rasterOrderGroups) { pWritableExtns->vk_EXT_fragment_shader_interlock.enabled = false; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm index 9fb584e6..05892524 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm @@ -1019,11 +1019,11 @@ void MVKPixelFormats::initMTLPixelFormatCapabilities() { // Depth and stencil pixel formats addMTLPixelFormatDesc( Depth16Unorm, None, None ); addMTLPixelFormatDesc( Depth32Float, DRM, DRFMR ); - addMTLPixelFormatDesc( Stencil8, DRM, DRM ); + addMTLPixelFormatDesc( Stencil8, DRM, DRMR ); addMTLPixelFormatDesc( Depth24Unorm_Stencil8, None, None ); addMTLPixelFormatDesc( Depth32Float_Stencil8, DRM, DRFMR ); - addMTLPixelFormatDesc( X24_Stencil8, None, DRM ); - addMTLPixelFormatDesc( X32_Stencil8, DRM, DRM ); + addMTLPixelFormatDesc( X24_Stencil8, None, DRMR ); + addMTLPixelFormatDesc( X32_Stencil8, DRM, DRMR ); // When adding to this list, be sure to ensure _mtlPixelFormatCount is large enough for the format count } @@ -1330,6 +1330,7 @@ void MVKPixelFormats::modifyMTLFormatCapabilities(id mtlDevice) { 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 ); @@ -1468,6 +1469,7 @@ void MVKPixelFormats::modifyMTLFormatCapabilities(id mtlDevice) { 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 ); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h index ca51bd0c..7706fd39 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h @@ -143,6 +143,9 @@ private: MVKSmallVector _resolveAttachments; MVKSmallVector _preserveAttachments; VkAttachmentReference2 _depthStencilAttachment; + VkAttachmentReference2 _depthStencilResolveAttachment; + VkResolveModeFlagBits _depthResolveMode = VK_RESOLVE_MODE_NONE; + VkResolveModeFlagBits _stencilResolveMode = VK_RESOLVE_MODE_NONE; id _mtlDummyTex = nil; VkSampleCountFlagBits _defaultSampleCount = VK_SAMPLE_COUNT_1_BIT; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm index 464f1d03..52d21bc3 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm @@ -21,6 +21,10 @@ #include "MVKCommandBuffer.h" #include "MVKFoundation.h" #include "mvk_datatypes.hpp" +#include "MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h" +#if MVK_MACOS_OR_IOS +#include "MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h" +#endif #include using namespace std; @@ -224,17 +228,31 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* // Populate the Metal depth and stencil attachments uint32_t dsRPAttIdx = _depthStencilAttachment.attachment; + uint32_t dsRslvRPAttIdx = _depthStencilResolveAttachment.attachment; if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) { MVKRenderPassAttachment* dsMVKRPAtt = &_renderPass->_attachments[dsRPAttIdx]; MVKImageView* dsImage = framebuffer->getAttachment(dsRPAttIdx); + MVKImageView* dsRslvImage = nullptr; MTLPixelFormat mtlDSFormat = dsImage->getMTLPixelFormat(0); + if (dsRslvRPAttIdx != VK_ATTACHMENT_UNUSED) { + dsRslvImage = framebuffer->getAttachment(dsRslvRPAttIdx); + } + if (pixFmts->isDepthFormat(mtlDSFormat)) { MTLRenderPassDepthAttachmentDescriptor* mtlDepthAttDesc = mtlRPDesc.depthAttachment; + bool hasResolveAttachment = (dsRslvRPAttIdx != VK_ATTACHMENT_UNUSED && _depthResolveMode != VK_RESOLVE_MODE_NONE); + if (hasResolveAttachment) { + dsRslvImage->populateMTLRenderPassAttachmentDescriptorResolve(mtlDepthAttDesc); + mtlDepthAttDesc.depthResolveFilterMVK = mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBits(_depthResolveMode); + if (isMultiview()) { + mtlDepthAttDesc.resolveSlice += getFirstViewIndexInMetalPass(passIdx); + } + } dsImage->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc); if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this, isRenderingEntireAttachment, - false, false, + hasResolveAttachment, false, loadOverride)) { mtlDepthAttDesc.clearDepth = pixFmts->getMTLClearDepthValue(clearValues[dsRPAttIdx]); } @@ -244,10 +262,20 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* } if (pixFmts->isStencilFormat(mtlDSFormat)) { MTLRenderPassStencilAttachmentDescriptor* mtlStencilAttDesc = mtlRPDesc.stencilAttachment; + bool hasResolveAttachment = (dsRslvRPAttIdx != VK_ATTACHMENT_UNUSED && _stencilResolveMode != VK_RESOLVE_MODE_NONE); + if (hasResolveAttachment) { + dsRslvImage->populateMTLRenderPassAttachmentDescriptorResolve(mtlStencilAttDesc); +#if MVK_MACOS_OR_IOS + mtlStencilAttDesc.stencilResolveFilterMVK = mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBits(_stencilResolveMode); +#endif + if (isMultiview()) { + mtlStencilAttDesc.resolveSlice += getFirstViewIndexInMetalPass(passIdx); + } + } dsImage->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc); if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this, isRenderingEntireAttachment, - false, true, + hasResolveAttachment, true, loadOverride)) { mtlStencilAttDesc.clearStencil = pixFmts->getMTLClearStencilValue(clearValues[dsRPAttIdx]); } @@ -337,8 +365,11 @@ void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder, } uint32_t dsRPAttIdx = _depthStencilAttachment.attachment; if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) { - _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, false, 0, false, storeOverride); - _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, false, 0, true, storeOverride); + bool hasResolveAttachment = _depthStencilResolveAttachment.attachment != VK_ATTACHMENT_UNUSED; + bool hasDepthResolveAttachment = hasResolveAttachment && _depthResolveMode != VK_RESOLVE_MODE_NONE; + bool hasStencilResolveAttachment = hasResolveAttachment && _stencilResolveMode != VK_RESOLVE_MODE_NONE; + _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, hasDepthResolveAttachment, 0, false, storeOverride); + _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, hasStencilResolveAttachment, 0, true, storeOverride); } } @@ -416,6 +447,7 @@ MVKMTLFmtCaps MVKRenderSubpass::getRequiredFormatCapabilitiesForAttachmentAt(uin } } if (_depthStencilAttachment.attachment == rpAttIdx) { mvkEnableFlags(caps, kMVKMTLFmtCapsDSAtt); } + if (_depthStencilResolveAttachment.attachment == rpAttIdx) { mvkEnableFlags(caps, kMVKMTLFmtCapsResolve); } return caps; } @@ -464,6 +496,8 @@ MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass, _depthStencilAttachment.attachment = VK_ATTACHMENT_UNUSED; } + _depthStencilResolveAttachment.attachment = VK_ATTACHMENT_UNUSED; + _preserveAttachments.reserve(pCreateInfo->preserveAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->preserveAttachmentCount; i++) { _preserveAttachments.push_back(pCreateInfo->pPreserveAttachments[i]); @@ -472,6 +506,18 @@ MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass, MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass, const VkSubpassDescription2* pCreateInfo) { + + VkSubpassDescriptionDepthStencilResolve* pDSResolveInfo = nullptr; + for (auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE: + pDSResolveInfo = (VkSubpassDescriptionDepthStencilResolve*)next; + break; + default: + break; + } + } + _renderPass = renderPass; _subpassIndex = (uint32_t)_renderPass->_subpasses.size(); _viewMask = pCreateInfo->viewMask; @@ -500,6 +546,14 @@ MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass, _depthStencilAttachment.attachment = VK_ATTACHMENT_UNUSED; } + if (pDSResolveInfo && pDSResolveInfo->pDepthStencilResolveAttachment) { + _depthStencilResolveAttachment = *pDSResolveInfo->pDepthStencilResolveAttachment; + _depthResolveMode = pDSResolveInfo->depthResolveMode; + _stencilResolveMode = pDSResolveInfo->stencilResolveMode; + } else { + _depthStencilResolveAttachment.attachment = VK_ATTACHMENT_UNUSED; + } + _preserveAttachments.reserve(pCreateInfo->preserveAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->preserveAttachmentCount; i++) { _preserveAttachments.push_back(pCreateInfo->pPreserveAttachments[i]); diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index 805c7ac6..cd54eb65 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -44,6 +44,7 @@ MVK_EXTENSION(KHR_8bit_storage, KHR_8BIT_STORAGE, DEVICE) MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2, DEVICE) MVK_EXTENSION(KHR_create_renderpass2, KHR_CREATE_RENDERPASS_2, DEVICE) MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION, DEVICE) +MVK_EXTENSION(KHR_depth_stencil_resolve, KHR_DEPTH_STENCIL_RESOLVE, DEVICE) MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, DEVICE) MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, DEVICE) MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, INSTANCE) diff --git a/MoltenVK/MoltenVK/OS/MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h b/MoltenVK/MoltenVK/OS/MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h new file mode 100644 index 00000000..4ea08a57 --- /dev/null +++ b/MoltenVK/MoltenVK/OS/MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h @@ -0,0 +1,34 @@ +/* + * MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h + * + * Copyright (c) 2020 Chip Davis for CodeWeavers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#import + +/** Extensions to MTLRenderPassDepthAttachmentDescriptor to support MoltenVK. */ +@interface MTLRenderPassDepthAttachmentDescriptor (MoltenVK) + +/** + * Replacement for the depthResolveFilter property. + * + * This property allows support under all OS versions. Delegates to the depthResolveFilter + * property if it is available. Otherwise, returns MTLMultisampleDepthResolveFilterSample0 when read and does nothing when set. + */ +@property(nonatomic, readwrite) MTLMultisampleDepthResolveFilter depthResolveFilterMVK; + +@end diff --git a/MoltenVK/MoltenVK/OS/MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m b/MoltenVK/MoltenVK/OS/MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m new file mode 100644 index 00000000..eb249da0 --- /dev/null +++ b/MoltenVK/MoltenVK/OS/MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m @@ -0,0 +1,42 @@ +/* + * MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m + * + * Copyright (c) 2020 Chip Davis for CodeWeavers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h" +#include "MVKEnvironment.h" + +@implementation MTLRenderPassDepthAttachmentDescriptor (MoltenVK) + +-(MTLMultisampleDepthResolveFilter) depthResolveFilterMVK { + + if ( [self respondsToSelector: @selector(depthResolveFilter)] ) { + return self.depthResolveFilter; + } + return MTLMultisampleDepthResolveFilterSample0; + +} + +-(void) setDepthResolveFilterMVK: (MTLMultisampleDepthResolveFilter) filter { + + if ( [self respondsToSelector: @selector(setDepthResolveFilter:)] ) { + self.depthResolveFilter = filter; + } + +} + +@end diff --git a/MoltenVK/MoltenVK/OS/MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h b/MoltenVK/MoltenVK/OS/MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h new file mode 100644 index 00000000..d2fb4fe2 --- /dev/null +++ b/MoltenVK/MoltenVK/OS/MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h @@ -0,0 +1,34 @@ +/* + * MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h + * + * Copyright (c) 2020 Chip Davis for CodeWeavers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#import + +/** Extensions to MTLRenderPassStencilAttachmentDescriptor to support MoltenVK. */ +@interface MTLRenderPassStencilAttachmentDescriptor (MoltenVK) + +/** + * Replacement for the stencilResolveFilter property. + * + * This property allows support under all OS versions. Delegates to the stencilResolveFilter + * property if it is available. Otherwise, returns MTLMultisampleStencilResolveFilterSample0 when read and does nothing when set. + */ +@property(nonatomic, readwrite) MTLMultisampleStencilResolveFilter stencilResolveFilterMVK; + +@end diff --git a/MoltenVK/MoltenVK/OS/MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m b/MoltenVK/MoltenVK/OS/MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m new file mode 100644 index 00000000..4cbda588 --- /dev/null +++ b/MoltenVK/MoltenVK/OS/MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m @@ -0,0 +1,42 @@ +/* + * MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m + * + * Copyright (c) 2020 Chip Davis for CodeWeavers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h" +#include "MVKEnvironment.h" + +@implementation MTLRenderPassStencilAttachmentDescriptor (MoltenVK) + +-(MTLMultisampleStencilResolveFilter) stencilResolveFilterMVK { + + if ( [self respondsToSelector: @selector(stencilResolveFilter)] ) { + return self.stencilResolveFilter; + } + return MTLMultisampleStencilResolveFilterSample0; + +} + +-(void) setStencilResolveFilterMVK: (MTLMultisampleStencilResolveFilter) filter { + + if ( [self respondsToSelector: @selector(setStencilResolveFilter:)] ) { + self.stencilResolveFilter = filter; + } + +} + +@end diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp index be0c519b..7a2a5d9c 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp @@ -62,6 +62,14 @@ MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOpInObj(VkAttachmentLoadOp vkL MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOpInObj(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment, MVKBaseObject* mvkObj); #define mvkMTLStoreActionFromVkAttachmentStoreOp(vkStoreOp, hasResolveAttachment) mvkMTLStoreActionFromVkAttachmentStoreOpInObj(vkStoreOp, hasResolveAttachment, this) +MTLMultisampleDepthResolveFilter mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBitsInObj(VkResolveModeFlagBits vkResolveMode, MVKBaseObject* mvkObj); +#define mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBits(vkResolveMode) mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBitsInObj(vkResolveMode, this) + +#if MVK_MACOS_OR_IOS +MTLMultisampleStencilResolveFilter mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBitsInObj(VkResolveModeFlagBits vkResolveMode, MVKBaseObject* mvkObj); +#define mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBits(vkResolveMode) mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBitsInObj(vkResolveMode, this) +#endif + MVKShaderStage mvkShaderStageFromVkShaderStageFlagBitsInObj(VkShaderStageFlagBits vkStage, MVKBaseObject* mvkObj); #define mvkShaderStageFromVkShaderStageFlagBits(vkStage) mvkShaderStageFromVkShaderStageFlagBitsInObj(vkStage, this) diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm index 57d6de19..8bee86e3 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm @@ -509,6 +509,40 @@ MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOpInObj(VkAttachmentStoreOp } } +#undef mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBits +MVK_PUBLIC_SYMBOL MTLMultisampleDepthResolveFilter mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBits(VkResolveModeFlagBits vkResolveMode) { + return mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBitsInObj(vkResolveMode, nullptr); +} + +MTLMultisampleDepthResolveFilter mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBitsInObj(VkResolveModeFlagBits vkResolveMode, MVKBaseObject* mvkObj) { + switch (vkResolveMode) { + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT: return MTLMultisampleDepthResolveFilterSample0; + case VK_RESOLVE_MODE_MIN_BIT: return MTLMultisampleDepthResolveFilterMin; + case VK_RESOLVE_MODE_MAX_BIT: return MTLMultisampleDepthResolveFilterMax; + + default: + MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkResolveModeFlagBits value %d is not supported.", vkResolveMode); + return MTLMultisampleDepthResolveFilterSample0; + } +} + +#if MVK_MACOS_OR_IOS +#undef mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBits +MVK_PUBLIC_SYMBOL MTLMultisampleStencilResolveFilter mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBits(VkResolveModeFlagBits vkResolveMode) { + return mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBitsInObj(vkResolveMode, nullptr); +} + +MTLMultisampleStencilResolveFilter mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBitsInObj(VkResolveModeFlagBits vkResolveMode, MVKBaseObject* mvkObj) { + switch (vkResolveMode) { + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT: return MTLMultisampleStencilResolveFilterSample0; + + default: + MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkResolveModeFlagBits value %d is not supported.", vkResolveMode); + return MTLMultisampleStencilResolveFilterSample0; + } +} +#endif + MVK_PUBLIC_SYMBOL MTLViewport mvkMTLViewportFromVkViewport(VkViewport vkViewport) { MTLViewport mtlViewport; mtlViewport.originX = vkViewport.x;