Support separate depth and stencil attachments during dynamic rendering.

- MVKRenderSubpass add separate getDepthFormat() & getStencilFormat(),
  and isDepthAttachmentUsed() & isStencilAttachmentUsed() and use
  instead of testing pixel format for depth and stencil components.
- Add MVKRenderingAttachmentIterator class to consistently iterate,
  and take actions, on the attachments in VkRenderingInfo to create
  synthetic MVKRenderPass and extract image views and clear colors.
- Remove mvkCreateRenderPass() and mvkCreateFramebuffer() in favor
  of additional constructors, and remove mvkGetDepthStencilFormat() in
  favor of retrieving formats for separate depth and stencil attachments.
- MVKRenderpass constructors reorganize order of adding attachments and
  subpasses, and connecting the two.
- Renmame MVKRenderPassAttachment to MVKAttachmentDescription.
- MVKPipeline reorganize member variables to minimize gaps in content
  and remove unnecessary _isRasterizingDepthStencil member var (unrelated).
This commit is contained in:
Bill Hollings 2023-04-24 15:23:46 -04:00
parent 5cbeaaa82c
commit 4aa2b6dd9f
13 changed files with 540 additions and 561 deletions

View File

@ -21,6 +21,7 @@ Released TBD
- Add support for extensions:
- `VK_KHR_map_memory2`
- Support BC compression on iOS/tvOS where available (iOS/tvOS 16.4 and above and supported by the GPU).
- Support separate depth and stencil attachments during dynamic rendering.
- Fix memory leak when waiting on timeline semaphores.
- Ensure shaders that use `PhysicalStorageBufferAddresses` encode the use of the associated `MTLBuffer`.
- Add `MVK_ENABLE_EXPLICIT_LOD_WORKAROUND` environment variable to selectively

View File

@ -1446,21 +1446,17 @@ void MVKCmdClearAttachments<N>::encode(MVKCommandEncoder* cmdEncoder) {
// The depth value (including vertex position Z value) is held in the last index.
clearColors[kMVKClearAttachmentDepthStencilIndex] = { _mtlDepthVal, _mtlDepthVal, _mtlDepthVal, _mtlDepthVal };
VkFormat vkAttFmt = subpass->getDepthStencilFormat();
MTLPixelFormat mtlAttFmt = pixFmts->getMTLPixelFormat(vkAttFmt);
_rpsKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthStencilIndex] = mtlAttFmt;
bool isClearingDepth = _isClearingDepth && pixFmts->isDepthFormat(mtlAttFmt);
bool isClearingStencil = _isClearingStencil && pixFmts->isStencilFormat(mtlAttFmt);
if (!isClearingDepth && !isClearingStencil) {
// If the subpass attachment isn't actually used, don't try to clear it.
bool isClearingDepth = _isClearingDepth && subpass->isDepthAttachmentUsed();
bool isClearingStencil = _isClearingStencil && subpass->isStencilAttachmentUsed();
if (isClearingDepth) {
_rpsKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthStencilIndex] = pixFmts->getMTLPixelFormat(subpass->getDepthFormat());
} else if (isClearingStencil) {
_rpsKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthStencilIndex] = pixFmts->getMTLPixelFormat(subpass->getStencilFormat());
} else {
_rpsKey.disableAttachment(kMVKClearAttachmentDepthStencilIndex);
}
if (!_rpsKey.isAnyAttachmentEnabled()) {
// Nothing to do.
return;
}
if ( !_rpsKey.isAnyAttachmentEnabled() ) { return; }
// Render the clear colors to the attachments
MVKCommandEncodingPool* cmdEncPool = cmdEncoder->getCommandEncodingPool();

View File

