Commit 6d33e8c3 by Ben Clayton

System/Synchronization.hpp: Add the sw::TaskEvents interface

This is implemented by sw::WaitGroup, and vk::Fence. The goal here is to abstract the underlying implementation of the task tracker. We currently (ab)use vk::Fence for queue tracking when a sw::WaitGroup could be used. This also allows us to implement a task logger in the future that can show what's inflight at any time. Bug: b/133127573 Change-Id: I0177b26e7577ffd5cb687a5105a69a22070a7ac6 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31682Tested-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent 6779e5e0
...@@ -24,13 +24,28 @@ ...@@ -24,13 +24,28 @@
namespace sw namespace sw
{ {
// TaskEvents is an interface for notifying when tasks begin and end.
// Tasks can be nested and/or overlapping.
// TaskEvents is used for task queue synchronization.
class TaskEvents
{
public:
// start() is called before a task begins.
virtual void start() = 0;
// finish() is called after a task ends. finish() must only be called after
// a corresponding call to start().
virtual void finish() = 0;
// complete() is a helper for calling start() followed by finish().
inline void complete() { start(); finish(); }
};
// WaitGroup is a synchronization primitive that allows you to wait for // WaitGroup is a synchronization primitive that allows you to wait for
// collection of asynchronous tasks to finish executing. // collection of asynchronous tasks to finish executing.
// Call add() before each task begins, and then call done() when after each task // Call add() before each task begins, and then call done() when after each task
// is finished. // is finished.
// At the same time, wait() can be used to block until all tasks have finished. // At the same time, wait() can be used to block until all tasks have finished.
// WaitGroup takes its name after Golang's sync.WaitGroup. // WaitGroup takes its name after Golang's sync.WaitGroup.
class WaitGroup class WaitGroup : public TaskEvents
{ {
public: public:
// add() begins a new task. // add() begins a new task.
...@@ -82,6 +97,10 @@ public: ...@@ -82,6 +97,10 @@ public:
return count_; return count_;
} }
// TaskEvents compliance
void start() override { add(); }
void finish() override { done(); }
private: private:
int32_t count_ = 0; // guarded by mutex int32_t count_ = 0; // guarded by mutex
std::mutex mutex; std::mutex mutex;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
namespace vk namespace vk
{ {
class Fence : public Object<Fence, VkFence> class Fence : public Object<Fence, VkFence>, public sw::TaskEvents
{ {
public: public:
Fence() : signaled(sw::Event::ClearMode::Manual, false) {} Fence() : signaled(sw::Event::ClearMode::Manual, false) {}
...@@ -57,13 +57,14 @@ public: ...@@ -57,13 +57,14 @@ public:
return signaled.wait(timeout) ? VK_SUCCESS : VK_TIMEOUT; return signaled.wait(timeout) ? VK_SUCCESS : VK_TIMEOUT;
} }
void start() // TaskEvents compliance
void start() override
{ {
ASSERT(!signaled); ASSERT(!signaled);
wg.add(); wg.add();
} }
void finish() void finish() override
{ {
ASSERT(!signaled); ASSERT(!signaled);
if (wg.done()) if (wg.done())
......
...@@ -193,8 +193,7 @@ VkResult SwapchainKHR::getNextImage(uint64_t timeout, VkSemaphore semaphore, VkF ...@@ -193,8 +193,7 @@ VkResult SwapchainKHR::getNextImage(uint64_t timeout, VkSemaphore semaphore, VkF
if(fence) if(fence)
{ {
vk::Cast(fence)->start(); vk::Cast(fence)->complete();
vk::Cast(fence)->finish();
} }
return VK_SUCCESS; return VK_SUCCESS;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment