diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index 51a63e3a..f1fc2116 100644 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -274,6 +274,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 3de75fc3..4c1567c5 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 */, @@ -1375,6 +1398,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 */, @@ -1417,6 +1441,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 */, @@ -1451,6 +1476,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 */, @@ -1474,6 +1500,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 */, @@ -1508,6 +1535,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 575ee3f7..614f0647 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) ) { @@ -2239,6 +2261,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/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h index a4eae12f..b88450f6 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -366,6 +366,7 @@ protected: bool _isLinear; bool _is3DCompressed; bool _isAliasable; + bool _hasExtendedUsage; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index f748d0ab..173655de 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -123,7 +123,7 @@ MTLTextureDescriptor* MVKImagePlane::newMTLTextureDescriptor() { mtlTexDesc.mipmapLevelCount = _image->_mipLevels; mtlTexDesc.sampleCount = mvkSampleCountFromVkSampleCountFlagBits(_image->_samples); mtlTexDesc.arrayLength = _image->_arrayLayers; - mtlTexDesc.usageMVK = _image->getPixelFormats()->getMTLTextureUsage(_image->_usage, mtlPixFmt, minUsage, _image->_isLinear); + mtlTexDesc.usageMVK = _image->getPixelFormats()->getMTLTextureUsage(_image->_usage, mtlPixFmt, minUsage, _image->_isLinear, _image->_hasExtendedUsage); mtlTexDesc.storageModeMVK = _image->getMTLStorageMode(); mtlTexDesc.cpuCacheMode = _image->getMTLCPUCacheMode(); @@ -604,10 +604,11 @@ VkResult MVKImage::getMemoryRequirements(VkMemoryRequirements* pMemoryRequiremen VkResult MVKImage::getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements) { uint8_t planeIndex = 0; - for (auto* next = (VkBaseOutStructure*)pMemoryRequirements->pNext; next; next = next->pNext) { + const auto* pImageInfo = (const VkImageMemoryRequirementsInfo2*)pInfo; + for (const auto* next = (const VkBaseInStructure*)pImageInfo->pNext; next; next = next->pNext) { switch (next->sType) { case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: { - auto* planeReqs = (VkImagePlaneMemoryRequirementsInfo*)next; + const auto* planeReqs = (const VkImagePlaneMemoryRequirementsInfo*)next; planeIndex = MVKImage::getPlaneFromVkImageAspectFlags(planeReqs->planeAspect); break; } @@ -615,7 +616,9 @@ VkResult MVKImage::getMemoryRequirements(const void* pInfo, VkMemoryRequirements break; } } - return getMemoryRequirements(&pMemoryRequirements->memoryRequirements, planeIndex); + VkResult rslt = getMemoryRequirements(&pMemoryRequirements->memoryRequirements, planeIndex); + if (rslt != VK_SUCCESS) { return rslt; } + return _memoryBindings[planeIndex]->getMemoryRequirements(pInfo, pMemoryRequirements); } VkResult MVKImage::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset, uint8_t planeIndex) { @@ -758,10 +761,12 @@ MTLStorageMode MVKImage::getMTLStorageMode() { if (_ioSurface && stgMode == MTLStorageModePrivate) { stgMode = MTLStorageModeShared; } +#if MVK_MACOS // For macOS prior to 10.15.5, textures cannot use Shared storage mode, so change to Managed storage mode. if (stgMode == MTLStorageModeShared && !_device->_pMetalFeatures->sharedLinearTextures) { stgMode = MTLStorageModeManaged; } +#endif return stgMode; } @@ -799,6 +804,7 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV MVKPixelFormats* pixFmts = getPixelFormats(); _vkFormat = pCreateInfo->format; _usage = pCreateInfo->usage; + _hasExtendedUsage = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_EXTENDED_USAGE_BIT); _is3DCompressed = (getImageType() == VK_IMAGE_TYPE_3D) && (pixFmts->getFormatType(pCreateInfo->format) == kMVKFormatCompressed) && !_device->_pMetalFeatures->native3DCompressedTextures; _isDepthStencilAttachment = (mvkAreAllFlagsEnabled(pCreateInfo->usage, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) || diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h index 1df4621c..e87063e0 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h @@ -77,6 +77,61 @@ typedef enum : uint16_t { kMVKMTLFmtCapsMultiPlanar = kMVKMTLFmtCapsChromaSubsampling, } MVKMTLFmtCaps; +inline MVKMTLFmtCaps operator|(MVKMTLFmtCaps leftCaps, MVKMTLFmtCaps rightCaps) { + return static_cast(static_cast(leftCaps) | rightCaps); +} + +inline MVKMTLFmtCaps& operator|=(MVKMTLFmtCaps& leftCaps, MVKMTLFmtCaps rightCaps) { + return (leftCaps = leftCaps | rightCaps); +} + + +#pragma mark - +#pragma mark Metal view classes + +enum class MVKMTLViewClass : uint8_t { + None, + Color8, + Color16, + Color32, + Color64, + Color128, + PVRTC_RGB_2BPP, + PVRTC_RGB_4BPP, + PVRTC_RGBA_2BPP, + PVRTC_RGBA_4BPP, + EAC_R11, + EAC_RG11, + EAC_RGBA8, + ETC2_RGB8, + ETC2_RGB8A1, + ASTC_4x4, + ASTC_5x4, + ASTC_5x5, + ASTC_6x5, + ASTC_6x6, + ASTC_8x5, + ASTC_8x6, + ASTC_8x8, + ASTC_10x5, + ASTC_10x6, + ASTC_10x8, + ASTC_10x10, + ASTC_12x10, + ASTC_12x12, + BC1_RGBA, + BC2_RGBA, + BC3_RGBA, + BC4_R, + BC5_RG, + BC6H_RGB, + BC7_RGBA, + Depth24_Stencil8, + Depth32_Stencil8, + BGRA10_XR, + BGR10_XR +}; + #pragma mark - #pragma mark Format descriptors @@ -114,6 +169,7 @@ typedef struct { }; VkFormat vkFormat; MVKMTLFmtCaps mtlFmtCaps; + MVKMTLViewClass mtlViewClass; const char* name; inline bool isSupported() const { return (mtlPixelFormat != MTLPixelFormatInvalid) && (mtlFmtCaps != kMVKMTLFmtCapsNone); }; @@ -254,10 +310,13 @@ public: VkFormatProperties& getVkFormatProperties(VkFormat vkFormat); /** Returns the Metal format capabilities supported by the specified Vulkan format, without substitution. */ - MVKMTLFmtCaps getCapabilities(VkFormat vkFormat); + MVKMTLFmtCaps getCapabilities(VkFormat vkFormat, bool isExtended = false); /** Returns the Metal format capabilities supported by the specified Metal format. */ - MVKMTLFmtCaps getCapabilities(MTLPixelFormat mtlFormat); + MVKMTLFmtCaps getCapabilities(MTLPixelFormat mtlFormat, bool isExtended = false); + + /** Returns the Metal view class of the specified Metal format. */ + MVKMTLViewClass getViewClass(MTLPixelFormat mtlFormat); /** Returns the name of the specified Vulkan format. */ const char* getName(VkFormat vkFormat); @@ -283,12 +342,15 @@ public: /** * Returns the Metal texture usage from the Vulkan image usage and Metal format, ensuring that at least the * usages in minUsage are included, even if they wouldn't naturally be included based on the other two parameters. - * isLinear further restricts the allowed usage to those that are valid for linear textures. + * isLinear further restricts the allowed usage to those that are valid for linear textures. + * isExtended expands the allowed usage to those that are valid for all formats which + * can be used in a view created from the specified format. */ MTLTextureUsage getMTLTextureUsage(VkImageUsageFlags vkImageUsageFlags, MTLPixelFormat mtlFormat, MTLTextureUsage minUsage = MTLTextureUsageUnknown, - bool isLinear = false); + bool isLinear = false, + bool isExtended = false); /** Enumerates all formats that support the given features, calling a specified function for each one. */ void enumerateSupportedFormats(VkFormatProperties properties, bool any, std::function func); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm index 9fb584e6..d27b4b2b 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm @@ -320,12 +320,23 @@ VkFormatProperties& MVKPixelFormats::getVkFormatProperties(VkFormat vkFormat) { return getVkFormatDesc(vkFormat).properties; } -MVKMTLFmtCaps MVKPixelFormats::getCapabilities(VkFormat vkFormat) { - return getMTLPixelFormatDesc(getVkFormatDesc(vkFormat).mtlPixelFormat).mtlFmtCaps; +MVKMTLFmtCaps MVKPixelFormats::getCapabilities(VkFormat vkFormat, bool isExtended) { + return getCapabilities(getVkFormatDesc(vkFormat).mtlPixelFormat, isExtended); } -MVKMTLFmtCaps MVKPixelFormats::getCapabilities(MTLPixelFormat mtlFormat) { - return getMTLPixelFormatDesc(mtlFormat).mtlFmtCaps; +MVKMTLFmtCaps MVKPixelFormats::getCapabilities(MTLPixelFormat mtlFormat, bool isExtended) { + MVKMTLFormatDesc& mtlDesc = getMTLPixelFormatDesc(mtlFormat); + MVKMTLFmtCaps caps = mtlDesc.mtlFmtCaps; + if (!isExtended || mtlDesc.mtlViewClass == MVKMTLViewClass::None) { return caps; } + // Now get caps of all formats in the view class. + for (auto& otherDesc : _mtlPixelFormatDescriptions) { + if (otherDesc.mtlViewClass == mtlDesc.mtlViewClass) { caps |= otherDesc.mtlFmtCaps; } + } + return caps; +} + +MVKMTLViewClass MVKPixelFormats::getViewClass(MTLPixelFormat mtlFormat) { + return getMTLPixelFormatDesc(mtlFormat).mtlViewClass; } const char* MVKPixelFormats::getName(VkFormat vkFormat) { @@ -453,13 +464,14 @@ VkImageUsageFlags MVKPixelFormats::getVkImageUsageFlags(MTLTextureUsage mtlUsage MTLTextureUsage MVKPixelFormats::getMTLTextureUsage(VkImageUsageFlags vkImageUsageFlags, MTLPixelFormat mtlFormat, MTLTextureUsage minUsage, - bool isLinear) { + bool isLinear, + bool isExtended) { bool isDepthFmt = isDepthFormat(mtlFormat); bool isStencilFmt = isStencilFormat(mtlFormat); bool isCombinedDepthStencilFmt = isDepthFmt && isStencilFmt; bool isColorFormat = !(isDepthFmt || isStencilFmt); bool supportsStencilViews = _physicalDevice ? _physicalDevice->getMetalFeatures()->stencilViews : false; - MVKMTLFmtCaps mtlFmtCaps = getCapabilities(mtlFormat); + MVKMTLFmtCaps mtlFmtCaps = getCapabilities(mtlFormat, isExtended); MTLTextureUsage mtlUsage = minUsage; @@ -479,7 +491,7 @@ MTLTextureUsage MVKPixelFormats::getMTLTextureUsage(VkImageUsageFlags vkImageUsa } #if MVK_MACOS // Clearing a linear image may use shader writes. - if (mvkIsAnyFlagEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_TRANSFER_DST_BIT) && + if (mvkIsAnyFlagEnabled(vkImageUsageFlags, (VK_IMAGE_USAGE_TRANSFER_DST_BIT)) && mvkIsAnyFlagEnabled(mtlFmtCaps, kMVKMTLFmtCapsWrite) && isLinear) { mvkEnableFlags(mtlUsage, MTLTextureUsageShaderWrite); @@ -856,11 +868,11 @@ void MVKPixelFormats::initVkFormatCapabilities() { // When adding to this list, be sure to ensure _vkFormatCount is large enough for the format count } -#define addMTLPixelFormatDesc(MTL_FMT, IOS_CAPS, MACOS_CAPS) \ +#define addMTLPixelFormatDesc(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS) \ MVKAssert(fmtIdx < _mtlPixelFormatCount, "Attempting to describe %d MTLPixelFormats, but only have space for %d. Increase the value of _mtlPixelFormatCount", fmtIdx + 1, _mtlPixelFormatCount); \ _mtlPixelFormatDescriptions[fmtIdx++] = { .mtlPixelFormat = MTLPixelFormat ##MTL_FMT, VK_FORMAT_UNDEFINED, \ mvkSelectPlatformValue(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS), \ - "MTLPixelFormat" #MTL_FMT } + MVKMTLViewClass:: VIEW_CLASS, "MTLPixelFormat" #MTL_FMT } void MVKPixelFormats::initMTLPixelFormatCapabilities() { @@ -871,159 +883,157 @@ void MVKPixelFormats::initMTLPixelFormatCapabilities() { // When adding to this list, be sure to ensure _mtlPixelFormatCount is large enough for the format count // MTLPixelFormatInvalid must come first. - addMTLPixelFormatDesc( Invalid, None, None ); + addMTLPixelFormatDesc( Invalid, None, None, None ); // Ordinary 8-bit pixel formats - addMTLPixelFormatDesc( A8Unorm, RF, RF ); - addMTLPixelFormatDesc( R8Unorm, All, All ); - addMTLPixelFormatDesc( R8Unorm_sRGB, RFCMRB, None ); - addMTLPixelFormatDesc( R8Snorm, RFWCMB, All ); - addMTLPixelFormatDesc( R8Uint, RWCM, RWCM ); - addMTLPixelFormatDesc( R8Sint, RWCM, RWCM ); + addMTLPixelFormatDesc( A8Unorm, Color8, RF, RF ); + addMTLPixelFormatDesc( R8Unorm, Color8, All, All ); + addMTLPixelFormatDesc( R8Unorm_sRGB, Color8, RFCMRB, None ); + addMTLPixelFormatDesc( R8Snorm, Color8, RFWCMB, All ); + addMTLPixelFormatDesc( R8Uint, Color8, RWCM, RWCM ); + addMTLPixelFormatDesc( R8Sint, Color8, RWCM, RWCM ); // Ordinary 16-bit pixel formats - addMTLPixelFormatDesc( R16Unorm, RFWCMB, All ); - addMTLPixelFormatDesc( R16Snorm, RFWCMB, All ); - addMTLPixelFormatDesc( R16Uint, RWCM, RWCM ); - addMTLPixelFormatDesc( R16Sint, RWCM, RWCM ); - addMTLPixelFormatDesc( R16Float, All, All ); + addMTLPixelFormatDesc( R16Unorm, Color16, RFWCMB, All ); + addMTLPixelFormatDesc( R16Snorm, Color16, RFWCMB, All ); + addMTLPixelFormatDesc( R16Uint, Color16, RWCM, RWCM ); + addMTLPixelFormatDesc( R16Sint, Color16, RWCM, RWCM ); + addMTLPixelFormatDesc( R16Float, Color16, All, All ); - addMTLPixelFormatDesc( RG8Unorm, All, All ); - addMTLPixelFormatDesc( RG8Unorm_sRGB, RFCMRB, None ); - addMTLPixelFormatDesc( RG8Snorm, RFWCMB, All ); - addMTLPixelFormatDesc( RG8Uint, RWCM, RWCM ); - addMTLPixelFormatDesc( RG8Sint, RWCM, RWCM ); + addMTLPixelFormatDesc( RG8Unorm, Color16, All, All ); + addMTLPixelFormatDesc( RG8Unorm_sRGB, Color16, RFCMRB, None ); + addMTLPixelFormatDesc( RG8Snorm, Color16, RFWCMB, All ); + addMTLPixelFormatDesc( RG8Uint, Color16, RWCM, RWCM ); + addMTLPixelFormatDesc( RG8Sint, Color16, RWCM, RWCM ); // Packed 16-bit pixel formats - addMTLPixelFormatDesc( B5G6R5Unorm, RFCMRB, None ); - addMTLPixelFormatDesc( A1BGR5Unorm, RFCMRB, None ); - addMTLPixelFormatDesc( ABGR4Unorm, RFCMRB, None ); - addMTLPixelFormatDesc( BGR5A1Unorm, RFCMRB, None ); + addMTLPixelFormatDesc( B5G6R5Unorm, Color16, RFCMRB, None ); + addMTLPixelFormatDesc( A1BGR5Unorm, Color16, RFCMRB, None ); + addMTLPixelFormatDesc( ABGR4Unorm, Color16, RFCMRB, None ); + addMTLPixelFormatDesc( BGR5A1Unorm, Color16, RFCMRB, None ); // Ordinary 32-bit pixel formats - addMTLPixelFormatDesc( R32Uint, RC, RWCM ); - addMTLPixelFormatDesc( R32Sint, RC, RWCM ); - addMTLPixelFormatDesc( R32Float, RCMB, All ); + addMTLPixelFormatDesc( R32Uint, Color32, RC, RWCM ); + addMTLPixelFormatDesc( R32Sint, Color32, RC, RWCM ); + addMTLPixelFormatDesc( R32Float, Color32, RCMB, All ); - addMTLPixelFormatDesc( RG16Unorm, RFWCMB, All ); - addMTLPixelFormatDesc( RG16Snorm, RFWCMB, All ); - addMTLPixelFormatDesc( RG16Uint, RWCM, RWCM ); - addMTLPixelFormatDesc( RG16Sint, RWCM, RWCM ); - addMTLPixelFormatDesc( RG16Float, All, All ); + addMTLPixelFormatDesc( RG16Unorm, Color32, RFWCMB, All ); + addMTLPixelFormatDesc( RG16Snorm, Color32, RFWCMB, All ); + addMTLPixelFormatDesc( RG16Uint, Color32, RWCM, RWCM ); + addMTLPixelFormatDesc( RG16Sint, Color32, RWCM, RWCM ); + addMTLPixelFormatDesc( RG16Float, Color32, All, All ); - addMTLPixelFormatDesc( RGBA8Unorm, All, All ); - addMTLPixelFormatDesc( RGBA8Unorm_sRGB, RFCMRB, RFCMRB ); - addMTLPixelFormatDesc( RGBA8Snorm, RFWCMB, All ); - addMTLPixelFormatDesc( RGBA8Uint, RWCM, RWCM ); - addMTLPixelFormatDesc( RGBA8Sint, RWCM, RWCM ); + addMTLPixelFormatDesc( RGBA8Unorm, Color32, All, All ); + addMTLPixelFormatDesc( RGBA8Unorm_sRGB, Color32, RFCMRB, RFCMRB ); + addMTLPixelFormatDesc( RGBA8Snorm, Color32, RFWCMB, All ); + addMTLPixelFormatDesc( RGBA8Uint, Color32, RWCM, RWCM ); + addMTLPixelFormatDesc( RGBA8Sint, Color32, RWCM, RWCM ); - addMTLPixelFormatDesc( BGRA8Unorm, All, All ); - addMTLPixelFormatDesc( BGRA8Unorm_sRGB, RFCMRB, RFCMRB ); + addMTLPixelFormatDesc( BGRA8Unorm, Color32, All, All ); + addMTLPixelFormatDesc( BGRA8Unorm_sRGB, Color32, RFCMRB, RFCMRB ); // Packed 32-bit pixel formats - addMTLPixelFormatDesc( RGB10A2Unorm, RFCMRB, All ); - addMTLPixelFormatDesc( RGB10A2Uint, RCM, RWCM ); - addMTLPixelFormatDesc( RG11B10Float, RFCMRB, All ); - addMTLPixelFormatDesc( RGB9E5Float, RFCMRB, RF ); + addMTLPixelFormatDesc( RGB10A2Unorm, Color32, RFCMRB, All ); + addMTLPixelFormatDesc( RGB10A2Uint, Color32, RCM, RWCM ); + addMTLPixelFormatDesc( RG11B10Float, Color32, RFCMRB, All ); + addMTLPixelFormatDesc( RGB9E5Float, Color32, RFCMRB, RF ); // Ordinary 64-bit pixel formats - addMTLPixelFormatDesc( RG32Uint, RC, RWCM ); - addMTLPixelFormatDesc( RG32Sint, RC, RWCM ); - addMTLPixelFormatDesc( RG32Float, RCB, All ); + addMTLPixelFormatDesc( RG32Uint, Color64, RC, RWCM ); + addMTLPixelFormatDesc( RG32Sint, Color64, RC, RWCM ); + addMTLPixelFormatDesc( RG32Float, Color64, RCB, All ); - addMTLPixelFormatDesc( RGBA16Unorm, RFWCMB, All ); - addMTLPixelFormatDesc( RGBA16Snorm, RFWCMB, All ); - addMTLPixelFormatDesc( RGBA16Uint, RWCM, RWCM ); - addMTLPixelFormatDesc( RGBA16Sint, RWCM, RWCM ); - addMTLPixelFormatDesc( RGBA16Float, All, All ); + addMTLPixelFormatDesc( RGBA16Unorm, Color64, RFWCMB, All ); + addMTLPixelFormatDesc( RGBA16Snorm, Color64, RFWCMB, All ); + addMTLPixelFormatDesc( RGBA16Uint, Color64, RWCM, RWCM ); + addMTLPixelFormatDesc( RGBA16Sint, Color64, RWCM, RWCM ); + addMTLPixelFormatDesc( RGBA16Float, Color64, All, All ); // Ordinary 128-bit pixel formats - addMTLPixelFormatDesc( RGBA32Uint, RC, RWCM ); - addMTLPixelFormatDesc( RGBA32Sint, RC, RWCM ); - addMTLPixelFormatDesc( RGBA32Float, RC, All ); + addMTLPixelFormatDesc( RGBA32Uint, Color128, RC, RWCM ); + addMTLPixelFormatDesc( RGBA32Sint, Color128, RC, RWCM ); + addMTLPixelFormatDesc( RGBA32Float, Color128, RC, All ); // Compressed pixel formats - addMTLPixelFormatDesc( PVRTC_RGBA_2BPP, RF, None ); - addMTLPixelFormatDesc( PVRTC_RGBA_4BPP, RF, None ); - addMTLPixelFormatDesc( PVRTC_RGBA_2BPP_sRGB, RF, None ); - addMTLPixelFormatDesc( PVRTC_RGBA_4BPP_sRGB, RF, None ); + addMTLPixelFormatDesc( PVRTC_RGBA_2BPP, PVRTC_RGBA_2BPP, RF, None ); + addMTLPixelFormatDesc( PVRTC_RGBA_4BPP, PVRTC_RGBA_4BPP, RF, None ); + addMTLPixelFormatDesc( PVRTC_RGBA_2BPP_sRGB, PVRTC_RGBA_2BPP, RF, None ); + addMTLPixelFormatDesc( PVRTC_RGBA_4BPP_sRGB, PVRTC_RGBA_4BPP, RF, None ); - addMTLPixelFormatDesc( ETC2_RGB8, RF, None ); - addMTLPixelFormatDesc( ETC2_RGB8_sRGB, RF, None ); - addMTLPixelFormatDesc( ETC2_RGB8A1, RF, None ); - addMTLPixelFormatDesc( ETC2_RGB8A1_sRGB, RF, None ); - addMTLPixelFormatDesc( EAC_RGBA8, RF, None ); - addMTLPixelFormatDesc( EAC_RGBA8_sRGB, RF, None ); - addMTLPixelFormatDesc( EAC_R11Unorm, RF, None ); - addMTLPixelFormatDesc( EAC_R11Snorm, RF, None ); - addMTLPixelFormatDesc( EAC_RG11Unorm, RF, None ); - addMTLPixelFormatDesc( EAC_RG11Snorm, RF, None ); + addMTLPixelFormatDesc( ETC2_RGB8, ETC2_RGB8, RF, None ); + addMTLPixelFormatDesc( ETC2_RGB8_sRGB, ETC2_RGB8, RF, None ); + addMTLPixelFormatDesc( ETC2_RGB8A1, ETC2_RGB8A1, RF, None ); + addMTLPixelFormatDesc( ETC2_RGB8A1_sRGB, ETC2_RGB8A1, RF, None ); + addMTLPixelFormatDesc( EAC_RGBA8, EAC_RGBA8, RF, None ); + addMTLPixelFormatDesc( EAC_RGBA8_sRGB, EAC_RGBA8, RF, None ); + addMTLPixelFormatDesc( EAC_R11Unorm, EAC_R11, RF, None ); + addMTLPixelFormatDesc( EAC_R11Snorm, EAC_R11, RF, None ); + addMTLPixelFormatDesc( EAC_RG11Unorm, EAC_RG11, RF, None ); + addMTLPixelFormatDesc( EAC_RG11Snorm, EAC_RG11, RF, None ); - addMTLPixelFormatDesc( ASTC_4x4_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_4x4_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_5x4_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_5x4_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_5x5_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_5x5_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_6x5_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_6x5_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_6x6_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_6x6_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_8x5_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_8x5_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_8x6_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_8x6_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_8x8_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_8x8_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_10x5_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_10x5_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_10x6_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_10x6_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_10x8_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_10x8_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_10x10_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_10x10_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_12x10_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_12x10_sRGB, None, None ); - addMTLPixelFormatDesc( ASTC_12x12_LDR, None, None ); - addMTLPixelFormatDesc( ASTC_12x12_sRGB, None, None ); + addMTLPixelFormatDesc( ASTC_4x4_LDR, ASTC_4x4, None, None ); + addMTLPixelFormatDesc( ASTC_4x4_sRGB, ASTC_4x4, None, None ); + addMTLPixelFormatDesc( ASTC_5x4_LDR, ASTC_5x4, None, None ); + addMTLPixelFormatDesc( ASTC_5x4_sRGB, ASTC_5x4, None, None ); + addMTLPixelFormatDesc( ASTC_5x5_LDR, ASTC_5x5, None, None ); + addMTLPixelFormatDesc( ASTC_5x5_sRGB, ASTC_5x5, None, None ); + addMTLPixelFormatDesc( ASTC_6x5_LDR, ASTC_6x5, None, None ); + addMTLPixelFormatDesc( ASTC_6x5_sRGB, ASTC_6x5, None, None ); + addMTLPixelFormatDesc( ASTC_6x6_LDR, ASTC_6x6, None, None ); + addMTLPixelFormatDesc( ASTC_6x6_sRGB, ASTC_6x6, None, None ); + addMTLPixelFormatDesc( ASTC_8x5_LDR, ASTC_8x5, None, None ); + addMTLPixelFormatDesc( ASTC_8x5_sRGB, ASTC_8x5, None, None ); + addMTLPixelFormatDesc( ASTC_8x6_LDR, ASTC_8x6, None, None ); + addMTLPixelFormatDesc( ASTC_8x6_sRGB, ASTC_8x6, None, None ); + addMTLPixelFormatDesc( ASTC_8x8_LDR, ASTC_8x8, None, None ); + addMTLPixelFormatDesc( ASTC_8x8_sRGB, ASTC_8x8, None, None ); + addMTLPixelFormatDesc( ASTC_10x5_LDR, ASTC_10x5, None, None ); + addMTLPixelFormatDesc( ASTC_10x5_sRGB, ASTC_10x5, None, None ); + addMTLPixelFormatDesc( ASTC_10x6_LDR, ASTC_10x6, None, None ); + addMTLPixelFormatDesc( ASTC_10x6_sRGB, ASTC_10x6, None, None ); + addMTLPixelFormatDesc( ASTC_10x8_LDR, ASTC_10x8, None, None ); + addMTLPixelFormatDesc( ASTC_10x8_sRGB, ASTC_10x8, None, None ); + addMTLPixelFormatDesc( ASTC_10x10_LDR, ASTC_10x10, None, None ); + addMTLPixelFormatDesc( ASTC_10x10_sRGB, ASTC_10x10, None, None ); + addMTLPixelFormatDesc( ASTC_12x10_LDR, ASTC_12x10, None, None ); + addMTLPixelFormatDesc( ASTC_12x10_sRGB, ASTC_12x10, None, None ); + addMTLPixelFormatDesc( ASTC_12x12_LDR, ASTC_12x12, None, None ); + addMTLPixelFormatDesc( ASTC_12x12_sRGB, ASTC_12x12, None, None ); - addMTLPixelFormatDesc( BC1_RGBA, None, RF ); - addMTLPixelFormatDesc( BC1_RGBA_sRGB, None, RF ); - addMTLPixelFormatDesc( BC1_RGBA, None, RF ); - addMTLPixelFormatDesc( BC1_RGBA_sRGB, None, RF ); - addMTLPixelFormatDesc( BC2_RGBA, None, RF ); - addMTLPixelFormatDesc( BC2_RGBA_sRGB, None, RF ); - addMTLPixelFormatDesc( BC3_RGBA, None, RF ); - addMTLPixelFormatDesc( BC3_RGBA_sRGB, None, RF ); - addMTLPixelFormatDesc( BC4_RUnorm, None, RF ); - addMTLPixelFormatDesc( BC4_RSnorm, None, RF ); - addMTLPixelFormatDesc( BC5_RGUnorm, None, RF ); - addMTLPixelFormatDesc( BC5_RGSnorm, None, RF ); - addMTLPixelFormatDesc( BC6H_RGBUfloat, None, RF ); - addMTLPixelFormatDesc( BC6H_RGBFloat, None, RF ); - addMTLPixelFormatDesc( BC7_RGBAUnorm, None, RF ); - addMTLPixelFormatDesc( BC7_RGBAUnorm_sRGB, None, RF ); + addMTLPixelFormatDesc( BC1_RGBA, BC1_RGBA, None, RF ); + addMTLPixelFormatDesc( BC1_RGBA_sRGB, BC1_RGBA, None, RF ); + addMTLPixelFormatDesc( BC2_RGBA, BC2_RGBA, None, RF ); + addMTLPixelFormatDesc( BC2_RGBA_sRGB, BC2_RGBA, None, RF ); + addMTLPixelFormatDesc( BC3_RGBA, BC3_RGBA, None, RF ); + addMTLPixelFormatDesc( BC3_RGBA_sRGB, BC3_RGBA, None, RF ); + addMTLPixelFormatDesc( BC4_RUnorm, BC4_R, None, RF ); + addMTLPixelFormatDesc( BC4_RSnorm, BC4_R, None, RF ); + addMTLPixelFormatDesc( BC5_RGUnorm, BC5_RG, None, RF ); + addMTLPixelFormatDesc( BC5_RGSnorm, BC5_RG, None, RF ); + addMTLPixelFormatDesc( BC6H_RGBUfloat, BC6H_RGB, None, RF ); + addMTLPixelFormatDesc( BC6H_RGBFloat, BC6H_RGB, None, RF ); + addMTLPixelFormatDesc( BC7_RGBAUnorm, BC7_RGBA, None, RF ); + addMTLPixelFormatDesc( BC7_RGBAUnorm_sRGB, BC7_RGBA, None, RF ); // YUV pixel formats - addMTLPixelFormatDesc( GBGR422, RF, RF ); - addMTLPixelFormatDesc( BGRG422, RF, RF ); + addMTLPixelFormatDesc( GBGR422, None, RF, RF ); + addMTLPixelFormatDesc( BGRG422, None, RF, RF ); // Extended range and wide color pixel formats - addMTLPixelFormatDesc( BGRA10_XR, None, None ); - addMTLPixelFormatDesc( BGRA10_XR_sRGB, None, None ); - addMTLPixelFormatDesc( BGR10_XR, None, None ); - addMTLPixelFormatDesc( BGR10_XR_sRGB, None, None ); - addMTLPixelFormatDesc( BGR10A2Unorm, None, None ); + addMTLPixelFormatDesc( BGRA10_XR, BGRA10_XR, None, None ); + addMTLPixelFormatDesc( BGRA10_XR_sRGB, BGRA10_XR, None, None ); + addMTLPixelFormatDesc( BGR10_XR, BGR10_XR, None, None ); + addMTLPixelFormatDesc( BGR10_XR_sRGB, BGR10_XR, None, None ); + addMTLPixelFormatDesc( BGR10A2Unorm, Color32, None, None ); // Depth and stencil pixel formats - addMTLPixelFormatDesc( Depth16Unorm, None, None ); - addMTLPixelFormatDesc( Depth32Float, DRM, DRFMR ); - addMTLPixelFormatDesc( Stencil8, DRM, DRM ); - addMTLPixelFormatDesc( Depth24Unorm_Stencil8, None, None ); - addMTLPixelFormatDesc( Depth32Float_Stencil8, DRM, DRFMR ); - addMTLPixelFormatDesc( X24_Stencil8, None, DRM ); - addMTLPixelFormatDesc( X32_Stencil8, DRM, DRM ); + 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 ); // When adding to this list, be sure to ensure _mtlPixelFormatCount is large enough for the format count } @@ -1032,7 +1042,7 @@ void MVKPixelFormats::initMTLPixelFormatCapabilities() { MVKAssert(fmtIdx < _mtlVertexFormatCount, "Attempting to describe %d MTLVertexFormats, but only have space for %d. Increase the value of _mtlVertexFormatCount", fmtIdx + 1, _mtlVertexFormatCount); \ _mtlVertexFormatDescriptions[fmtIdx++] = { .mtlVertexFormat = MTLVertexFormat ##MTL_VTX_FMT, VK_FORMAT_UNDEFINED, \ mvkSelectPlatformValue(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS), \ - "MTLVertexFormat" #MTL_VTX_FMT } + MVKMTLViewClass::None, "MTLVertexFormat" #MTL_VTX_FMT } void MVKPixelFormats::initMTLVertexFormatCapabilities() { @@ -1330,6 +1340,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 +1479,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;