@ -401,10 +401,17 @@ void MVKCommandEncoder::beginRendering(MVKCommand* rendCmd, const VkRenderingInf
? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
: VK_SUBPASS_CONTENTS_INLINE);
uint32_t maxAttCnt = (pRenderingInfo->colorAttachmentCount + 1) * 2;
MVKImageView* attachments[maxAttCnt];
uint32_t maxAttCnt = (pRenderingInfo->colorAttachmentCount + 2) * 2;
MVKImageView* imageViews[maxAttCnt];
VkClearValue clearValues[maxAttCnt];
uint32_t attCnt = mvkGetAttachments(pRenderingInfo, attachments, clearValues);
uint32_t attCnt = 0;
MVKRenderingAttachmentIterator attIter(pRenderingInfo);
attIter.iterate([&](const VkRenderingAttachmentInfo* pAttInfo, VkImageAspectFlagBits aspect, bool isResolveAttachment)->void {
imageViews[attCnt] = (MVKImageView*)(isResolveAttachment ? pAttInfo->resolveImageView : pAttInfo->imageView);
clearValues[attCnt] = pAttInfo->clearValue;
attCnt++;
});
// If we're resuming a suspended renderpass, continue to use the existing renderpass
// (with updated rendering flags) and framebuffer. Otherwise, create new transient
@ -419,13 +426,14 @@ void MVKCommandEncoder::beginRendering(MVKCommand* rendCmd, const VkRenderingInf
mvkRP->setRenderingFlags(pRenderingInfo->flags);
mvkFB = _pEncodingContext->getFramebuffer();
} else {
mvkRP = mvkCreateRenderPass(getDevice(), pRenderingInfo);
mvkFB = mvkCreateFramebuffer(getDevice(), pRenderingInfo, mvkRP);
auto* mvkDev = getDevice();
mvkRP = mvkDev->createRenderPass(pRenderingInfo, nullptr);
mvkFB = mvkDev->createFramebuffer(pRenderingInfo, nullptr);
}
beginRenderpass(rendCmd, contents, mvkRP, mvkFB,
pRenderingInfo->renderArea,
MVKArrayRef(clearValues, attCnt),
MVKArrayRef(attachments, attCnt),
MVKArrayRef(imageViews, attCnt),
MVKArrayRef<MVKArrayRef<MTLSamplePosition>>(),
kMVKCommandUseBeginRendering);

View File

@ -328,15 +328,12 @@ void MVKDepthStencilCommandEncoderState::beginMetalRenderPass() {
MVKCommandEncoderState::beginMetalRenderPass();
MVKRenderSubpass* mvkSubpass = _cmdEncoder->getSubpass();
MVKPixelFormats* pixFmts = _cmdEncoder->getPixelFormats();
MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(mvkSubpass->getDepthStencilFormat());
bool prevHasDepthAttachment = _hasDepthAttachment;
_hasDepthAttachment = pixFmts->isDepthFormat(mtlDSFormat);
_hasDepthAttachment = mvkSubpass->isDepthAttachmentUsed();
if (_hasDepthAttachment != prevHasDepthAttachment) { markDirty(); }
bool prevHasStencilAttachment = _hasStencilAttachment;
_hasStencilAttachment = pixFmts->isStencilFormat(mtlDSFormat);
_hasStencilAttachment = mvkSubpass->isStencilAttachmentUsed();
if (_hasStencilAttachment != prevHasStencilAttachment) { markDirty(); }
}

View File

