diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 5bea0fe2..94ff4d86 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -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. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h index a4eccabe..a2a28fcb 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h @@ -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; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm index 93c39097..82612d1a 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm @@ -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. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm index aeed37cc..7368e346 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm @@ -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; } diff --git a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.h b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.h index ad18bbf2..bb6a599a 100644 --- a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.h +++ b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.h @@ -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; diff --git a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m index 726128f7..3bbb8604 100644 --- a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m +++ b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m @@ -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); - - // Only update property value if it needs to be, in case - // updating to same value causes internal reconfigurations. + return drawSize; +} + +// 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; } diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index d0ffe9ca..28fa8a96 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -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); }