From a723dc1f21cf5d2bb5f25807c52b369bb4f46995 Mon Sep 17 00:00:00 2001 From: UnsafeBy Date: Fri, 28 May 2021 23:28:20 +0800 Subject: [PATCH 1/6] Support the VK_KHR_imageless_framebuffer extension. I'm not sure this is the elegant way but it works in my own project:) --- Docs/MoltenVK_Runtime_UserGuide.md | 1 + MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h | 1 + .../MoltenVK/Commands/MVKCmdRenderPass.mm | 16 +++++++- MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h | 4 +- .../MoltenVK/Commands/MVKCommandBuffer.mm | 13 +++++-- MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 1 + MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 20 +++++++++- MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h | 3 ++ .../MoltenVK/GPUObjects/MVKFramebuffer.mm | 15 +++++--- MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h | 6 ++- MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm | 38 +++++++++++++++---- MoltenVK/MoltenVK/Layers/MVKExtensions.def | 1 + 12 files changed, 100 insertions(+), 19 deletions(-) diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index 3ee145f6..413436cc 100644 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -273,6 +273,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_KHR_get_memory_requirements2` - `VK_KHR_get_physical_device_properties2` - `VK_KHR_get_surface_capabilities2` +- `VK_KHR_imageless_framebuffer` - `VK_KHR_image_format_list` - `VK_KHR_maintenance1` - `VK_KHR_maintenance2` diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h index 70c7ba2d..c5b76f88 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h @@ -50,6 +50,7 @@ protected: MVKFramebuffer* _framebuffer; VkRect2D _renderArea; VkSubpassContents _contents; + MVKSmallVector _imagelessAttachments; }; diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm index 7f523f10..a987c52a 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm @@ -36,6 +36,20 @@ VkResult MVKCmdBeginRenderPassBase::setContent(MVKCommandBuffer* cmdBuff, _framebuffer = (MVKFramebuffer*)pRenderPassBegin->framebuffer; _renderArea = pRenderPassBegin->renderArea; + for (auto* next = (const VkBaseInStructure*)pRenderPassBegin->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: { + const auto* pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next; + for(uint32_t i = 0; i < pAttachmentBegin->attachmentCount; i++) { + _imagelessAttachments.push_back((MVKImageView*)pAttachmentBegin->pAttachments[i]); + } + break; + } + default: + break; + } + } + return VK_SUCCESS; } @@ -70,7 +84,7 @@ VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, template void MVKCmdBeginRenderPass::encode(MVKCommandEncoder* cmdEncoder) { // MVKLogDebug("Encoding vkCmdBeginRenderPass(). Elapsed time: %.6f ms.", mvkGetElapsedMilliseconds()); - cmdEncoder->beginRenderpass(this, _contents, _renderPass, _framebuffer, _renderArea, _clearValues.contents()); + cmdEncoder->beginRenderpass(this, _contents, _renderPass, _framebuffer, _renderArea, _clearValues.contents(), _imagelessAttachments.contents()); } template class MVKCmdBeginRenderPass<1>; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h index 6bc4f4e5..9cd4ab54 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h @@ -275,7 +275,8 @@ public: MVKRenderPass* renderPass, MVKFramebuffer* framebuffer, VkRect2D& renderArea, - MVKArrayRef clearValues); + MVKArrayRef clearValues, + MVKArrayRef imageless_attachments); /** Begins the next render subpass. */ void beginNextSubpass(MVKCommand* subpassCmd, VkSubpassContents renderpassContents); @@ -494,6 +495,7 @@ protected: VkRect2D _renderArea; MVKActivatedQueries* _pActivatedQueries; MVKSmallVector _clearValues; + MVKSmallVector _imagelessAttachments; id _mtlComputeEncoder; MVKCommandUse _mtlComputeEncoderUse; id _mtlBlitEncoder; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index 2de0f531..54424cd0 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -288,13 +288,17 @@ void MVKCommandEncoder::beginRenderpass(MVKCommand* passCmd, MVKRenderPass* renderPass, MVKFramebuffer* framebuffer, VkRect2D& renderArea, - MVKArrayRef clearValues) { + MVKArrayRef clearValues, + MVKArrayRef imagelessAttachments) { _renderPass = renderPass; _framebuffer = framebuffer; _renderArea = renderArea; _isRenderingEntireAttachment = (mvkVkOffset2DsAreEqual(_renderArea.offset, {0,0}) && mvkVkExtent2DsAreEqual(_renderArea.extent, _framebuffer->getExtent2D())); _clearValues.assign(clearValues.begin(), clearValues.end()); + for(auto* v : imagelessAttachments) { + _imagelessAttachments.push_back(v); + } setSubpass(passCmd, subpassContents, 0); } @@ -334,7 +338,7 @@ void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) { endCurrentMetalEncoding(); MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor]; - getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _multiviewPassIndex, _framebuffer, _clearValues.contents(), _isRenderingEntireAttachment, loadOverride); + getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _multiviewPassIndex, _framebuffer, _imagelessAttachments.contents(), _clearValues.contents(), _isRenderingEntireAttachment, loadOverride); if (_cmdBuffer->_needsVisibilityResultMTLBuffer) { if (!_visibilityResultMTLBuffer) { _visibilityResultMTLBuffer = getTempMTLBuffer(_pDeviceMetalFeatures->maxQueryBufferSize, true, true); @@ -393,7 +397,10 @@ void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) { } void MVKCommandEncoder::encodeStoreActions(bool storeOverride) { - getSubpass()->encodeStoreActions(this, _isRenderingEntireAttachment, storeOverride); + getSubpass()->encodeStoreActions(this, + _isRenderingEntireAttachment, + _imagelessAttachments.contents(), + storeOverride); } MVKRenderSubpass* MVKCommandEncoder::getSubpass() { return _renderPass->getSubpass(_renderSubpassIndex); } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index b1bd3577..8eef871d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -738,6 +738,7 @@ public: const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT _enabledTexelBuffAlignFeatures; const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT _enabledVtxAttrDivFeatures; const VkPhysicalDevicePortabilitySubsetFeaturesKHR _enabledPortabilityFeatures; + const VkPhysicalDeviceImagelessFramebufferFeaturesKHR _enabledImagelessFramebufferFeatures; /** The list of Vulkan extensions, indicating whether each has been enabled by the app for this device. */ const MVKExtensionList _enabledExtensions; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index e70de7e3..013b2518 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -267,6 +267,11 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) { inlineUniformBlockFeatures->descriptorBindingInlineUniformBlockUpdateAfterBind = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES: { + auto* imagelessFramebufferFeatures = (VkPhysicalDeviceImagelessFramebufferFeaturesKHR*)next; + imagelessFramebufferFeatures->imagelessFramebuffer = true; + break; + } default: break; } @@ -3789,6 +3794,7 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo _enabledVtxAttrDivFeatures(), _enabledPrivateDataFeatures(), _enabledPortabilityFeatures(), + _enabledImagelessFramebufferFeatures(), _enabledExtensions(this), _isCurrentlyAutoGPUCapturing(false) { @@ -3899,11 +3905,16 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) { mvkClear(&_enabledTexelBuffAlignFeatures); mvkClear(&_enabledVtxAttrDivFeatures); mvkClear(&_enabledPortabilityFeatures); + mvkClear(&_enabledImagelessFramebufferFeatures); + VkPhysicalDeviceImagelessFramebufferFeaturesKHR pdImagelessFramebufferFeatures; + pdImagelessFramebufferFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES; + pdImagelessFramebufferFeatures.pNext = NULL; + // Fetch the available physical device features. VkPhysicalDevicePortabilitySubsetFeaturesKHR pdPortabilityFeatures; pdPortabilityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR; - pdPortabilityFeatures.pNext = NULL; + pdPortabilityFeatures.pNext = &pdImagelessFramebufferFeatures; VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT pdVtxAttrDivFeatures; pdVtxAttrDivFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; @@ -4088,6 +4099,13 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) { &pdPortabilityFeatures.constantAlphaColorBlendFactors, 15); break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES: { + auto* requestedFeatures = (VkPhysicalDeviceImagelessFramebufferFeaturesKHR*)next; + enableFeatures(&_enabledImagelessFramebufferFeatures.imagelessFramebuffer, + &requestedFeatures->imagelessFramebuffer, + &pdImagelessFramebufferFeatures.imagelessFramebuffer, 1); + break; + } default: break; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h index 16a2a22c..0fc06b41 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h @@ -45,6 +45,7 @@ public: /** Returns the attachment at the specified index. */ inline MVKImageView* getAttachment(uint32_t index) { return _attachments[index]; } + inline bool getImageless() { return _imageless; } #pragma mark Construction @@ -57,5 +58,7 @@ protected: VkExtent2D _extent; uint32_t _layerCount; MVKSmallVector _attachments; + bool _imageless; + MVKSmallVector _imagelessAttachments; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm index 66af186c..18d442a4 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm @@ -28,10 +28,15 @@ MVKFramebuffer::MVKFramebuffer(MVKDevice* device, _extent = { .width = pCreateInfo->width, .height = pCreateInfo->height }; _layerCount = pCreateInfo->layers; - // Add attachments - _attachments.reserve(pCreateInfo->attachmentCount); - for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { - _attachments.push_back((MVKImageView*)pCreateInfo->pAttachments[i]); + if (pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR) { + _imageless = true; + } + else { + _imageless = false; + // Add attachments + _attachments.reserve(pCreateInfo->attachmentCount); + for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { + _attachments.push_back((MVKImageView*)pCreateInfo->pAttachments[i]); + } } } - diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h index fdb90771..8c0a89f1 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h @@ -96,6 +96,7 @@ public: void populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc, uint32_t passIdx, MVKFramebuffer* framebuffer, + const MVKArrayRef& imagelessAttachments, const MVKArrayRef& clearValues, bool isRenderingEntireAttachment, bool loadOverride = false); @@ -117,7 +118,10 @@ public: uint32_t caIdx, VkImageAspectFlags aspectMask); /** If a render encoder is active, sets the store actions for all attachments to it. */ - void encodeStoreActions(MVKCommandEncoder* cmdEncoder, bool isRenderingEntireAttachment, bool storeOverride = false); + void encodeStoreActions(MVKCommandEncoder* cmdEncoder, + bool isRenderingEntireAttachment, + const MVKArrayRef& imagelessAttachments, + bool storeOverride = false); /** Constructs an instance for the specified parent renderpass. */ MVKRenderSubpass(MVKRenderPass* renderPass, const VkSubpassDescription* pCreateInfo, diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm index 4a09569b..0b8f2a9d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm @@ -176,10 +176,12 @@ uint32_t MVKRenderSubpass::getViewCountUpToMetalPass(uint32_t passIdx) const { void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc, uint32_t passIdx, MVKFramebuffer* framebuffer, + const MVKArrayRef& imagelessAttachments, const MVKArrayRef& clearValues, bool isRenderingEntireAttachment, bool loadOverride) { MVKPixelFormats* pixFmts = _renderPass->getPixelFormats(); + bool imageless = framebuffer->getImageless(); // Populate the Metal color attachments uint32_t caCnt = getColorAttachmentCount(); @@ -195,7 +197,13 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* uint32_t rslvRPAttIdx = _resolveAttachments.empty() ? VK_ATTACHMENT_UNUSED : _resolveAttachments[caIdx].attachment; bool hasResolveAttachment = (rslvRPAttIdx != VK_ATTACHMENT_UNUSED); if (hasResolveAttachment) { - framebuffer->getAttachment(rslvRPAttIdx)->populateMTLRenderPassAttachmentDescriptorResolve(mtlColorAttDesc); + if (imageless) { + imagelessAttachments[rslvRPAttIdx]->populateMTLRenderPassAttachmentDescriptorResolve(mtlColorAttDesc); + } + else { + framebuffer->getAttachment(rslvRPAttIdx)->populateMTLRenderPassAttachmentDescriptorResolve(mtlColorAttDesc); + } + // In a multiview render pass, we need to override the starting layer to ensure // only the enabled views are loaded. if (isMultiview()) { @@ -209,10 +217,17 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* // Configure the color attachment MVKRenderPassAttachment* clrMVKRPAtt = &_renderPass->_attachments[clrRPAttIdx]; - framebuffer->getAttachment(clrRPAttIdx)->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc); + if (imageless) { + imagelessAttachments[clrRPAttIdx]->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc); + } + else { + framebuffer->getAttachment(clrRPAttIdx)->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc); + } bool isMemorylessAttachment = false; #if MVK_APPLE_SILICON - isMemorylessAttachment = framebuffer->getAttachment(clrRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; + isMemorylessAttachment = imageless + ? imagelessAttachments[clrRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless + : framebuffer->getAttachment(clrRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; #endif if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this, isRenderingEntireAttachment, @@ -236,12 +251,16 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* uint32_t dsRslvRPAttIdx = _depthStencilResolveAttachment.attachment; if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) { MVKRenderPassAttachment* dsMVKRPAtt = &_renderPass->_attachments[dsRPAttIdx]; - MVKImageView* dsImage = framebuffer->getAttachment(dsRPAttIdx); + MVKImageView* dsImage = imageless + ? imagelessAttachments[dsRPAttIdx] + : framebuffer->getAttachment(dsRPAttIdx); MVKImageView* dsRslvImage = nullptr; MTLPixelFormat mtlDSFormat = dsImage->getMTLPixelFormat(0); if (dsRslvRPAttIdx != VK_ATTACHMENT_UNUSED) { - dsRslvImage = framebuffer->getAttachment(dsRslvRPAttIdx); + dsRslvImage = imageless + ? imagelessAttachments[dsRslvRPAttIdx] + : framebuffer->getAttachment(dsRslvRPAttIdx); } if (pixFmts->isDepthFormat(mtlDSFormat)) { @@ -366,6 +385,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder, bool isRenderingEntireAttachment, + const MVKArrayRef& imagelessAttachments, bool storeOverride) { if (!cmdEncoder->_mtlRenderEncoder) { return; } if (!_renderPass->getDevice()->_pMetalFeatures->deferredStoreActions) { return; } @@ -377,7 +397,9 @@ void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder, bool hasResolveAttachment = _resolveAttachments.empty() ? false : _resolveAttachments[caIdx].attachment != VK_ATTACHMENT_UNUSED; bool isMemorylessAttachment = false; #if MVK_APPLE_SILICON - isMemorylessAttachment = cmdEncoder->_framebuffer->getAttachment(clrRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; + isMemorylessAttachment = cmdEncoder->_framebuffer->getImageless() + ? imagelessAttachments[clrRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless + : cmdEncoder->_framebuffer->getAttachment(clrRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; #endif _renderPass->_attachments[clrRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, caIdx, false, storeOverride); } @@ -389,7 +411,9 @@ void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder, bool hasStencilResolveAttachment = hasResolveAttachment && _stencilResolveMode != VK_RESOLVE_MODE_NONE; bool isMemorylessAttachment = false; #if MVK_APPLE_SILICON - isMemorylessAttachment = cmdEncoder->_framebuffer->getAttachment(dsRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; + isMemorylessAttachment = cmdEncoder->_framebuffer->getImageless() + ? imagelessAttachments[dsRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless + : cmdEncoder->_framebuffer->getAttachment(dsRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; #endif _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasDepthResolveAttachment, 0, false, storeOverride); _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasStencilResolveAttachment, 0, true, storeOverride); diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index 5fb1c189..a80de24a 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -58,6 +58,7 @@ MVK_EXTENSION(KHR_external_semaphore_capabilities, KHR_EXTERNAL_SEMAPHORE_CAPABI MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, DEVICE) MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, INSTANCE) MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, INSTANCE) +MVK_EXTENSION(KHR_imageless_framebuffer, KHR_IMAGELESS_FRAMEBUFFER, DEVICE) MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, DEVICE) MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, DEVICE) MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, DEVICE) From 797b92e606626eaf8f2933c898b897dab9af76bd Mon Sep 17 00:00:00 2001 From: UnsafeBy <12209857+f32by@users.noreply.github.com> Date: Sat, 29 May 2021 10:00:19 +0800 Subject: [PATCH 2/6] Update MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h Co-authored-by: Chip Davis --- MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h index 9cd4ab54..f6f93ee8 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h @@ -276,7 +276,7 @@ public: MVKFramebuffer* framebuffer, VkRect2D& renderArea, MVKArrayRef clearValues, - MVKArrayRef imageless_attachments); + MVKArrayRef imagelessAttachments); /** Begins the next render subpass. */ void beginNextSubpass(MVKCommand* subpassCmd, VkSubpassContents renderpassContents); @@ -522,4 +522,3 @@ NSString* mvkMTLBlitCommandEncoderLabel(MVKCommandUse cmdUse); /** Returns a name, suitable for use as a MTLComputeCommandEncoder label, based on the MVKCommandUse. */ NSString* mvkMTLComputeCommandEncoderLabel(MVKCommandUse cmdUse); - From c49ad89ffac8e0275950388514534a7eb5e27472 Mon Sep 17 00:00:00 2001 From: UnsafeBy <12209857+f32by@users.noreply.github.com> Date: Sat, 29 May 2021 10:00:27 +0800 Subject: [PATCH 3/6] Update MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm Co-authored-by: Chip Davis --- MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index 54424cd0..c52bb98d 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -296,9 +296,7 @@ void MVKCommandEncoder::beginRenderpass(MVKCommand* passCmd, _isRenderingEntireAttachment = (mvkVkOffset2DsAreEqual(_renderArea.offset, {0,0}) && mvkVkExtent2DsAreEqual(_renderArea.extent, _framebuffer->getExtent2D())); _clearValues.assign(clearValues.begin(), clearValues.end()); - for(auto* v : imagelessAttachments) { - _imagelessAttachments.push_back(v); - } + _imagelessAttachments.assign(imagelessAttachments.begin(), imagelessAttachments.end()); setSubpass(passCmd, subpassContents, 0); } @@ -843,4 +841,3 @@ NSString* mvkMTLComputeCommandEncoderLabel(MVKCommandUse cmdUse) { default: return @"Unknown Use ComputeEncoder"; } } - From 703cdcf332d089ae9f910f9f6b8be3cdbb1f1df0 Mon Sep 17 00:00:00 2001 From: UnsafeBy Date: Sat, 29 May 2021 11:59:42 +0800 Subject: [PATCH 4/6] Update: support the VK_KHR_imageless_framebuffer extension. Remove framebuffer reference in MVKCommandEncoder. Instead, 1) non-imageless: copy the attachment vector from VkFramebufferCreateInfo if it does not contain the VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR flag. or 2) imageless: copy the attachment vector from VkRenderPassAttachmentBeginInfo when calling vkBeginRenderPass/vkBeginRenderPass2. --- MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h | 20 ++++-- .../MoltenVK/Commands/MVKCmdRenderPass.mm | 72 ++++++++++++------- MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm | 4 +- MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h | 15 ++-- .../MoltenVK/Commands/MVKCommandBuffer.mm | 36 ++++++---- .../MoltenVK/Commands/MVKCommandTypePools.def | 12 +++- MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h | 6 +- .../MoltenVK/GPUObjects/MVKFramebuffer.mm | 6 +- MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h | 7 +- MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm | 48 ++++--------- MoltenVK/MoltenVK/Vulkan/vulkan.mm | 61 +++++++++++++++- 11 files changed, 187 insertions(+), 100 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h index c5b76f88..858473b1 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h @@ -50,7 +50,6 @@ protected: MVKFramebuffer* _framebuffer; VkRect2D _renderArea; VkSubpassContents _contents; - MVKSmallVector _imagelessAttachments; }; @@ -61,7 +60,7 @@ protected: * Vulkan command to begin a render pass. * Template class to balance vector pre-allocations between very common low counts and fewer larger counts. */ -template +template class MVKCmdBeginRenderPass : public MVKCmdBeginRenderPassBase { public: @@ -77,13 +76,22 @@ public: protected: MVKCommandTypePool* getTypePool(MVKCommandPool* cmdPool) override; - MVKSmallVector _clearValues; + MVKSmallVector _clearValues; + MVKSmallVector _attachments; }; // Concrete template class implementations. -typedef MVKCmdBeginRenderPass<1> MVKCmdBeginRenderPass1; -typedef MVKCmdBeginRenderPass<2> MVKCmdBeginRenderPass2; -typedef MVKCmdBeginRenderPass<9> MVKCmdBeginRenderPassMulti; +typedef MVKCmdBeginRenderPass<1, 0> MVKCmdBeginRenderPass10; +typedef MVKCmdBeginRenderPass<2, 0> MVKCmdBeginRenderPass20; +typedef MVKCmdBeginRenderPass<9, 0> MVKCmdBeginRenderPassMulti0; + +typedef MVKCmdBeginRenderPass<1, 1> MVKCmdBeginRenderPass11; +typedef MVKCmdBeginRenderPass<2, 1> MVKCmdBeginRenderPass21; +typedef MVKCmdBeginRenderPass<9, 1> MVKCmdBeginRenderPassMulti1; + +typedef MVKCmdBeginRenderPass<1, 8> MVKCmdBeginRenderPass1Multi; +typedef MVKCmdBeginRenderPass<2, 8> MVKCmdBeginRenderPass2Multi; +typedef MVKCmdBeginRenderPass<9, 8> MVKCmdBeginRenderPassMultiMulti; #pragma mark - diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm index a987c52a..08113104 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm @@ -19,6 +19,7 @@ #include "MVKCmdRenderPass.h" #include "MVKCommandBuffer.h" #include "MVKCommandPool.h" +#include "MVKFramebuffer.h" #include "MVKRenderPass.h" #include "MVKPipeline.h" #include "MVKFoundation.h" @@ -36,20 +37,6 @@ VkResult MVKCmdBeginRenderPassBase::setContent(MVKCommandBuffer* cmdBuff, _framebuffer = (MVKFramebuffer*)pRenderPassBegin->framebuffer; _renderArea = pRenderPassBegin->renderArea; - for (auto* next = (const VkBaseInStructure*)pRenderPassBegin->pNext; next; next = next->pNext) { - switch (next->sType) { - case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: { - const auto* pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next; - for(uint32_t i = 0; i < pAttachmentBegin->attachmentCount; i++) { - _imagelessAttachments.push_back((MVKImageView*)pAttachmentBegin->pAttachments[i]); - } - break; - } - default: - break; - } - } - return VK_SUCCESS; } @@ -57,8 +44,8 @@ VkResult MVKCmdBeginRenderPassBase::setContent(MVKCommandBuffer* cmdBuff, #pragma mark - #pragma mark MVKCmdBeginRenderPass -template -VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, +template +VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) { MVKCmdBeginRenderPassBase::setContent(cmdBuff, pRenderPassBegin, contents); @@ -71,25 +58,62 @@ VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, _clearValues.push_back(pRenderPassBegin->pClearValues[i]); } + bool imageless = false; + for (auto* next = (const VkBaseInStructure*)pRenderPassBegin->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: { + const auto* pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next; + for(uint32_t i = 0; i < pAttachmentBegin->attachmentCount; i++) { + _attachments.push_back((MVKImageView*)pAttachmentBegin->pAttachments[i]); + } + imageless = true; + break; + } + default: + break; + } + } + + if (!imageless) { + for(uint32_t i = 0; i < _framebuffer->getAttachmentCount(); i++) { + _attachments.push_back((MVKImageView*)_framebuffer->getAttachment(i)); + } + } + return VK_SUCCESS; } -template -VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, +template +VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo) { return setContent(cmdBuff, pRenderPassBegin, pSubpassBeginInfo->contents); } -template -void MVKCmdBeginRenderPass::encode(MVKCommandEncoder* cmdEncoder) { +template +void MVKCmdBeginRenderPass::encode(MVKCommandEncoder* cmdEncoder) { // MVKLogDebug("Encoding vkCmdBeginRenderPass(). Elapsed time: %.6f ms.", mvkGetElapsedMilliseconds()); - cmdEncoder->beginRenderpass(this, _contents, _renderPass, _framebuffer, _renderArea, _clearValues.contents(), _imagelessAttachments.contents()); + cmdEncoder->beginRenderpass(this, + _contents, + _renderPass, + _framebuffer->getExtent2D(), + _framebuffer->getLayerCount(), + _renderArea, + _clearValues.contents(), + _attachments.contents()); } -template class MVKCmdBeginRenderPass<1>; -template class MVKCmdBeginRenderPass<2>; -template class MVKCmdBeginRenderPass<9>; +template class MVKCmdBeginRenderPass<1, 0>; +template class MVKCmdBeginRenderPass<2, 0>; +template class MVKCmdBeginRenderPass<9, 0>; + +template class MVKCmdBeginRenderPass<1, 1>; +template class MVKCmdBeginRenderPass<2, 1>; +template class MVKCmdBeginRenderPass<9, 1>; + +template class MVKCmdBeginRenderPass<1, 8>; +template class MVKCmdBeginRenderPass<2, 8>; +template class MVKCmdBeginRenderPass<9, 8>; #pragma mark - diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm index df50a7d0..7d1d3797 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm @@ -1236,7 +1236,7 @@ void MVKCmdClearAttachments::encode(MVKCommandEncoder* cmdEncoder) { simd::float4 vertices[vtxCnt]; simd::float4 clearColors[kMVKClearAttachmentCount]; - VkExtent2D fbExtent = cmdEncoder->_framebuffer->getExtent2D(); + VkExtent2D fbExtent = cmdEncoder->_framebufferExtent; #if MVK_MACOS_OR_IOS // I need to know if the 'renderTargetWidth' and 'renderTargetHeight' properties // actually do something, but [MTLRenderPassDescriptor instancesRespondToSelector: @selector(renderTargetWidth)] @@ -1257,7 +1257,7 @@ void MVKCmdClearAttachments::encode(MVKCommandEncoder* cmdEncoder) { // Populate the render pipeline state attachment key with info from the subpass and framebuffer. _rpsKey.mtlSampleCount = mvkSampleCountFromVkSampleCountFlagBits(subpass->getSampleCount()); if (cmdEncoder->_canUseLayeredRendering && - (cmdEncoder->_framebuffer->getLayerCount() > 1 || cmdEncoder->getSubpass()->isMultiview())) { + (cmdEncoder->_framebufferLayerCount > 1 || cmdEncoder->getSubpass()->isMultiview())) { _rpsKey.enableLayeredRendering(); } diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h index f6f93ee8..88d7813e 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h @@ -273,10 +273,11 @@ public: void beginRenderpass(MVKCommand* passCmd, VkSubpassContents subpassContents, MVKRenderPass* renderPass, - MVKFramebuffer* framebuffer, + VkExtent2D framebufferExtent, + uint32_t framebufferLayerCount, VkRect2D& renderArea, MVKArrayRef clearValues, - MVKArrayRef imagelessAttachments); + MVKArrayRef attachments); /** Begins the next render subpass. */ void beginNextSubpass(MVKCommand* subpassCmd, VkSubpassContents renderpassContents); @@ -421,9 +422,6 @@ public: /** The command buffer whose commands are being encoded. */ MVKCommandBuffer* _cmdBuffer; - /** The framebuffer to which rendering is currently directed. */ - MVKFramebuffer* _framebuffer; - /** The current Metal command buffer. */ id _mtlCmdBuffer; @@ -475,6 +473,11 @@ public: /** Indicates whether the current draw is an indexed draw. */ bool _isIndexedDraw; + /** The extent of current framebuffer.*/ + VkExtent2D _framebufferExtent; + + /** The layer count of current framebuffer.*/ + uint32_t _framebufferLayerCount; #pragma mark Construction @@ -495,7 +498,7 @@ protected: VkRect2D _renderArea; MVKActivatedQueries* _pActivatedQueries; MVKSmallVector _clearValues; - MVKSmallVector _imagelessAttachments; + MVKSmallVector _attachments; id _mtlComputeEncoder; MVKCommandUse _mtlComputeEncoderUse; id _mtlBlitEncoder; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index c52bb98d..15f8daac 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -20,7 +20,6 @@ #include "MVKCommandPool.h" #include "MVKQueue.h" #include "MVKPipeline.h" -#include "MVKFramebuffer.h" #include "MVKQueryPool.h" #include "MVKFoundation.h" #include "MTLRenderPassDescriptor+MoltenVK.h" @@ -286,17 +285,21 @@ void MVKCommandEncoder::encodeSecondary(MVKCommandBuffer* secondaryCmdBuffer) { void MVKCommandEncoder::beginRenderpass(MVKCommand* passCmd, VkSubpassContents subpassContents, MVKRenderPass* renderPass, - MVKFramebuffer* framebuffer, + VkExtent2D framebufferExtent, + uint32_t framebufferLayerCount, VkRect2D& renderArea, MVKArrayRef clearValues, - MVKArrayRef imagelessAttachments) { + MVKArrayRef attachments) { _renderPass = renderPass; - _framebuffer = framebuffer; + _framebufferExtent = framebufferExtent; + _framebufferLayerCount = framebufferLayerCount; _renderArea = renderArea; _isRenderingEntireAttachment = (mvkVkOffset2DsAreEqual(_renderArea.offset, {0,0}) && - mvkVkExtent2DsAreEqual(_renderArea.extent, _framebuffer->getExtent2D())); + mvkVkExtent2DsAreEqual(_renderArea.extent, _framebufferExtent)); _clearValues.assign(clearValues.begin(), clearValues.end()); - _imagelessAttachments.assign(imagelessAttachments.begin(), imagelessAttachments.end()); + for(auto* v : attachments) { + _attachments.push_back(v); + } setSubpass(passCmd, subpassContents, 0); } @@ -336,7 +339,14 @@ void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) { endCurrentMetalEncoding(); MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor]; - getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _multiviewPassIndex, _framebuffer, _imagelessAttachments.contents(), _clearValues.contents(), _isRenderingEntireAttachment, loadOverride); + getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, + _multiviewPassIndex, + _framebufferExtent, + _framebufferLayerCount, + _attachments.contents(), + _clearValues.contents(), + _isRenderingEntireAttachment, + loadOverride); if (_cmdBuffer->_needsVisibilityResultMTLBuffer) { if (!_visibilityResultMTLBuffer) { _visibilityResultMTLBuffer = getTempMTLBuffer(_pDeviceMetalFeatures->maxQueryBufferSize, true, true); @@ -344,7 +354,7 @@ void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) { mtlRPDesc.visibilityResultBuffer = _visibilityResultMTLBuffer->_mtlBuffer; } - VkExtent2D fbExtent = _framebuffer->getExtent2D(); + VkExtent2D fbExtent = _framebufferExtent; mtlRPDesc.renderTargetWidthMVK = max(min(_renderArea.offset.x + _renderArea.extent.width, fbExtent.width), 1u); mtlRPDesc.renderTargetHeightMVK = max(min(_renderArea.offset.y + _renderArea.extent.height, fbExtent.height), 1u); if (_canUseLayeredRendering) { @@ -364,9 +374,9 @@ void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) { if (getSubpass()->isMultiview()) { // In the case of a multiview pass, the framebuffer layer count will be one. // We need to use the view count for this multiview pass. - renderTargetArrayLength = getSubpass()->getViewCountInMetalPass(_multiviewPassIndex); + renderTargetArrayLength = getSubpass()->getViewCountInMetalPass(_multiviewPassIndex); } else { - renderTargetArrayLength = _framebuffer->getLayerCount(); + renderTargetArrayLength = _framebufferLayerCount; } // Metal does not allow layered render passes where some RTs are 3D and others are 2D. if (!(found3D && found2D) || renderTargetArrayLength > 1) { @@ -397,7 +407,7 @@ void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) { void MVKCommandEncoder::encodeStoreActions(bool storeOverride) { getSubpass()->encodeStoreActions(this, _isRenderingEntireAttachment, - _imagelessAttachments.contents(), + _attachments.contents(), storeOverride); } @@ -513,7 +523,7 @@ void MVKCommandEncoder::clearRenderArea() { VkClearRect clearRect; clearRect.rect = _renderArea; clearRect.baseArrayLayer = 0; - clearRect.layerCount = _framebuffer->getLayerCount(); + clearRect.layerCount = _framebufferLayerCount; // Create and execute a temporary clear attachments command. // To be threadsafe...do NOT acquire and return the command from the pool. @@ -560,7 +570,7 @@ void MVKCommandEncoder::endRenderpass() { endMetalRenderEncoding(); _renderPass = nullptr; - _framebuffer = nullptr; + _attachments.clear(); _renderSubpassIndex = 0; } diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def b/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def index 26009aaf..6f74ed4a 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def +++ b/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def @@ -56,11 +56,21 @@ MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##threshold3) \ MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi) +#define MVK_CMD_TYPE_POOLS_FROM_4_THRESHOLDS(cmdType, arg1Threshold1, arg1Threshold2, arg2Threshold1, arg2Threshold2) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##arg2Threshold1) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##arg2Threshold2) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##Multi) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##arg2Threshold1) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##arg2Threshold2) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##Multi) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##arg2Threshold1) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##arg2Threshold2) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##Multi) MVK_CMD_TYPE_POOLS_FROM_2_THRESHOLDS(PipelineBarrier, 1, 4) MVK_CMD_TYPE_POOL(BindGraphicsPipeline) MVK_CMD_TYPE_POOL(BindComputePipeline) -MVK_CMD_TYPE_POOLS_FROM_2_THRESHOLDS(BeginRenderPass, 1, 2) +MVK_CMD_TYPE_POOLS_FROM_4_THRESHOLDS(BeginRenderPass, 1, 2, 0, 1) MVK_CMD_TYPE_POOL(NextSubpass) MVK_CMD_TYPE_POOL(EndRenderPass) MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(ExecuteCommands, 1) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h index 0fc06b41..32cd5dd8 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h @@ -44,8 +44,8 @@ public: /** Returns the attachment at the specified index. */ inline MVKImageView* getAttachment(uint32_t index) { return _attachments[index]; } - - inline bool getImageless() { return _imageless; } + + inline size_t getAttachmentCount() {return _attachments.size(); } #pragma mark Construction @@ -58,7 +58,5 @@ protected: VkExtent2D _extent; uint32_t _layerCount; MVKSmallVector _attachments; - bool _imageless; - MVKSmallVector _imagelessAttachments; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm index 18d442a4..91d3bded 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm @@ -28,11 +28,7 @@ MVKFramebuffer::MVKFramebuffer(MVKDevice* device, _extent = { .width = pCreateInfo->width, .height = pCreateInfo->height }; _layerCount = pCreateInfo->layers; - if (pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR) { - _imageless = true; - } - else { - _imageless = false; + if (!(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR)) { // Add attachments _attachments.reserve(pCreateInfo->attachmentCount); for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h index 8c0a89f1..c813fa60 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h @@ -95,8 +95,9 @@ public: */ void populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc, uint32_t passIdx, - MVKFramebuffer* framebuffer, - const MVKArrayRef& imagelessAttachments, + VkExtent2D framebufferExtent, + uint32_t framebufferLayerCount, + const MVKArrayRef& attachments, const MVKArrayRef& clearValues, bool isRenderingEntireAttachment, bool loadOverride = false); @@ -120,7 +121,7 @@ public: /** If a render encoder is active, sets the store actions for all attachments to it. */ void encodeStoreActions(MVKCommandEncoder* cmdEncoder, bool isRenderingEntireAttachment, - const MVKArrayRef& imagelessAttachments, + const MVKArrayRef& attachments, bool storeOverride = false); /** Constructs an instance for the specified parent renderpass. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm index 0b8f2a9d..0443597f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm @@ -175,13 +175,13 @@ uint32_t MVKRenderSubpass::getViewCountUpToMetalPass(uint32_t passIdx) const { void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc, uint32_t passIdx, - MVKFramebuffer* framebuffer, - const MVKArrayRef& imagelessAttachments, + VkExtent2D framebufferExtent, + uint32_t framebufferLayerCount, + const MVKArrayRef& attachments, const MVKArrayRef& clearValues, bool isRenderingEntireAttachment, bool loadOverride) { MVKPixelFormats* pixFmts = _renderPass->getPixelFormats(); - bool imageless = framebuffer->getImageless(); // Populate the Metal color attachments uint32_t caCnt = getColorAttachmentCount(); @@ -197,12 +197,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* uint32_t rslvRPAttIdx = _resolveAttachments.empty() ? VK_ATTACHMENT_UNUSED : _resolveAttachments[caIdx].attachment; bool hasResolveAttachment = (rslvRPAttIdx != VK_ATTACHMENT_UNUSED); if (hasResolveAttachment) { - if (imageless) { - imagelessAttachments[rslvRPAttIdx]->populateMTLRenderPassAttachmentDescriptorResolve(mtlColorAttDesc); - } - else { - framebuffer->getAttachment(rslvRPAttIdx)->populateMTLRenderPassAttachmentDescriptorResolve(mtlColorAttDesc); - } + attachments[rslvRPAttIdx]->populateMTLRenderPassAttachmentDescriptorResolve(mtlColorAttDesc); // In a multiview render pass, we need to override the starting layer to ensure // only the enabled views are loaded. @@ -217,17 +212,10 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* // Configure the color attachment MVKRenderPassAttachment* clrMVKRPAtt = &_renderPass->_attachments[clrRPAttIdx]; - if (imageless) { - imagelessAttachments[clrRPAttIdx]->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc); - } - else { - framebuffer->getAttachment(clrRPAttIdx)->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc); - } + attachments[clrRPAttIdx]->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc); bool isMemorylessAttachment = false; #if MVK_APPLE_SILICON - isMemorylessAttachment = imageless - ? imagelessAttachments[clrRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless - : framebuffer->getAttachment(clrRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; + isMemorylessAttachment = attachments[clrRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; #endif if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this, isRenderingEntireAttachment, @@ -251,16 +239,12 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* uint32_t dsRslvRPAttIdx = _depthStencilResolveAttachment.attachment; if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) { MVKRenderPassAttachment* dsMVKRPAtt = &_renderPass->_attachments[dsRPAttIdx]; - MVKImageView* dsImage = imageless - ? imagelessAttachments[dsRPAttIdx] - : framebuffer->getAttachment(dsRPAttIdx); + MVKImageView* dsImage = attachments[dsRPAttIdx]; MVKImageView* dsRslvImage = nullptr; MTLPixelFormat mtlDSFormat = dsImage->getMTLPixelFormat(0); if (dsRslvRPAttIdx != VK_ATTACHMENT_UNUSED) { - dsRslvImage = imageless - ? imagelessAttachments[dsRslvRPAttIdx] - : framebuffer->getAttachment(dsRslvRPAttIdx); + dsRslvImage = attachments[dsRslvRPAttIdx]; } if (pixFmts->isDepthFormat(mtlDSFormat)) { @@ -331,7 +315,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* } // Add a dummy attachment so this passes validation. - VkExtent2D fbExtent = framebuffer->getExtent2D(); + VkExtent2D fbExtent = framebufferExtent; MTLTextureDescriptor* mtlTexDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatR8Unorm width: fbExtent.width height: fbExtent.height mipmapped: NO]; if (isMultiview()) { #if MVK_MACOS_OR_IOS @@ -345,7 +329,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlTexDesc.textureType = MTLTextureType2DArray; #endif mtlTexDesc.arrayLength = getViewCountInMetalPass(passIdx); - } else if (framebuffer->getLayerCount() > 1) { + } else if (framebufferLayerCount > 1) { #if MVK_MACOS if (sampleCount > 1 && _renderPass->getDevice()->_pMetalFeatures->multisampleLayeredRendering) { mtlTexDesc.textureType = MTLTextureType2DMultisampleArray; @@ -356,7 +340,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* #else mtlTexDesc.textureType = MTLTextureType2DArray; #endif - mtlTexDesc.arrayLength = framebuffer->getLayerCount(); + mtlTexDesc.arrayLength = framebufferLayerCount; } else if (sampleCount > 1) { mtlTexDesc.textureType = MTLTextureType2DMultisample; mtlTexDesc.sampleCount = sampleCount; @@ -385,7 +369,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder, bool isRenderingEntireAttachment, - const MVKArrayRef& imagelessAttachments, + const MVKArrayRef& attachments, bool storeOverride) { if (!cmdEncoder->_mtlRenderEncoder) { return; } if (!_renderPass->getDevice()->_pMetalFeatures->deferredStoreActions) { return; } @@ -397,9 +381,7 @@ void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder, bool hasResolveAttachment = _resolveAttachments.empty() ? false : _resolveAttachments[caIdx].attachment != VK_ATTACHMENT_UNUSED; bool isMemorylessAttachment = false; #if MVK_APPLE_SILICON - isMemorylessAttachment = cmdEncoder->_framebuffer->getImageless() - ? imagelessAttachments[clrRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless - : cmdEncoder->_framebuffer->getAttachment(clrRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; + isMemorylessAttachment = attachments[clrRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; #endif _renderPass->_attachments[clrRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, caIdx, false, storeOverride); } @@ -411,9 +393,7 @@ void MVKRenderSubpass::encodeStoreActions(MVKCommandEncoder* cmdEncoder, bool hasStencilResolveAttachment = hasResolveAttachment && _stencilResolveMode != VK_RESOLVE_MODE_NONE; bool isMemorylessAttachment = false; #if MVK_APPLE_SILICON - isMemorylessAttachment = cmdEncoder->_framebuffer->getImageless() - ? imagelessAttachments[dsRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless - : cmdEncoder->_framebuffer->getAttachment(dsRPAttIdx)->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; + isMemorylessAttachment = attachments[dsRPAttIdx]->getMTLTexture(0).storageMode == MTLStorageModeMemoryless; #endif _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasDepthResolveAttachment, 0, false, storeOverride); _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, isRenderingEntireAttachment, isMemorylessAttachment, hasStencilResolveAttachment, 0, true, storeOverride); diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index 2546e840..d9070f7d 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -131,6 +131,29 @@ static inline void MVKTraceVulkanCallEndImpl(const char* funcName, uint64_t star MVKAddCmd(baseCmdType ##Multi, vkCmdBuff, ##__VA_ARGS__); \ } +// Add one of nine commands, based on comparing a command parameter against four threshold values +#define MVKAddCmdFrom4Thresholds(baseCmdType, value1, arg1Threshold1, arg1Threshold2, \ + value2, arg2Threshold1, arg2Threshold2, vkCmdBuff, ...) \ + if (value1 <= arg1Threshold1 && value2 <= arg2Threshold1) { \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold2 && value2 <= arg2Threshold1) { \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 > arg1Threshold2 && value2 <= arg2Threshold1) { \ + MVKAddCmd(baseCmdType ##Multi ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold1 && value2 <= arg2Threshold2) { \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold2 && value2 <= arg2Threshold2) { \ + MVKAddCmd(baseCmdType ##arg1Threshold2 ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 > arg1Threshold2 && value2 <= arg2Threshold2) { \ + MVKAddCmd(baseCmdType ##Multi ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold1 && value2 > arg2Threshold2) { \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##Multi, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold2 && value2 > arg2Threshold2) { \ + MVKAddCmd(baseCmdType ##arg1Threshold2 ##Multi, vkCmdBuff, ##__VA_ARGS__); \ + } else { \ + MVKAddCmd(baseCmdType ##Multi ##Multi, vkCmdBuff, ##__VA_ARGS__); \ + } + // Define an extension call as an alias of a core call #define MVK_PUBLIC_CORE_ALIAS(vkf) MVK_PUBLIC_ALIAS(vkf##KHR, vkf) @@ -1869,7 +1892,24 @@ MVK_PUBLIC_SYMBOL void vkCmdBeginRenderPass( VkSubpassContents contents) { MVKTraceVulkanCallStart(); - MVKAddCmdFrom2Thresholds(BeginRenderPass, pRenderPassBegin->clearValueCount, 1, 2, commandBuffer,pRenderPassBegin, contents); + uint32_t attachmentCount = 0; + for (const auto* next = (VkBaseInStructure*)pRenderPassBegin->pNext; next; next = next->pNext) { + switch(next->sType) { + case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: { + auto* pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next; + attachmentCount = pAttachmentBegin->attachmentCount; + break; + } + default: + break; + } + } + MVKAddCmdFrom4Thresholds(BeginRenderPass, + pRenderPassBegin->clearValueCount, 1, 2, + attachmentCount, 0, 1, + commandBuffer, + pRenderPassBegin, + contents); MVKTraceVulkanCallEnd(); } @@ -2283,7 +2323,24 @@ MVK_PUBLIC_SYMBOL void vkCmdBeginRenderPass2KHR( const VkSubpassBeginInfo* pSubpassBeginInfo) { MVKTraceVulkanCallStart(); - MVKAddCmdFrom2Thresholds(BeginRenderPass, pRenderPassBegin->clearValueCount, 1, 2, commandBuffer, pRenderPassBegin, pSubpassBeginInfo); + uint32_t attachmentCount = 0; + for (const auto* next = (VkBaseInStructure*)pRenderPassBegin->pNext; next; next = next->pNext) { + switch(next->sType) { + case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: { + auto* pAttachmentBegin = (VkRenderPassAttachmentBeginInfo*)next; + attachmentCount = pAttachmentBegin->attachmentCount; + break; + } + default: + break; + } + } + MVKAddCmdFrom4Thresholds(BeginRenderPass, + pRenderPassBegin->clearValueCount, 1, 2, + attachmentCount, 0, 1, + commandBuffer, + pRenderPassBegin, + pSubpassBeginInfo); MVKTraceVulkanCallEnd(); } From d402a3265f0aa229f4a30b0065fb3a396958b13b Mon Sep 17 00:00:00 2001 From: UnsafeBy Date: Sun, 30 May 2021 11:01:09 +0800 Subject: [PATCH 5/6] Implement iterator-based assign() in pointer verion of MVKSmallVectorImpl. --- MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm | 6 ++---- MoltenVK/MoltenVK/Utility/MVKSmallVector.h | 12 ++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index 15f8daac..a0aa4cb4 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -297,9 +297,7 @@ void MVKCommandEncoder::beginRenderpass(MVKCommand* passCmd, _isRenderingEntireAttachment = (mvkVkOffset2DsAreEqual(_renderArea.offset, {0,0}) && mvkVkExtent2DsAreEqual(_renderArea.extent, _framebufferExtent)); _clearValues.assign(clearValues.begin(), clearValues.end()); - for(auto* v : attachments) { - _attachments.push_back(v); - } + _attachments.assign(attachments.begin(), attachments.end()); setSubpass(passCmd, subpassContents, 0); } @@ -339,7 +337,7 @@ void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) { endCurrentMetalEncoding(); MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor]; - getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, + getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _multiviewPassIndex, _framebufferExtent, _framebufferLayerCount, diff --git a/MoltenVK/MoltenVK/Utility/MVKSmallVector.h b/MoltenVK/MoltenVK/Utility/MVKSmallVector.h index 4648d19e..e20e7faf 100755 --- a/MoltenVK/MoltenVK/Utility/MVKSmallVector.h +++ b/MoltenVK/MoltenVK/Utility/MVKSmallVector.h @@ -781,6 +781,18 @@ public: alc.num_elements_used = new_size; } + template + void assign( InputIterator first, InputIterator last ) + { + clear(); + + while( first != last ) + { + push_back( *first ); + ++first; + } + } + void resize( const size_t new_size, const Type *t = nullptr ) { if ( new_size == alc.num_elements_used ) From 6fe4cc5e13f7fdd270e1092af4be0450d1260d14 Mon Sep 17 00:00:00 2001 From: UnsafeBy Date: Mon, 31 May 2021 14:11:13 +0800 Subject: [PATCH 6/6] Add MVKCmdBeginRenderPass template specializations for 2 framebuffer attachments. --- MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h | 10 ++-- .../MoltenVK/Commands/MVKCmdRenderPass.mm | 17 ++++--- .../MoltenVK/Commands/MVKCommandBuffer.mm | 2 + .../MoltenVK/Commands/MVKCommandTypePools.def | 25 ++++++---- MoltenVK/MoltenVK/Vulkan/vulkan.mm | 49 +++++++++++-------- 5 files changed, 62 insertions(+), 41 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h index 858473b1..8a667856 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h @@ -89,9 +89,13 @@ typedef MVKCmdBeginRenderPass<1, 1> MVKCmdBeginRenderPass11; typedef MVKCmdBeginRenderPass<2, 1> MVKCmdBeginRenderPass21; typedef MVKCmdBeginRenderPass<9, 1> MVKCmdBeginRenderPassMulti1; -typedef MVKCmdBeginRenderPass<1, 8> MVKCmdBeginRenderPass1Multi; -typedef MVKCmdBeginRenderPass<2, 8> MVKCmdBeginRenderPass2Multi; -typedef MVKCmdBeginRenderPass<9, 8> MVKCmdBeginRenderPassMultiMulti; +typedef MVKCmdBeginRenderPass<1, 2> MVKCmdBeginRenderPass12; +typedef MVKCmdBeginRenderPass<2, 2> MVKCmdBeginRenderPass22; +typedef MVKCmdBeginRenderPass<9, 2> MVKCmdBeginRenderPassMulti2; + +typedef MVKCmdBeginRenderPass<1, 9> MVKCmdBeginRenderPass1Multi; +typedef MVKCmdBeginRenderPass<2, 9> MVKCmdBeginRenderPass2Multi; +typedef MVKCmdBeginRenderPass<9, 9> MVKCmdBeginRenderPassMultiMulti; #pragma mark - diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm index 08113104..4fc1146b 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm @@ -46,8 +46,8 @@ VkResult MVKCmdBeginRenderPassBase::setContent(MVKCommandBuffer* cmdBuff, template VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, - const VkRenderPassBeginInfo* pRenderPassBegin, - VkSubpassContents contents) { + const VkRenderPassBeginInfo* pRenderPassBegin, + VkSubpassContents contents) { MVKCmdBeginRenderPassBase::setContent(cmdBuff, pRenderPassBegin, contents); // Add clear values @@ -85,8 +85,8 @@ VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, template VkResult MVKCmdBeginRenderPass::setContent(MVKCommandBuffer* cmdBuff, - const VkRenderPassBeginInfo* pRenderPassBegin, - const VkSubpassBeginInfo* pSubpassBeginInfo) { + const VkRenderPassBeginInfo* pRenderPassBegin, + const VkSubpassBeginInfo* pSubpassBeginInfo) { return setContent(cmdBuff, pRenderPassBegin, pSubpassBeginInfo->contents); } @@ -111,10 +111,13 @@ template class MVKCmdBeginRenderPass<1, 1>; template class MVKCmdBeginRenderPass<2, 1>; template class MVKCmdBeginRenderPass<9, 1>; -template class MVKCmdBeginRenderPass<1, 8>; -template class MVKCmdBeginRenderPass<2, 8>; -template class MVKCmdBeginRenderPass<9, 8>; +template class MVKCmdBeginRenderPass<1, 2>; +template class MVKCmdBeginRenderPass<2, 2>; +template class MVKCmdBeginRenderPass<9, 2>; +template class MVKCmdBeginRenderPass<1, 9>; +template class MVKCmdBeginRenderPass<2, 9>; +template class MVKCmdBeginRenderPass<9, 9>; #pragma mark - #pragma mark MVKCmdNextSubpass diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index a0aa4cb4..125e122a 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -568,6 +568,8 @@ void MVKCommandEncoder::endRenderpass() { endMetalRenderEncoding(); _renderPass = nullptr; + _framebufferExtent = {}; + _framebufferLayerCount = 0; _attachments.clear(); _renderSubpassIndex = 0; } diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def b/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def index 6f74ed4a..a6966f42 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def +++ b/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def @@ -56,21 +56,26 @@ MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##threshold3) \ MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi) -#define MVK_CMD_TYPE_POOLS_FROM_4_THRESHOLDS(cmdType, arg1Threshold1, arg1Threshold2, arg2Threshold1, arg2Threshold2) \ - MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##arg2Threshold1) \ - MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##arg2Threshold2) \ - MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##Multi) \ - MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##arg2Threshold1) \ - MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##arg2Threshold2) \ - MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##Multi) \ - MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##arg2Threshold1) \ - MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##arg2Threshold2) \ +#define MVK_CMD_TYPE_POOLS_FROM_5_THRESHOLDS(cmdType, \ + arg1Threshold1, arg1Threshold2, \ + arg2Threshold1, arg2Threshold2, arg2Threshold3) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##arg2Threshold1) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##arg2Threshold2) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##arg2Threshold3) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold1 ##Multi) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##arg2Threshold1) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##arg2Threshold2) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##arg2Threshold3) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##arg1Threshold2 ##Multi) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##arg2Threshold1) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##arg2Threshold2) \ + MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##arg2Threshold3) \ MVK_TMPLT_DECL MVK_CMD_TYPE_POOL(cmdType ##Multi ##Multi) MVK_CMD_TYPE_POOLS_FROM_2_THRESHOLDS(PipelineBarrier, 1, 4) MVK_CMD_TYPE_POOL(BindGraphicsPipeline) MVK_CMD_TYPE_POOL(BindComputePipeline) -MVK_CMD_TYPE_POOLS_FROM_4_THRESHOLDS(BeginRenderPass, 1, 2, 0, 1) +MVK_CMD_TYPE_POOLS_FROM_5_THRESHOLDS(BeginRenderPass, 1, 2, 0, 1, 2) MVK_CMD_TYPE_POOL(NextSubpass) MVK_CMD_TYPE_POOL(EndRenderPass) MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(ExecuteCommands, 1) diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index d9070f7d..60fc694e 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -132,24 +132,31 @@ static inline void MVKTraceVulkanCallEndImpl(const char* funcName, uint64_t star } // Add one of nine commands, based on comparing a command parameter against four threshold values -#define MVKAddCmdFrom4Thresholds(baseCmdType, value1, arg1Threshold1, arg1Threshold2, \ - value2, arg2Threshold1, arg2Threshold2, vkCmdBuff, ...) \ +#define MVKAddCmdFrom5Thresholds(baseCmdType, value1, arg1Threshold1, arg1Threshold2, \ + value2, arg2Threshold1, arg2Threshold2, arg2Threshold3, \ + vkCmdBuff, ...) \ if (value1 <= arg1Threshold1 && value2 <= arg2Threshold1) { \ - MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ - } else if (value1 <= arg1Threshold2 && value2 <= arg2Threshold1) { \ - MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ - } else if (value1 > arg1Threshold2 && value2 <= arg2Threshold1) { \ - MVKAddCmd(baseCmdType ##Multi ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ - } else if (value1 <= arg1Threshold1 && value2 <= arg2Threshold2) { \ - MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ - } else if (value1 <= arg1Threshold2 && value2 <= arg2Threshold2) { \ - MVKAddCmd(baseCmdType ##arg1Threshold2 ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ - } else if (value1 > arg1Threshold2 && value2 <= arg2Threshold2) { \ - MVKAddCmd(baseCmdType ##Multi ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ - } else if (value1 <= arg1Threshold1 && value2 > arg2Threshold2) { \ - MVKAddCmd(baseCmdType ##arg1Threshold1 ##Multi, vkCmdBuff, ##__VA_ARGS__); \ - } else if (value1 <= arg1Threshold2 && value2 > arg2Threshold2) { \ - MVKAddCmd(baseCmdType ##arg1Threshold2 ##Multi, vkCmdBuff, ##__VA_ARGS__); \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold2 && value2 <= arg2Threshold1) { \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 > arg1Threshold2 && value2 <= arg2Threshold1) { \ + MVKAddCmd(baseCmdType ##Multi ##arg2Threshold1, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold1 && value2 <= arg2Threshold2) { \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold2 && value2 <= arg2Threshold2) { \ + MVKAddCmd(baseCmdType ##arg1Threshold2 ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 > arg1Threshold2 && value2 <= arg2Threshold2) { \ + MVKAddCmd(baseCmdType ##Multi ##arg2Threshold2, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold1 && value2 <= arg2Threshold3) { \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##arg2Threshold3, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold2 && value2 <= arg2Threshold3) { \ + MVKAddCmd(baseCmdType ##arg1Threshold2 ##arg2Threshold3, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 > arg1Threshold2 && value2 <= arg2Threshold3) { \ + MVKAddCmd(baseCmdType ##Multi ##arg2Threshold3, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold1 && value2 > arg2Threshold3) { \ + MVKAddCmd(baseCmdType ##arg1Threshold1 ##Multi, vkCmdBuff, ##__VA_ARGS__); \ + } else if (value1 <= arg1Threshold2 && value2 > arg2Threshold3) { \ + MVKAddCmd(baseCmdType ##arg1Threshold2 ##Multi, vkCmdBuff, ##__VA_ARGS__); \ } else { \ MVKAddCmd(baseCmdType ##Multi ##Multi, vkCmdBuff, ##__VA_ARGS__); \ } @@ -1904,9 +1911,9 @@ MVK_PUBLIC_SYMBOL void vkCmdBeginRenderPass( break; } } - MVKAddCmdFrom4Thresholds(BeginRenderPass, + MVKAddCmdFrom5Thresholds(BeginRenderPass, pRenderPassBegin->clearValueCount, 1, 2, - attachmentCount, 0, 1, + attachmentCount, 0, 1, 2, commandBuffer, pRenderPassBegin, contents); @@ -2335,9 +2342,9 @@ MVK_PUBLIC_SYMBOL void vkCmdBeginRenderPass2KHR( break; } } - MVKAddCmdFrom4Thresholds(BeginRenderPass, + MVKAddCmdFrom5Thresholds(BeginRenderPass, pRenderPassBegin->clearValueCount, 1, 2, - attachmentCount, 0, 1, + attachmentCount, 0, 1, 2, commandBuffer, pRenderPassBegin, pSubpassBeginInfo);