aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/frame_span.cc24
-rw-r--r--src/frame_span.hh37
-rw-r--r--src/layer.cc30
-rw-r--r--src/strategies/anti_lag/device_strategy.cc26
-rw-r--r--src/strategies/anti_lag/queue_strategy.cc33
-rw-r--r--src/strategies/anti_lag/queue_strategy.hh21
-rw-r--r--src/strategies/low_latency2/device_strategy.cc10
-rw-r--r--src/strategies/low_latency2/queue_strategy.cc44
-rw-r--r--src/strategies/low_latency2/queue_strategy.hh21
-rw-r--r--src/strategies/low_latency2/swapchain_monitor.cc33
-rw-r--r--src/strategies/low_latency2/swapchain_monitor.hh16
-rw-r--r--src/strategies/queue_strategy.hh11
-rw-r--r--src/submission.cc5
-rw-r--r--src/submission.hh17
-rw-r--r--src/timestamp_pool.cc14
-rw-r--r--src/timestamp_pool.hh12
16 files changed, 186 insertions, 168 deletions
diff --git a/src/frame_span.cc b/src/frame_span.cc
new file mode 100644
index 0000000..732d6f3
--- /dev/null
+++ b/src/frame_span.cc
@@ -0,0 +1,24 @@
+#include "frame_span.hh"
+
+namespace low_latency {
+
+FrameSpan::FrameSpan(std::shared_ptr<TimestampPool::Handle> handle)
+ : head_handle(std::move(handle)) {
+ assert(this->head_handle); // Must not be null
+}
+
+FrameSpan::~FrameSpan() {}
+
+void FrameSpan::update(std::shared_ptr<TimestampPool::Handle> handle) {
+ this->tail_handle = std::move(handle);
+}
+
+void FrameSpan::await_completed() const {
+ if (this->tail_handle) {
+ this->tail_handle->await_end();
+ return;
+ }
+ this->head_handle->await_end();
+}
+
+} // namespace low_latency \ No newline at end of file
diff --git a/src/frame_span.hh b/src/frame_span.hh
new file mode 100644
index 0000000..5220702
--- /dev/null
+++ b/src/frame_span.hh
@@ -0,0 +1,37 @@
+#ifndef FRAME_SPAN_HH_
+#define FRAME_SPAN_HH_
+
+#include "timestamp_pool.hh"
+
+namespace low_latency {
+
+// A class which contains timestamps that represent a Queue's contribution to
+// a frame. It reduces the (possibly) huge amount of TimestampPool::Handle's
+// that a queue needs to keep track of. It only keeps at max two - the first
+// head handle and the tail handle, which is allowed to be null in the case of
+// only a single submission for that queue.
+class FrameSpan {
+ public:
+ const std::shared_ptr<TimestampPool::Handle> head_handle;
+ std::shared_ptr<TimestampPool::Handle> tail_handle;
+
+ public:
+ FrameSpan(std::shared_ptr<TimestampPool::Handle> handle);
+ FrameSpan(const FrameSpan&) = delete;
+ FrameSpan(FrameSpan&&) = delete;
+ FrameSpan operator=(const FrameSpan&) = delete;
+ FrameSpan operator=(FrameSpan&&) = delete;
+ ~FrameSpan();
+
+ public:
+ // Update the framespan's tail to include this timestamp.
+ void update(std::shared_ptr<TimestampPool::Handle> handle);
+
+ public:
+ // Wait for for GPU work to complete.
+ void await_completed() const;
+};
+
+} // namespace low_latency
+
+#endif \ No newline at end of file
diff --git a/src/layer.cc b/src/layer.cc
index 6c275ba..5df896a 100644
--- a/src/layer.cc
+++ b/src/layer.cc
@@ -394,19 +394,14 @@ vkQueueSubmit(VkQueue queue, std::uint32_t submit_count,
// pointers to our command buffer arrays - of which the position in memory
// of can change on vector reallocation. So we use unique_ptrs here.
auto next_cbs = std::vector<std::unique_ptr<cbs_t>>{};
- auto submissions = std::vector<std::unique_ptr<Submission>>{};
+ auto handles = std::vector<std::shared_ptr<TimestampPool::Handle>>{};
- const auto now = DeviceClock::now();
const auto submit_span = std::span{submit_infos, submit_count};
std::ranges::transform(
submit_span, std::back_inserter(next_submits), [&](const auto& submit) {
const auto handle = context->timestamp_pool->acquire();
-
- submissions.push_back(std::make_unique<Submission>(Submission{
- .handle = handle,
- .time = now,
- }));
+ handles.push_back(handle);
next_cbs.emplace_back([&]() -> auto {
auto cbs = std::make_unique<cbs_t>();
@@ -431,10 +426,8 @@ vkQueueSubmit(VkQueue queue, std::uint32_t submit_count,
// We have to notify after we submit - otherwise we have a race where we
// wait for work that wasn't submitted.
- for (auto&& [submit, submission] :
- std::views::zip(submit_span, submissions)) {
-
- context->strategy->notify_submit(submit, std::move(submission));
+ for (auto&& [submit, handle] : std::views::zip(submit_span, handles)) {
+ context->strategy->notify_submit(submit, std::move(handle));
}
return result;
@@ -455,19 +448,14 @@ vkQueueSubmit2(VkQueue queue, std::uint32_t submit_count,
using cbs_t = std::vector<VkCommandBufferSubmitInfo>;
auto next_submits = std::vector<VkSubmitInfo2>{};
auto next_cbs = std::vector<std::unique_ptr<cbs_t>>{};
- auto submissions = std::vector<std::unique_ptr<Submission>>{};
+ auto handles = std::vector<std::shared_ptr<TimestampPool::Handle>>{};
- const auto now = DeviceClock::now();
const auto submit_span = std::span{submit_infos, submit_count};
std::ranges::transform(
submit_span, std::back_inserter(next_submits), [&](const auto& submit) {
const auto handle = context->timestamp_pool->acquire();
-
- submissions.push_back(std::make_unique<Submission>(Submission{
- .handle = handle,
- .time = now,
- }));
+ handles.push_back(handle);
next_cbs.emplace_back([&]() -> auto {
auto cbs = std::make_unique<cbs_t>();
@@ -496,10 +484,8 @@ vkQueueSubmit2(VkQueue queue, std::uint32_t submit_count,
queue, static_cast<std::uint32_t>(std::size(next_submits)),
std::data(next_submits), fence);
- for (auto&& [submit, submission] :
- std::views::zip(submit_span, submissions)) {
-
- context->strategy->notify_submit(submit, std::move(submission));
+ for (auto&& [submit, handle] : std::views::zip(submit_span, handles)) {
+ context->strategy->notify_submit(submit, std::move(handle));
}
return result;
diff --git a/src/strategies/anti_lag/device_strategy.cc b/src/strategies/anti_lag/device_strategy.cc
index b391371..2d1d9ad 100644
--- a/src/strategies/anti_lag/device_strategy.cc
+++ b/src/strategies/anti_lag/device_strategy.cc
@@ -15,7 +15,7 @@ AntiLagDeviceStrategy::AntiLagDeviceStrategy(DeviceContext& device)
AntiLagDeviceStrategy::~AntiLagDeviceStrategy() {}
void AntiLagDeviceStrategy::notify_update(const VkAntiLagDataAMD& data) {
- const auto lock = std::scoped_lock{this->mutex};
+ auto lock = std::unique_lock{this->mutex};
this->is_enabled = !(data.mode == VK_ANTI_LAG_MODE_OFF_AMD);
@@ -37,11 +37,14 @@ void AntiLagDeviceStrategy::notify_update(const VkAntiLagDataAMD& data) {
this->frame_index.reset();
return;
}
-
// If we're at the input stage, start marking submissions as relevant.
this->frame_index.emplace(data.pPresentationInfo->frameIndex);
- { // Input stage needs to wait for all queue submissions to complete.
+ lock.unlock();
+ // We need to collect all queue submission and wait on them in this thread.
+ // Input stage needs to wait for all queue submissions to complete.
+ const auto queue_frame_spans = [&]() -> auto {
+ auto queue_frame_spans = std::vector<std::unique_ptr<FrameSpan>>{};
const auto device_lock = std::shared_lock{this->device.mutex};
for (const auto& iter : this->device.queues) {
const auto& queue = iter.second;
@@ -50,15 +53,30 @@ void AntiLagDeviceStrategy::notify_update(const VkAntiLagDataAMD& data) {
dynamic_cast<AntiLagQueueStrategy*>(queue->strategy.get());
assert(strategy);
- strategy->await_complete();
+ // Grab it from the queue, don't hold the lock.
+ const auto queue_lock = std::scoped_lock{strategy->mutex};
+ queue_frame_spans.emplace_back(std::move(strategy->frame_span));
+ strategy->frame_span.reset();
+ }
+ return queue_frame_spans;
+ }();
+
+ // Wait on them and relock the mutex.
+ for (const auto& frame_span : queue_frame_spans) {
+ if (frame_span) { // Can still be null here.
+ frame_span->await_completed();
}
}
+ lock.lock();
+
// We might need to wait a little more time to meet our frame limit.
using namespace std::chrono;
if (this->delay != 0us && this->previous_input_release.has_value()) {
+ lock.unlock();
std::this_thread::sleep_until(*this->previous_input_release +
this->delay);
+ lock.lock();
}
this->previous_input_release = steady_clock::now();
diff --git a/src/strategies/anti_lag/queue_strategy.cc b/src/strategies/anti_lag/queue_strategy.cc
index 27a9337..9c49e7c 100644
--- a/src/strategies/anti_lag/queue_strategy.cc
+++ b/src/strategies/anti_lag/queue_strategy.cc
@@ -12,7 +12,7 @@ AntiLagQueueStrategy::~AntiLagQueueStrategy() {}
void AntiLagQueueStrategy::notify_submit(
[[maybe_unused]] const VkSubmitInfo& submit,
- std::unique_ptr<Submission> submission) {
+ std::shared_ptr<TimestampPool::Handle> handle) {
const auto strategy =
dynamic_cast<AntiLagDeviceStrategy*>(this->queue.device.strategy.get());
@@ -22,12 +22,16 @@ void AntiLagQueueStrategy::notify_submit(
}
const auto lock = std::scoped_lock(this->mutex);
- this->pending_submissions.push_back(std::move(submission));
+ if (this->frame_span) {
+ this->frame_span->update(std::move(handle));
+ } else {
+ this->frame_span = std::make_unique<FrameSpan>(std::move(handle));
+ }
}
void AntiLagQueueStrategy::notify_submit(
[[maybe_unused]] const VkSubmitInfo2& submit,
- std::unique_ptr<Submission> submission) {
+ std::shared_ptr<TimestampPool::Handle> handle) {
const auto strategy =
dynamic_cast<AntiLagDeviceStrategy*>(this->queue.device.strategy.get());
@@ -37,26 +41,11 @@ void AntiLagQueueStrategy::notify_submit(
}
const auto lock = std::scoped_lock(this->mutex);
- this->pending_submissions.push_back(std::move(submission));
-}
-
-void AntiLagQueueStrategy::await_complete() {
-
- // Grab submissions while under a lock.
- const auto submissions = [&]() -> std::deque<std::unique_ptr<Submission>> {
- const auto lock = std::scoped_lock{this->mutex};
-
- auto submissions = std::move(this->pending_submissions);
- this->pending_submissions.clear();
- return submissions;
- }();
-
- // Wait for completion on the last submission.
- if (submissions.empty()) {
- return;
+ if (this->frame_span) {
+ this->frame_span->update(std::move(handle));
+ } else {
+ this->frame_span = std::make_unique<FrameSpan>(std::move(handle));
}
- const auto& last = submissions.back();
- last->handle->await_end_time();
}
// Stub - AntiLag doesn't care about presents.
diff --git a/src/strategies/anti_lag/queue_strategy.hh b/src/strategies/anti_lag/queue_strategy.hh
index 37c44a5..b1ae3e6 100644
--- a/src/strategies/anti_lag/queue_strategy.hh
+++ b/src/strategies/anti_lag/queue_strategy.hh
@@ -3,7 +3,7 @@
#include "strategies/queue_strategy.hh"
-#include <deque>
+#include "frame_span.hh"
#include <memory>
#include <mutex>
@@ -12,25 +12,22 @@ namespace low_latency {
class QueueContext;
class AntiLagQueueStrategy final : public QueueStrategy {
- private:
+ public:
std::mutex mutex;
- std::deque<std::unique_ptr<Submission>> pending_submissions;
+ std::unique_ptr<FrameSpan> frame_span; // Null represents no work.
public:
AntiLagQueueStrategy(QueueContext& queue);
virtual ~AntiLagQueueStrategy();
public:
- virtual void notify_submit(const VkSubmitInfo& submit,
- std::unique_ptr<Submission> submission) override;
- virtual void notify_submit(const VkSubmitInfo2& submit,
- std::unique_ptr<Submission> submission) override;
+ virtual void
+ notify_submit(const VkSubmitInfo& submit,
+ std::shared_ptr<TimestampPool::Handle> handle) override;
+ virtual void
+ notify_submit(const VkSubmitInfo2& submit,
+ std::shared_ptr<TimestampPool::Handle> handle) override;
virtual void notify_present(const VkPresentInfoKHR& present) override;
-
- public:
- // Wait for all pending submissions to complete. Resets pending submissions
- // once done.
- void await_complete();
};
} // namespace low_latency
diff --git a/src/strategies/low_latency2/device_strategy.cc b/src/strategies/low_latency2/device_strategy.cc
index 32ff981..227c385 100644
--- a/src/strategies/low_latency2/device_strategy.cc
+++ b/src/strategies/low_latency2/device_strategy.cc
@@ -68,8 +68,8 @@ void LowLatency2DeviceStrategy::submit_swapchain_present_id(
// Iterate through all queues and grab any work that's associated with this
// present_id. Turn it into a vector of work that we give to our swapchain
// monitor.
- auto work = [&]() -> std::vector<std::deque<std::unique_ptr<Submission>>> {
- auto work = std::vector<std::deque<std::unique_ptr<Submission>>>{};
+ auto work = [&]() -> std::vector<std::unique_ptr<FrameSpan>> {
+ auto work = std::vector<std::unique_ptr<FrameSpan>>{};
const auto lock = std::scoped_lock{this->device.mutex};
for (const auto& queue_iter : this->device.queues) {
const auto& queue = queue_iter.second;
@@ -84,14 +84,14 @@ void LowLatency2DeviceStrategy::submit_swapchain_present_id(
// Need the lock now - we're modifying it.
const auto strategy_lock = std::unique_lock{strategy->mutex};
- const auto iter = strategy->present_id_submissions.find(present_id);
- if (iter == std::end(strategy->present_id_submissions)) {
+ const auto iter = strategy->frame_spans.find(present_id);
+ if (iter == std::end(strategy->frame_spans)) {
continue;
}
// Make sure we clean it up from the present as well.
work.push_back(std::move(iter->second));
- strategy->present_id_submissions.erase(iter);
+ strategy->frame_spans.erase(iter);
}
return work;
}();
diff --git a/src/strategies/low_latency2/queue_strategy.cc b/src/strategies/low_latency2/queue_strategy.cc
index 9a68b78..a020c0d 100644
--- a/src/strategies/low_latency2/queue_strategy.cc
+++ b/src/strategies/low_latency2/queue_strategy.cc
@@ -16,50 +16,48 @@ LowLatency2QueueStrategy::~LowLatency2QueueStrategy() {}
template <typename T>
static void notify_submit_impl(LowLatency2QueueStrategy& strategy,
const T& submit,
- std::unique_ptr<Submission> submission) {
+ std::shared_ptr<TimestampPool::Handle> handle) {
// It's actually not a requirement that we have this present id.
- const auto lspi = find_next<VkLatencySubmissionPresentIdNV>(
- &submit, VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV);
- const auto present_id = lspi ? lspi->presentID : 0;
+ const auto present_id = [&]() -> std::uint64_t {
+ const auto lspi = find_next<VkLatencySubmissionPresentIdNV>(
+ &submit, VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV);
+ return lspi ? lspi->presentID : 0;
+ }();
const auto lock = std::scoped_lock{strategy.mutex};
- const auto [iter, inserted] =
- strategy.present_id_submissions.try_emplace(present_id);
- iter->second.push_back(std::move(submission));
-
- // Remove stale submissions if we're presenting a lot to the same
- // present_id. This doesn't affect anything because we're waiting on the
- // last. It begs the question: should we should just store the last only?
- if (std::size(iter->second) >=
- LowLatency2QueueStrategy::MAX_TRACKED_OBJECTS) {
-
- iter->second.pop_front();
+ const auto [iter, inserted] = strategy.frame_spans.try_emplace(present_id);
+ if (inserted) {
+ iter->second = std::make_unique<FrameSpan>(std::move(handle));
+ } else {
+ iter->second->update(std::move(handle));
}
// Add our present_id to our ring tracking if it's non-zero.
if (inserted && present_id) {
- strategy.present_id_ring.push_back(present_id);
+ strategy.stale_present_ids.push_back(present_id);
}
// Remove stale present_id's if they weren't presented to.
- if (std::size(strategy.present_id_ring) >
- LowLatency2QueueStrategy::MAX_TRACKED_OBJECTS) {
+ if (std::size(strategy.stale_present_ids) >
+ LowLatency2QueueStrategy::MAX_TRACKED_PRESENTS) {
- const auto to_remove = strategy.present_id_ring.front();
- strategy.present_id_ring.pop_front();
- strategy.present_id_submissions.erase(to_remove);
+ const auto stale_present_id = strategy.stale_present_ids.front();
+ strategy.stale_present_ids.pop_front();
+ strategy.frame_spans.erase(stale_present_id);
}
}
void LowLatency2QueueStrategy::notify_submit(
- const VkSubmitInfo& submit, std::unique_ptr<Submission> submission) {
+ const VkSubmitInfo& submit,
+ std::shared_ptr<TimestampPool::Handle> submission) {
notify_submit_impl(*this, submit, std::move(submission));
}
void LowLatency2QueueStrategy::notify_submit(
- const VkSubmitInfo2& submit, std::unique_ptr<Submission> submission) {
+ const VkSubmitInfo2& submit,
+ std::shared_ptr<TimestampPool::Handle> submission) {
notify_submit_impl(*this, submit, std::move(submission));
}
diff --git a/src/strategies/low_latency2/queue_strategy.hh b/src/strategies/low_latency2/queue_strategy.hh
index a090e1b..6d41027 100644
--- a/src/strategies/low_latency2/queue_strategy.hh
+++ b/src/strategies/low_latency2/queue_strategy.hh
@@ -1,8 +1,8 @@
#ifndef STRATEGIES_LOW_LATENCY2_QUEUE_STRATEGY_HH_
#define STRATEGIES_LOW_LATENCY2_QUEUE_STRATEGY_HH_
+#include "frame_span.hh"
#include "strategies/queue_strategy.hh"
-#include "submission.hh"
#include <atomic>
#include <deque>
@@ -16,26 +16,27 @@ class QueueContext;
class LowLatency2QueueStrategy final : public QueueStrategy {
public:
- static constexpr auto MAX_TRACKED_OBJECTS = 50;
+ static constexpr auto MAX_TRACKED_PRESENTS = 50;
// Mapping of present_id's to submissions. Grabbed later by the device
// strategy when we present and actually can associate them to some
// vkSwapchainKHR.
std::mutex mutex{};
- std::unordered_map<std::uint64_t, std::deque<std::unique_ptr<Submission>>>
- present_id_submissions{};
- std::deque<std::uint64_t> present_id_ring{};
- std::atomic<bool> is_out_of_band{}; // atomic so we don't need a lock check
+ std::unordered_map<std::uint64_t, std::unique_ptr<FrameSpan>> frame_spans{};
+ std::deque<std::uint64_t> stale_present_ids{};
+ std::atomic<bool> is_out_of_band{}; // atomic to avoid lock
public:
LowLatency2QueueStrategy(QueueContext& queue);
virtual ~LowLatency2QueueStrategy();
public:
- virtual void notify_submit(const VkSubmitInfo& submit,
- std::unique_ptr<Submission> submission) override;
- virtual void notify_submit(const VkSubmitInfo2& submit,
- std::unique_ptr<Submission> submission) override;
+ virtual void
+ notify_submit(const VkSubmitInfo& submit,
+ std::shared_ptr<TimestampPool::Handle> handle) override;
+ virtual void
+ notify_submit(const VkSubmitInfo2& submit,
+ std::shared_ptr<TimestampPool::Handle> handle) override;
virtual void notify_present(const VkPresentInfoKHR& present) override;
public:
diff --git a/src/strategies/low_latency2/swapchain_monitor.cc b/src/strategies/low_latency2/swapchain_monitor.cc
index b6d4dd0..a70fa6c 100644
--- a/src/strategies/low_latency2/swapchain_monitor.cc
+++ b/src/strategies/low_latency2/swapchain_monitor.cc
@@ -35,32 +35,29 @@ void SwapchainMonitor::do_monitor(const std::stop_token stoken) {
for (;;) {
auto lock = std::unique_lock{this->mutex};
this->cv.wait(lock, stoken,
- [&]() { return this->semaphore_submission.has_value(); });
+ [&]() { return this->semaphore_spans.has_value(); });
// Stop only if we're stopped and we have nothing to signal.
- if (stoken.stop_requested() &&
- !this->semaphore_submission.has_value()) {
+ if (stoken.stop_requested() && !this->semaphore_spans.has_value()) {
break;
}
// Grab the most recent semaphore. When work completes, signal it.
- const auto semaphore_submission =
- std::move(*this->semaphore_submission);
- this->semaphore_submission.reset();
+ const auto semaphore_span = std::move(*this->semaphore_spans);
+ this->semaphore_spans.reset();
// If we're stopping, signal the semaphore and don't worry about work
// actually completing.
if (stoken.stop_requested()) {
- semaphore_submission.wakeup_semaphore.signal(this->device);
+ semaphore_span.wakeup_semaphore.signal(this->device);
break;
}
// Unlock, wait for work to finish, lock again.
lock.unlock();
- for (const auto& submission : semaphore_submission.submissions) {
- if (!submission.empty()) {
- const auto& last = submission.back();
- last->handle->await_end_time();
+ for (const auto& frame_span : semaphore_span.frame_spans) {
+ if (frame_span) {
+ frame_span->await_completed();
}
}
@@ -78,7 +75,7 @@ void SwapchainMonitor::do_monitor(const std::stop_token stoken) {
}
lock.unlock();
- semaphore_submission.wakeup_semaphore.signal(this->device);
+ semaphore_span.wakeup_semaphore.signal(this->device);
}
}
@@ -97,29 +94,29 @@ void SwapchainMonitor::notify_semaphore(const VkSemaphore& timeline_semaphore,
}
// Signal immediately if we have no outstanding work.
- if (this->pending_submissions.empty()) {
+ if (this->pending_frame_spans.empty()) {
wakeup_semaphore.signal(this->device);
return;
}
- this->semaphore_submission.emplace(SemaphoreSubmissions{
+ this->semaphore_spans.emplace(SemaphoreSpans{
.wakeup_semaphore = wakeup_semaphore,
- .submissions = std::move(this->pending_submissions),
+ .frame_spans = std::move(this->pending_frame_spans),
});
- this->pending_submissions.clear();
+ this->pending_frame_spans.clear();
lock.unlock();
this->cv.notify_one();
}
void SwapchainMonitor::attach_work(
- std::vector<std::deque<std::unique_ptr<Submission>>> submissions) {
+ std::vector<std::unique_ptr<FrameSpan>> frame_spans) {
const auto lock = std::scoped_lock{this->mutex};
if (!this->was_low_latency_requested) {
return;
}
- this->pending_submissions = std::move(submissions);
+ this->pending_frame_spans = std::move(frame_spans);
}
} // namespace low_latency \ No newline at end of file
diff --git a/src/strategies/low_latency2/swapchain_monitor.hh b/src/strategies/low_latency2/swapchain_monitor.hh
index 47c3a75..837f8e4 100644
--- a/src/strategies/low_latency2/swapchain_monitor.hh
+++ b/src/strategies/low_latency2/swapchain_monitor.hh
@@ -2,17 +2,16 @@
#ifndef SWAPCHAIN_MONITOR_HH_
#define SWAPCHAIN_MONITOR_HH_
+#include "frame_span.hh"
+
#include <vulkan/vulkan.h>
#include <chrono>
#include <condition_variable>
-#include <deque>
#include <memory>
#include <mutex>
#include <thread>
-#include "submission.hh"
-
namespace low_latency {
class DeviceContext;
@@ -28,15 +27,15 @@ class SwapchainMonitor final {
};
// An empty vector here represents our 'no work' state.
- std::vector<std::deque<std::unique_ptr<Submission>>> pending_submissions{};
+ std::vector<std::unique_ptr<FrameSpan>> pending_frame_spans{};
// A pairing of semaphore -> submissions.
// If the Submissions completes then signal the bundled semaphore.
- struct SemaphoreSubmissions {
+ struct SemaphoreSpans {
WakeupSemaphore wakeup_semaphore{};
- std::vector<std::deque<std::unique_ptr<Submission>>> submissions{};
+ std::vector<std::unique_ptr<FrameSpan>> frame_spans{};
};
- std::optional<SemaphoreSubmissions> semaphore_submission{};
+ std::optional<SemaphoreSpans> semaphore_spans{};
protected:
const DeviceContext& device;
@@ -67,8 +66,7 @@ class SwapchainMonitor final {
void notify_semaphore(const VkSemaphore& timeline_semaphore,
const std::uint64_t& value);
- void attach_work(
- std::vector<std::deque<std::unique_ptr<Submission>>> submissions);
+ void attach_work(std::vector<std::unique_ptr<FrameSpan>> submissions);
};
} // namespace low_latency
diff --git a/src/strategies/queue_strategy.hh b/src/strategies/queue_strategy.hh
index b4fbcb9..0bc0dbb 100644
--- a/src/strategies/queue_strategy.hh
+++ b/src/strategies/queue_strategy.hh
@@ -1,7 +1,6 @@
#ifndef STRATEGIES_QUEUE_STRATEGY_HH_
#define STRATEGIES_QUEUE_STRATEGY_HH_
-#include "submission.hh"
#include "timestamp_pool.hh"
#include <vulkan/vulkan.h>
@@ -19,10 +18,12 @@ class QueueStrategy {
virtual ~QueueStrategy();
public:
- virtual void notify_submit(const VkSubmitInfo& submit,
- std::unique_ptr<Submission> submission) = 0;
- virtual void notify_submit(const VkSubmitInfo2& submit,
- std::unique_ptr<Submission> submission) = 0;
+ virtual void
+ notify_submit(const VkSubmitInfo& submit,
+ std::shared_ptr<TimestampPool::Handle> handle) = 0;
+ virtual void
+ notify_submit(const VkSubmitInfo2& submit,
+ std::shared_ptr<TimestampPool::Handle> handle) = 0;
virtual void notify_present(const VkPresentInfoKHR& present) = 0;
};
diff --git a/src/submission.cc b/src/submission.cc
deleted file mode 100644
index 1a6cb72..0000000
--- a/src/submission.cc
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "submission.hh"
-
-namespace low_latency {
-
-} // namespace low_latency \ No newline at end of file
diff --git a/src/submission.hh b/src/submission.hh
deleted file mode 100644
index ba721c2..0000000
--- a/src/submission.hh
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef SUBMISSIONS_HH_
-#define SUBMISSIONS_HH_
-
-#include "device_clock.hh"
-#include "timestamp_pool.hh"
-
-namespace low_latency {
-
-class Submission {
- public:
- std::shared_ptr<TimestampPool::Handle> handle;
- DeviceClock::time_point_t time;
-};
-
-} // namespace low_latency
-
-#endif \ No newline at end of file
diff --git a/src/timestamp_pool.cc b/src/timestamp_pool.cc
index b52e8f8..afb12f7 100644
--- a/src/timestamp_pool.cc
+++ b/src/timestamp_pool.cc
@@ -164,7 +164,7 @@ void TimestampPool::do_reaper(const std::stop_token stoken) {
// Allow more to go on the queue while we wait for it to finish.
lock.unlock();
- handle_ptr->await_end_time();
+ handle_ptr->await_end();
// Lock our mutex, allow the queue to use it again and delete it.
lock.lock();
@@ -185,7 +185,7 @@ const VkCommandBuffer& TimestampPool::Handle::get_end_buffer() const {
return command_buffers[this->query_index + 1];
}
-DeviceClock::time_point_t
+std::uint64_t
TimestampPool::Handle::await_time_impl(const std::uint32_t offset) const {
const auto& context = this->timestamp_pool.queue_context.device;
@@ -201,15 +201,11 @@ TimestampPool::Handle::await_time_impl(const std::uint32_t offset) const {
VK_QUERY_RESULT_WAIT_BIT));
assert(query_result[1]);
- return context.clock->ticks_to_time(query_result[0]);
+ return query_result[0];
}
-DeviceClock::time_point_t TimestampPool::Handle::await_start_time() const {
- return this->await_time_impl(0);
-}
-DeviceClock::time_point_t TimestampPool::Handle::await_end_time() const {
- return this->await_time_impl(1);
-}
+void TimestampPool::Handle::await_start() const { this->await_time_impl(0); }
+void TimestampPool::Handle::await_end() const { this->await_time_impl(1); }
TimestampPool::~TimestampPool() {}
diff --git a/src/timestamp_pool.hh b/src/timestamp_pool.hh
index 9044864..809c6a4 100644
--- a/src/timestamp_pool.hh
+++ b/src/timestamp_pool.hh
@@ -14,8 +14,6 @@
#include <unordered_set>
#include <vector>
-#include "device_clock.hh"
-
namespace low_latency {
class QueueContext;
@@ -125,13 +123,13 @@ class TimestampPool final {
const VkCommandBuffer& get_end_buffer() const;
private:
- DeviceClock::time_point_t
- await_time_impl(const std::uint32_t offset) const;
+ // Returns the device ticks. FIXME wrap device ticks.
+ std::uint64_t await_time_impl(const std::uint32_t offset) const;
public:
- // Waits until the time is available and returns it.
- DeviceClock::time_point_t await_start_time() const;
- DeviceClock::time_point_t await_end_time() const;
+ // Blocks until the time is available.
+ void await_start() const;
+ void await_end() const;
};
private: