Basic CommandBuffer::waitEvents implementation
Implemented waitEvents as a sync operation, like pipeline barriers,
since, as the Vulkan spec states:
"vkCmdWaitEvents is used with vkCmdSetEvent to define a memory
dependency between two sets of action commands, roughly in the
same way as pipeline barriers, but split into two commands such
that work between the two may execute unhindered."
Only the pEvents parameter is supported and currently doesn't support
pMemoryBarrier, pBufferMemoryBarriers or pImageMemoryBarriers.
Bug b/118620868
Change-Id: I30ccc65c65dfc7d9a99e25ebb535061c618375cb
Tests: dEQP-VK.api.command_buffers.record_simul_use_primary
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27348
Tested-by: Alexis Hétu <sugoi@google.com>
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index dd74fa9..d6ef037 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -540,7 +540,11 @@
void play(CommandBuffer::ExecutionState& executionState) override
{
- Cast(ev)->signal();
+ if(Cast(ev)->signal())
+ {
+ // Was waiting for signal on this event, sync now
+ executionState.renderer->synchronize();
+ }
}
private:
@@ -564,6 +568,25 @@
VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and reset the event at the last stage
};
+struct WaitEvent : public CommandBuffer::Command
+{
+ WaitEvent(VkEvent ev) : ev(ev)
+ {
+ }
+
+ void play(CommandBuffer::ExecutionState& executionState) override
+ {
+ if(!Cast(ev)->wait())
+ {
+ // Already signaled, sync now
+ executionState.renderer->synchronize();
+ }
+ }
+
+private:
+ VkEvent ev;
+};
+
struct BindDescriptorSet : public CommandBuffer::Command
{
BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, uint32_t set, const VkDescriptorSet& descriptorSet)
@@ -1030,7 +1053,15 @@
uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers)
{
- UNIMPLEMENTED("waitEvents");
+ ASSERT(state == RECORDING);
+
+ // TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored
+
+ // Note: srcStageMask and dstStageMask are currently ignored
+ for(uint32_t i = 0; i < eventCount; i++)
+ {
+ addCommand<WaitEvent>(pEvents[i]);
+ }
}
void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
diff --git a/src/Vulkan/VkEvent.hpp b/src/Vulkan/VkEvent.hpp
index 538668b..4735564 100644
--- a/src/Vulkan/VkEvent.hpp
+++ b/src/Vulkan/VkEvent.hpp
@@ -34,9 +34,12 @@
return 0;
}
- void signal()
+ bool signal()
{
status = VK_EVENT_SET;
+ bool wasWaiting = waiting;
+ waiting = false;
+ return wasWaiting;
}
void reset()
@@ -49,8 +52,19 @@
return status;
}
+ bool wait()
+ {
+ if(status != VK_EVENT_SET)
+ {
+ waiting = true;
+ }
+
+ return waiting;
+ }
+
private:
VkResult status = VK_EVENT_RESET;
+ bool waiting = false;
};
static inline Event* Cast(VkEvent object)