From 2d627c6b8f9370f43b93223937c98330c701aa53 Mon Sep 17 00:00:00 2001 From: Michael Barriault Date: Tue, 16 Apr 2019 18:03:15 +0100 Subject: [PATCH 1/7] Fix intermediate Metal renderpasses load and store actions maintaining attachments appropriately. --- MoltenVK/MoltenVK/Commands/MVKCmdDraw.h | 8 +-- MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm | 20 +++++-- MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h | 2 + MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm | 8 +++ MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h | 2 +- .../MoltenVK/Commands/MVKCmdRenderPass.mm | 6 ++- MoltenVK/MoltenVK/Commands/MVKCommand.h | 16 ++++++ MoltenVK/MoltenVK/Commands/MVKCommand.mm | 13 +++++ MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h | 35 ++++++++++-- .../MoltenVK/Commands/MVKCommandBuffer.mm | 53 ++++++++++++++++--- MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h | 6 ++- MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm | 17 ++++-- 12 files changed, 159 insertions(+), 27 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h index d9be7761..f31c465d 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h @@ -70,7 +70,7 @@ protected: #pragma mark MVKCmdDraw /** Vulkan command to draw vertices. */ -class MVKCmdDraw : public MVKCommand { +class MVKCmdDraw : public MVKCommand, public MVKLoadStoreOverride { public: void setContent(uint32_t vertexCount, @@ -94,7 +94,7 @@ protected: #pragma mark MVKCmdDrawIndexed /** Vulkan command to draw indexed vertices. */ -class MVKCmdDrawIndexed : public MVKCommand { +class MVKCmdDrawIndexed : public MVKCommand, public MVKLoadStoreOverride { public: void setContent(uint32_t indexCount, @@ -120,7 +120,7 @@ protected: #pragma mark MVKCmdDrawIndirect /** Vulkan command to draw vertices indirectly. */ -class MVKCmdDrawIndirect : public MVKCommand { +class MVKCmdDrawIndirect : public MVKCommand, public MVKLoadStoreOverride { public: void setContent(VkBuffer buffer, @@ -144,7 +144,7 @@ protected: #pragma mark MVKCmdDrawIndexedIndirect /** Vulkan command to draw indexed vertices indirectly. */ -class MVKCmdDrawIndexedIndirect : public MVKCommand { +class MVKCmdDrawIndexedIndirect : public MVKCommand, public MVKLoadStoreOverride { public: void setContent(VkBuffer buffer, diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm index 83e5e004..88d88a8a 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm @@ -84,6 +84,8 @@ void MVKCmdDraw::setContent(uint32_t vertexCount, _instanceCount = instanceCount; _firstVertex = firstVertex; _firstInstance = firstInstance; + _loadOverride = false; + _storeOverride = false; // Validate clearConfigurationResult(); @@ -198,7 +200,7 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) { threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)]; // Running this stage prematurely ended the render pass, so we have to start it up again. // TODO: On iOS, maybe we could use a tile shader to avoid this. - cmdEncoder->beginMetalRenderPass(true); + cmdEncoder->beginMetalRenderPass(_loadOverride, _storeOverride); break; case kMVKGraphicsStageRasterization: if (pipeline->isTessellationPipeline()) { @@ -267,6 +269,8 @@ void MVKCmdDrawIndexed::setContent(uint32_t indexCount, _firstIndex = firstIndex; _vertexOffset = vertexOffset; _firstInstance = firstInstance; + _loadOverride = false; + _storeOverride = false; // Validate clearConfigurationResult(); @@ -419,7 +423,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) { threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)]; // Running this stage prematurely ended the render pass, so we have to start it up again. // TODO: On iOS, maybe we could use a tile shader to avoid this. - cmdEncoder->beginMetalRenderPass(true); + cmdEncoder->beginMetalRenderPass(_loadOverride, _storeOverride); break; case kMVKGraphicsStageRasterization: if (pipeline->isTessellationPipeline()) { @@ -493,6 +497,8 @@ void MVKCmdDrawIndirect::setContent(VkBuffer buffer, _mtlIndirectBufferOffset = mvkBuffer->getMTLBufferOffset() + offset; _mtlIndirectBufferStride = stride; _drawCount = drawCount; + _loadOverride = false; + _storeOverride = false; // Validate clearConfigurationResult(); @@ -669,7 +675,7 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) { mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments); // Running this stage prematurely ended the render pass, so we have to start it up again. // TODO: On iOS, maybe we could use a tile shader to avoid this. - cmdEncoder->beginMetalRenderPass(true); + cmdEncoder->beginMetalRenderPass(_loadOverride, _storeOverride); break; case kMVKGraphicsStageRasterization: if (pipeline->isTessellationPipeline()) { @@ -728,6 +734,8 @@ void MVKCmdDrawIndexedIndirect::setContent(VkBuffer buffer, _mtlIndirectBufferOffset = mvkBuffer->getMTLBufferOffset() + offset; _mtlIndirectBufferStride = stride; _drawCount = drawCount; + _loadOverride = false; + _storeOverride = false; // Validate clearConfigurationResult(); @@ -915,7 +923,7 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) { mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments); // Running this stage prematurely ended the render pass, so we have to start it up again. // TODO: On iOS, maybe we could use a tile shader to avoid this. - cmdEncoder->beginMetalRenderPass(true); + cmdEncoder->beginMetalRenderPass(_loadOverride, _storeOverride); break; case kMVKGraphicsStageRasterization: if (pipeline->isTessellationPipeline()) { @@ -985,6 +993,7 @@ void mvkCmdDraw(MVKCommandBuffer* cmdBuff, uint32_t firstInstance) { MVKCmdDraw* cmd = cmdBuff->_commandPool->_cmdDrawPool.acquireObject(); cmd->setContent(vertexCount, instanceCount, firstVertex, firstInstance); + cmdBuff->recordDraw(cmd); cmdBuff->addCommand(cmd); } @@ -996,6 +1005,7 @@ void mvkCmdDrawIndexed(MVKCommandBuffer* cmdBuff, uint32_t firstInstance) { MVKCmdDrawIndexed* cmd = cmdBuff->_commandPool->_cmdDrawIndexedPool.acquireObject(); cmd->setContent(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); + cmdBuff->recordDraw(cmd); cmdBuff->addCommand(cmd); } @@ -1015,6 +1025,7 @@ void mvkCmdDrawIndirect(MVKCommandBuffer* cmdBuff, uint32_t stride) { MVKCmdDrawIndirect* cmd = cmdBuff->_commandPool->_cmdDrawIndirectPool.acquireObject(); cmd->setContent(buffer, offset, drawCount, stride); + cmdBuff->recordDraw(cmd); cmdBuff->addCommand(cmd); } @@ -1025,6 +1036,7 @@ void mvkCmdDrawIndexedIndirect(MVKCommandBuffer* cmdBuff, uint32_t stride) { MVKCmdDrawIndexedIndirect* cmd = cmdBuff->_commandPool->_cmdDrawIndexedIndirectPool.acquireObject(); cmd->setContent(buffer, offset, drawCount, stride); + cmdBuff->recordDraw(cmd); cmdBuff->addCommand(cmd); } diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h index 2044f66c..e05abdb5 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h @@ -73,6 +73,8 @@ public: MVKCmdBindPipeline(MVKCommandTypePool* pool); + bool isTessellationPipeline(); + private: VkPipelineBindPoint _bindPoint; MVKPipeline* _pipeline; diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm index bdd47ef5..6b75a9c5 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm @@ -109,6 +109,13 @@ void MVKCmdBindPipeline::encode(MVKCommandEncoder* cmdEncoder) { MVKCmdBindPipeline::MVKCmdBindPipeline(MVKCommandTypePool* pool) : MVKCommand::MVKCommand((MVKCommandTypePool*)pool) {} +bool MVKCmdBindPipeline::isTessellationPipeline() { + if (_bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) + return ((MVKGraphicsPipeline*)_pipeline)->isTessellationPipeline(); + else + return false; +} + #pragma mark - #pragma mark MVKCmdBindDescriptorSets @@ -327,6 +334,7 @@ void mvkCmdBindPipeline(MVKCommandBuffer* cmdBuff, VkPipeline pipeline) { MVKCmdBindPipeline* cmd = cmdBuff->_commandPool->_cmdBindPipelinePool.acquireObject(); cmd->setContent(pipelineBindPoint, pipeline); + cmdBuff->recordBindPipeline(cmd); cmdBuff->addCommand(cmd); } diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h index 8a28da3b..4f9b3c9e 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h @@ -33,7 +33,7 @@ class MVKFramebuffer; #pragma mark MVKCmdBeginRenderPass /** Vulkan command to begin a render pass. */ -class MVKCmdBeginRenderPass : public MVKCommand { +class MVKCmdBeginRenderPass : public MVKCommand, public MVKLoadStoreOverride { public: void setContent(const VkRenderPassBeginInfo* pRenderPassBegin, diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm index 2b798977..ff431fd2 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm @@ -34,6 +34,8 @@ void MVKCmdBeginRenderPass::setContent(const VkRenderPassBeginInfo* pRenderPassB _contents = contents; _renderPass = (MVKRenderPass*)_info.renderPass; _framebuffer = (MVKFramebuffer*)_info.framebuffer; + _loadOverride = false; + _storeOverride = false; // Add clear values _clearValues.clear(); // Clear for reuse @@ -45,7 +47,7 @@ void MVKCmdBeginRenderPass::setContent(const VkRenderPassBeginInfo* pRenderPassB void MVKCmdBeginRenderPass::encode(MVKCommandEncoder* cmdEncoder) { // MVKLogDebug("Encoding vkCmdBeginRenderPass(). Elapsed time: %.6f ms.", mvkGetElapsedMilliseconds()); - cmdEncoder->beginRenderpass(_contents, _renderPass, _framebuffer, _info.renderArea, &_clearValues); + cmdEncoder->beginRenderpass(_contents, _renderPass, _framebuffer, _info.renderArea, &_clearValues, _loadOverride, _storeOverride); } MVKCmdBeginRenderPass::MVKCmdBeginRenderPass(MVKCommandTypePool* pool) @@ -277,6 +279,7 @@ void mvkCmdBeginRenderPass(MVKCommandBuffer* cmdBuff, VkSubpassContents contents) { MVKCmdBeginRenderPass* cmd = cmdBuff->_commandPool->_cmdBeginRenderPassPool.acquireObject(); cmd->setContent(pRenderPassBegin, contents); + cmdBuff->recordBeginRenderPass(cmd); cmdBuff->addCommand(cmd); } @@ -288,6 +291,7 @@ void mvkCmdNextSubpass(MVKCommandBuffer* cmdBuff, VkSubpassContents contents) { void mvkCmdEndRenderPass(MVKCommandBuffer* cmdBuff) { MVKCmdEndRenderPass* cmd = cmdBuff->_commandPool->_cmdEndRenderPassPool.acquireObject(); + cmdBuff->recordEndRenderPass(cmd); cmdBuff->addCommand(cmd); } diff --git a/MoltenVK/MoltenVK/Commands/MVKCommand.h b/MoltenVK/MoltenVK/Commands/MVKCommand.h index 3f3c4983..0bb2ff0f 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommand.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommand.h @@ -112,3 +112,19 @@ protected: MVKCommandPool* _commandPool; }; + +#pragma mark - +#pragma mark MVKLoadStoreOverride + +/** Shared state with all draw commands */ +class MVKLoadStoreOverride { +public: + void setLoadOverride(bool loadOverride); + void setStoreOverride(bool storeOverride); + +protected: + bool _loadOverride; + bool _storeOverride; +}; + + diff --git a/MoltenVK/MoltenVK/Commands/MVKCommand.mm b/MoltenVK/MoltenVK/Commands/MVKCommand.mm index e9c564cc..e10759e6 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommand.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommand.mm @@ -37,3 +37,16 @@ MVKDevice* MVKCommand::getDevice() { return getCommandPool()->getDevice(); } id MVKCommand::getMTLDevice() { return getCommandPool()->getMTLDevice(); } + +#pragma mark - +#pragma mark MVKLoadStoreOverride + +void MVKLoadStoreOverride::setLoadOverride(bool loadOverride) { + _loadOverride = loadOverride; +} + +void MVKLoadStoreOverride::setStoreOverride(bool storeOverride) { + _storeOverride = storeOverride; +} + + diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h index 09e28544..5ad5c913 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h @@ -39,6 +39,9 @@ class MVKQueryPool; class MVKPipeline; class MVKGraphicsPipeline; class MVKComputePipeline; +class MVKCmdBeginRenderPass; +class MVKCmdEndRenderPass; +class MVKLoadStoreOverride; typedef uint64_t MVKMTLCommandBufferID; @@ -98,6 +101,29 @@ public: MVKCommandBuffer* _next; +#pragma mark Constituent render pass management + /** Preps metadata for recording render pass */ + void recordBeginRenderPass(MVKCmdBeginRenderPass* mvkBeginRenderPass); + + /** Finishes metadata for recording render pass */ + void recordEndRenderPass(MVKCmdEndRenderPass* mvkEndRenderPass); + + /** Update the last recorded pipeline if it will end and start a new Metal render pass (ie, in tessellation) */ + void recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline); + + /** Update the last recorded drawcall to determine load/store actions */ + void recordDraw(MVKLoadStoreOverride* mvkDraw); + + /** The most recent recorded begin renderpass */ + MVKCmdBeginRenderPass* _lastBeginRenderPass; + + /** The most recent recorded multi-pass (ie, tessellation) pipeline */ + MVKCmdBindPipeline* _lastTessellationPipeline; + + /** The most recent recorded multi-pass (ie, tessellation) draw */ + MVKLoadStoreOverride* _lastTessellationDraw; + + #pragma mark Construction MVKCommandBuffer(MVKDevice* device) : MVKDispatchableDeviceObject(device) {} @@ -240,13 +266,15 @@ public: MVKRenderPass* renderPass, MVKFramebuffer* framebuffer, VkRect2D& renderArea, - MVKVector* clearValues); + MVKVector* clearValues, + bool loadOverride = false, + bool storeOverride = false); /** Begins the next render subpass. */ void beginNextSubpass(VkSubpassContents renderpassContents); /** Begins a Metal render pass for the current render subpass. */ - void beginMetalRenderPass(bool loadOverride = false); + void beginMetalRenderPass(bool loadOverride = false, bool storeOverride = false); /** Returns the render subpass that is currently active. */ MVKRenderSubpass* getSubpass(); @@ -327,7 +355,6 @@ public: /** Marks a timestamp for the specified query. */ void markTimestamp(MVKQueryPool* pQueryPool, uint32_t query); - #pragma mark Dynamic encoding state accessed directly /** A reference to the Metal features supported by the device. */ @@ -398,7 +425,7 @@ public: protected: void addActivatedQuery(MVKQueryPool* pQueryPool, uint32_t query); void finishQueries(); - void setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex); + void setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex, bool loadOverride = false, bool storeOverride = false); void clearRenderArea(); const MVKMTLBufferAllocation* copyToTempMTLBufferAllocation(const void* bytes, NSUInteger length); NSString* getMTLRenderCommandEncoderName(); diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index 4aabdd2f..9532c87d 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -25,6 +25,7 @@ #include "MVKQueryPool.h" #include "MVKFoundation.h" #include "MTLRenderPassDescriptor+MoltenVK.h" +#include "MVKCmdDraw.h" using namespace std; @@ -188,6 +189,44 @@ MVKCommandBuffer::~MVKCommandBuffer() { } +#pragma mark - +#pragma mark Constituent render pass management + +void MVKCommandBuffer::recordBeginRenderPass(MVKCmdBeginRenderPass* mvkBeginRenderPass) { + _lastBeginRenderPass = mvkBeginRenderPass; + _lastTessellationPipeline = nullptr; + _lastTessellationDraw = nullptr; +} + +void MVKCommandBuffer::recordEndRenderPass(MVKCmdEndRenderPass* /*mvkEndRenderPass*/) { + // Unset the store override for the last draw call + if (_lastTessellationDraw != nullptr) + { + _lastTessellationDraw->setStoreOverride(false); + _lastBeginRenderPass->setStoreOverride(true); + } + _lastBeginRenderPass = nullptr; + _lastTessellationPipeline = nullptr; + _lastTessellationDraw = nullptr; +} + +void MVKCommandBuffer::recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline) { + if (mvkBindPipeline->isTessellationPipeline()) + _lastTessellationPipeline = mvkBindPipeline; + else + _lastTessellationPipeline = nullptr; +} + +void MVKCommandBuffer::recordDraw(MVKLoadStoreOverride* mvkDraw) { + if (_lastTessellationPipeline != nullptr) { + // If a multi-pass pipeline is bound and we've already drawn something, need to override load actions + mvkDraw->setLoadOverride(true); + mvkDraw->setStoreOverride(true); + _lastTessellationDraw = mvkDraw; + } +} + + #pragma mark - #pragma mark MVKCommandEncoder @@ -219,14 +258,16 @@ void MVKCommandEncoder::beginRenderpass(VkSubpassContents subpassContents, MVKRenderPass* renderPass, MVKFramebuffer* framebuffer, VkRect2D& renderArea, - MVKVector* clearValues) { + MVKVector* clearValues, + bool loadOverride, + bool storeOverride) { _renderPass = renderPass; _framebuffer = framebuffer; _renderArea = renderArea; _isRenderingEntireAttachment = (mvkVkOffset2DsAreEqual(_renderArea.offset, {0,0}) && mvkVkExtent2DsAreEqual(_renderArea.extent, _framebuffer->getExtent2D())); _clearValues.assign(clearValues->begin(), clearValues->end()); - setSubpass(subpassContents, 0); + setSubpass(subpassContents, 0, loadOverride, storeOverride); } void MVKCommandEncoder::beginNextSubpass(VkSubpassContents contents) { @@ -234,20 +275,20 @@ void MVKCommandEncoder::beginNextSubpass(VkSubpassContents contents) { } // Sets the current render subpass to the subpass with the specified index. -void MVKCommandEncoder::setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex) { +void MVKCommandEncoder::setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex, bool loadOverride, bool storeOverride) { _subpassContents = subpassContents; _renderSubpassIndex = subpassIndex; - beginMetalRenderPass(); + beginMetalRenderPass(loadOverride, storeOverride); } // Creates _mtlRenderEncoder and marks cached render state as dirty so it will be set into the _mtlRenderEncoder. -void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) { +void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride, bool storeOverride) { endCurrentMetalEncoding(); MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor]; - getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _framebuffer, _clearValues, _isRenderingEntireAttachment, loadOverride); + getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _framebuffer, _clearValues, _isRenderingEntireAttachment, loadOverride, storeOverride); mtlRPDesc.visibilityResultBuffer = _occlusionQueryState.getVisibilityResultMTLBuffer(); if (_device->_pMetalFeatures->layeredRendering) { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h index 769c9fa9..45c87888 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h @@ -59,7 +59,8 @@ public: MVKFramebuffer* framebuffer, MVKVector& clearValues, bool isRenderingEntireAttachment, - bool loadOverride = false); + bool loadOverride = false, + bool storeOverride = false); /** * Populates the specified vector with the attachments that need to be cleared @@ -113,7 +114,8 @@ public: bool isRenderingEntireAttachment, bool hasResolveAttachment, bool isStencil, - bool loadOverride = false); + bool loadOverride = false, + bool storeOverride = false); /** Returns whether this attachment should be cleared in the subpass. */ bool shouldUseClearAttachment(MVKRenderSubpass* subpass); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm index 67c2980b..c98965c5 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm @@ -69,7 +69,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* MVKFramebuffer* framebuffer, MVKVector& clearValues, bool isRenderingEntireAttachment, - bool loadOverride) { + bool loadOverride, + bool storeOverride) { // Populate the Metal color attachments uint32_t caCnt = getColorAttachmentCount(); for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) { @@ -91,7 +92,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this, isRenderingEntireAttachment, hasResolveAttachment, false, - loadOverride)) { + loadOverride, + storeOverride)) { mtlColorAttDesc.clearColor = mvkMTLClearColorFromVkClearValue(clearValues[clrRPAttIdx], clrMVKRPAtt->getFormat()); } @@ -113,7 +115,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this, isRenderingEntireAttachment, false, false, - loadOverride)) { + loadOverride, + storeOverride)) { mtlDepthAttDesc.clearDepth = mvkMTLClearDepthFromVkClearValue(clearValues[dsRPAttIdx]); } } @@ -123,7 +126,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this, isRenderingEntireAttachment, false, true, - loadOverride)) { + loadOverride, + storeOverride)) { mtlStencilAttDesc.clearStencil = mvkMTLClearStencilFromVkClearValue(clearValues[dsRPAttIdx]); } } @@ -257,7 +261,8 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende bool isRenderingEntireAttachment, bool hasResolveAttachment, bool isStencil, - bool loadOverride) { + bool loadOverride, + bool storeOverride) { bool willClear = false; // Assume the attachment won't be cleared @@ -278,6 +283,8 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende // to the entire attachment and we're in the last subpass. if (hasResolveAttachment && !_renderPass->getDevice()->getPhysicalDevice()->getMetalFeatures()->combinedStoreResolveAction) { mtlAttDesc.storeAction = MTLStoreActionMultisampleResolve; + } else if ( storeOverride ) { + mtlAttDesc.storeAction = MTLStoreActionStore; } else if ( isRenderingEntireAttachment && (subpass->_subpassIndex == _lastUseSubpassIdx) ) { VkAttachmentStoreOp storeOp = isStencil ? _info.stencilStoreOp : _info.storeOp; mtlAttDesc.storeAction = mvkMTLStoreActionFromVkAttachmentStoreOp(storeOp, hasResolveAttachment); From ef3e59061783c20f585d20e63c4a3b6fcb15cc34 Mon Sep 17 00:00:00 2001 From: Michael Barriault Date: Tue, 16 Apr 2019 18:03:51 +0100 Subject: [PATCH 2/7] Use empty depth state for tessellation vertex pre-pass. --- MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm | 12 ++++++++++++ MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm index 88d88a8a..5ba285d1 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm @@ -115,6 +115,8 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) { } for (uint32_t s : stages) { auto stage = MVKGraphicsStage(s); + if (stage == kMVKGraphicsStageVertex) + cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->finalizeDrawState(stage); // Ensure all updated state has been submitted to Metal id mtlTessCtlEncoder = nil; @@ -150,6 +152,7 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) { // so I apply them during the next stage. cmdEncoder->_graphicsPipelineState.beginMetalRenderPass(); cmdEncoder->_graphicsResourcesState.beginMetalRenderPass(); + cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass(); break; case kMVKGraphicsStageTessControl: @@ -343,6 +346,8 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) { atIndex: 4]; [mtlTessCtlEncoder dispatchThreadgroups: MTLSizeMake(1, 1, 1) threadsPerThreadgroup: MTLSizeMake(1, 1, 1)]; } + if (stage == kMVKGraphicsStageVertex) + cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->finalizeDrawState(stage); // Ensure all updated state has been submitted to Metal switch (stage) { @@ -380,6 +385,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) { // so I apply them during the next stage. cmdEncoder->_graphicsPipelineState.beginMetalRenderPass(); cmdEncoder->_graphicsResourcesState.beginMetalRenderPass(); + cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass(); break; case kMVKGraphicsStageTessControl: @@ -610,6 +616,8 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) { threadsPerThreadgroup: MTLSizeMake(mtlConvertState.threadExecutionWidth, 1, 1)]; } + if (stage == kMVKGraphicsStageVertex) + cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->finalizeDrawState(stage); // Ensure all updated state has been submitted to Metal switch (stage) { @@ -630,6 +638,7 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) { // so I apply them during the next stage. cmdEncoder->_graphicsPipelineState.beginMetalRenderPass(); cmdEncoder->_graphicsResourcesState.beginMetalRenderPass(); + cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass(); break; case kMVKGraphicsStageTessControl: @@ -857,6 +866,8 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) { [mtlTessCtlEncoder dispatchThreadgroups: MTLSizeMake(1, 1, 1) threadsPerThreadgroup: MTLSizeMake(1, 1, 1)]; } + if (stage == kMVKGraphicsStageVertex) + cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->finalizeDrawState(stage); // Ensure all updated state has been submitted to Metal switch (stage) { @@ -880,6 +891,7 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) { // so I apply them during the next stage. cmdEncoder->_graphicsPipelineState.beginMetalRenderPass(); cmdEncoder->_graphicsResourcesState.beginMetalRenderPass(); + cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass(); break; case kMVKGraphicsStageTessControl: diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm index cd5ef52d..b671f790 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm @@ -277,10 +277,10 @@ void MVKDepthStencilCommandEncoderState::setStencilWriteMask(VkStencilFaceFlags } void MVKDepthStencilCommandEncoderState::encodeImpl(uint32_t stage) { - if (stage != kMVKGraphicsStageRasterization) { return; } + if (stage != kMVKGraphicsStageRasterization && stage != kMVKGraphicsStageVertex) { return; } MVKRenderSubpass *subpass = _cmdEncoder->getSubpass(); id mtlDSS = nil; - if (subpass->getDepthStencilFormat() != VK_FORMAT_UNDEFINED) { + if (stage != kMVKGraphicsStageVertex && subpass->getDepthStencilFormat() != VK_FORMAT_UNDEFINED) { mtlDSS = _cmdEncoder->getCommandEncodingPool()->getMTLDepthStencilState(_depthStencilData); } else { // If there is no depth attachment but the depth/stencil state contains a non-always depth From 0aed9167c16a6dbd93df3d8fd5d5d00a685a2adb Mon Sep 17 00:00:00 2001 From: Michael Barriault Date: Tue, 16 Apr 2019 18:12:10 +0100 Subject: [PATCH 3/7] Tweak tabbing for consistency. --- MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm | 4 ++-- MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index 9532c87d..3a4e02dc 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -259,8 +259,8 @@ void MVKCommandEncoder::beginRenderpass(VkSubpassContents subpassContents, MVKFramebuffer* framebuffer, VkRect2D& renderArea, MVKVector* clearValues, - bool loadOverride, - bool storeOverride) { + bool loadOverride, + bool storeOverride) { _renderPass = renderPass; _framebuffer = framebuffer; _renderArea = renderArea; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm index c98965c5..fd58aecd 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm @@ -69,8 +69,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* MVKFramebuffer* framebuffer, MVKVector& clearValues, bool isRenderingEntireAttachment, - bool loadOverride, - bool storeOverride) { + bool loadOverride, + bool storeOverride) { // Populate the Metal color attachments uint32_t caCnt = getColorAttachmentCount(); for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) { From be54e748f02c9cee347a376d4527e95d48103c5a Mon Sep 17 00:00:00 2001 From: Michael Barriault Date: Wed, 17 Apr 2019 21:30:42 +0100 Subject: [PATCH 4/7] Fix tessellated indirect draws using wrong kernels to map parameters. --- MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm index fad8ff66..f948dae4 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm @@ -386,8 +386,8 @@ id MVKCommandResourceFactory::newCmdCopyBufferToImage3D } id MVKCommandResourceFactory::newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed) { - return newMTLComputePipelineState(getFunctionNamed(indexed ? "cmdDrawIndirectConvertBuffers" : - "cmdDrawIndexedIndirectConvertBuffers")); + return newMTLComputePipelineState(getFunctionNamed(indexed ? "cmdDrawIndexedIndirectConvertBuffers" : + "cmdDrawIndirectConvertBuffers")); } id MVKCommandResourceFactory::newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type) { From ea5e38093aad2b30842f8af29f294dc11c68f366 Mon Sep 17 00:00:00 2001 From: Michael Barriault Date: Wed, 17 Apr 2019 21:31:38 +0100 Subject: [PATCH 5/7] Work around potential Metal bug with stage in indirect buffers. Exact size isn't needed in our case anyway. --- MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm | 12 ++++++++---- .../MVKCommandPipelineStateFactoryShaderSource.h | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm index 5ba285d1..3b6f29bb 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm @@ -665,8 +665,10 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) { offset: vtxOutBuff->_offset atIndex: kMVKTessCtlInputBufferIndex]; if ([mtlTessCtlEncoder respondsToSelector: @selector(setStageInRegionWithIndirectBuffer:indirectBufferOffset:)]) { - [mtlTessCtlEncoder setStageInRegionWithIndirectBuffer: tcIndirectBuff->_mtlBuffer - indirectBufferOffset: mtlTCIndBuffOfst]; + // setStageInRegionWithIndirectBuffer appears to be broken. We have a 1D linear region anyway, so size is irrelevant + //[mtlTessCtlEncoder setStageInRegionWithIndirectBuffer: tcIndirectBuff->_mtlBuffer + // indirectBufferOffset: mtlTCIndBuffOfst]; + [mtlTessCtlEncoder setStageInRegion: MTLRegionMake1D(0, std::max(inControlPointCount, outControlPointCount) * patchCount)]; mtlTCIndBuffOfst += sizeof(MTLStageInRegionIndirectArguments); } else { // We must assume we can read up to the maximum number of vertices. @@ -918,8 +920,10 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) { offset: vtxOutBuff->_offset atIndex: kMVKTessCtlInputBufferIndex]; if ([mtlTessCtlEncoder respondsToSelector: @selector(setStageInRegionWithIndirectBuffer:indirectBufferOffset:)]) { - [mtlTessCtlEncoder setStageInRegionWithIndirectBuffer: tcIndirectBuff->_mtlBuffer - indirectBufferOffset: mtlTCIndBuffOfst]; + // setStageInRegionWithIndirectBuffer appears to be broken. We have a 1D linear region anyway, so size is irrelevant + //[mtlTessCtlEncoder setStageInRegionWithIndirectBuffer: tcIndirectBuff->_mtlBuffer + // indirectBufferOffset: mtlTCIndBuffOfst]; + [mtlTessCtlEncoder setStageInRegion: MTLRegionMake1D(0, std::max(inControlPointCount, outControlPointCount) * patchCount)]; mtlTCIndBuffOfst += sizeof(MTLStageInRegionIndirectArguments); } else { // We must assume we can read up to the maximum number of vertices. diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPipelineStateFactoryShaderSource.h b/MoltenVK/MoltenVK/Commands/MVKCommandPipelineStateFactoryShaderSource.h index f8196335..918fdd5d 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandPipelineStateFactoryShaderSource.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandPipelineStateFactoryShaderSource.h @@ -168,7 +168,7 @@ kernel void cmdCopyBufferToImage3DDecompressTempBufferDXTn(constant uint8_t* src } \n\ } \n\ \n\ -#if __METAL_VERSION__ == 210 \n\ +#if __METAL_VERSION__ >= 210 \n\ // This structure is missing from the MSL headers. :/ \n\ struct MTLStageInRegionIndirectArguments { \n\ uint32_t stageInOrigin[3]; \n\ From 08d3d910164ccc26d42ab149f94a984fe950c458 Mon Sep 17 00:00:00 2001 From: Michael Barriault Date: Wed, 17 Apr 2019 22:37:52 +0100 Subject: [PATCH 6/7] Update to latest SPIRV-Cross. --- ExternalRevisions/SPIRV-Cross_repo_revision | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ExternalRevisions/SPIRV-Cross_repo_revision b/ExternalRevisions/SPIRV-Cross_repo_revision index 206e577d..480b2b8d 100644 --- a/ExternalRevisions/SPIRV-Cross_repo_revision +++ b/ExternalRevisions/SPIRV-Cross_repo_revision @@ -1 +1 @@ -ac5a9570a744eb72725c23c34f36fbc564c0bb51 +942273dc7b107d4f0c2cf3449ae306525e1cbae7 From 231196092b2d994588e6a876d13307298d24e9fa Mon Sep 17 00:00:00 2001 From: Michael Barriault Date: Wed, 17 Apr 2019 22:51:40 +0100 Subject: [PATCH 7/7] Fix spaces->tabs for consistency. --- MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm | 24 +++++----- MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h | 2 +- MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm | 10 ++-- .../MoltenVK/Commands/MVKCmdRenderPass.mm | 4 +- MoltenVK/MoltenVK/Commands/MVKCommand.mm | 4 +- MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h | 44 +++++++++--------- .../MoltenVK/Commands/MVKCommandBuffer.mm | 46 +++++++++---------- 7 files changed, 67 insertions(+), 67 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm index 3b6f29bb..f1404b1c 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm @@ -84,8 +84,8 @@ void MVKCmdDraw::setContent(uint32_t vertexCount, _instanceCount = instanceCount; _firstVertex = firstVertex; _firstInstance = firstInstance; - _loadOverride = false; - _storeOverride = false; + _loadOverride = false; + _storeOverride = false; // Validate clearConfigurationResult(); @@ -272,8 +272,8 @@ void MVKCmdDrawIndexed::setContent(uint32_t indexCount, _firstIndex = firstIndex; _vertexOffset = vertexOffset; _firstInstance = firstInstance; - _loadOverride = false; - _storeOverride = false; + _loadOverride = false; + _storeOverride = false; // Validate clearConfigurationResult(); @@ -503,8 +503,8 @@ void MVKCmdDrawIndirect::setContent(VkBuffer buffer, _mtlIndirectBufferOffset = mvkBuffer->getMTLBufferOffset() + offset; _mtlIndirectBufferStride = stride; _drawCount = drawCount; - _loadOverride = false; - _storeOverride = false; + _loadOverride = false; + _storeOverride = false; // Validate clearConfigurationResult(); @@ -745,8 +745,8 @@ void MVKCmdDrawIndexedIndirect::setContent(VkBuffer buffer, _mtlIndirectBufferOffset = mvkBuffer->getMTLBufferOffset() + offset; _mtlIndirectBufferStride = stride; _drawCount = drawCount; - _loadOverride = false; - _storeOverride = false; + _loadOverride = false; + _storeOverride = false; // Validate clearConfigurationResult(); @@ -1009,7 +1009,7 @@ void mvkCmdDraw(MVKCommandBuffer* cmdBuff, uint32_t firstInstance) { MVKCmdDraw* cmd = cmdBuff->_commandPool->_cmdDrawPool.acquireObject(); cmd->setContent(vertexCount, instanceCount, firstVertex, firstInstance); - cmdBuff->recordDraw(cmd); + cmdBuff->recordDraw(cmd); cmdBuff->addCommand(cmd); } @@ -1021,7 +1021,7 @@ void mvkCmdDrawIndexed(MVKCommandBuffer* cmdBuff, uint32_t firstInstance) { MVKCmdDrawIndexed* cmd = cmdBuff->_commandPool->_cmdDrawIndexedPool.acquireObject(); cmd->setContent(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); - cmdBuff->recordDraw(cmd); + cmdBuff->recordDraw(cmd); cmdBuff->addCommand(cmd); } @@ -1041,7 +1041,7 @@ void mvkCmdDrawIndirect(MVKCommandBuffer* cmdBuff, uint32_t stride) { MVKCmdDrawIndirect* cmd = cmdBuff->_commandPool->_cmdDrawIndirectPool.acquireObject(); cmd->setContent(buffer, offset, drawCount, stride); - cmdBuff->recordDraw(cmd); + cmdBuff->recordDraw(cmd); cmdBuff->addCommand(cmd); } @@ -1052,7 +1052,7 @@ void mvkCmdDrawIndexedIndirect(MVKCommandBuffer* cmdBuff, uint32_t stride) { MVKCmdDrawIndexedIndirect* cmd = cmdBuff->_commandPool->_cmdDrawIndexedIndirectPool.acquireObject(); cmd->setContent(buffer, offset, drawCount, stride); - cmdBuff->recordDraw(cmd); + cmdBuff->recordDraw(cmd); cmdBuff->addCommand(cmd); } diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h index e05abdb5..d5bf3dd7 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h @@ -73,7 +73,7 @@ public: MVKCmdBindPipeline(MVKCommandTypePool* pool); - bool isTessellationPipeline(); + bool isTessellationPipeline(); private: VkPipelineBindPoint _bindPoint; diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm index 6b75a9c5..afe05efc 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm @@ -110,10 +110,10 @@ MVKCmdBindPipeline::MVKCmdBindPipeline(MVKCommandTypePool* p : MVKCommand::MVKCommand((MVKCommandTypePool*)pool) {} bool MVKCmdBindPipeline::isTessellationPipeline() { - if (_bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) - return ((MVKGraphicsPipeline*)_pipeline)->isTessellationPipeline(); - else - return false; + if (_bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) + return ((MVKGraphicsPipeline*)_pipeline)->isTessellationPipeline(); + else + return false; } @@ -334,7 +334,7 @@ void mvkCmdBindPipeline(MVKCommandBuffer* cmdBuff, VkPipeline pipeline) { MVKCmdBindPipeline* cmd = cmdBuff->_commandPool->_cmdBindPipelinePool.acquireObject(); cmd->setContent(pipelineBindPoint, pipeline); - cmdBuff->recordBindPipeline(cmd); + cmdBuff->recordBindPipeline(cmd); cmdBuff->addCommand(cmd); } diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm index ff431fd2..6911aa2e 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm @@ -279,7 +279,7 @@ void mvkCmdBeginRenderPass(MVKCommandBuffer* cmdBuff, VkSubpassContents contents) { MVKCmdBeginRenderPass* cmd = cmdBuff->_commandPool->_cmdBeginRenderPassPool.acquireObject(); cmd->setContent(pRenderPassBegin, contents); - cmdBuff->recordBeginRenderPass(cmd); + cmdBuff->recordBeginRenderPass(cmd); cmdBuff->addCommand(cmd); } @@ -291,7 +291,7 @@ void mvkCmdNextSubpass(MVKCommandBuffer* cmdBuff, VkSubpassContents contents) { void mvkCmdEndRenderPass(MVKCommandBuffer* cmdBuff) { MVKCmdEndRenderPass* cmd = cmdBuff->_commandPool->_cmdEndRenderPassPool.acquireObject(); - cmdBuff->recordEndRenderPass(cmd); + cmdBuff->recordEndRenderPass(cmd); cmdBuff->addCommand(cmd); } diff --git a/MoltenVK/MoltenVK/Commands/MVKCommand.mm b/MoltenVK/MoltenVK/Commands/MVKCommand.mm index e10759e6..ee433718 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommand.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommand.mm @@ -42,11 +42,11 @@ id MVKCommand::getMTLDevice() { return getCommandPool()->getMTLDevice #pragma mark MVKLoadStoreOverride void MVKLoadStoreOverride::setLoadOverride(bool loadOverride) { - _loadOverride = loadOverride; + _loadOverride = loadOverride; } void MVKLoadStoreOverride::setStoreOverride(bool storeOverride) { - _storeOverride = storeOverride; + _storeOverride = storeOverride; } diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h index 5ad5c913..61a4aad6 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h @@ -103,25 +103,25 @@ public: #pragma mark Constituent render pass management /** Preps metadata for recording render pass */ - void recordBeginRenderPass(MVKCmdBeginRenderPass* mvkBeginRenderPass); - - /** Finishes metadata for recording render pass */ - void recordEndRenderPass(MVKCmdEndRenderPass* mvkEndRenderPass); - - /** Update the last recorded pipeline if it will end and start a new Metal render pass (ie, in tessellation) */ - void recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline); - - /** Update the last recorded drawcall to determine load/store actions */ - void recordDraw(MVKLoadStoreOverride* mvkDraw); - - /** The most recent recorded begin renderpass */ - MVKCmdBeginRenderPass* _lastBeginRenderPass; - - /** The most recent recorded multi-pass (ie, tessellation) pipeline */ - MVKCmdBindPipeline* _lastTessellationPipeline; - - /** The most recent recorded multi-pass (ie, tessellation) draw */ - MVKLoadStoreOverride* _lastTessellationDraw; + void recordBeginRenderPass(MVKCmdBeginRenderPass* mvkBeginRenderPass); + + /** Finishes metadata for recording render pass */ + void recordEndRenderPass(MVKCmdEndRenderPass* mvkEndRenderPass); + + /** Update the last recorded pipeline if it will end and start a new Metal render pass (ie, in tessellation) */ + void recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline); + + /** Update the last recorded drawcall to determine load/store actions */ + void recordDraw(MVKLoadStoreOverride* mvkDraw); + + /** The most recent recorded begin renderpass */ + MVKCmdBeginRenderPass* _lastBeginRenderPass; + + /** The most recent recorded multi-pass (ie, tessellation) pipeline */ + MVKCmdBindPipeline* _lastTessellationPipeline; + + /** The most recent recorded multi-pass (ie, tessellation) draw */ + MVKLoadStoreOverride* _lastTessellationDraw; #pragma mark Construction @@ -267,8 +267,8 @@ public: MVKFramebuffer* framebuffer, VkRect2D& renderArea, MVKVector* clearValues, - bool loadOverride = false, - bool storeOverride = false); + bool loadOverride = false, + bool storeOverride = false); /** Begins the next render subpass. */ void beginNextSubpass(VkSubpassContents renderpassContents); @@ -425,7 +425,7 @@ public: protected: void addActivatedQuery(MVKQueryPool* pQueryPool, uint32_t query); void finishQueries(); - void setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex, bool loadOverride = false, bool storeOverride = false); + void setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex, bool loadOverride = false, bool storeOverride = false); void clearRenderArea(); const MVKMTLBufferAllocation* copyToTempMTLBufferAllocation(const void* bytes, NSUInteger length); NSString* getMTLRenderCommandEncoderName(); diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index 3a4e02dc..3e6da6b2 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -193,37 +193,37 @@ MVKCommandBuffer::~MVKCommandBuffer() { #pragma mark Constituent render pass management void MVKCommandBuffer::recordBeginRenderPass(MVKCmdBeginRenderPass* mvkBeginRenderPass) { - _lastBeginRenderPass = mvkBeginRenderPass; - _lastTessellationPipeline = nullptr; - _lastTessellationDraw = nullptr; + _lastBeginRenderPass = mvkBeginRenderPass; + _lastTessellationPipeline = nullptr; + _lastTessellationDraw = nullptr; } void MVKCommandBuffer::recordEndRenderPass(MVKCmdEndRenderPass* /*mvkEndRenderPass*/) { - // Unset the store override for the last draw call - if (_lastTessellationDraw != nullptr) - { - _lastTessellationDraw->setStoreOverride(false); - _lastBeginRenderPass->setStoreOverride(true); - } - _lastBeginRenderPass = nullptr; - _lastTessellationPipeline = nullptr; - _lastTessellationDraw = nullptr; + // Unset the store override for the last draw call + if (_lastTessellationDraw != nullptr) + { + _lastTessellationDraw->setStoreOverride(false); + _lastBeginRenderPass->setStoreOverride(true); + } + _lastBeginRenderPass = nullptr; + _lastTessellationPipeline = nullptr; + _lastTessellationDraw = nullptr; } void MVKCommandBuffer::recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline) { - if (mvkBindPipeline->isTessellationPipeline()) - _lastTessellationPipeline = mvkBindPipeline; - else - _lastTessellationPipeline = nullptr; + if (mvkBindPipeline->isTessellationPipeline()) + _lastTessellationPipeline = mvkBindPipeline; + else + _lastTessellationPipeline = nullptr; } void MVKCommandBuffer::recordDraw(MVKLoadStoreOverride* mvkDraw) { - if (_lastTessellationPipeline != nullptr) { - // If a multi-pass pipeline is bound and we've already drawn something, need to override load actions - mvkDraw->setLoadOverride(true); - mvkDraw->setStoreOverride(true); - _lastTessellationDraw = mvkDraw; - } + if (_lastTessellationPipeline != nullptr) { + // If a multi-pass pipeline is bound and we've already drawn something, need to override load actions + mvkDraw->setLoadOverride(true); + mvkDraw->setStoreOverride(true); + _lastTessellationDraw = mvkDraw; + } } @@ -267,7 +267,7 @@ void MVKCommandEncoder::beginRenderpass(VkSubpassContents subpassContents, _isRenderingEntireAttachment = (mvkVkOffset2DsAreEqual(_renderArea.offset, {0,0}) && mvkVkExtent2DsAreEqual(_renderArea.extent, _framebuffer->getExtent2D())); _clearValues.assign(clearValues->begin(), clearValues->end()); - setSubpass(subpassContents, 0, loadOverride, storeOverride); + setSubpass(subpassContents, 0, loadOverride, storeOverride); } void MVKCommandEncoder::beginNextSubpass(VkSubpassContents contents) {