Skip to content

Commit

Permalink
Merge pull request #2021 from billhollings/VK_KHR_synchronization2
Browse files Browse the repository at this point in the history
Add support for extension VK_KHR_synchronization2
  • Loading branch information
billhollings authored Sep 19, 2023
2 parents aed91cb + 6127918 commit 6a4271c
Show file tree
Hide file tree
Showing 25 changed files with 606 additions and 245 deletions.
1 change: 1 addition & 0 deletions Docs/MoltenVK_Runtime_UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
- `VK_KHR_surface`
- `VK_KHR_swapchain`
- `VK_KHR_swapchain_mutable_format`
- `VK_KHR_synchronization2`
- `VK_KHR_timeline_semaphore`
- `VK_KHR_uniform_buffer_standard_layout`
- `VK_KHR_variable_pointers`
Expand Down
2 changes: 2 additions & 0 deletions Docs/Whats_New.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ MoltenVK 1.2.6

Released TBD

- Add support for extensions:
- `VK_KHR_synchronization2`
- Fix rare case where vertex attribute buffers are not bound to Metal
when no other bindings change between pipelines.
- Ensure objects retained for life of `MTLCommandBuffer` during `vkCmdBlitImage()` & `vkQueuePresentKHR()`.
Expand Down
8 changes: 4 additions & 4 deletions MoltenVK/MoltenVK/API/mvk_datatypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,13 +414,13 @@ MTLWinding mvkMTLWindingFromSpvExecutionMode(uint32_t spvMode);
MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionMode(uint32_t spvMode);

/**
* Returns the combination of Metal MTLRenderStage bits corresponding to the specified Vulkan VkPiplineStageFlags,
* Returns the combination of Metal MTLRenderStage bits corresponding to the specified Vulkan VkPipelineStageFlags2,
* taking into consideration whether the barrier is to be placed before or after the specified pipeline stages.
*/
MTLRenderStages mvkMTLRenderStagesFromVkPipelineStageFlags(VkPipelineStageFlags vkStages, bool placeBarrierBefore);
MTLRenderStages mvkMTLRenderStagesFromVkPipelineStageFlags(VkPipelineStageFlags2 vkStages, bool placeBarrierBefore);

/** Returns the combination of Metal MTLBarrierScope bits corresponding to the specified Vulkan VkAccessFlags. */
MTLBarrierScope mvkMTLBarrierScopeFromVkAccessFlags(VkAccessFlags vkAccess);
/** Returns the combination of Metal MTLBarrierScope bits corresponding to the specified Vulkan VkAccessFlags2. */
MTLBarrierScope mvkMTLBarrierScopeFromVkAccessFlags(VkAccessFlags2 vkAccess);

#pragma mark -
#pragma mark Geometry conversions
Expand Down
41 changes: 22 additions & 19 deletions MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ template <size_t N>
class MVKCmdPipelineBarrier : public MVKCommand {

public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
const VkDependencyInfo* pDependencyInfo);

VkResult setContent(MVKCommandBuffer* cmdBuff,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
Expand All @@ -59,8 +62,6 @@ class MVKCmdPipelineBarrier : public MVKCommand {
bool coversTextures();

MVKSmallVector<MVKPipelineBarrier, N> _barriers;
VkPipelineStageFlags _srcStageMask;
VkPipelineStageFlags _dstStageMask;
VkDependencyFlags _dependencyFlags;
};

Expand Down Expand Up @@ -281,49 +282,46 @@ class MVKCmdPushDescriptorSetWithTemplate : public MVKCommand {


#pragma mark -
#pragma mark MVKCmdSetResetEvent
#pragma mark MVKCmdSetEvent

/** Abstract Vulkan command to set or reset an event. */
class MVKCmdSetResetEvent : public MVKCommand {
/** Vulkan command to set an event. */
class MVKCmdSetEvent : public MVKCommand {

public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkEvent event,
VkPipelineStageFlags stageMask);

protected:
MVKEvent* _mvkEvent;

};


#pragma mark -
#pragma mark MVKCmdSetEvent
const VkDependencyInfo* pDependencyInfo);

/** Vulkan command to set an event. */
class MVKCmdSetEvent : public MVKCmdSetResetEvent {
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkEvent event,
VkPipelineStageFlags stageMask);

public:
void encode(MVKCommandEncoder* cmdEncoder) override;

protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;

MVKEvent* _mvkEvent;
};


#pragma mark -
#pragma mark MVKCmdResetEvent

/** Vulkan command to reset an event. */
class MVKCmdResetEvent : public MVKCmdSetResetEvent {
class MVKCmdResetEvent : public MVKCommand {

public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkEvent event,
VkPipelineStageFlags2 stageMask);

void encode(MVKCommandEncoder* cmdEncoder) override;

protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;

MVKEvent* _mvkEvent;
};


Expand All @@ -339,6 +337,11 @@ template <size_t N>
class MVKCmdWaitEvents : public MVKCommand {

public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
uint32_t eventCount,
const VkEvent* pEvents,
const VkDependencyInfo* pDependencyInfos);