@ -631,6 +631,8 @@ public:
MVKFramebuffer* createFramebuffer(const VkFramebufferCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
MVKFramebuffer* createFramebuffer(const VkRenderingInfo* pRenderingInfo,
const VkAllocationCallbacks* pAllocator);
void destroyFramebuffer(MVKFramebuffer* mvkFB,
const VkAllocationCallbacks* pAllocator);
@ -638,6 +640,8 @@ public:
const VkAllocationCallbacks* pAllocator);
MVKRenderPass* createRenderPass(const VkRenderPassCreateInfo2* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
MVKRenderPass* createRenderPass(const VkRenderingInfo* pRenderingInfo,
const VkAllocationCallbacks* pAllocator);
void destroyRenderPass(MVKRenderPass* mvkRP,
const VkAllocationCallbacks* pAllocator);

View File

@ -3893,6 +3893,11 @@ MVKFramebuffer* MVKDevice::createFramebuffer(const VkFramebufferCreateInfo* pCre
return new MVKFramebuffer(this, pCreateInfo);
}
MVKFramebuffer* MVKDevice::createFramebuffer(const VkRenderingInfo* pRenderingInfo,
const VkAllocationCallbacks* pAllocator) {
return new MVKFramebuffer(this, pRenderingInfo);
}
void MVKDevice::destroyFramebuffer(MVKFramebuffer* mvkFB,
const VkAllocationCallbacks* pAllocator) {
if (mvkFB) { mvkFB->destroy(); }
@ -3908,6 +3913,11 @@ MVKRenderPass* MVKDevice::createRenderPass(const VkRenderPassCreateInfo2* pCreat
return new MVKRenderPass(this, pCreateInfo);
}
MVKRenderPass* MVKDevice::createRenderPass(const VkRenderingInfo* pRenderingInfo,
const VkAllocationCallbacks* pAllocator) {
return new MVKRenderPass(this, pRenderingInfo);
}
void MVKDevice::destroyRenderPass(MVKRenderPass* mvkRP,
const VkAllocationCallbacks* pAllocator) {
if (mvkRP) { mvkRP->destroy(); }

View File

@ -58,6 +58,8 @@ public:
MVKFramebuffer(MVKDevice* device, const VkFramebufferCreateInfo* pCreateInfo);
MVKFramebuffer(MVKDevice* device, const VkRenderingInfo* pRenderingInfo);
~MVKFramebuffer() override;
protected:
@ -69,12 +71,3 @@ protected:
VkExtent2D _extent;
uint32_t _layerCount;
};
#pragma mark -
#pragma mark Support functions
/** Returns an image-less MVKFramebuffer object created from the rendering info. */
MVKFramebuffer* mvkCreateFramebuffer(MVKDevice* device,
const VkRenderingInfo* pRenderingInfo,
MVKRenderPass* mvkRenderPass);

View File

@ -82,8 +82,8 @@ id<MTLTexture> MVKFramebuffer::getDummyAttachmentMTLTexture(MVKRenderSubpass* su
MVKFramebuffer::MVKFramebuffer(MVKDevice* device,
const VkFramebufferCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
_extent = { .width = pCreateInfo->width, .height = pCreateInfo->height };
_layerCount = pCreateInfo->layers;
_extent = { .width = pCreateInfo->width, .height = pCreateInfo->height };
// If this is not an image-less framebuffer, add the attachments
if ( !mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT) ) {
@ -94,51 +94,25 @@ MVKFramebuffer::MVKFramebuffer(MVKDevice* device,
}
}
MVKFramebuffer::~MVKFramebuffer() {
[_mtlDummyTex release];
}
MVKFramebuffer::MVKFramebuffer(MVKDevice* device,
const VkRenderingInfo* pRenderingInfo) : MVKVulkanAPIDeviceObject(device) {
_layerCount = pRenderingInfo->layerCount;
#pragma mark -
#pragma mark Support functions
MVKFramebuffer* mvkCreateFramebuffer(MVKDevice* device,
const VkRenderingInfo* pRenderingInfo,
MVKRenderPass* mvkRenderPass) {
uint32_t attCnt = 0;
VkExtent3D fbExtent = {};
_extent = {};
for (uint32_t caIdx = 0; caIdx < pRenderingInfo->colorAttachmentCount; caIdx++) {
auto& clrAtt = pRenderingInfo->pColorAttachments[caIdx];
if (clrAtt.imageView) {
fbExtent = ((MVKImageView*)clrAtt.imageView)->getExtent3D();
attCnt++;
if (clrAtt.resolveImageView && clrAtt.resolveMode != VK_RESOLVE_MODE_NONE) {
attCnt++;
}
_extent = mvkVkExtent2DFromVkExtent3D(((MVKImageView*)clrAtt.imageView)->getExtent3D());
}
}
auto* pDSAtt = pRenderingInfo->pDepthAttachment ? pRenderingInfo->pDepthAttachment : pRenderingInfo->pStencilAttachment;
if (pDSAtt) {
if (pDSAtt->imageView) {
fbExtent = ((MVKImageView*)pDSAtt->imageView)->getExtent3D();
attCnt++;
}
if (pDSAtt->resolveImageView && pDSAtt->resolveMode != VK_RESOLVE_MODE_NONE) {
attCnt++;
}
if (pRenderingInfo->pDepthAttachment && pRenderingInfo->pDepthAttachment->imageView) {
_extent = mvkVkExtent2DFromVkExtent3D(((MVKImageView*)pRenderingInfo->pDepthAttachment->imageView)->getExtent3D());
}
if (pRenderingInfo->pStencilAttachment && pRenderingInfo->pStencilAttachment->imageView) {
_extent = mvkVkExtent2DFromVkExtent3D(((MVKImageView*)pRenderingInfo->pStencilAttachment->imageView)->getExtent3D());
}
VkFramebufferCreateInfo fbCreateInfo;
fbCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbCreateInfo.pNext = nullptr;
fbCreateInfo.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
fbCreateInfo.renderPass = (VkRenderPass)mvkRenderPass;
fbCreateInfo.attachmentCount = attCnt;
fbCreateInfo.pAttachments = nullptr;
fbCreateInfo.width = fbExtent.width;
fbCreateInfo.height = fbExtent.height;
fbCreateInfo.layers = pRenderingInfo->layerCount;
return device->createFramebuffer(&fbCreateInfo, nullptr);
}
MVKFramebuffer::~MVKFramebuffer() {
[_mtlDummyTex release];
}

View File

@ -346,11 +346,6 @@ protected:
void markIfUsingPhysicalStorageBufferAddressesCapability(SPIRVToMSLConversionResultInfo& resultsInfo,
MVKShaderStage stage);
const VkPipelineShaderStageCreateInfo* _pVertexSS = nullptr;
const VkPipelineShaderStageCreateInfo* _pTessCtlSS = nullptr;
const VkPipelineShaderStageCreateInfo* _pTessEvalSS = nullptr;
const VkPipelineShaderStageCreateInfo* _pFragmentSS = nullptr;
VkPipelineTessellationStateCreateInfo _tessInfo;
VkPipelineRasterizationStateCreateInfo _rasterInfo;
VkPipelineDepthStencilStateCreateInfo _depthStencilInfo;
@ -364,7 +359,12 @@ protected:
MVKSmallVector<MVKStagedMTLArgumentEncoders> _mtlArgumentEncoders;
MVKSmallVector<MVKStagedDescriptorBindingUse> _descriptorBindingUse;
MVKSmallVector<MVKShaderStage> _stagesUsingPhysicalStorageBufferAddressesCapability;
std::unordered_map<uint32_t, id<MTLRenderPipelineState>> _multiviewMTLPipelineStates;
const VkPipelineShaderStageCreateInfo* _pVertexSS = nullptr;
const VkPipelineShaderStageCreateInfo* _pTessCtlSS = nullptr;
const VkPipelineShaderStageCreateInfo* _pTessEvalSS = nullptr;
const VkPipelineShaderStageCreateInfo* _pFragmentSS = nullptr;
MTLComputePipelineDescriptor* _mtlTessVertexStageDesc = nil;
id<MTLFunction> _mtlTessVertexFunctions[3] = {nil, nil, nil};
@ -373,18 +373,17 @@ protected:
id<MTLComputePipelineState> _mtlTessVertexStageIndex32State = nil;
id<MTLComputePipelineState> _mtlTessControlStageState = nil;
id<MTLRenderPipelineState> _mtlPipelineState = nil;
std::unordered_map<uint32_t, id<MTLRenderPipelineState>> _multiviewMTLPipelineStates;
float _blendConstants[4] = { 0.0, 0.0, 0.0, 1.0 };
MTLCullMode _mtlCullMode;
MTLWinding _mtlFrontWinding;
MTLTriangleFillMode _mtlFillMode;
MTLDepthClipMode _mtlDepthClipMode;
MTLPrimitiveType _mtlPrimitiveType;
float _blendConstants[4] = { 0.0, 0.0, 0.0, 1.0 };
uint32_t _outputControlPointCount;
MVKShaderImplicitRezBinding _reservedVertexAttributeBufferCount;
MVKShaderImplicitRezBinding _viewRangeBufferIndex;
MVKShaderImplicitRezBinding _outputBufferIndex;
uint32_t _outputControlPointCount;
uint32_t _tessCtlPatchOutputBufferIndex = 0;
uint32_t _tessCtlLevelBufferIndex = 0;
@ -408,7 +407,6 @@ protected:
bool _needsFragmentViewRangeBuffer = false;
bool _isRasterizing = false;
bool _isRasterizingColor = false;
bool _isRasterizingDepthStencil = false;
bool _isUsingCustomSamplePositions = false;
};

View File

@ -401,7 +401,6 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
const VkPipelineRenderingCreateInfo* pRendInfo = getRenderingCreateInfo(pCreateInfo);
_isRasterizing = !isRasterizationDisabled(pCreateInfo);
_isRasterizingColor = _isRasterizing && mvkHasColorAttachments(pRendInfo);
_isRasterizingDepthStencil = _isRasterizing && mvkGetDepthStencilFormat(pRendInfo) != VK_FORMAT_UNDEFINED;
// Get the tessellation shaders, if present. Do this now, because we need to extract
// reflection data from them that informs everything else.
@ -488,8 +487,9 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
initCustomSamplePositions(pCreateInfo);
// Depth stencil content - clearing will disable depth and stencil testing
// Must ignore allowed bad pDepthStencilState pointer if rasterization disabled or no depth attachment
mvkSetOrClear(&_depthStencilInfo, _isRasterizingDepthStencil ? pCreateInfo->pDepthStencilState : nullptr);
// Must ignore allowed bad pDepthStencilState pointer if rasterization disabled or no depth or stencil attachment format
bool isRasterizingDepthStencil = _isRasterizing && (pRendInfo->depthAttachmentFormat || pRendInfo->stencilAttachmentFormat);
mvkSetOrClear(&_depthStencilInfo, isRasterizingDepthStencil ? pCreateInfo->pDepthStencilState : nullptr);
// Viewports and scissors - must ignore allowed bad pViewportState pointer if rasterization is disabled
auto pVPState = _isRasterizing ? pCreateInfo->pViewportState : nullptr;
@ -1469,16 +1469,15 @@ void MVKGraphicsPipeline::addFragmentOutputToPipeline(MTLRenderPipelineDescripto
}
}
// Depth & stencil attachments
// Depth & stencil attachment formats
MVKPixelFormats* pixFmts = getPixelFormats();
MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(mvkGetDepthStencilFormat(pRendInfo));
if (pixFmts->isDepthFormat(mtlDSFormat)) { plDesc.depthAttachmentPixelFormat = mtlDSFormat; }
if (pixFmts->isStencilFormat(mtlDSFormat)) { plDesc.stencilAttachmentPixelFormat = mtlDSFormat; }
plDesc.depthAttachmentPixelFormat = pixFmts->getMTLPixelFormat(pRendInfo->depthAttachmentFormat);
plDesc.stencilAttachmentPixelFormat = pixFmts->getMTLPixelFormat(pRendInfo->stencilAttachmentFormat);
// In Vulkan, it's perfectly valid to render with no attachments. In Metal we need to check for
// support for it. If we have no attachments, then we may have to add a dummy attachment.
if (!caCnt && !pixFmts->isDepthFormat(mtlDSFormat) && !pixFmts->isStencilFormat(mtlDSFormat) &&
!getDevice()->_pMetalFeatures->renderWithoutAttachments) {
// In Vulkan, it's perfectly valid to render without any attachments. In Metal, if that
// isn't supported, and we have no attachments, then we have to add a dummy attachment.
if (!getDevice()->_pMetalFeatures->renderWithoutAttachments &&
!caCnt && !pRendInfo->depthAttachmentFormat && !pRendInfo->stencilAttachmentFormat) {
MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[0];
colorDesc.pixelFormat = MTLPixelFormatR8Unorm;
@ -1553,8 +1552,6 @@ void MVKGraphicsPipeline::initShaderConversionConfig(SPIRVToMSLConversionConfigu
_viewRangeBufferIndex = _indirectParamsIndex;
const VkPipelineRenderingCreateInfo* pRendInfo = getRenderingCreateInfo(pCreateInfo);
MVKPixelFormats* pixFmts = getPixelFormats();
MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(mvkGetDepthStencilFormat(pRendInfo));
// Disable any unused color attachments, because Metal validation can complain if the
// fragment shader outputs a color value without a corresponding color attachment.
@ -1574,8 +1571,8 @@ void MVKGraphicsPipeline::initShaderConversionConfig(SPIRVToMSLConversionConfigu
shaderConfig.options.mslOptions.ios_support_base_vertex_instance = getDevice()->_pMetalFeatures->baseVertexInstanceDrawing;
shaderConfig.options.mslOptions.texture_1D_as_2D = mvkConfig().texture1DAs2D;
shaderConfig.options.mslOptions.enable_point_size_builtin = isRenderingPoints(pCreateInfo) || reflectData.pointMode;
shaderConfig.options.mslOptions.enable_frag_depth_builtin = pixFmts->isDepthFormat(mtlDSFormat);
shaderConfig.options.mslOptions.enable_frag_stencil_ref_builtin = pixFmts->isStencilFormat(mtlDSFormat);
shaderConfig.options.mslOptions.enable_frag_depth_builtin = (pRendInfo->depthAttachmentFormat != VK_FORMAT_UNDEFINED);
shaderConfig.options.mslOptions.enable_frag_stencil_ref_builtin = (pRendInfo->stencilAttachmentFormat != VK_FORMAT_UNDEFINED);
shaderConfig.options.shouldFlipVertexY = mvkConfig().shaderConversionFlipVertexY;
shaderConfig.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle;
shaderConfig.options.mslOptions.tess_domain_origin_lower_left = pTessDomainOriginState && pTessDomainOriginState->domainOrigin == VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;

View File

@ -54,9 +54,6 @@ public:
/** Returns whether this subpass has any color attachments. */
bool hasColorAttachments();
/** Returns whether this subpass has a depth/stencil attachment. */
bool hasDepthStencilAttachment() { return _depthStencilAttachment.attachment != VK_ATTACHMENT_UNUSED; }
/** Returns the number of color attachments, which may be zero for depth-only rendering. */
uint32_t getColorAttachmentCount() { return uint32_t(_colorAttachments.size()); }
@ -69,8 +66,17 @@ public:
/** Returns whether or not the color attachment is used as both a color attachment and an input attachment. */
bool isColorAttachmentAlsoInputAttachment(uint32_t colorAttIdx);
/** Returns the format of the depth/stencil attachment. */
VkFormat getDepthStencilFormat();
/** Returns whether or not the depth attachment is being used. */
bool isDepthAttachmentUsed() { return _depthAttachment.attachment != VK_ATTACHMENT_UNUSED; }
/** Returns whether or not the stencil attachment is being used. */
bool isStencilAttachmentUsed() { return _stencilAttachment.attachment != VK_ATTACHMENT_UNUSED; }
/** Return the depth attachment format. */
VkFormat getDepthFormat();
/** Return the stencil attachment format. */
VkFormat getStencilFormat();
/** Returns the Vulkan sample count of the attachments used in this subpass. */
VkSampleCountFlagBits getSampleCount();
@ -146,10 +152,11 @@ public:
MVKRenderSubpass(MVKRenderPass* renderPass, const VkSubpassDescription2* pCreateInfo);
private:
MVKRenderSubpass(MVKRenderPass* renderPass, const VkRenderingInfo* pRenderingInfo);
protected:
friend class MVKRenderPass;
friend class MVKRenderPassAttachment;
friend class MVKAttachmentDescription;
uint32_t getViewMaskGroupForMetalPass(uint32_t passIdx);
MVKMTLFmtCaps getRequiredFormatCapabilitiesForAttachmentAt(uint32_t rpAttIdx);
@ -162,8 +169,10 @@ private:
MVKSmallVector<uint32_t, kMVKDefaultAttachmentCount> _preserveAttachments;
MVKSmallVector<VkFormat, kMVKDefaultAttachmentCount> _colorAttachmentFormats;
VkPipelineRenderingCreateInfo _pipelineRenderingCreateInfo;
VkAttachmentReference2 _depthStencilAttachment;
VkAttachmentReference2 _depthStencilResolveAttachment;
VkAttachmentReference2 _depthAttachment;
VkAttachmentReference2 _stencilAttachment;
VkAttachmentReference2 _depthResolveAttachment;
VkAttachmentReference2 _stencilResolveAttachment;
VkResolveModeFlagBits _depthResolveMode = VK_RESOLVE_MODE_NONE;
VkResolveModeFlagBits _stencilResolveMode = VK_RESOLVE_MODE_NONE;
VkSampleCountFlagBits _defaultSampleCount = VK_SAMPLE_COUNT_1_BIT;
@ -172,10 +181,10 @@ private:
#pragma mark -
#pragma mark MVKRenderPassAttachment
#pragma mark MVKAttachmentDescription
/** Represents an attachment within a Vulkan render pass. */
class MVKRenderPassAttachment : public MVKBaseObject {
class MVKAttachmentDescription : public MVKBaseObject {
public:
@ -218,13 +227,20 @@ public:
/** Returns whether this attachment should be cleared in the subpass. */
bool shouldClearAttachment(MVKRenderSubpass* subpass, bool isStencil);
MVKRenderPassAttachment(MVKRenderPass* renderPass,
MVKAttachmentDescription(MVKRenderPass* renderPass,
const VkAttachmentDescription* pCreateInfo);
MVKRenderPassAttachment(MVKRenderPass* renderPass,
MVKAttachmentDescription(MVKRenderPass* renderPass,
const VkAttachmentDescription2* pCreateInfo);
MVKAttachmentDescription(MVKRenderPass* renderPass,
const VkRenderingAttachmentInfo* pAttInfo,
bool isResolveAttachment);
protected:
friend class MVKRenderPass;
friend class MVKRenderSubpass;
bool isFirstUseOfAttachment(MVKRenderSubpass* subpass);
bool isLastUseOfAttachment(MVKRenderSubpass* subpass);
MTLStoreAction getMTLStoreAction(MVKRenderSubpass* subpass,
@ -234,7 +250,7 @@ protected:
bool canResolveFormat,
bool isStencil,
bool storeOverride);
void validateFormat();
void linkToSubpasses();
VkAttachmentDescription2 _info;
MVKRenderPass* _renderPass;
@ -282,13 +298,15 @@ public:
MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo2* pCreateInfo);
MVKRenderPass(MVKDevice* device, const VkRenderingInfo* pRenderingInfo);
protected:
friend class MVKRenderSubpass;
friend class MVKRenderPassAttachment;
friend class MVKAttachmentDescription;
void propagateDebugName() override {}
MVKSmallVector<MVKRenderPassAttachment> _attachments;
MVKSmallVector<MVKAttachmentDescription> _attachments;
MVKSmallVector<MVKRenderSubpass> _subpasses;
MVKSmallVector<VkSubpassDependency2> _subpassDependencies;
VkRenderingFlags _renderingFlags = 0;
@ -297,21 +315,44 @@ protected:
#pragma mark -
#pragma mark Support functions
#pragma mark MVKRenderingAttachmentIterator
/** Returns a MVKRenderPass object created from the rendering info. */
MVKRenderPass* mvkCreateRenderPass(MVKDevice* device, const VkRenderingInfo* pRenderingInfo);
typedef std::function<void(const VkRenderingAttachmentInfo* pAttInfo,
VkImageAspectFlagBits aspect,
bool isResolveAttachment)> MVKRenderingAttachmentInfoOperation;
/**
* Extracts the usable attachments and their clear values from the rendering info,
* and sets them in the corresponding arrays, which must be large enough to hold
* all of the extracted values, and returns the number of attachments extracted.
* For consistency, the clear value of any resolve attachments are populated,
* even though they are ignored.
* Iterates the attachments in a VkRenderingInfo, and processes an operation
* on each attachment, once for the imageView, and once for the resolveImageView.
*
* Attachments are sequentially processed in this order:
* [color, color-resolve], ...,
* depth, depth-resolve,
* stencil, stencil-resolve
* skipping any attachments that do not have a VkImageView
*/
uint32_t mvkGetAttachments(const VkRenderingInfo* pRenderingInfo,
MVKImageView* attachments[],
VkClearValue clearValues[]);
class MVKRenderingAttachmentIterator : public MVKBaseObject {
public:
MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; }
/** Iterates the attachments with the specified lambda function. */
void iterate(MVKRenderingAttachmentInfoOperation attOperation);
MVKRenderingAttachmentIterator(const VkRenderingInfo* pRenderingInfo) : _pRenderingInfo(pRenderingInfo) {}
protected:
void handleAttachment(const VkRenderingAttachmentInfo* pAttInfo,
VkImageAspectFlagBits aspect,
MVKRenderingAttachmentInfoOperation attOperation);
const VkRenderingInfo* _pRenderingInfo;
};
#pragma mark -
#pragma mark Support functions
/** Returns whether the view mask uses multiview. */
static constexpr bool mvkIsMultiview(uint32_t viewMask) { return viewMask != 0; }
@ -322,9 +363,6 @@ bool mvkIsColorAttachmentUsed(const VkPipelineRenderingCreateInfo* pRendInfo, ui
/** Returns whether any attachment is being used. */
bool mvkHasColorAttachments(const VkPipelineRenderingCreateInfo* pRendInfo);
/** Extracts and returns the combined depth/stencil format . */
VkFormat mvkGetDepthStencilFormat(const VkPipelineRenderingCreateInfo* pRendInfo);
/**
* Extracts the first view, number of views, and the portion of the mask
* to be rendered from the lowest clump of set bits in a view mask.

File diff suppressed because it is too large Load Diff

View File

@ -70,7 +70,7 @@ MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST,
MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_map_memory2, KHR_MAP_MEMORY_2, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_map_memory2, KHR_MAP_MEMORY_2, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_multiview, KHR_MULTIVIEW, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_portability_subset, KHR_PORTABILITY_SUBSET, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE, 10.11, 8.0)