Skip to content

Commit

Permalink
Merge pull request #1972 from cdavis5e/incremental-present
Browse files Browse the repository at this point in the history
Support the `VK_KHR_incremental_present` extension.
  • Loading branch information
billhollings authored Jul 11, 2023
2 parents 1728f7f + 3914b0f commit dff64e9
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 4 deletions.
6 changes: 6 additions & 0 deletions MoltenVK/MoltenVK/API/mvk_datatypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,12 @@ VkExtent2D mvkVkExtent2DFromCGSize(CGSize cgSize);
/** Returns a CGSize that corresponds to the specified VkExtent2D. */
CGSize mvkCGSizeFromVkExtent2D(VkExtent2D vkExtent);

/** Returns a CGPoint that corresponds to the specified VkOffset2D. */
CGPoint mvkCGPointFromVkOffset2D(VkOffset2D vkOffset);

/** Returns a CGRect that corresponds to the specified VkRectLayerKHR. The layer is ignored. */
CGRect mvkCGRectFromVkRectLayerKHR(VkRectLayerKHR vkRect);

/** Returns a Metal MTLOrigin constructed from a VkOffset3D. */
static inline MTLOrigin mvkMTLOriginFromVkOffset3D(VkOffset3D vkOffset) {
return MTLOriginMake(vkOffset.x, vkOffset.y, vkOffset.z);
Expand Down
9 changes: 9 additions & 0 deletions MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
Original file line number Diff line number Diff line change
Expand Up @@ -583,8 +583,12 @@
const VkPresentTimesInfoGOOGLE* pPresentTimesInfo = nullptr;
const VkSwapchainPresentFenceInfoEXT* pPresentFenceInfo = nullptr;
const VkSwapchainPresentModeInfoEXT* pPresentModeInfo = nullptr;
const VkPresentRegionsKHR* pPresentRegions = nullptr;
for (auto* next = (const VkBaseInStructure*)pPresentInfo->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
pPresentRegions = (const VkPresentRegionsKHR*) next;
break;
case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT:
pPresentFenceInfo = (const VkSwapchainPresentFenceInfoEXT*) next;
break;
Expand Down Expand Up @@ -616,6 +620,10 @@
pFences = pPresentFenceInfo->pFences;
MVKAssert(pPresentFenceInfo->swapchainCount == scCnt, "VkSwapchainPresentFenceInfoEXT swapchainCount must match VkPresentInfo swapchainCount.");
}
const VkPresentRegionKHR* pRegions = nullptr;
if (pPresentRegions) {
pRegions = pPresentRegions->pRegions;
}

VkResult* pSCRslts = pPresentInfo->pResults;
_presentInfo.reserve(scCnt);
Expand All @@ -630,6 +638,7 @@
presentInfo.presentID = pPresentTimes[scIdx].presentID;
presentInfo.desiredPresentTime = pPresentTimes[scIdx].desiredPresentTime;
}
mvkSC->setLayerNeedsDisplay(pRegions ? &pRegions[scIdx] : nullptr);
_presentInfo.push_back(presentInfo);
VkResult scRslt = mvkSC->getSurfaceStatus();
if (pSCRslts) { pSCRslts[scIdx] = scRslt; }
Expand Down
3 changes: 3 additions & 0 deletions MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ class MVKSwapchain : public MVKVulkanAPIDeviceObject {
/** VK_GOOGLE_display_timing - returns past presentation times */
VkResult getPastPresentationTiming(uint32_t *pCount, VkPastPresentationTimingGOOGLE *pPresentationTimings);

/** Marks parts of the underlying CAMetalLayer as needing update. */
void setLayerNeedsDisplay(const VkPresentRegionKHR* pRegion);

void destroy() override;

#pragma mark Construction
Expand Down
24 changes: 24 additions & 0 deletions MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,30 @@ static CALayerContentsGravity getCALayerContentsGravity(VkSwapchainPresentScalin
_presentHistoryIndex = (_presentHistoryIndex + 1) % kMaxPresentationHistory;
}

void MVKSwapchain::setLayerNeedsDisplay(const VkPresentRegionKHR* pRegion) {
if (!pRegion || pRegion->rectangleCount == 0) {
[_mtlLayer setNeedsDisplay];
return;
}

for (uint32_t i = 0; i < pRegion->rectangleCount; ++i) {
CGRect cgRect = mvkCGRectFromVkRectLayerKHR(pRegion->pRectangles[i]);
#if MVK_MACOS
// VK_KHR_incremental_present specifies an upper-left origin, but macOS by default
// uses a lower-left origin.
cgRect.origin.y = _mtlLayer.bounds.size.height - cgRect.origin.y;
#endif
// We were given rectangles in pixels, but -[CALayer setNeedsDisplayInRect:] wants them
// in points, which is pixels / contentsScale.
CGFloat scaleFactor = _mtlLayer.contentsScale;
cgRect.origin.x /= scaleFactor;
cgRect.origin.y /= scaleFactor;
cgRect.size.width /= scaleFactor;
cgRect.size.height /= scaleFactor;
[_mtlLayer setNeedsDisplayInRect:cgRect];
}
}

// A retention loop exists between the swapchain and its images. The swapchain images
// retain the swapchain because they can be in flight when the app destroys the swapchain.
// Release the images now, when the app destroys the swapchain, so they will be destroyed when
Expand Down
1 change: 1 addition & 0 deletions MoltenVK/MoltenVK/Layers/MVKExtensions.def
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PR
MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, INSTANCE, 10.11, 8.0)
MVK_EXTENSION(KHR_imageless_framebuffer, KHR_IMAGELESS_FRAMEBUFFER, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_incremental_present, KHR_INCREMENTAL_PRESENT, DEVICE, 10.11, 8.0)
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)
Expand Down
13 changes: 9 additions & 4 deletions MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm
Original file line number Diff line number Diff line change
Expand Up @@ -780,10 +780,15 @@ MVK_PUBLIC_SYMBOL VkExtent2D mvkVkExtent2DFromCGSize(CGSize cgSize) {
}

MVK_PUBLIC_SYMBOL CGSize mvkCGSizeFromVkExtent2D(VkExtent2D vkExtent) {
CGSize cgSize;
cgSize.width = vkExtent.width;
cgSize.height = vkExtent.height;
return cgSize;
return CGSizeMake(vkExtent.width, vkExtent.height);
}

MVK_PUBLIC_SYMBOL CGPoint mvkCGPointFromVkOffset2D(VkOffset2D vkOffset) {
return CGPointMake(vkOffset.x, vkOffset.y);
}

MVK_PUBLIC_SYMBOL CGRect mvkCGRectFromVkRectLayerKHR(VkRectLayerKHR vkRect) {
return { mvkCGPointFromVkOffset2D(vkRect.offset), mvkCGSizeFromVkExtent2D(vkRect.extent) };
}


Expand Down

0 comments on commit dff64e9

Please sign in to comment.