VkResult setContent(MVKCommandBuffer* cmdBuff,
uint32_t eventCount,
const VkEvent* pEvents,
Expand Down
116 changes: 81 additions & 35 deletions MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@
#pragma mark -
#pragma mark MVKCmdPipelineBarrier

template <size_t N>
VkResult MVKCmdPipelineBarrier<N>::setContent(MVKCommandBuffer* cmdBuff,
const VkDependencyInfo* pDependencyInfo) {
_dependencyFlags = pDependencyInfo->dependencyFlags;

_barriers.clear(); // Clear for reuse
_barriers.reserve(pDependencyInfo->memoryBarrierCount +
pDependencyInfo->bufferMemoryBarrierCount +
pDependencyInfo->imageMemoryBarrierCount);

for (uint32_t i = 0; i < pDependencyInfo->memoryBarrierCount; i++) {
_barriers.emplace_back(pDependencyInfo->pMemoryBarriers[i]);
}
for (uint32_t i = 0; i < pDependencyInfo->bufferMemoryBarrierCount; i++) {
_barriers.emplace_back(pDependencyInfo->pBufferMemoryBarriers[i]);
}
for (uint32_t i = 0; i < pDependencyInfo->imageMemoryBarrierCount; i++) {
_barriers.emplace_back(pDependencyInfo->pImageMemoryBarriers[i]);
}

return VK_SUCCESS;
}

template <size_t N>
VkResult MVKCmdPipelineBarrier<N>::setContent(MVKCommandBuffer* cmdBuff,
VkPipelineStageFlags srcStageMask,
Expand All @@ -40,21 +63,19 @@
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers) {
_srcStageMask = srcStageMask;
_dstStageMask = dstStageMask;
_dependencyFlags = dependencyFlags;

_barriers.clear(); // Clear for reuse
_barriers.reserve(memoryBarrierCount + bufferMemoryBarrierCount + imageMemoryBarrierCount);

for (uint32_t i = 0; i < memoryBarrierCount; i++) {
_barriers.emplace_back(pMemoryBarriers[i]);
_barriers.emplace_back(pMemoryBarriers[i], srcStageMask, dstStageMask);
}
for (uint32_t i = 0; i < bufferMemoryBarrierCount; i++) {
_barriers.emplace_back(pBufferMemoryBarriers[i]);
_barriers.emplace_back(pBufferMemoryBarriers[i], srcStageMask, dstStageMask);
}
for (uint32_t i = 0; i < imageMemoryBarrierCount; i++) {
_barriers.emplace_back(pImageMemoryBarriers[i]);
_barriers.emplace_back(pImageMemoryBarriers[i], srcStageMask, dstStageMask);
}

return VK_SUCCESS;
Expand All @@ -67,13 +88,9 @@
// Calls below invoke MTLBlitCommandEncoder so must apply this first.
// Check if pipeline barriers are available and we are in a renderpass.
if (cmdEncoder->getDevice()->_pMetalFeatures->memoryBarriers && cmdEncoder->_mtlRenderEncoder) {
MTLRenderStages srcStages = mvkMTLRenderStagesFromVkPipelineStageFlags(_srcStageMask, false);
MTLRenderStages dstStages = mvkMTLRenderStagesFromVkPipelineStageFlags(_dstStageMask, true);

id<MTLResource> resources[_barriers.size()];
uint32_t rezCnt = 0;

for (auto& b : _barriers) {
MTLRenderStages srcStages = mvkMTLRenderStagesFromVkPipelineStageFlags(b.srcStageMask, false);
MTLRenderStages dstStages = mvkMTLRenderStagesFromVkPipelineStageFlags(b.dstStageMask, true);
switch (b.type) {
case MVKPipelineBarrier::Memory: {
MTLBarrierScope scope = (mvkMTLBarrierScopeFromVkAccessFlags(b.srcAccessMask) |
Expand All @@ -84,27 +101,30 @@
break;
}

case MVKPipelineBarrier::Buffer:
resources[rezCnt++] = b.mvkBuffer->getMTLBuffer();
case MVKPipelineBarrier::Buffer: {
id<MTLResource> mtlRez = b.mvkBuffer->getMTLBuffer();
[cmdEncoder->_mtlRenderEncoder memoryBarrierWithResources: &mtlRez
count: 1
afterStages: srcStages
beforeStages: dstStages];
break;

case MVKPipelineBarrier::Image:
for (uint8_t planeIndex = 0; planeIndex < b.mvkImage->getPlaneCount(); planeIndex++) {
resources[rezCnt++] = b.mvkImage->getMTLTexture(planeIndex);
}
}
case MVKPipelineBarrier::Image: {
uint32_t plnCnt = b.mvkImage->getPlaneCount();
id<MTLResource> mtlRezs[plnCnt];
for (uint8_t plnIdx = 0; plnIdx < plnCnt; plnIdx++) {
mtlRezs[plnIdx] = b.mvkImage->getMTLTexture(plnIdx);
}
[cmdEncoder->_mtlRenderEncoder memoryBarrierWithResources: mtlRezs
count: plnCnt
afterStages: srcStages
beforeStages: dstStages];
break;

}
default:
break;
}
}

if (rezCnt) {
[cmdEncoder->_mtlRenderEncoder memoryBarrierWithResources: resources
count: rezCnt
afterStages: srcStages
beforeStages: dstStages];
}
} else if (cmdEncoder->getDevice()->_pMetalFeatures->textureBarriers) {
#if !MVK_MACCAT
if (coversTextures()) { [cmdEncoder->_mtlRenderEncoder textureBarrier]; }
Expand Down Expand Up @@ -138,15 +158,15 @@
for (auto& b : _barriers) {
switch (b.type) {
case MVKPipelineBarrier::Memory:
mvkDvc->applyMemoryBarrier(_srcStageMask, _dstStageMask, b, cmdEncoder, cmdUse);
mvkDvc->applyMemoryBarrier(b, cmdEncoder, cmdUse);
break;

case MVKPipelineBarrier::Buffer:
b.mvkBuffer->applyBufferMemoryBarrier(_srcStageMask, _dstStageMask, b, cmdEncoder, cmdUse);
b.mvkBuffer->applyBufferMemoryBarrier(b, cmdEncoder, cmdUse);
break;

case MVKPipelineBarrier::Image:
b.mvkImage->applyImageMemoryBarrier(_srcStageMask, _dstStageMask, b, cmdEncoder, cmdUse);
b.mvkImage->applyImageMemoryBarrier(b, cmdEncoder, cmdUse);
break;

default:
Expand Down Expand Up @@ -493,19 +513,23 @@


#pragma mark -
#pragma mark MVKCmdSetResetEvent
#pragma mark MVKCmdSetEvent

VkResult MVKCmdSetResetEvent::setContent(MVKCommandBuffer* cmdBuff,
VkEvent event,
VkPipelineStageFlags stageMask) {
VkResult MVKCmdSetEvent::setContent(MVKCommandBuffer* cmdBuff,
VkEvent event,
VkPipelineStageFlags stageMask) {
_mvkEvent = (MVKEvent*)event;

return VK_SUCCESS;
}

VkResult MVKCmdSetEvent::setContent(MVKCommandBuffer* cmdBuff,
VkEvent event,
const VkDependencyInfo* pDependencyInfo) {
_mvkEvent = (MVKEvent*)event;

#pragma mark -
#pragma mark MVKCmdSetEvent
return VK_SUCCESS;
}

void MVKCmdSetEvent::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->signalEvent(_mvkEvent, true);
Expand All @@ -515,6 +539,14 @@
#pragma mark -
#pragma mark MVKCmdResetEvent

VkResult MVKCmdResetEvent::setContent(MVKCommandBuffer* cmdBuff,
VkEvent event,
VkPipelineStageFlags2 stageMask) {
_mvkEvent = (MVKEvent*)event;

return VK_SUCCESS;
}

void MVKCmdResetEvent::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->signalEvent(_mvkEvent, false);
}
Expand All @@ -523,6 +555,20 @@
#pragma mark -
#pragma mark MVKCmdWaitEvents

template <size_t N>
VkResult MVKCmdWaitEvents<N>::setContent(MVKCommandBuffer* cmdBuff,
uint32_t eventCount,
const VkEvent* pEvents,
const VkDependencyInfo* pDependencyInfos) {
_mvkEvents.clear(); // Clear for reuse
_mvkEvents.reserve(eventCount);
for (uint32_t i = 0; i < eventCount; i++) {
_mvkEvents.push_back((MVKEvent*)pEvents[i]);
}

return VK_SUCCESS;
}

template <size_t N>
VkResult MVKCmdWaitEvents<N>::setContent(MVKCommandBuffer* cmdBuff,
uint32_t eventCount,
Expand Down
4 changes: 2 additions & 2 deletions MoltenVK/MoltenVK/Commands/MVKCmdQueries.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class MVKCmdWriteTimestamp : public MVKCmdQuery {

public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkPipelineStageFlagBits pipelineStage,
VkPipelineStageFlags2 stage,
VkQueryPool queryPool,
uint32_t query);

Expand All @@ -94,7 +94,7 @@ class MVKCmdWriteTimestamp : public MVKCmdQuery {
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;

VkPipelineStageFlagBits _pipelineStage;
VkPipelineStageFlags2 _stage;
};


Expand Down
4 changes: 2 additions & 2 deletions MoltenVK/MoltenVK/Commands/MVKCmdQueries.mm
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@
#pragma mark MVKCmdWriteTimestamp

VkResult MVKCmdWriteTimestamp::setContent(MVKCommandBuffer* cmdBuff,
VkPipelineStageFlagBits pipelineStage,
VkPipelineStageFlags2 stage,
VkQueryPool queryPool,
uint32_t query) {

VkResult rslt = MVKCmdQuery::setContent(cmdBuff, queryPool, query);

_pipelineStage = pipelineStage;
_stage = stage;

cmdBuff->recordTimestampCommand();

Expand Down
Loading

0 comments on commit 6a4271c

Please sign in to comment.