Only update CAMetalLayer drawableSize property during swapchain creation.

Simplify structure of MVKQueue::submit() functions.
This commit is contained in:
Bill Hollings 2018-08-01 15:29:15 -04:00
parent d2aea464de
commit e39d7e6394
7 changed files with 40 additions and 30 deletions

View File

@ -174,7 +174,7 @@ VkResult MVKPhysicalDevice::getSurfaceCapabilities(MVKSurface* surface,
CAMetalLayer* mtlLayer = surface->getCAMetalLayer();
if ( !mtlLayer ) { return surface->getConfigurationResult(); }
VkExtent2D surfExtnt = mvkVkExtent2DFromCGSize(mtlLayer.updatedDrawableSizeMVK);
VkExtent2D surfExtnt = mvkVkExtent2DFromCGSize(mtlLayer.naturalDrawableSizeMVK);
// Metal supports 3 concurrent drawables, but if the swapchain is destroyed and
// rebuilt as part of resizing, one will be held by the current display image.

View File

@ -81,7 +81,7 @@ public:
VkFence fence, MVKCommandUse cmdBuffUse);
/** Submits the specified presentation command to the queue. */
VkResult submitPresentKHR(const VkPresentInfoKHR* pPresentInfo);
VkResult submit(const VkPresentInfoKHR* pPresentInfo);
/** Block the current thread until this queue is idle. */
VkResult waitIdle(MVKCommandUse cmdBuffUse);
@ -145,7 +145,7 @@ protected:
void initExecQueue();
void initMTLCommandQueue();
void destroyExecQueue();
void submit(MVKQueueSubmission* qSubmit);
VkResult submit(MVKQueueSubmission* qSubmit);
MVKQueueFamily* _queueFamily;
uint32_t _index;

View File

@ -64,41 +64,37 @@ MVKQueueFamily::~MVKQueueFamily() {
// Submissions to the execution queue are wrapped in a dedicated autorelease pool.
// Relying on the dispatch queue to find time to drain the autorelease pool can
// result in significant memory creep under heavy workloads.
void MVKQueue::submit(MVKQueueSubmission* qSubmit) {
if ( !qSubmit ) { return; } // Ignore nils
VkResult MVKQueue::submit(MVKQueueSubmission* qSubmit) {
if ( !qSubmit ) { return VK_SUCCESS; } // Ignore nils
VkResult rslt = qSubmit->_submissionResult; // Extract result before submission to avoid race condition with early destruction
if (_execQueue) {
dispatch_async(_execQueue, ^{ @autoreleasepool { qSubmit->execute(); } } );
} else {
qSubmit->execute();
}
return rslt;
}
VkResult MVKQueue::submit(uint32_t submitCount, const VkSubmitInfo* pSubmits,
VkFence fence, MVKCommandUse cmdBuffUse) {
// Fence-only submission
if (submitCount == 0 && fence) {
return submit(new MVKQueueCommandBufferSubmission(_device, this, VK_NULL_HANDLE, fence, cmdBuffUse));
}
VkResult rslt = VK_SUCCESS;
for (uint32_t sIdx = 0; sIdx < submitCount; sIdx++) {
VkFence fenceOrNil = (sIdx == (submitCount - 1)) ? fence : VK_NULL_HANDLE; // last one gets the fence
MVKQueueSubmission* qSub = new MVKQueueCommandBufferSubmission(_device, this, &pSubmits[sIdx], fenceOrNil, cmdBuffUse);
if (rslt == VK_SUCCESS) { rslt = qSub->_submissionResult; } // Extract result before submission to avoid race condition with early destruction
submit(qSub);
VkResult subRslt = submit(new MVKQueueCommandBufferSubmission(_device, this, &pSubmits[sIdx], fenceOrNil, cmdBuffUse));
if (rslt == VK_SUCCESS) { rslt = subRslt; }
}
// Support fence-only submission
if (submitCount == 0 && fence) {
MVKQueueSubmission* qSub = new MVKQueueCommandBufferSubmission(_device, this, VK_NULL_HANDLE, fence, cmdBuffUse);
if (rslt == VK_SUCCESS) { rslt = qSub->_submissionResult; } // Extract result before submission to avoid race condition with early destruction
submit(qSub);
}
return rslt;
}
VkResult MVKQueue::submitPresentKHR(const VkPresentInfoKHR* pPresentInfo) {
MVKQueueSubmission* qSub = new MVKQueuePresentSurfaceSubmission(_device, this, pPresentInfo);
VkResult rslt = qSub->_submissionResult; // Extract result before submission to avoid race condition with early destruction
submit(qSub);
return rslt;
VkResult MVKQueue::submit(const VkPresentInfoKHR* pPresentInfo) {
return submit(new MVKQueuePresentSurfaceSubmission(_device, this, pPresentInfo));
}
// Create an empty submit struct and fence, submit to queue and wait on fence.

View File

@ -83,7 +83,7 @@ VkResult MVKSwapchain::acquireNextImageKHR(uint64_t timeout,
}
bool MVKSwapchain::getHasSurfaceSizeChanged() {
return !CGSizeEqualToSize(_mtlLayer.updatedDrawableSizeMVK, _mtlLayerOrigDrawSize);
return !CGSizeEqualToSize(_mtlLayer.naturalDrawableSizeMVK, _mtlLayerOrigDrawSize);
}
uint64_t MVKSwapchain::getNextAcquisitionID() { return ++_currentAcquisitionID; }

View File

@ -24,8 +24,19 @@
@interface CAMetalLayer (MoltenVK)
/**
* Ensures the drawableSize property of this layer is up to date, by combining the size
* of the bounds property and the contentScale property, and returns the updated value.
* Returns the natural drawable size for this layer.
*
* The natural drawable size is the size of the bounds property of this layer, multiplied
* by the contentsScale property of this layer, and is the value that the drawableSize
* property will be set to when the updatedDrawableSizeMVK nethod is invoked.
*/
@property(nonatomic, readonly) CGSize naturalDrawableSizeMVK;
/**
* Ensures the drawableSize property of this layer is up to date, by ensuring
* it is set to the value returned by the naturalDrawableSizeMVK property.
*
* Returns the updated drawableSize value.
*/
-(CGSize) updatedDrawableSizeMVK;

View File

@ -22,18 +22,21 @@
@implementation CAMetalLayer (MoltenVK)
-(CGSize) updatedDrawableSizeMVK {
-(CGSize) naturalDrawableSizeMVK {
CGSize drawSize = self.bounds.size;
CGFloat scaleFactor = self.contentsScale;
drawSize.width = trunc(drawSize.width * scaleFactor);
drawSize.height = trunc(drawSize.height * scaleFactor);
return drawSize;
}
// Only update property value if it needs to be, in case
// updating to same value causes internal reconfigurations.
// Only update drawableSize property value if it needs to be,
// in case updating to same value causes internal reconfigurations.
-(CGSize) updatedDrawableSizeMVK {
CGSize drawSize = self.naturalDrawableSizeMVK;
if ( !CGSizeEqualToSize(drawSize, self.drawableSize) ) {
self.drawableSize = drawSize;
}
return drawSize;
}

View File

@ -1524,7 +1524,7 @@ MVK_PUBLIC_SYMBOL VkResult vkQueuePresentKHR(
const VkPresentInfoKHR* pPresentInfo) {
MVKQueue* mvkQ = MVKQueue::getMVKQueue(queue);
return mvkQ->submitPresentKHR(pPresentInfo);
return mvkQ->submit(pPresentInfo);
}