Merge pull request #569 from mbarriault/master

Fix tessellation pipeline re-clearing attachments.
This commit is contained in:
Bill Hollings 2019-04-11 18:31:15 -04:00 committed by GitHub
commit c425602ee7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 25 additions and 16 deletions

View File

@ -194,7 +194,7 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) {
threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)]; threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)];
// Running this stage prematurely ended the render pass, so we have to start it up again. // 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. // TODO: On iOS, maybe we could use a tile shader to avoid this.
cmdEncoder->beginMetalRenderPass(); cmdEncoder->beginMetalRenderPass(true);
break; break;
case kMVKGraphicsStageRasterization: case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) { if (pipeline->isTessellationPipeline()) {
@ -413,7 +413,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) {
threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)]; threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)];
// Running this stage prematurely ended the render pass, so we have to start it up again. // 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. // TODO: On iOS, maybe we could use a tile shader to avoid this.
cmdEncoder->beginMetalRenderPass(); cmdEncoder->beginMetalRenderPass(true);
break; break;
case kMVKGraphicsStageRasterization: case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) { if (pipeline->isTessellationPipeline()) {
@ -663,7 +663,7 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments); mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments);
// Running this stage prematurely ended the render pass, so we have to start it up again. // 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. // TODO: On iOS, maybe we could use a tile shader to avoid this.
cmdEncoder->beginMetalRenderPass(); cmdEncoder->beginMetalRenderPass(true);
break; break;
case kMVKGraphicsStageRasterization: case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) { if (pipeline->isTessellationPipeline()) {
@ -909,7 +909,7 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) {
mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments); mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments);
// Running this stage prematurely ended the render pass, so we have to start it up again. // 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. // TODO: On iOS, maybe we could use a tile shader to avoid this.
cmdEncoder->beginMetalRenderPass(); cmdEncoder->beginMetalRenderPass(true);
break; break;
case kMVKGraphicsStageRasterization: case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) { if (pipeline->isTessellationPipeline()) {

View File

@ -246,7 +246,7 @@ public:
void beginNextSubpass(VkSubpassContents renderpassContents); void beginNextSubpass(VkSubpassContents renderpassContents);
/** Begins a Metal render pass for the current render subpass. */ /** Begins a Metal render pass for the current render subpass. */
void beginMetalRenderPass(); void beginMetalRenderPass(bool loadOverride = false);
/** Returns the render subpass that is currently active. */ /** Returns the render subpass that is currently active. */
MVKRenderSubpass* getSubpass(); MVKRenderSubpass* getSubpass();

View File

@ -242,12 +242,12 @@ void MVKCommandEncoder::setSubpass(VkSubpassContents subpassContents, uint32_t s
} }
// Creates _mtlRenderEncoder and marks cached render state as dirty so it will be set into the _mtlRenderEncoder. // Creates _mtlRenderEncoder and marks cached render state as dirty so it will be set into the _mtlRenderEncoder.
void MVKCommandEncoder::beginMetalRenderPass() { void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) {
endCurrentMetalEncoding(); endCurrentMetalEncoding();
MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor]; MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor];
getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _framebuffer, _clearValues, _isRenderingEntireAttachment); getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _framebuffer, _clearValues, _isRenderingEntireAttachment, loadOverride);
mtlRPDesc.visibilityResultBuffer = _occlusionQueryState.getVisibilityResultMTLBuffer(); mtlRPDesc.visibilityResultBuffer = _occlusionQueryState.getVisibilityResultMTLBuffer();
if (_device->_pMetalFeatures->layeredRendering) { if (_device->_pMetalFeatures->layeredRendering) {

View File

@ -58,7 +58,8 @@ public:
void populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc, void populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc,
MVKFramebuffer* framebuffer, MVKFramebuffer* framebuffer,
MVKVector<VkClearValue>& clearValues, MVKVector<VkClearValue>& clearValues,
bool isRenderingEntireAttachment); bool isRenderingEntireAttachment,
bool loadOverride = false);
/** /**
* Populates the specified vector with the attachments that need to be cleared * Populates the specified vector with the attachments that need to be cleared
@ -111,7 +112,8 @@ public:
MVKRenderSubpass* subpass, MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment, bool isRenderingEntireAttachment,
bool hasResolveAttachment, bool hasResolveAttachment,
bool isStencil); bool isStencil,
bool loadOverride = false);
/** Returns whether this attachment should be cleared in the subpass. */ /** Returns whether this attachment should be cleared in the subpass. */
bool shouldUseClearAttachment(MVKRenderSubpass* subpass); bool shouldUseClearAttachment(MVKRenderSubpass* subpass);

