Reimplement vk::Query using sw sync primitives.
Hide all the error-prone synchronization logic in the class, and expose a documented API.
This should have no impact on behavior - it was authored to make it harder to break things in the future.
That said, it appears to fix a whole bunch of flakes with the dEQP query tests.
Bug: b/133127573
Change-Id: I5c30b79b9b1cd36dba1fa2d3c34af0f5bd62772a
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31816
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Vulkan/VkQueryPool.hpp b/src/Vulkan/VkQueryPool.hpp
index d85bf85..88ca21b 100644
--- a/src/Vulkan/VkQueryPool.hpp
+++ b/src/Vulkan/VkQueryPool.hpp
@@ -15,6 +15,8 @@
#ifndef VK_QUERY_POOL_HPP_
#define VK_QUERY_POOL_HPP_
+#include "System/Synchronization.hpp"
+
#include "VkObject.hpp"
#include <atomic>
#include <condition_variable>
@@ -23,8 +25,13 @@
namespace vk
{
-struct Query
+class Query
{
+public:
+ static auto constexpr INVALID_TYPE = VK_QUERY_TYPE_MAX_ENUM;
+
+ Query();
+
enum State
{
UNAVAILABLE,
@@ -32,12 +39,53 @@
FINISHED
};
- std::mutex mutex;
- std::condition_variable condition;
- State state; // guarded by mutex
- int64_t data; // guarded by mutex
- std::atomic<int> reference;
- VkQueryType type;
+ struct Data
+ {
+ State state; // The current query state.
+ int64_t value; // The current query value.
+ };
+
+ // reset() sets the state of the Query to UNAVAILABLE, sets the type to
+ // INVALID_TYPE and clears the query value.
+ // reset() must not be called while the query is in the ACTIVE state.
+ void reset();
+
+ // prepare() sets the Query type to ty, and sets the state to ACTIVE.
+ // prepare() must not be called when the query is already ACTIVE.
+ void prepare(VkQueryType ty);
+
+ // start() begins a query task which is closed with a call to finish().
+ // Query tasks can be nested.
+ // start() must only be called when in the ACTIVE state.
+ void start();
+
+ // finish() ends a query task begun with a call to start().
+ // Once all query tasks are complete the query will transition to the
+ // FINISHED state.
+ // finish() must only be called when in the ACTIVE state.
+ void finish();
+
+ // wait() blocks until the query reaches the FINISHED state.
+ void wait();
+
+ // getData() returns the current query state and value.
+ Data getData() const;
+
+ // getType() returns the type of query.
+ VkQueryType getType() const;
+
+ // set() replaces the current query value with val.
+ void set(int64_t val);
+
+ // add() adds val to the current query value.
+ void add(int64_t val);
+
+private:
+ sw::WaitGroup wg;
+ sw::Event finished;
+ std::atomic<State> state;
+ std::atomic<VkQueryType> type;
+ std::atomic<int64_t> value;
};
class QueryPool : public Object<QueryPool, VkQueryPool>