mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-13 16:08:50 +01:00
[dxvk] Introduce sequence numbers for CS submissions
This commit is contained in:
parent
bc137fdf37
commit
37f3d9208b
@ -548,8 +548,7 @@ namespace dxvk {
|
||||
// recorded prior to this function will be run
|
||||
FlushCsChunk();
|
||||
|
||||
if (m_csThread.isBusy())
|
||||
m_csThread.synchronize();
|
||||
m_csThread.synchronize(DxvkCsThread::SynchronizeAll);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4759,8 +4759,7 @@ namespace dxvk {
|
||||
// recorded prior to this function will be run
|
||||
FlushCsChunk();
|
||||
|
||||
if (m_csThread.isBusy())
|
||||
m_csThread.synchronize();
|
||||
m_csThread.synchronize(DxvkCsThread::SynchronizeAll);
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,22 +111,32 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkCsThread::dispatchChunk(DxvkCsChunkRef&& chunk) {
|
||||
uint64_t DxvkCsThread::dispatchChunk(DxvkCsChunkRef&& chunk) {
|
||||
uint64_t seq;
|
||||
|
||||
{ std::unique_lock<dxvk::mutex> lock(m_mutex);
|
||||
seq = ++m_chunksDispatched;
|
||||
m_chunksQueued.push(std::move(chunk));
|
||||
m_chunksPending += 1;
|
||||
}
|
||||
|
||||
m_condOnAdd.notify_one();
|
||||
return seq;
|
||||
}
|
||||
|
||||
|
||||
void DxvkCsThread::synchronize() {
|
||||
std::unique_lock<dxvk::mutex> lock(m_mutex);
|
||||
void DxvkCsThread::synchronize(uint64_t seq) {
|
||||
// Avoid locking if we know the sync is a no-op, may
|
||||
// reduce overhead if this is being called frequently
|
||||
if (seq > m_chunksExecuted.load(std::memory_order_acquire)) {
|
||||
std::unique_lock<dxvk::mutex> lock(m_mutex);
|
||||
|
||||
m_condOnSync.wait(lock, [this] {
|
||||
return !m_chunksPending.load();
|
||||
});
|
||||
if (seq == SynchronizeAll)
|
||||
seq = m_chunksDispatched.load();
|
||||
|
||||
m_condOnSync.wait(lock, [this, seq] {
|
||||
return m_chunksExecuted.load() >= seq;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -139,8 +149,8 @@ namespace dxvk {
|
||||
while (!m_stopped.load()) {
|
||||
{ std::unique_lock<dxvk::mutex> lock(m_mutex);
|
||||
if (chunk) {
|
||||
if (--m_chunksPending == 0)
|
||||
m_condOnSync.notify_one();
|
||||
m_chunksExecuted++;
|
||||
m_condOnSync.notify_one();
|
||||
|
||||
chunk = DxvkCsChunkRef();
|
||||
}
|
||||
|
@ -380,6 +380,8 @@ namespace dxvk {
|
||||
|
||||
public:
|
||||
|
||||
constexpr static uint64_t SynchronizeAll = ~0ull;
|
||||
|
||||
DxvkCsThread(const Rc<DxvkContext>& context);
|
||||
~DxvkCsThread();
|
||||
|
||||
@ -389,41 +391,43 @@ namespace dxvk {
|
||||
* Can be used to efficiently play back large
|
||||
* command lists recorded on another thread.
|
||||
* \param [in] chunk The chunk to dispatch
|
||||
* \returns Sequence number of the submission
|
||||
*/
|
||||
void dispatchChunk(DxvkCsChunkRef&& chunk);
|
||||
uint64_t dispatchChunk(DxvkCsChunkRef&& chunk);
|
||||
|
||||
/**
|
||||
* \brief Synchronizes with the thread
|
||||
*
|
||||
* This waits for all chunks in the dispatch
|
||||
* queue to be processed by the thread. Note
|
||||
* that this does \e not implicitly call
|
||||
* \ref flush.
|
||||
* This waits for all chunks in the dispatch queue to
|
||||
* be processed by the thread, up to the given sequence
|
||||
* number. If the sequence number is 0, this will wait
|
||||
* for all pending chunks to complete execution.
|
||||
* \param [in] seq Sequence number to wait for.
|
||||
*/
|
||||
void synchronize();
|
||||
void synchronize(uint64_t seq);
|
||||
|
||||
/**
|
||||
* \brief Checks whether the worker thread is busy
|
||||
* \brief Retrieves last executed sequence number
|
||||
*
|
||||
* Note that this information is only reliable if
|
||||
* only the calling thread dispatches jobs to the
|
||||
* worker queue and if the result is \c false.
|
||||
* \returns \c true if there is still work to do
|
||||
* Can be used to avoid synchronization in some cases.
|
||||
* \returns Sequence number of last executed chunk
|
||||
*/
|
||||
bool isBusy() const {
|
||||
return m_chunksPending.load() != 0;
|
||||
uint64_t lastSequenceNumber() const {
|
||||
return m_chunksExecuted.load();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const Rc<DxvkContext> m_context;
|
||||
|
||||
std::atomic<uint64_t> m_chunksDispatched = { 0ull };
|
||||
std::atomic<uint64_t> m_chunksExecuted = { 0ull };
|
||||
|
||||
std::atomic<bool> m_stopped = { false };
|
||||
dxvk::mutex m_mutex;
|
||||
dxvk::condition_variable m_condOnAdd;
|
||||
dxvk::condition_variable m_condOnSync;
|
||||
std::queue<DxvkCsChunkRef> m_chunksQueued;
|
||||
std::atomic<uint32_t> m_chunksPending = { 0u };
|
||||
dxvk::thread m_thread;
|
||||
|
||||
void threadFunc();
|
||||
|
Loading…
Reference in New Issue
Block a user