View File

@ -68,7 +68,8 @@ VkSampleCountFlagBits MVKRenderSubpass::getSampleCount() {
void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc, void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc,
MVKFramebuffer* framebuffer, MVKFramebuffer* framebuffer,
MVKVector<VkClearValue>& clearValues, MVKVector<VkClearValue>& clearValues,
bool isRenderingEntireAttachment) { bool isRenderingEntireAttachment,
bool loadOverride) {
// Populate the Metal color attachments // Populate the Metal color attachments
uint32_t caCnt = getColorAttachmentCount(); uint32_t caCnt = getColorAttachmentCount();
for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) { for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) {
@ -89,7 +90,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
framebuffer->getAttachment(clrRPAttIdx)->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc); framebuffer->getAttachment(clrRPAttIdx)->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc);
if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this, if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this,
isRenderingEntireAttachment, isRenderingEntireAttachment,
hasResolveAttachment, false)) { hasResolveAttachment, false,
loadOverride)) {
mtlColorAttDesc.clearColor = mvkMTLClearColorFromVkClearValue(clearValues[clrRPAttIdx], clrMVKRPAtt->getFormat()); mtlColorAttDesc.clearColor = mvkMTLClearColorFromVkClearValue(clearValues[clrRPAttIdx], clrMVKRPAtt->getFormat());
} }
@ -110,8 +112,9 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
dsImage->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc); dsImage->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc);
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this, if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this,
isRenderingEntireAttachment, isRenderingEntireAttachment,
false, false)) { false, false,
mtlDepthAttDesc.clearDepth = mvkMTLClearDepthFromVkClearValue(clearValues[dsRPAttIdx]); loadOverride)) {
mtlDepthAttDesc.clearDepth = mvkMTLClearDepthFromVkClearValue(clearValues[dsRPAttIdx]);
} }
} }
if (mvkMTLPixelFormatIsStencilFormat(mtlDSFormat)) { if (mvkMTLPixelFormatIsStencilFormat(mtlDSFormat)) {
@ -119,7 +122,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
dsImage->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc); dsImage->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc);
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this, if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this,
isRenderingEntireAttachment, isRenderingEntireAttachment,
false, true)) { false, true,
loadOverride)) {
mtlStencilAttDesc.clearStencil = mvkMTLClearStencilFromVkClearValue(clearValues[dsRPAttIdx]); mtlStencilAttDesc.clearStencil = mvkMTLClearStencilFromVkClearValue(clearValues[dsRPAttIdx]);
} }
} }
@ -252,13 +256,16 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende
MVKRenderSubpass* subpass, MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment, bool isRenderingEntireAttachment,
bool hasResolveAttachment, bool hasResolveAttachment,
bool isStencil) { bool isStencil,
bool loadOverride) {
bool willClear = false; // Assume the attachment won't be cleared bool willClear = false; // Assume the attachment won't be cleared
// Only allow clearing of entire attachment if we're actually rendering to the entire // Only allow clearing of entire attachment if we're actually rendering to the entire
// attachment AND we're in the first subpass. // attachment AND we're in the first subpass.
if ( isRenderingEntireAttachment && (subpass->_subpassIndex == _firstUseSubpassIdx) ) { if ( loadOverride ) {
mtlAttDesc.loadAction = MTLLoadActionLoad;
} else if ( isRenderingEntireAttachment && (subpass->_subpassIndex == _firstUseSubpassIdx) ) {
VkAttachmentLoadOp loadOp = isStencil ? _info.stencilLoadOp : _info.loadOp; VkAttachmentLoadOp loadOp = isStencil ? _info.stencilLoadOp : _info.loadOp;
mtlAttDesc.loadAction = mvkMTLLoadActionFromVkAttachmentLoadOp(loadOp); mtlAttDesc.loadAction = mvkMTLLoadActionFromVkAttachmentLoadOp(loadOp);
willClear = (_info.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR); willClear = (_info.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);