Skip to content

Commit 98b0c2c

Browse files
committed
Implement VK_KHR_present_id and VK_KHR_present_wait
1 parent 20698a7 commit 98b0c2c

File tree

10 files changed

+73
-5
lines changed

10 files changed

+73
-5
lines changed

Docs/MoltenVK_Runtime_UserGuide.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
268268
- `VK_KHR_map_memory2`
269269
- `VK_KHR_multiview`
270270
- `VK_KHR_portability_subset`
271+
- `VK_KHR_present_id`
272+
- `VK_KHR_present_wait`
271273
- `VK_KHR_push_descriptor`
272274
- `VK_KHR_relaxed_block_layout`
273275
- `VK_KHR_sampler_mirror_clamp_to_edge`

MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,16 @@
531531
portabilityFeatures->vertexAttributeAccessBeyondStride = true; // Costs additional buffers. Should make configuration switch.
532532
break;
533533
}
534+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR: {
535+
auto* presentIdFeatures = (VkPhysicalDevicePresentIdFeaturesKHR*)next;
536+
presentIdFeatures->presentId = true;
537+
break;
538+
}
539+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR: {
540+
auto* presentWaitFeatures = (VkPhysicalDevicePresentWaitFeaturesKHR*)next;
541+
presentWaitFeatures->presentWait = true;
542+
break;
543+
}
534544
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES: {
535545
auto* shaderExpectAssume = (VkPhysicalDeviceShaderExpectAssumeFeatures*)next;
536546
shaderExpectAssume->shaderExpectAssume = true;

MoltenVK/MoltenVK/GPUObjects/MVKDeviceFeatureStructs.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ MVK_DEVICE_FEATURE_EXTN(FragmentShaderBarycentric, FRAGMENT_SHADER_BARYCE
7373
MVK_DEVICE_FEATURE_EXTN(Maintenance6, MAINTENANCE_6, KHR, 1)
7474
MVK_DEVICE_FEATURE_EXTN(Maintenance7, MAINTENANCE_7, KHR, 1)
7575
MVK_DEVICE_FEATURE_EXTN(PortabilitySubset, PORTABILITY_SUBSET, KHR, 15)
76+
MVK_DEVICE_FEATURE_EXTN(PresentId, PRESENT_ID, KHR, 1)
77+
MVK_DEVICE_FEATURE_EXTN(PresentWait, PRESENT_WAIT, KHR, 1)
7678
MVK_DEVICE_FEATURE_EXTN(ShaderExpectAssume, SHADER_EXPECT_ASSUME, KHR, 1)
7779
MVK_DEVICE_FEATURE_EXTN(ShaderRelaxedExtendedInstruction, SHADER_RELAXED_EXTENDED_INSTRUCTION, KHR, 1)
7880
MVK_DEVICE_FEATURE_EXTN(ShaderSubgroupRotate, SHADER_SUBGROUP_ROTATE, KHR, 2)

MoltenVK/MoltenVK/GPUObjects/MVKImage.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,8 +452,9 @@ typedef struct {
452452
MVKPresentableSwapchainImage* presentableImage;
453453
MVKQueue* queue; // The queue on which the vkQueuePresentKHR() command was executed.
454454
MVKFence* fence; // VK_EXT_swapchain_maintenance1 fence signaled when resources can be destroyed
455-
uint64_t desiredPresentTime; // VK_GOOGLE_display_timing desired presentation time in nanoseconds
456-
uint32_t presentID; // VK_GOOGLE_display_timing presentID
455+
uint64_t presentId; // VK_KHR_present_id presentId
456+
uint64_t desiredPresentTime; // VK_GOOGLE_display_timing desired presentation time in nanoseconds
457+
uint32_t presentIDGoogle; // VK_GOOGLE_display_timing presentID
457458
VkPresentModeKHR presentMode; // VK_EXT_swapchain_maintenance1 present mode specialization
458459
} MVKImagePresentInfo;
459460

MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,9 @@
450450
#define ADD_INST_EXT2_ENTRY_POINT(func, API, EXT1, EXT2) ADD_ENTRY_POINT(func, VK_API_VERSION_##API, VK_##EXT1##_EXTENSION_NAME, VK_##EXT2##_EXTENSION_NAME, nullptr, false)
451451
#define ADD_DVC_EXT2_ENTRY_POINT(func, API, EXT1, EXT2) ADD_ENTRY_POINT(func, VK_API_VERSION_##API, VK_##EXT1##_EXTENSION_NAME, VK_##EXT2##_EXTENSION_NAME, nullptr, true)
452452

453+
#define ADD_INST_EXT3_ENTRY_POINT(func, EXT1, EXT2, EXT3) ADD_ENTRY_POINT(func, 0, VK_##EXT1##_EXTENSION_NAME, VK_##EXT2##_EXTENSION_NAME, VK_##EXT3##_EXTENSION_NAME, false)
454+
#define ADD_DVC_EXT3_ENTRY_POINT(func, EXT1, EXT2, EXT3) ADD_ENTRY_POINT(func, 0, VK_##EXT1##_EXTENSION_NAME, VK_##EXT2##_EXTENSION_NAME, VK_##EXT3##_EXTENSION_NAME, true)
455+
453456
#define ADD_INST_EXT_ENTRY_POINT_ALIAS(alias, func, EXT) ADD_ENTRY_POINT_MAP(alias, func, 0, VK_##EXT##_EXTENSION_NAME, nullptr, nullptr, false)
454457
#define ADD_DVC_EXT_ENTRY_POINT_ALIAS(alias, func, EXT) ADD_ENTRY_POINT_MAP(alias, func, 0, VK_##EXT##_EXTENSION_NAME, nullptr, nullptr, true)
455458

@@ -757,6 +760,7 @@
757760
ADD_DVC_EXT_ENTRY_POINT(vkGetSwapchainImagesKHR, KHR_SWAPCHAIN);
758761
ADD_DVC_EXT_ENTRY_POINT(vkAcquireNextImageKHR, KHR_SWAPCHAIN);
759762
ADD_DVC_EXT_ENTRY_POINT(vkQueuePresentKHR, KHR_SWAPCHAIN);
763+
ADD_DVC_EXT3_ENTRY_POINT(vkWaitForPresentKHR, KHR_SWAPCHAIN, KHR_PRESENT_ID, KHR_PRESENT_WAIT);
760764
ADD_DVC_EXT2_ENTRY_POINT(vkGetDeviceGroupPresentCapabilitiesKHR, 1_1, KHR_SWAPCHAIN, KHR_DEVICE_GROUP);
761765
ADD_DVC_EXT2_ENTRY_POINT(vkGetDeviceGroupSurfacePresentModesKHR, 1_1, KHR_SWAPCHAIN, KHR_DEVICE_GROUP);
762766
ADD_DVC_EXT2_ENTRY_POINT(vkGetPhysicalDevicePresentRectanglesKHR, 1_1, KHR_SWAPCHAIN, KHR_DEVICE_GROUP);

MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,11 +788,15 @@
788788
const VkSwapchainPresentFenceInfoEXT* pPresentFenceInfo = nullptr;
789789
const VkSwapchainPresentModeInfoEXT* pPresentModeInfo = nullptr;
790790
const VkPresentRegionsKHR* pPresentRegions = nullptr;
791+
const VkPresentIdKHR* pPresentId = nullptr;
791792
for (auto* next = (const VkBaseInStructure*)pPresentInfo->pNext; next; next = next->pNext) {
792793
switch (next->sType) {
793794
case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
794795
pPresentRegions = (const VkPresentRegionsKHR*) next;
795796
break;
797+
case VK_STRUCTURE_TYPE_PRESENT_ID_KHR:
798+
pPresentId = (const VkPresentIdKHR*) next;
799+
break;
796800
case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT:
797801
pPresentFenceInfo = (const VkSwapchainPresentFenceInfoEXT*) next;
798802
break;
@@ -828,6 +832,10 @@
828832
if (pPresentRegions) {
829833
pRegions = pPresentRegions->pRegions;
830834
}
835+
const uint64_t* pPresentIds = nullptr;
836+
if (pPresentId) {
837+
pPresentIds = pPresentId->pPresentIds;
838+
}
831839

832840
VkResult* pSCRslts = pPresentInfo->pResults;
833841
_presentInfo.reserve(scCnt);
@@ -838,8 +846,9 @@
838846
presentInfo.presentableImage = mvkSC->getPresentableImage(pPresentInfo->pImageIndices[scIdx]);
839847
presentInfo.presentMode = pPresentModes ? pPresentModes[scIdx] : VK_PRESENT_MODE_MAX_ENUM_KHR;
840848
presentInfo.fence = pFences ? (MVKFence*)pFences[scIdx] : nullptr;
849+
presentInfo.presentId = pPresentIds ? pPresentIds[scIdx] : 0;
841850
if (pPresentTimes) {
842-
presentInfo.presentID = pPresentTimes[scIdx].presentID;
851+
presentInfo.presentIDGoogle = pPresentTimes[scIdx].presentID;
843852
presentInfo.desiredPresentTime = pPresentTimes[scIdx].desiredPresentTime;
844853
}
845854
mvkSC->setLayerNeedsDisplay(pRegions ? &pRegions[scIdx] : nullptr);

MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class MVKSwapchain : public MVKVulkanAPIDeviceObject {
9494
/** VK_GOOGLE_display_timing - returns past presentation times */
9595
VkResult getPastPresentationTiming(uint32_t *pCount, VkPastPresentationTimingGOOGLE *pPresentationTimings);
9696

97+
/** Waits for the swapchain present ID to meet or exceed the provided ID. */
98+
VkResult waitForPresent(uint64_t presentId, uint64_t timeout);
99+
97100
/** Marks parts of the underlying CAMetalLayer as needing update. */
98101
void setLayerNeedsDisplay(const VkPresentRegionKHR* pRegion);
99102

@@ -138,4 +141,7 @@ class MVKSwapchain : public MVKVulkanAPIDeviceObject {
138141
uint32_t _presentHistoryIndex = 0;
139142
uint32_t _presentHistoryHeadIndex = 0;
140143
bool _isDeliberatelyScaled = false;
144+
uint64_t _currentPresentId = 0;
145+
std::mutex _currentPresentIdMutex;
146+
std::condition_variable _currentPresentIdCondVar;
141147
};

MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,15 @@
245245
return res;
246246
}
247247

248+
VkResult MVKSwapchain::waitForPresent(uint64_t presentId, uint64_t timeout) {
249+
std::unique_lock lock(_currentPresentIdMutex);
250+
const auto success = _currentPresentIdCondVar.wait_for(lock, std::chrono::nanoseconds(timeout), [this, presentId] {
251+
return _currentPresentId >= presentId || getConfigurationResult() == VK_ERROR_OUT_OF_DATE_KHR;
252+
});
253+
if (getConfigurationResult() == VK_ERROR_OUT_OF_DATE_KHR) return VK_ERROR_OUT_OF_DATE_KHR;
254+
return success ? VK_SUCCESS : VK_TIMEOUT;
255+
}
256+
248257
void MVKSwapchain::beginPresentation(const MVKImagePresentInfo& presentInfo) {
249258
_unpresentedImageCount++;
250259
}
@@ -261,13 +270,19 @@
261270
_presentHistoryHeadIndex = (_presentHistoryHeadIndex + 1) % kMaxPresentationHistory;
262271
}
263272

264-
_presentTimingHistory[_presentHistoryIndex].presentID = presentInfo.presentID;
273+
_presentTimingHistory[_presentHistoryIndex].presentID = presentInfo.presentIDGoogle;
265274
_presentTimingHistory[_presentHistoryIndex].desiredPresentTime = presentInfo.desiredPresentTime;
266275
_presentTimingHistory[_presentHistoryIndex].actualPresentTime = actualPresentTime;
267276
// These details are not available in Metal, but can estimate earliestPresentTime by using actualPresentTime instead
268277
_presentTimingHistory[_presentHistoryIndex].earliestPresentTime = actualPresentTime;
269278
_presentTimingHistory[_presentHistoryIndex].presentMargin = actualPresentTime > beginPresentTime ? actualPresentTime - beginPresentTime : 0;
270279
_presentHistoryIndex = (_presentHistoryIndex + 1) % kMaxPresentationHistory;
280+
281+
if (presentInfo.presentId != 0) {
282+
std::unique_lock lock(_currentPresentIdMutex);
283+
_currentPresentId = std::max(_currentPresentId, presentInfo.presentId);
284+
_currentPresentIdCondVar.notify_all();
285+
}
271286
}
272287

273288
// Because of a regression in Metal, the most recent one or two presentations may not complete

MoltenVK/MoltenVK/Layers/MVKExtensions.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ MVK_EXTENSION(KHR_format_feature_flags2, KHR_FORMAT_FEATURE_FLAGS_
6868
MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, DEVICE, 10.11, 8.0, 1.0)
6969
MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, INSTANCE, 10.11, 8.0, 1.0)
7070
MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, INSTANCE, 10.11, 8.0, 1.0)
71-
MVK_EXTENSION(KHR_imageless_framebuffer, KHR_IMAGELESS_FRAMEBUFFER, DEVICE, 10.11, 8.0, 1.0)
7271
MVK_EXTENSION(KHR_global_priority, KHR_GLOBAL_PRIORITY, DEVICE, 10.11, 8.0, 1.0)
7372
MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, DEVICE, 10.11, 8.0, 1.0)
73+
MVK_EXTENSION(KHR_imageless_framebuffer, KHR_IMAGELESS_FRAMEBUFFER, DEVICE, 10.11, 8.0, 1.0)
7474
MVK_EXTENSION(KHR_incremental_present, KHR_INCREMENTAL_PRESENT, DEVICE, 10.11, 8.0, 1.0)
7575
MVK_EXTENSION(KHR_index_type_uint8, KHR_INDEX_TYPE_UINT8, DEVICE, 10.11, 8.0, 1.0)
7676
MVK_EXTENSION(KHR_load_store_op_none, KHR_LOAD_STORE_OP_NONE, DEVICE, 10.11, 8.0, 1.0)
@@ -82,6 +82,8 @@ MVK_EXTENSION(KHR_maintenance6, KHR_MAINTENANCE_6,
8282
MVK_EXTENSION(KHR_maintenance7, KHR_MAINTENANCE_7, DEVICE, 10.11, 8.0, 1.0)
8383
MVK_EXTENSION(KHR_map_memory2, KHR_MAP_MEMORY_2, DEVICE, 10.11, 8.0, 1.0)
8484
MVK_EXTENSION(KHR_multiview, KHR_MULTIVIEW, DEVICE, 10.11, 8.0, 1.0)
85+
MVK_EXTENSION(KHR_present_id, KHR_PRESENT_ID, DEVICE, 10.11, 8.0, 1.0)
86+
MVK_EXTENSION(KHR_present_wait, KHR_PRESENT_WAIT, DEVICE, 10.11, 8.0, 1.0)
8587
MVK_EXTENSION(KHR_portability_subset, KHR_PORTABILITY_SUBSET, DEVICE, 10.11, 8.0, 1.0)
8688
MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE, 10.11, 8.0, 1.0)
8789
MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, DEVICE, 10.11, 8.0, 1.0)

MoltenVK/MoltenVK/Vulkan/vulkan.mm

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3357,6 +3357,23 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetMemoryMetalHandlePropertiesEXT(
33573357
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkUnmapMemory2, KHR);
33583358

33593359

3360+
#pragma mark -
3361+
#pragma mark VK_KHR_present_wait extension
3362+
3363+
MVK_PUBLIC_VULKAN_SYMBOL VkResult vkWaitForPresentKHR(
3364+
VkDevice device,
3365+
VkSwapchainKHR swapchain,
3366+
uint64_t presentId,
3367+
uint64_t timeout) {
3368+
3369+
MVKTraceVulkanCallStart();
3370+
MVKSwapchain* mvkSC = (MVKSwapchain*)swapchain;
3371+
VkResult rslt = mvkSC->waitForPresent(presentId, timeout);
3372+
MVKTraceVulkanCallEnd();
3373+
return rslt;
3374+
}
3375+
3376+
33603377
#pragma mark -
33613378
#pragma mark VK_KHR_push_descriptor extension
33623379

0 commit comments

Comments
 (0)