diff --git a/LICENSE b/LICENSE index b02cd99f..d6456956 100644 --- a/LICENSE +++ b/LICENSE @@ -1,115 +1,202 @@ -Khronos Open Source Contributor License Agreement -In order to clarify the intellectual property license granted with -Open Source Contributions from any person or entity to any products -The Khronos Group (“Khronos”) manages or maintains and makes available -under the www.apache.org/licenses/LICENSE-2.0 license, as indicated by -a copyright notice that is included in or attached to the product (the -"Work"), Khronos must have an Open Source Contributor License Grant -("Grant") on file that has been signed by each Contributor, indicating -agreement to the license terms below. This license is for your -protection as a Contributor as well as the protection of Khronos; it -does not change your rights to use your own Contributions for any -other purpose. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -You accept and agree to the following terms and conditions for Your -present and future Contributions submitted to Khronos. Except for the -license granted herein to Khronos and recipients of software -distributed by Khronos, You reserve all right, title, and interest in -and to Your Contributions. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -1. Definitions. + 1. Definitions. - "You" (or "Your") shall mean the copyright owner or legal entity - authorized by the copyright owner that is making this Grant. For - legal entities, the entity making a Contribution and all other - entities that directly or indirectly control, are controlled by, or - are under common control with that entity are considered to be a - single Contributor. For the purposes of this definition, "control" - means (i) the power, direct or indirect, to cause the direction or - management of such entity, whether by contract or otherwise, or - (ii) ownership of fifty percent (50%) or more of the outstanding - shares, or (iii) beneficial ownership of such entity. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. - "Contribution" shall mean any original work of authorship, - including any modifications or additions to an existing work, that - is intentionally submitted by You to Khronos for inclusion in, or - documentation of, the Work. For the purposes of this definition, - "submitted" means any form of electronic, verbal, or written - communication sent to Khronos or its representatives, including but - not limited to communication on electronic mailing lists, source - code control systems, and issue tracking systems that are managed - by, or on behalf of, Khronos for the purpose of discussing and - improving the Work, but excluding communication that is - conspicuously marked or otherwise designated in writing by You as - "Not a Contribution." + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -2. Grant of Copyright License. Subject to the terms and conditions of - this Grant, You hereby grant to Khronos and to recipients of - software distributed by Khronos a perpetual, worldwide, non- - exclusive, no-charge, royalty-free, irrevocable copyright license - to reproduce, prepare derivative works of, publicly display, - publicly perform, sublicense, and distribute Your Contributions and - such derivative works. You acknowledge that Khronos is not - obligated to use Your Contribution as part of the Work and may - decide to include only Contributions that Khronos considers - appropriate. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -3. Grant of Patent License. Subject to the terms and conditions of - this Grant, You hereby grant to Khronos and to recipients of - software distributed by Khronos a perpetual, worldwide, non- - exclusive, no-charge, royalty-free, irrevocable (except as stated - in this section) patent license to make, have made, use, offer to - sell, sell, import, and otherwise transfer the Work, where such - license applies only to those patent claims licensable by You that - are necessarily infringed by Your Contribution(s) alone or by - combination of Your Contribution(s) with the Work to which such - Contribution(s) was submitted. If any entity institutes patent - litigation against You or any other entity (including a cross-claim - or counterclaim in a lawsuit) alleging that your Contribution, or - the Work to which you have contributed, constitutes direct or - contributory patent infringement, then any patent licenses granted - to that entity under this Grant for that Contribution or Work shall - terminate as of the date such litigation is filed. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -4. Moral Rights. If moral rights apply to Your Contribution, to the - maximum extent permitted by law, You waive and agree not to assert - such moral rights against Khronos, our successors in interest, or - any of our licensees, either direct or indirect. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -5. You represent that you are legally entitled to grant the above - license. If your employer(s) has rights to intellectual property - that you create that includes your Contributions, you represent - that you have received permission to make Contributions on behalf - of that employer, that your employer has waived such rights for - your Contributions to Khronos, or that your employer has executed a - separate Corporate Contributor License Grant with Khronos. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -6. You represent that each of Your Contributions is Your original - creation (see section 8 for submissions on behalf of others). You - represent that Your Contribution submissions include complete - details of any third-party license or other restriction (including, - but not limited to, related patents and trademarks) of which you - are personally aware and which are associated with any part of Your - Contributions. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -7. You are not expected to provide support for Your Contributions, - except to the extent You desire to provide support. You may provide - support for free, for a fee, or not at all. Unless required by - applicable law or agreed to in writing, You provide Your - Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS - OF ANY KIND, either express or implied, including, without - limitation, any warranties or conditions of TITLE, NON- - INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -8. Should You wish to submit work that is not Your original creation, - You may submit it to Khronos separately from any other - Contribution, identifying the complete details of its source and of - any license or other restriction (including, but not limited to, - related patents, trademarks, and license agreements) of which you - are personally aware, and conspicuously marking the work as - "Submitted on behalf of a third-party: [named here]". + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -9. You agree to notify Khronos of any facts or circumstances of which - you become aware that would make these representations inaccurate - in any respect. + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm index e0d9f65e..723cfd01 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm @@ -59,12 +59,9 @@ void MVKCmdCopyImage::setContent(VkImage srcImage, // Validate clearConfigurationResult(); - if (_srcImage->getMTLPixelFormat() != _dstImage->getMTLPixelFormat()) { - setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): The source and destination images must have the same format.")); + if ((_srcImage->getMTLTextureType() == MTLTextureType3D) != (_dstImage->getMTLTextureType() == MTLTextureType3D)) { + setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Metal does not support copying to or from slices of a 3D texture.")); } - if ((_srcImage->getMTLTextureType() == MTLTextureType3D) || (_dstImage->getMTLTextureType() == MTLTextureType3D)) { - setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Metal does not support copying to or from slices of a 3D texture.")); - } } // Adds a Metal copy region structure for each layer in the specified copy region. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 23208efc..2e67a6a2 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -166,12 +166,17 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, VkExtent3D maxExt; uint32_t maxLayers; uint32_t maxLevels; + VkSampleCountFlags sampleCounts = _metalFeatures.supportedSampleCounts; switch (type) { case VK_IMAGE_TYPE_1D: // Metal does not allow 1D textures to be used as attachments if (mvkIsAnyFlagEnabled(usage, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } + // Metal does not allow linear tiling on 1D textures + if (tiling == VK_IMAGE_TILING_LINEAR) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } maxExt.width = pLimits->maxImageDimension1D; maxExt.height = 1; maxExt.depth = 1; @@ -182,10 +187,35 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, maxExt.width = pLimits->maxImageDimension2D; maxExt.height = pLimits->maxImageDimension2D; maxExt.depth = 1; - maxLevels = mvkMipmapLevels3D(maxExt); - maxLayers = pLimits->maxImageArrayLayers; + if (tiling == VK_IMAGE_TILING_LINEAR) { + // Linear textures have additional restrictions under Metal: + // - They may not be depth/stencil or compressed textures. + if (mvkFormatTypeFromVkFormat(format) == kMVKFormatDepthStencil || + mvkFormatTypeFromVkFormat(format) == kMVKFormatNone) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } +#if MVK_MACOS + // - On macOS, they may not be used as framebuffer attachments. + if (mvkIsAnyFlagEnabled(usage, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT|VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) ) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } +#endif + // - They may only have one mip level. + maxLevels = 1; + // - They may only have one layer. + maxLayers = 1; + // - They may not be multisampled. + sampleCounts = VK_SAMPLE_COUNT_1_BIT; + } else { + maxLevels = mvkMipmapLevels3D(maxExt); + maxLayers = pLimits->maxImageArrayLayers; + } break; case VK_IMAGE_TYPE_3D: + // Metal does not allow linear tiling on 3D textures + if (tiling == VK_IMAGE_TILING_LINEAR) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } maxExt.width = pLimits->maxImageDimension3D; maxExt.height = pLimits->maxImageDimension3D; maxExt.depth = pLimits->maxImageDimension3D; @@ -193,6 +223,10 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, maxLayers = 1; break; default: + // Metal does not allow linear tiling on anything but 2D textures + if (tiling == VK_IMAGE_TILING_LINEAR) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } maxExt = { 1, 1, 1}; maxLayers = 1; maxLevels = 1; @@ -202,7 +236,7 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, pImageFormatProperties->maxExtent = maxExt; pImageFormatProperties->maxMipLevels = maxLevels; pImageFormatProperties->maxArrayLayers = maxLayers; - pImageFormatProperties->sampleCounts = _metalFeatures.supportedSampleCounts; + pImageFormatProperties->sampleCounts = sampleCounts; pImageFormatProperties->maxResourceSize = kMVKUndefinedLargeUInt64; return VK_SUCCESS; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm index a470d24d..4ed44dc3 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm @@ -124,7 +124,6 @@ VkResult MVKDeviceMemory::addBuffer(MVKBuffer* mvkBuff) { void MVKDeviceMemory::removeBuffer(MVKBuffer* mvkBuff) { lock_guard lock(_rezLock); - if (_isDedicated) return; mvkRemoveAllOccurances(_buffers, mvkBuff); } @@ -145,7 +144,6 @@ VkResult MVKDeviceMemory::addImage(MVKImage* mvkImg) { void MVKDeviceMemory::removeImage(MVKImage* mvkImg) { lock_guard lock(_rezLock); - if (_isDedicated) return; mvkRemoveAllOccurances(_images, mvkImg); } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 030f0e24..8d936a5d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -546,10 +546,12 @@ bool MVKImage::validateLinear(const VkImageCreateInfo* pCreateInfo) { return false; } - if ( !mvkAreOnlyAnyFlagsEnabled(_usage, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)) ) { - setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, usage must only include VK_IMAGE_USAGE_TRANSFER_SRC_BIT and/or VK_IMAGE_USAGE_TRANSFER_DST_BIT.")); +#if MVK_MACOS + if ( mvkIsAnyFlagEnabled(_usage, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) ) { + setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, usage must not include VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, and/or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT.")); return false; } +#endif return true; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index 3200b547..eeb209d9 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -280,7 +280,7 @@ void MVKGraphicsPipeline::initMTLRenderPipelineState(const VkGraphicsPipelineCre MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo) { // Collect extension structures VkPipelineVertexInputDivisorStateCreateInfoEXT* pVertexInputDivisorState = nullptr; - VkStructureType* next = (VkStructureType*)pCreateInfo->pNext; + VkStructureType* next = (VkStructureType*)pCreateInfo->pVertexInputState->pNext; while (next) { switch (*next) { case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: @@ -288,7 +288,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor next = (VkStructureType*)pVertexInputDivisorState->pNext; break; default: - next = (VkStructureType*)((VkGraphicsPipelineCreateInfo*)next)->pNext; + next = (VkStructureType*)((VkPipelineVertexInputStateCreateInfo*)next)->pNext; break; } } @@ -383,13 +383,18 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx]; colorDesc.pixelFormat = mtlPixelFormatFromVkFormat(mvkRenderSubpass->getColorAttachmentFormat(caIdx)); colorDesc.writeMask = mvkMTLColorWriteMaskFromVkChannelFlags(pCA->colorWriteMask); - colorDesc.blendingEnabled = pCA->blendEnable; - colorDesc.rgbBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->colorBlendOp); - colorDesc.sourceRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcColorBlendFactor); - colorDesc.destinationRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstColorBlendFactor); - colorDesc.alphaBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->alphaBlendOp); - colorDesc.sourceAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcAlphaBlendFactor); - colorDesc.destinationAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstAlphaBlendFactor); + // Don't set the blend state if we're not using this attachment. + // The pixel format will be MTLPixelFormatInvalid in that case, and + // Metal asserts if we turn on blending with that pixel format. + if (mvkRenderSubpass->isColorAttachmentUsed(caIdx)) { + colorDesc.blendingEnabled = pCA->blendEnable; + colorDesc.rgbBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->colorBlendOp); + colorDesc.sourceRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcColorBlendFactor); + colorDesc.destinationRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstColorBlendFactor); + colorDesc.alphaBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->alphaBlendOp); + colorDesc.sourceAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcAlphaBlendFactor); + colorDesc.destinationAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstAlphaBlendFactor); + } } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h index 43fc8f14..74495507 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h @@ -41,6 +41,9 @@ public: /** Returns the format of the color attachment at the specified index. */ VkFormat getColorAttachmentFormat(uint32_t colorAttIdx); + /** Returns whether or not the color attachment at the specified index is being used. */ + bool isColorAttachmentUsed(uint32_t colorAttIdx); + /** Returns the format of the depth/stencil attachment. */ VkFormat getDepthStencilFormat(); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm index a4216d9f..69740dda 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm @@ -37,6 +37,13 @@ VkFormat MVKRenderSubpass::getColorAttachmentFormat(uint32_t colorAttIdx) { return VK_FORMAT_UNDEFINED; } +bool MVKRenderSubpass::isColorAttachmentUsed(uint32_t colorAttIdx) { + if (colorAttIdx >= _colorAttachments.size()) { + return false; + } + return _colorAttachments[colorAttIdx].attachment != VK_ATTACHMENT_UNUSED; +} + VkFormat MVKRenderSubpass::getDepthStencilFormat() { uint32_t rpAttIdx = _depthStencilAttachment.attachment; if (rpAttIdx == VK_ATTACHMENT_UNUSED) { return VK_FORMAT_UNDEFINED; } diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm index 3e67654a..535dacdc 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm @@ -61,10 +61,14 @@ using namespace std; # define MVK_FMT_DEPTH_FEATS (MVK_FMT_STENCIL_FEATS | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) #endif -#define MVK_FMT_LINEAR_TILING_FEATS (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT \ - | VK_FORMAT_FEATURE_TRANSFER_DST_BIT \ +#if MVK_MACOS +// macOS does not support linear images as framebuffer attachments. +#define MVK_FMT_LINEAR_TILING_FEATS (MVK_FMT_IMAGE_FEATS \ | VK_FORMAT_FEATURE_BLIT_SRC_BIT \ | VK_FORMAT_FEATURE_BLIT_DST_BIT) +#else +#define MVK_FMT_LINEAR_TILING_FEATS MVK_FMT_COLOR_FEATS +#endif #define MVK_FMT_BUFFER_FEATS (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT \ | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT \ @@ -269,7 +273,7 @@ static const MVKFormatDesc _formatDescriptions[] { MVK_MAKE_FMT_STRUCT( VK_FORMAT_A2R10G10B10_UINT_PACK32, MTLPixelFormatInvalid, MTLPixelFormatInvalid, kMTLFmtNA, kMTLFmtNA, 1, 1, 4, MTLVertexFormatInvalid, kMVKFormatColorUInt32, MVK_FMT_NO_FEATS, MVK_FMT_NO_FEATS ), MVK_MAKE_FMT_STRUCT( VK_FORMAT_A2R10G10B10_SINT_PACK32, MTLPixelFormatInvalid, MTLPixelFormatInvalid, kMTLFmtNA, kMTLFmtNA, 1, 1, 4, MTLVertexFormatInvalid, kMVKFormatColorInt32, MVK_FMT_NO_FEATS, MVK_FMT_NO_FEATS ), - MVK_MAKE_FMT_STRUCT( VK_FORMAT_A2B10G10R10_UNORM_PACK32, MTLPixelFormatRGB10A2Unorm, MTLPixelFormatInvalid, 8.0, 10.11, 1, 1, 4, MTLVertexFormatInvalid, kMVKFormatColorFloat, MVK_FMT_COLOR_FEATS, MVK_FMT_BUFFER_FEATS ), // Vulkan packed is reversed + MVK_MAKE_FMT_STRUCT( VK_FORMAT_A2B10G10R10_UNORM_PACK32, MTLPixelFormatRGB10A2Unorm, MTLPixelFormatInvalid, 8.0, 10.11, 1, 1, 4, MTLVertexFormatUInt1010102Normalized, kMVKFormatColorFloat, MVK_FMT_COLOR_FEATS, MVK_FMT_BUFFER_VTX_FEATS ), // Vulkan packed is reversed MVK_MAKE_FMT_STRUCT( VK_FORMAT_A2B10G10R10_SNORM_PACK32, MTLPixelFormatInvalid, MTLPixelFormatInvalid, kMTLFmtNA, kMTLFmtNA, 1, 1, 4, MTLVertexFormatInt1010102Normalized, kMVKFormatColorFloat, MVK_FMT_NO_FEATS, MVK_FMT_NO_FEATS ), MVK_MAKE_FMT_STRUCT( VK_FORMAT_A2B10G10R10_USCALED_PACK32, MTLPixelFormatInvalid, MTLPixelFormatInvalid, kMTLFmtNA, kMTLFmtNA, 1, 1, 4, MTLVertexFormatInvalid, kMVKFormatColorFloat, MVK_FMT_NO_FEATS, MVK_FMT_NO_FEATS ), MVK_MAKE_FMT_STRUCT( VK_FORMAT_A2B10G10R10_SSCALED_PACK32, MTLPixelFormatInvalid, MTLPixelFormatInvalid, kMTLFmtNA, kMTLFmtNA, 1, 1, 4, MTLVertexFormatInvalid, kMVKFormatColorFloat, MVK_FMT_NO_FEATS, MVK_FMT_NO_FEATS ),