MVKPipeline: Don't set blend state for unused attachments.

Some clients always set blend state for all eight attachments, even if
the attachments are unused. Since the attachments are unused, the
expectation is that the corresponding blend states won't matter. But in
Metal, there's no way to tell if an attachment won't be used. So, if you
enable blending on an unused attachment, its pixel format will be
`MTLPixelFormatInvalid`, which doesn't support blending; Metal will
assert on this.
This commit is contained in:
Chip Davis 2018-10-02 22:48:48 -05:00
parent 70dae8946a
commit a0a93e0cdb
3 changed files with 22 additions and 7 deletions

View File

@ -383,13 +383,18 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx];
colorDesc.pixelFormat = mtlPixelFormatFromVkFormat(mvkRenderSubpass->getColorAttachmentFormat(caIdx));
colorDesc.writeMask = mvkMTLColorWriteMaskFromVkChannelFlags(pCA->colorWriteMask);
colorDesc.blendingEnabled = pCA->blendEnable;
colorDesc.rgbBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->colorBlendOp);
colorDesc.sourceRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcColorBlendFactor);
colorDesc.destinationRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstColorBlendFactor);
colorDesc.alphaBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->alphaBlendOp);
colorDesc.sourceAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcAlphaBlendFactor);
colorDesc.destinationAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstAlphaBlendFactor);
// Don't set the blend state if we're not using this attachment.
// The pixel format will be MTLPixelFormatInvalid in that case, and
// Metal asserts if we turn on blending with that pixel format.
if (mvkRenderSubpass->isColorAttachmentUsed(caIdx)) {
colorDesc.blendingEnabled = pCA->blendEnable;
colorDesc.rgbBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->colorBlendOp);
colorDesc.sourceRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcColorBlendFactor);
colorDesc.destinationRGBBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstColorBlendFactor);
colorDesc.alphaBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->alphaBlendOp);
colorDesc.sourceAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcAlphaBlendFactor);
colorDesc.destinationAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstAlphaBlendFactor);
}
}
}

View File

@ -41,6 +41,9 @@ public:
/** Returns the format of the color attachment at the specified index. */
VkFormat getColorAttachmentFormat(uint32_t colorAttIdx);
/** Returns whether or not the color attachment at the specified index is being used. */
bool isColorAttachmentUsed(uint32_t colorAttIdx);
/** Returns the format of the depth/stencil attachment. */
VkFormat getDepthStencilFormat();

View File

@ -37,6 +37,13 @@ VkFormat MVKRenderSubpass::getColorAttachmentFormat(uint32_t colorAttIdx) {
return VK_FORMAT_UNDEFINED;
}
bool MVKRenderSubpass::isColorAttachmentUsed(uint32_t colorAttIdx) {
if (colorAttIdx >= _colorAttachments.size()) {
return false;
}
return _colorAttachments[colorAttIdx].attachment != VK_ATTACHMENT_UNUSED;
}
VkFormat MVKRenderSubpass::getDepthStencilFormat() {
uint32_t rpAttIdx = _depthStencilAttachment.attachment;
if (rpAttIdx == VK_ATTACHMENT_UNUSED) { return VK_FORMAT_UNDEFINED; }