From 5fea615ed782937c3d308b57a08609168d2073b7 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 18 Feb 2018 22:57:45 +0100 Subject: [PATCH] [dxvk] Implement backend part for event queries --- src/d3d11/d3d11_query.cpp | 7 ++++- src/dxvk/dxvk_cmdlist.h | 28 +++++++++++++++++--- src/dxvk/dxvk_context.cpp | 5 ++++ src/dxvk/dxvk_context.h | 9 +++++++ src/dxvk/dxvk_event.cpp | 2 +- src/dxvk/dxvk_event.h | 16 +++++++++++- src/dxvk/dxvk_event_tracker.cpp | 30 ++++++++++++++++++++++ src/dxvk/dxvk_event_tracker.h | 45 +++++++++++++++++++++++++++++++++ src/dxvk/dxvk_queue.cpp | 2 ++ src/dxvk/meson.build | 1 + 10 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 src/dxvk/dxvk_event_tracker.cpp create mode 100644 src/dxvk/dxvk_event_tracker.h diff --git a/src/d3d11/d3d11_query.cpp b/src/d3d11/d3d11_query.cpp index 8330f733..12d195d5 100644 --- a/src/d3d11/d3d11_query.cpp +++ b/src/d3d11/d3d11_query.cpp @@ -141,8 +141,13 @@ namespace dxvk { void D3D11Query::Signal(DxvkContext* ctx, uint32_t revision) { switch (m_desc.Query) { + case D3D11_QUERY_EVENT: { + DxvkEventRevision rev = { m_event, revision }; + ctx->signalEvent(rev); + } break; + case D3D11_QUERY_TIMESTAMP: { - DxvkQueryRevision rev = { m_query, m_revision }; + DxvkQueryRevision rev = { m_query, revision }; ctx->writeTimestamp(rev); } break; diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index b449d72c..695ab56b 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -4,6 +4,7 @@ #include "dxvk_binding.h" #include "dxvk_descriptor.h" +#include "dxvk_event_tracker.h" #include "dxvk_lifetime.h" #include "dxvk_limits.h" #include "dxvk_pipelayout.h" @@ -85,12 +86,32 @@ namespace dxvk { m_queryTracker.trackQueryRange(std::move(queries)); } + /** + * \brief Adds an event revision to track + * + * The event will be signaled after the command + * buffer has finished executing on the GPU. + */ + void trackEvent(const DxvkEventRevision& event) { + m_eventTracker.trackEvent(event); + } + + /** + * \brief Signals tracked events + * + * Marks all tracked events as signaled. Call this after + * synchronizing with a fence for this command list. + */ + void signalEvents() { + m_eventTracker.signalEvents(); + } + /** * \brief Writes back query results * - * Uses the query range to write back query data - * after the command list has finished executing - * on the GPU. + * Writes back query data to all queries tracked by the + * query range tracker. Call this after synchronizing + * with a fence for this command list. */ void writeQueryData() { m_queryTracker.writeQueryData(); @@ -486,6 +507,7 @@ namespace dxvk { DxvkDescriptorAlloc m_descAlloc; DxvkStagingAlloc m_stagingAlloc; DxvkQueryTracker m_queryTracker; + DxvkEventTracker m_eventTracker; }; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index b415ed01..8ff4bf39 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1201,6 +1201,11 @@ namespace dxvk { } + void DxvkContext::signalEvent(const DxvkEventRevision& event) { + m_cmd->trackEvent(event); + } + + void DxvkContext::writeTimestamp(const DxvkQueryRevision& query) { DxvkQueryHandle handle = this->allocQuery(query); diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 0a4d0447..41f91624 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -5,6 +5,8 @@ #include "dxvk_cmdlist.h" #include "dxvk_context_state.h" #include "dxvk_data.h" +#include "dxvk_event.h" +#include "dxvk_query.h" #include "dxvk_query_pool.h" #include "dxvk_util.h" @@ -542,6 +544,13 @@ namespace dxvk { uint32_t attachment, const DxvkBlendMode& blendMode); + /** + * \brief Signals an event + * \param [in] event The event + */ + void signalEvent( + const DxvkEventRevision& event); + /** * \brief Writes to a timestamp query * \param [in] query The timestamp query diff --git a/src/dxvk/dxvk_event.cpp b/src/dxvk/dxvk_event.cpp index 1bf2099c..31bce013 100644 --- a/src/dxvk/dxvk_event.cpp +++ b/src/dxvk/dxvk_event.cpp @@ -14,7 +14,7 @@ namespace dxvk { } - void DxvkEvent::signalEvent(uint32_t revision) { + void DxvkEvent::signal(uint32_t revision) { std::unique_lock lock(m_mutex); if (m_revision == revision) { diff --git a/src/dxvk/dxvk_event.h b/src/dxvk/dxvk_event.h index d9df247c..33c1e1ea 100644 --- a/src/dxvk/dxvk_event.h +++ b/src/dxvk/dxvk_event.h @@ -7,6 +7,9 @@ namespace dxvk { + /** + * \brief Event status + */ enum class DxvkEventStatus { Reset = 0, Signaled = 1, @@ -36,7 +39,7 @@ namespace dxvk { * \brief Signals the event * \param [in] revision The revision ID */ - void signalEvent(uint32_t revision); + void signal(uint32_t revision); /** * \brief Queries event status @@ -54,4 +57,15 @@ namespace dxvk { }; + /** + * \brief Event revision + * + * Stores the event object and the + * version ID for event operations. + */ + struct DxvkEventRevision { + Rc event; + uint32_t revision; + }; + } \ No newline at end of file diff --git a/src/dxvk/dxvk_event_tracker.cpp b/src/dxvk/dxvk_event_tracker.cpp new file mode 100644 index 00000000..09eb6840 --- /dev/null +++ b/src/dxvk/dxvk_event_tracker.cpp @@ -0,0 +1,30 @@ +#include "dxvk_event_tracker.h" + +namespace dxvk { + + DxvkEventTracker::DxvkEventTracker() { + + } + + + DxvkEventTracker::~DxvkEventTracker() { + + } + + + void DxvkEventTracker::trackEvent(const DxvkEventRevision& event) { + m_events.push_back(event); + } + + + void DxvkEventTracker::signalEvents() { + for (const DxvkEventRevision& event : m_events) + event.event->signal(event.revision); + } + + + void DxvkEventTracker::reset() { + m_events.clear(); + } + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_event_tracker.h b/src/dxvk/dxvk_event_tracker.h new file mode 100644 index 00000000..2939678a --- /dev/null +++ b/src/dxvk/dxvk_event_tracker.h @@ -0,0 +1,45 @@ +#pragma once + +#include "dxvk_event.h" + +namespace dxvk { + + /** + * \brief Event tracker + */ + class DxvkEventTracker { + + public: + + DxvkEventTracker(); + ~DxvkEventTracker(); + + /** + * \brief Adds an event to track + * \param [in] event The event revision + */ + void trackEvent(const DxvkEventRevision& event); + + /** + * \brief Signals tracked events + * + * Retrieves query data from the query pools + * and writes it back to the query objects. + */ + void signalEvents(); + + /** + * \brief Resets event tracker + * + * Releases all events from the tracker. + * Call this after signaling the events. + */ + void reset(); + + private: + + std::vector m_events; + + }; + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_queue.cpp b/src/dxvk/dxvk_queue.cpp index 26a2fb95..b1497ce2 100644 --- a/src/dxvk/dxvk_queue.cpp +++ b/src/dxvk/dxvk_queue.cpp @@ -58,7 +58,9 @@ namespace dxvk { entry.fence->wait(std::numeric_limits::max()); entry.cmdList->writeQueryData(); + entry.cmdList->signalEvents(); entry.cmdList->reset(); + m_device->recycleCommandList(entry.cmdList); } } diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index 2e1317a4..37b8824a 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -17,6 +17,7 @@ dxvk_src = files([ 'dxvk_device.cpp', 'dxvk_extensions.cpp', 'dxvk_event.cpp', + 'dxvk_event_tracker.cpp', 'dxvk_format.cpp', 'dxvk_framebuffer.cpp', 'dxvk_graphics.cpp',