mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-30 02:52:10 +01:00
Don't use std::thread.
Wine needs to setup each thread that has an access to Windows APIs. It means that in winelib builds, we can't let standard C++ library create threads and need to use Wine for that instead. I wrote a thin wrapper around Windows thread functions so that the rest of code just has to use new dxvk::thread class instead of std::thread.
This commit is contained in:
parent
cea1f15eab
commit
6d16bb4c87
@ -527,7 +527,7 @@ namespace dxvk {
|
||||
|
||||
// TODO implement properly in DxvkDevice
|
||||
while (Resource->isInUse())
|
||||
std::this_thread::yield();
|
||||
dxvk::this_thread::yield();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
#include "../util/thread.h"
|
||||
#include "dxvk_context.h"
|
||||
|
||||
namespace dxvk {
|
||||
@ -200,7 +200,7 @@ namespace dxvk {
|
||||
std::condition_variable m_condOnAdd;
|
||||
std::condition_variable m_condOnSync;
|
||||
std::queue<Rc<DxvkCsChunk>> m_chunksQueued;
|
||||
std::thread m_thread;
|
||||
dxvk::thread m_thread;
|
||||
|
||||
uint32_t m_chunksPending = 0;
|
||||
|
||||
@ -208,4 +208,4 @@ namespace dxvk {
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
#include "dxvk_include.h"
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace dxvk {
|
||||
m_compilerThreads.resize(threadCount);
|
||||
|
||||
for (uint32_t i = 0; i < threadCount; i++) {
|
||||
m_compilerThreads.at(i) = std::thread(
|
||||
m_compilerThreads.at(i) = dxvk::thread(
|
||||
[this] { this->runCompilerThread(); });
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
#include "../util/thread.h"
|
||||
#include "dxvk_include.h"
|
||||
|
||||
namespace dxvk {
|
||||
@ -49,7 +49,7 @@ namespace dxvk {
|
||||
std::mutex m_compilerLock;
|
||||
std::condition_variable m_compilerCond;
|
||||
std::queue<PipelineEntry> m_compilerQueue;
|
||||
std::vector<std::thread> m_compilerThreads;
|
||||
std::vector<dxvk::thread> m_compilerThreads;
|
||||
|
||||
void runCompilerThread();
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
#include "../util/thread.h"
|
||||
#include "dxvk_cmdlist.h"
|
||||
#include "dxvk_sync.h"
|
||||
|
||||
@ -56,10 +56,10 @@ namespace dxvk {
|
||||
std::condition_variable m_condOnAdd;
|
||||
std::condition_variable m_condOnTake;
|
||||
std::queue<Rc<DxvkCommandList>> m_entries;
|
||||
std::thread m_thread;
|
||||
dxvk::thread m_thread;
|
||||
|
||||
void threadFunc();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include "../thread.h"
|
||||
|
||||
namespace dxvk::sync {
|
||||
|
||||
@ -24,7 +24,7 @@ namespace dxvk::sync {
|
||||
|
||||
void lock() {
|
||||
while (!this->try_lock())
|
||||
std::this_thread::yield();
|
||||
dxvk::this_thread::yield();
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
@ -44,4 +44,4 @@ namespace dxvk::sync {
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
63
src/util/thread.h
Normal file
63
src/util/thread.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "util_error.h"
|
||||
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
|
||||
/*
|
||||
* This is needed mostly for winelib builds. Wine needs to setup each thread that
|
||||
* calls Windows APIs. It means that in winelib builds, we can't let standard C++
|
||||
* library create threads and need to use Wine for that instead. We use a thin wrapper
|
||||
* around Windows thread functions so that the rest of code just has to use
|
||||
* dxvk::thread class instead of std::thread.
|
||||
*/
|
||||
namespace dxvk {
|
||||
class thread {
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
|
||||
template<typename T>
|
||||
class thread_proc {
|
||||
private:
|
||||
T proc;
|
||||
public:
|
||||
thread_proc(T &proc) : proc(proc) {}
|
||||
|
||||
static DWORD WINAPI nativeProc(void *arg) {
|
||||
thread_proc *proc = reinterpret_cast<thread_proc*>(arg);
|
||||
proc->proc();
|
||||
delete proc;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template<class T>
|
||||
explicit thread(T &&func) {
|
||||
thread_proc<T> *proc = new thread_proc<T>(func);
|
||||
m_handle = ::CreateThread(nullptr, 0, thread_proc<T>::nativeProc, proc, 0, nullptr);
|
||||
if (!m_handle) {
|
||||
delete proc;
|
||||
throw DxvkError("Failed to create thread");
|
||||
}
|
||||
}
|
||||
|
||||
thread() : m_handle(nullptr) {}
|
||||
|
||||
~thread() {
|
||||
if (m_handle)
|
||||
::CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
void join() {
|
||||
::WaitForSingleObject(m_handle, INFINITE);
|
||||
}
|
||||
};
|
||||
|
||||
namespace this_thread {
|
||||
inline void yield() {
|
||||
Sleep(0);
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "../../src/util/thread.h"
|
||||
#include "../test_utils.h"
|
||||
|
||||
using namespace dxvk;
|
||||
|
Loading…
x
Reference in New Issue
Block a user