mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 20:52:10 +01:00
[util] Implement fence capable of signaling win32 events
This commit is contained in:
parent
ef37b5fed6
commit
6ebf3e1656
96
src/util/sync/sync_signal_win32.h
Normal file
96
src/util/sync/sync_signal_win32.h
Normal file
@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "sync_signal.h"
|
||||
|
||||
namespace dxvk::sync {
|
||||
|
||||
/**
|
||||
* \brief Win32 fence
|
||||
*
|
||||
* CPU-side fence that also has the
|
||||
* ability to signal Win32 events.
|
||||
*/
|
||||
class Win32Fence : public Signal {
|
||||
|
||||
public:
|
||||
|
||||
Win32Fence()
|
||||
: m_value(0ull) { }
|
||||
|
||||
explicit Win32Fence(uint64_t value)
|
||||
: m_value(value) { }
|
||||
|
||||
/**
|
||||
* \brief Last signaled value
|
||||
* \returns Last signaled value
|
||||
*/
|
||||
uint64_t value() const {
|
||||
return m_value.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Notifies signal
|
||||
*
|
||||
* In addition to waking up blocked threads, this
|
||||
* will also signal any queued win32 events with
|
||||
* a lower or equal value.
|
||||
* \param [in] value Value to set signal to
|
||||
*/
|
||||
void signal(uint64_t value) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_value.store(value, std::memory_order_release);
|
||||
m_cond.notify_all();
|
||||
|
||||
for (auto i = m_events.begin(); i != m_events.end(); ) {
|
||||
if (value >= i->second) {
|
||||
SetEvent(i->first);
|
||||
i = m_events.erase(i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Waits for signal
|
||||
* \param [in] value The value to wait for
|
||||
*/
|
||||
void wait(uint64_t value) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_cond.wait(lock, [this, value] {
|
||||
return value <= m_value.load(std::memory_order_acquire);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets Win32 event on completion
|
||||
*
|
||||
* When the signal gets signaled with a value equal to or
|
||||
* greater than the given value, the event will be signaled.
|
||||
* Signals the event immediately if the last signaled value
|
||||
* is already greater than or equal to the requested value.
|
||||
* \param [in] event Win32 Event to signal
|
||||
* \param [in] value Requested signal value
|
||||
*/
|
||||
void setEvent(HANDLE event, uint64_t value) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
if (value > this->value())
|
||||
m_events.push_back({ event, value });
|
||||
else
|
||||
SetEvent(event);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::atomic<uint64_t> m_value;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cond;
|
||||
|
||||
std::list<std::pair<HANDLE, uint64_t>> m_events;
|
||||
|
||||
};
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user