Skip to content

Commit

Permalink
Merge pull request #1124 from cdavis5e/khr-timeline-semaphore
Browse files Browse the repository at this point in the history
Support the VK_KHR_timeline_semaphore extension.
  • Loading branch information
billhollings authored Oct 28, 2020
2 parents dd08daa + 2b7f9ae commit 4a1a517
Show file tree
Hide file tree
Showing 9 changed files with 383 additions and 39 deletions.
38 changes: 33 additions & 5 deletions MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@
shaderSGTypesFeatures->shaderSubgroupExtendedTypes = _metalFeatures.subgroupSize != 0;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: {
auto* timelineSem4Features = (VkPhysicalDeviceTimelineSemaphoreFeatures*)next;
timelineSem4Features->timelineSemaphore = true;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR: {
auto* uboLayoutFeatures = (VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR*)next;
uboLayoutFeatures->uniformBufferStandardLayout = true;
Expand Down Expand Up @@ -305,6 +310,11 @@
}
break;
#endif
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES: {
auto* timelineSem4Props = (VkPhysicalDeviceTimelineSemaphoreProperties*)next;
timelineSem4Props->maxTimelineSemaphoreValueDifference = std::numeric_limits<uint64_t>::max();
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT: {
auto* inlineUniformBlockProps = (VkPhysicalDeviceInlineUniformBlockPropertiesEXT*)next;
inlineUniformBlockProps->maxInlineUniformBlockSize = _metalFeatures.dynamicMTLBufferSize;
Expand Down Expand Up @@ -2668,12 +2678,30 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope

MVKSemaphore* MVKDevice::createSemaphore(const VkSemaphoreCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator) {
if (_useMTLFenceForSemaphores) {
return new MVKSemaphoreMTLFence(this, pCreateInfo);
} else if (_useMTLEventForSemaphores) {
return new MVKSemaphoreMTLEvent(this, pCreateInfo);
const VkSemaphoreTypeCreateInfo* pTypeCreateInfo = nullptr;
for (auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO:
pTypeCreateInfo = (VkSemaphoreTypeCreateInfo*)next;
break;
default:
break;
}
}
if (pTypeCreateInfo && pTypeCreateInfo->semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE) {
if (_pMetalFeatures->events) {
return new MVKTimelineSemaphoreMTLEvent(this, pCreateInfo, pTypeCreateInfo);
} else {
return new MVKTimelineSemaphoreEmulated(this, pCreateInfo, pTypeCreateInfo);
}
} else {
return new MVKSemaphoreEmulated(this, pCreateInfo);
if (_useMTLFenceForSemaphores) {
return new MVKSemaphoreMTLFence(this, pCreateInfo);
} else if (_useMTLEventForSemaphores) {
return new MVKSemaphoreMTLEvent(this, pCreateInfo);
} else {
return new MVKSemaphoreEmulated(this, pCreateInfo);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1263,13 +1263,13 @@

if ( !_availabilitySignalers.empty() ) {
MVKSemaphore* mvkSem = _availabilitySignalers.front().first;
if (mvkSem) { mvkSem->encodeSignal(mtlCmdBuff); }
if (mvkSem) { mvkSem->encodeSignal(mtlCmdBuff, 0); }
}
}

// Signal either or both of the semaphore and fence in the specified tracker pair.
void MVKPresentableSwapchainImage::signal(MVKSwapchainSignaler& signaler, id<MTLCommandBuffer> mtlCmdBuff) {
if (signaler.first) { signaler.first->encodeSignal(mtlCmdBuff); }
if (signaler.first) { signaler.first->encodeSignal(mtlCmdBuff, 0); }
if (signaler.second) { signaler.second->signal(); }
}

Expand Down
3 changes: 3 additions & 0 deletions MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,9 @@
ADD_DVC_EXT2_ENTRY_POINT(vkGetDeviceGroupSurfacePresentModesKHR, KHR_SWAPCHAIN, KHR_DEVICE_GROUP);
ADD_DVC_EXT2_ENTRY_POINT(vkGetPhysicalDevicePresentRectanglesKHR, KHR_SWAPCHAIN, KHR_DEVICE_GROUP);
ADD_DVC_EXT2_ENTRY_POINT(vkAcquireNextImage2KHR, KHR_SWAPCHAIN, KHR_DEVICE_GROUP);
ADD_DVC_EXT_ENTRY_POINT(vkGetSemaphoreCounterValueKHR, KHR_TIMELINE_SEMAPHORE);
ADD_DVC_EXT_ENTRY_POINT(vkSignalSemaphoreKHR, KHR_TIMELINE_SEMAPHORE);
ADD_DVC_EXT_ENTRY_POINT(vkWaitSemaphoresKHR, KHR_TIMELINE_SEMAPHORE);
ADD_DVC_EXT_ENTRY_POINT(vkDebugMarkerSetObjectTagEXT, EXT_DEBUG_MARKER);
ADD_DVC_EXT_ENTRY_POINT(vkDebugMarkerSetObjectNameEXT, EXT_DEBUG_MARKER);
ADD_DVC_EXT_ENTRY_POINT(vkCmdDebugMarkerBeginEXT, EXT_DEBUG_MARKER);
Expand Down
4 changes: 2 additions & 2 deletions MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class MVKQueueSubmission : public MVKConfigurableObject {
friend class MVKQueue;

MVKQueue* _queue;
MVKSmallVector<MVKSemaphore*> _waitSemaphores;
MVKSmallVector<std::pair<MVKSemaphore*, uint64_t>> _waitSemaphores;
bool _trackPerformance;
};

Expand All @@ -203,7 +203,7 @@ class MVKQueueCommandBufferSubmission : public MVKQueueSubmission {
void finish();
virtual void submitCommandBuffers() {}

MVKSmallVector<MVKSemaphore*> _signalSemaphores;
MVKSmallVector<std::pair<MVKSemaphore*, uint64_t>> _signalSemaphores;
MVKFence* _fence;
id<MTLCommandBuffer> _activeMTLCommandBuffer;
};
Expand Down
35 changes: 27 additions & 8 deletions MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@

_waitSemaphores.reserve(waitSemaphoreCount);
for (uint32_t i = 0; i < waitSemaphoreCount; i++) {
_waitSemaphores.push_back((MVKSemaphore*)pWaitSemaphores[i]);
_waitSemaphores.push_back(make_pair((MVKSemaphore*)pWaitSemaphores[i], (uint64_t)0));
}
}

Expand All @@ -241,13 +241,13 @@
_queue->_submissionCaptureScope->beginScope();

// If using encoded semaphore waiting, do so now.
for (auto* ws : _waitSemaphores) { ws->encodeWait(getActiveMTLCommandBuffer()); }
for (auto& ws : _waitSemaphores) { ws.first->encodeWait(getActiveMTLCommandBuffer(), ws.second); }

// Submit each command buffer.
submitCommandBuffers();

// If using encoded semaphore signaling, do so now.
for (auto* ss : _signalSemaphores) { ss->encodeSignal(getActiveMTLCommandBuffer()); }
for (auto& ss : _signalSemaphores) { ss.first->encodeSignal(getActiveMTLCommandBuffer(), ss.second); }

// Commit the last MTLCommandBuffer.
// Nothing after this because callback might destroy this instance before this function ends.
Expand Down Expand Up @@ -278,7 +278,7 @@
void MVKQueueCommandBufferSubmission::commitActiveMTLCommandBuffer(bool signalCompletion) {

// If using inline semaphore waiting, do so now.
for (auto& ws : _waitSemaphores) { ws->encodeWait(nil); }
for (auto& ws : _waitSemaphores) { ws.first->encodeWait(nil, ws.second); }

MVKDevice* mkvDev = _queue->_device;
uint64_t startTime = mkvDev->getPerformanceTimestamp();
Expand Down Expand Up @@ -308,7 +308,7 @@
_queue->_submissionCaptureScope->endScope();

// If using inline semaphore signaling, do so now.
for (auto& ss : _signalSemaphores) { ss->encodeSignal(nil); }
for (auto& ss : _signalSemaphores) { ss.first->encodeSignal(nil, ss.second); }

// If a fence exists, signal it.
if (_fence) { _fence->signal(); }
Expand All @@ -325,10 +325,29 @@

// pSubmit can be null if just tracking the fence alone
if (pSubmit) {
VkTimelineSemaphoreSubmitInfo* pTimelineSubmit = nullptr;
for (const auto* next = (const VkBaseInStructure*)pSubmit->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO:
pTimelineSubmit = (VkTimelineSemaphoreSubmitInfo*)next;
break;
default:
break;
}
}
if (pTimelineSubmit) {
// Presentation doesn't support timeline semaphores, so handle wait values here.
uint32_t wsCnt = pTimelineSubmit->waitSemaphoreValueCount;
for (uint32_t i = 0; i < wsCnt; i++) {
_waitSemaphores[i].second = pTimelineSubmit->pWaitSemaphoreValues[i];
}
}
uint32_t ssCnt = pSubmit->signalSemaphoreCount;
_signalSemaphores.reserve(ssCnt);
for (uint32_t i = 0; i < ssCnt; i++) {
_signalSemaphores.push_back((MVKSemaphore*)pSubmit->pSignalSemaphores[i]);
auto ss = make_pair((MVKSemaphore*)pSubmit->pSignalSemaphores[i], (uint64_t)0);
if (pTimelineSubmit) { ss.second = pTimelineSubmit->pSignalSemaphoreValues[i]; }
_signalSemaphores.push_back(ss);
}
}

Expand All @@ -348,12 +367,12 @@
// If the semaphores are not encodable, wait on them inline after presenting.
// The semaphores know what to do.
id<MTLCommandBuffer> mtlCmdBuff = getMTLCommandBuffer();
for (auto& ws : _waitSemaphores) { ws->encodeWait(mtlCmdBuff); }
for (auto& ws : _waitSemaphores) { ws.first->encodeWait(mtlCmdBuff, 0); }
for (int i = 0; i < _presentInfo.size(); i++ ) {
MVKPresentableSwapchainImage *img = _presentInfo[i].presentableImage;
img->presentCAMetalDrawable(mtlCmdBuff, _presentInfo[i]);
}
for (auto& ws : _waitSemaphores) { ws->encodeWait(nil); }
for (auto& ws : _waitSemaphores) { ws.first->encodeWait(nil, 0); }
[mtlCmdBuff commit];

// Let Xcode know the current frame is done, then start a new frame
Expand Down
Loading

0 comments on commit 4a1a517

Please sign in to comment.