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:
parent
519b594ae0
commit
8fdbf8f6de
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user