MVKRenderPass: Use combined store-resolve ops when requested and supported.

There is nothing in the Vulkan spec to suggest that
`VK_ATTACHMENT_STORE_OP_STORE` and a resolve attachment cannot both be
specified, nor that one or the other has no effect. So, if the app
supplies a color attachment with both `VK_ATTACHMENT_STORE_OP_STORE` and
a resolve attachment, that means it wants the output to be both stored
to the color attachment and resolved to the resolve attachment. In that
case, we should respect the application's wishes and do both. We can
only do that if the device supports this, though. All devices on Mac
starting with macOS 10.12 support this. On iOS, only the A9 and above
support combined store-resolve actions.
This commit is contained in:
Chip Davis 2019-01-18 14:39:19 -06:00
parent 519b594ae0
commit 8fdbf8f6de
5 changed files with 12 additions and 8 deletions

View File

@ -354,7 +354,7 @@ MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFill
MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp);
/** Returns the Metal MTLStoreAction corresponding to the specified Vulkan VkAttachmentStoreOp. */
MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp);
MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment = false);
/** Returns the Metal MTLViewport corresponding to the specified Vulkan VkViewport. */
MTLViewport mvkMTLViewportFromVkViewport(VkViewport vkViewport);

View File

@ -53,7 +53,7 @@ extern "C" {
#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch))
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)
#define VK_MVK_MOLTENVK_SPEC_VERSION 16
#define VK_MVK_MOLTENVK_SPEC_VERSION 17
#define VK_MVK_MOLTENVK_EXTENSION_NAME "VK_MVK_moltenvk"
/**
@ -454,6 +454,8 @@ typedef struct {
VkSampleCountFlags supportedSampleCounts; /**< A bitmask identifying the sample counts supported by the device. */
uint32_t minSwapchainImageCount; /**< The minimum number of swapchain images that can be supported by a surface. */
uint32_t maxSwapchainImageCount; /**< The maximum number of swapchain images that can be supported by a surface. */
// v17
VkBool32 combinedStoreResolveAction; /**< If true, the device supports VK_ATTACHMENT_STORE_OP_STORE with a simultaneous resolve attachment. */
} MVKPhysicalDeviceMetalFeatures;
/**

View File

@ -615,6 +615,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1] ) {
_metalFeatures.indirectDrawing = true;
_metalFeatures.baseVertexInstanceDrawing = true;
_metalFeatures.combinedStoreResolveAction = true;
_metalFeatures.mtlBufferAlignment = 16; // Min float4 alignment for typical vertex buffers. MTLBuffer may go down to 4 bytes for other data.
_metalFeatures.maxTextureDimension = (16 * KIBI);
}
@ -636,6 +637,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
_metalFeatures.shaderSpecialization = true;
_metalFeatures.stencilViews = true;
_metalFeatures.samplerClampToBorder = true;
_metalFeatures.combinedStoreResolveAction = true;
_metalFeatures.maxMTLBufferSize = (1 * GIBI);
}

View File

@ -269,13 +269,13 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende
// If a resolve attachment exists, this attachment must resolve once complete.
// Otherwise only allow the attachment to be discarded if we're actually rendering
// to the entire attachment and we're in the last subpass.
if (hasResolveAttachment) {
if (hasResolveAttachment && !_renderPass->getDevice()->getPhysicalDevice()->getMetalFeatures()->combinedStoreResolveAction) {
mtlAttDesc.storeAction = MTLStoreActionMultisampleResolve;
} else if ( isRenderingEntireAttachment && (subpass->_subpassIndex == _lastUseSubpassIdx) ) {
VkAttachmentStoreOp storeOp = isStencil ? _info.stencilStoreOp : _info.storeOp;
mtlAttDesc.storeAction = mvkMTLStoreActionFromVkAttachmentStoreOp(storeOp);
mtlAttDesc.storeAction = mvkMTLStoreActionFromVkAttachmentStoreOp(storeOp, hasResolveAttachment);
} else {
mtlAttDesc.storeAction = MTLStoreActionStore;
mtlAttDesc.storeAction = hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore;
}
return willClear;
}

View File

@ -1138,10 +1138,10 @@ MVK_PUBLIC_SYMBOL MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachm
}
}
MVK_PUBLIC_SYMBOL MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp) {
MVK_PUBLIC_SYMBOL MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment) {
switch (vkStoreOp) {
case VK_ATTACHMENT_STORE_OP_STORE: return MTLStoreActionStore;
case VK_ATTACHMENT_STORE_OP_DONT_CARE: return MTLStoreActionDontCare;
case VK_ATTACHMENT_STORE_OP_STORE: return hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore;
case VK_ATTACHMENT_STORE_OP_DONT_CARE: return hasResolveAttachment ? MTLStoreActionMultisampleResolve : MTLStoreActionDontCare;
default:
mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkAttachmentStoreOp value %d is not supported.", vkStoreOp);