diff --git a/src/dxvk/dxvk_event.cpp b/src/dxvk/dxvk_event.cpp index 7d6fea76..068c42e8 100644 --- a/src/dxvk/dxvk_event.cpp +++ b/src/dxvk/dxvk_event.cpp @@ -2,35 +2,55 @@ namespace dxvk { - DxvkEvent:: DxvkEvent() { } - DxvkEvent::~DxvkEvent() { } + DxvkEvent::DxvkEvent() + : m_packed(pack({ DxvkEventStatus::Signaled, 0u })) { } + + + DxvkEvent::~DxvkEvent() { + + } uint32_t DxvkEvent::reset() { - std::unique_lock lock(m_mutex); - - m_status = DxvkEventStatus::Reset; - return ++m_revision; + Status info; + + uint64_t packed = m_packed.load(); + + do { + info.status = DxvkEventStatus::Reset; + info.revision = unpack(packed).revision + 1; + } while (!m_packed.compare_exchange_strong(packed, pack(info))); + + return info.revision; } void DxvkEvent::signal(uint32_t revision) { - std::unique_lock lock(m_mutex); - - if (m_revision == revision) - m_status = DxvkEventStatus::Signaled; + uint64_t expected = pack({ DxvkEventStatus::Reset, revision }); + uint64_t desired = pack({ DxvkEventStatus::Signaled, revision }); + m_packed.compare_exchange_strong(expected, desired); } - DxvkEventStatus DxvkEvent::getStatus() { - std::unique_lock lock(m_mutex); - return m_status; + DxvkEventStatus DxvkEvent::getStatus() const { + return unpack(m_packed.load()).status; } - void DxvkEvent::wait() { + void DxvkEvent::wait() const { while (this->getStatus() != DxvkEventStatus::Signaled) dxvk::this_thread::yield(); } + + + uint64_t DxvkEvent::pack(Status info) { + return (uint64_t(info.revision)) + | (uint64_t(info.status) << 32); + } + + + DxvkEvent::Status DxvkEvent::unpack(uint64_t packed) { + return { DxvkEventStatus(packed >> 32), uint32_t(packed) }; + } } \ No newline at end of file diff --git a/src/dxvk/dxvk_event.h b/src/dxvk/dxvk_event.h index d652f066..3a752543 100644 --- a/src/dxvk/dxvk_event.h +++ b/src/dxvk/dxvk_event.h @@ -44,7 +44,7 @@ namespace dxvk { * \brief Queries event status * \returns Current event status */ - DxvkEventStatus getStatus(); + DxvkEventStatus getStatus() const; /** * \brief Waits for event to get signaled @@ -53,14 +53,20 @@ namespace dxvk { * thread calls \ref signal for the current * revision of the event. */ - void wait(); + void wait() const; private: - std::mutex m_mutex; - - DxvkEventStatus m_status = DxvkEventStatus::Signaled; - uint32_t m_revision = 0; + struct Status { + DxvkEventStatus status = DxvkEventStatus::Signaled; + uint32_t revision = 0; + }; + + // Packed status and revision + std::atomic m_packed; + + static uint64_t pack(Status info); + static Status unpack(uint64_t packed); };