Skip to content

Commit d0698a6

Browse files
committed
Implement VK_KHR_present_id and VK_KHR_present_wait
1 parent d1f0757 commit d0698a6

File tree

10 files changed

+76
-8
lines changed

10 files changed

+76
-8
lines changed

Docs/MoltenVK_Runtime_UserGuide.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
269269
- `VK_KHR_map_memory2`
270270
- `VK_KHR_multiview`
271271
- `VK_KHR_portability_subset`
272+
- `VK_KHR_present_id`
273+
- `VK_KHR_present_wait`
272274
- `VK_KHR_push_descriptor`
273275
- `VK_KHR_relaxed_block_layout`
274276
- `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
@@ -535,6 +535,16 @@
535535
portabilityFeatures->vertexAttributeAccessBeyondStride = true; // Costs additional buffers. Should make configuration switch.
536536
break;
537537
}
538+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR: {
539+
auto* presentIdFeatures = (VkPhysicalDevicePresentIdFeaturesKHR*)next;
540+
presentIdFeatures->presentId = true;
541+
break;
542+
}
543+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR: {
544+
auto* presentWaitFeatures = (VkPhysicalDevicePresentWaitFeaturesKHR*)next;
545+
presentWaitFeatures->presentWait = true;
546+
break;
547+
}
538548
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES: {
539549
auto* shaderExpectAssume = (VkPhysicalDeviceShaderExpectAssumeFeatures*)next;
540550
shaderExpectAssume->shaderExpectAssume = true;

MoltenVK/MoltenVK/GPUObjects/MVKDeviceFeatureStructs.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ MVK_DEVICE_FEATURE_EXTN(Maintenance5, MAINTENANCE_5,
7474
MVK_DEVICE_FEATURE_EXTN(Maintenance6, MAINTENANCE_6, KHR, 1)
7575
MVK_DEVICE_FEATURE_EXTN(Maintenance7, MAINTENANCE_7, KHR, 1)
7676
MVK_DEVICE_FEATURE_EXTN(PortabilitySubset, PORTABILITY_SUBSET, KHR, 15)
77+
MVK_DEVICE_FEATURE_EXTN(PresentId, PRESENT_ID, KHR, 1)
78+
MVK_DEVICE_FEATURE_EXTN(PresentWait, PRESENT_WAIT, KHR, 1)
7779
MVK_DEVICE_FEATURE_EXTN(ShaderExpectAssume, SHADER_EXPECT_ASSUME, KHR, 1)
7880
MVK_DEVICE_FEATURE_EXTN(ShaderRelaxedExtendedInstruction, SHADER_RELAXED_EXTENDED_INSTRUCTION, KHR, 1)
7981
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

@@ -761,6 +764,7 @@
761764
ADD_DVC_EXT_ENTRY_POINT(vkGetSwapchainImagesKHR, KHR_SWAPCHAIN);
762765
ADD_DVC_EXT_ENTRY_POINT(vkAcquireNextImageKHR, KHR_SWAPCHAIN);
763766
ADD_DVC_EXT_ENTRY_POINT(vkQueuePresentKHR, KHR_SWAPCHAIN);
767+
ADD_DVC_EXT3_ENTRY_POINT(vkWaitForPresentKHR, KHR_SWAPCHAIN, KHR_PRESENT_ID, KHR_PRESENT_WAIT);
764768
ADD_DVC_EXT2_ENTRY_POINT(vkGetDeviceGroupPresentCapabilitiesKHR, 1_1, KHR_SWAPCHAIN, KHR_DEVICE_GROUP);
765769
ADD_DVC_EXT2_ENTRY_POINT(vkGetDeviceGroupSurfacePresentModesKHR, 1_1, KHR_SWAPCHAIN, KHR_DEVICE_GROUP);
766770
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: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ MVK_EXTENSION(KHR_external_memory, KHR_EXTERNAL_MEMORY,
6363
MVK_EXTENSION(KHR_external_memory_capabilities, KHR_EXTERNAL_MEMORY_CAPABILITIES, INSTANCE, 10.11, 8.0, 1.0)
6464
MVK_EXTENSION(KHR_external_semaphore, KHR_EXTERNAL_SEMAPHORE, DEVICE, 10.11, 8.0, 1.0)
6565
MVK_EXTENSION(KHR_external_semaphore_capabilities, KHR_EXTERNAL_SEMAPHORE_CAPABILITIES, INSTANCE, 10.11, 8.0, 1.0)
66-
MVK_EXTENSION(KHR_fragment_shader_barycentric, KHR_FRAGMENT_SHADER_BARYCENTRIC, DEVICE, 10.15, 14.0, 1.0)
6766
MVK_EXTENSION(KHR_format_feature_flags2, KHR_FORMAT_FEATURE_FLAGS_2, DEVICE, 10.11, 8.0, 1.0)
67+
MVK_EXTENSION(KHR_fragment_shader_barycentric, KHR_FRAGMENT_SHADER_BARYCENTRIC, DEVICE, 10.15, 14.0, 1.0)
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)
@@ -84,6 +84,8 @@ MVK_EXTENSION(KHR_maintenance7, KHR_MAINTENANCE_7,
8484
MVK_EXTENSION(KHR_map_memory2, KHR_MAP_MEMORY_2, DEVICE, 10.11, 8.0, 1.0)
8585
MVK_EXTENSION(KHR_multiview, KHR_MULTIVIEW, DEVICE, 10.11, 8.0, 1.0)
8686
MVK_EXTENSION(KHR_portability_subset, KHR_PORTABILITY_SUBSET, DEVICE, 10.11, 8.0, 1.0)
87+
MVK_EXTENSION(KHR_present_id, KHR_PRESENT_ID, DEVICE, 10.11, 8.0, 1.0)
88+
MVK_EXTENSION(KHR_present_wait, KHR_PRESENT_WAIT, DEVICE, 10.11, 8.0, 1.0)
8789
MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE, 10.11, 8.0, 1.0)
8890
MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, DEVICE, 10.11, 8.0, 1.0)
8991
MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, DEVICE, 10.11, 14.0, 1.0)
@@ -92,8 +94,8 @@ MVK_EXTENSION(KHR_separate_depth_stencil_layouts, KHR_SEPARATE_DEPTH_STENCI
9294
MVK_EXTENSION(KHR_shader_atomic_int64, KHR_SHADER_ATOMIC_INT64, DEVICE, MVK_NA, MVK_NA, MVK_NA)
9395
MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, DEVICE, 10.11, 8.0, 1.0)
9496
MVK_EXTENSION(KHR_shader_expect_assume, KHR_SHADER_EXPECT_ASSUME, DEVICE, 10.11, 8.0, 1.0)
95-
MVK_EXTENSION(KHR_shader_float_controls, KHR_SHADER_FLOAT_CONTROLS, DEVICE, 10.11, 8.0, 1.0)
9697
MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, DEVICE, 10.11, 8.0, 1.0)
98+
MVK_EXTENSION(KHR_shader_float_controls, KHR_SHADER_FLOAT_CONTROLS, DEVICE, 10.11, 8.0, 1.0)
9799
MVK_EXTENSION(KHR_shader_integer_dot_product, KHR_SHADER_INTEGER_DOT_PRODUCT, DEVICE, 10.11, 8.0, 1.0)
98100
MVK_EXTENSION(KHR_shader_non_semantic_info, KHR_SHADER_NON_SEMANTIC_INFO, DEVICE, 10.11, 8.0, 1.0)
99101
MVK_EXTENSION(KHR_shader_relaxed_extended_instruction, KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION, DEVICE, 10.11, 8.0, 1.0)
@@ -118,8 +120,8 @@ MVK_EXTENSION(EXT_calibrated_timestamps, EXT_CALIBRATED_TIMESTAMPS
118120
MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, DEVICE, 10.11, 8.0, 1.0)
119121
MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, INSTANCE, 10.11, 8.0, 1.0)
120122
MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, INSTANCE, 10.11, 8.0, 1.0)
121-
MVK_EXTENSION(EXT_descriptor_indexing, EXT_DESCRIPTOR_INDEXING, DEVICE, 10.11, 8.0, 1.0)
122123
MVK_EXTENSION(EXT_depth_clip_control, EXT_DEPTH_CLIP_CONTROL, DEVICE, 10.11, 8.0, 1.0)
124+
MVK_EXTENSION(EXT_descriptor_indexing, EXT_DESCRIPTOR_INDEXING, DEVICE, 10.11, 8.0, 1.0)
123125
MVK_EXTENSION(EXT_extended_dynamic_state, EXT_EXTENDED_DYNAMIC_STATE, DEVICE, 10.11, 8.0, 1.0)
124126
MVK_EXTENSION(EXT_extended_dynamic_state2, EXT_EXTENDED_DYNAMIC_STATE_2, DEVICE, 10.11, 8.0, 1.0)
125127
MVK_EXTENSION(EXT_extended_dynamic_state3, EXT_EXTENDED_DYNAMIC_STATE_3, 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
@@ -3401,6 +3401,23 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetMemoryMetalHandlePropertiesEXT(
34013401
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkUnmapMemory2, KHR);
34023402

34033403

3404+
#pragma mark -
3405+
#pragma mark VK_KHR_present_wait extension
3406+
3407+
MVK_PUBLIC_VULKAN_SYMBOL VkResult vkWaitForPresentKHR(
3408+
VkDevice device,
3409+
VkSwapchainKHR swapchain,
3410+
uint64_t presentId,
3411+
uint64_t timeout) {
3412+
3413+
MVKTraceVulkanCallStart();
3414+
MVKSwapchain* mvkSC = (MVKSwapchain*)swapchain;
3415+
VkResult rslt = mvkSC->waitForPresent(presentId, timeout);
3416+
MVKTraceVulkanCallEnd();
3417+
return rslt;
3418+
}
3419+
3420+
34043421
#pragma mark -
34053422
#pragma mark VK_KHR_push_descriptor extension
34063423

0 commit comments

Comments
 (0)