mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-06 22:54:16 +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
|
// TODO implement properly in DxvkDevice
|
||||||
while (Resource->isInUse())
|
while (Resource->isInUse())
|
||||||
std::this_thread::yield();
|
dxvk::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
|
#include "../util/thread.h"
|
||||||
#include "dxvk_context.h"
|
#include "dxvk_context.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
@ -200,7 +200,7 @@ namespace dxvk {
|
|||||||
std::condition_variable m_condOnAdd;
|
std::condition_variable m_condOnAdd;
|
||||||
std::condition_variable m_condOnSync;
|
std::condition_variable m_condOnSync;
|
||||||
std::queue<Rc<DxvkCsChunk>> m_chunksQueued;
|
std::queue<Rc<DxvkCsChunk>> m_chunksQueued;
|
||||||
std::thread m_thread;
|
dxvk::thread m_thread;
|
||||||
|
|
||||||
uint32_t m_chunksPending = 0;
|
uint32_t m_chunksPending = 0;
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "dxvk_include.h"
|
#include "dxvk_include.h"
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ namespace dxvk {
|
|||||||
m_compilerThreads.resize(threadCount);
|
m_compilerThreads.resize(threadCount);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < threadCount; i++) {
|
for (uint32_t i = 0; i < threadCount; i++) {
|
||||||
m_compilerThreads.at(i) = std::thread(
|
m_compilerThreads.at(i) = dxvk::thread(
|
||||||
[this] { this->runCompilerThread(); });
|
[this] { this->runCompilerThread(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
|
#include "../util/thread.h"
|
||||||
#include "dxvk_include.h"
|
#include "dxvk_include.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
@ -49,7 +49,7 @@ namespace dxvk {
|
|||||||
std::mutex m_compilerLock;
|
std::mutex m_compilerLock;
|
||||||
std::condition_variable m_compilerCond;
|
std::condition_variable m_compilerCond;
|
||||||
std::queue<PipelineEntry> m_compilerQueue;
|
std::queue<PipelineEntry> m_compilerQueue;
|
||||||
std::vector<std::thread> m_compilerThreads;
|
std::vector<dxvk::thread> m_compilerThreads;
|
||||||
|
|
||||||
void runCompilerThread();
|
void runCompilerThread();
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
|
#include "../util/thread.h"
|
||||||
#include "dxvk_cmdlist.h"
|
#include "dxvk_cmdlist.h"
|
||||||
#include "dxvk_sync.h"
|
#include "dxvk_sync.h"
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ namespace dxvk {
|
|||||||
std::condition_variable m_condOnAdd;
|
std::condition_variable m_condOnAdd;
|
||||||
std::condition_variable m_condOnTake;
|
std::condition_variable m_condOnTake;
|
||||||
std::queue<Rc<DxvkCommandList>> m_entries;
|
std::queue<Rc<DxvkCommandList>> m_entries;
|
||||||
std::thread m_thread;
|
dxvk::thread m_thread;
|
||||||
|
|
||||||
void threadFunc();
|
void threadFunc();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <thread>
|
#include "../thread.h"
|
||||||
|
|
||||||
namespace dxvk::sync {
|
namespace dxvk::sync {
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ namespace dxvk::sync {
|
|||||||
|
|
||||||
void lock() {
|
void lock() {
|
||||||
while (!this->try_lock())
|
while (!this->try_lock())
|
||||||
std::this_thread::yield();
|
dxvk::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock() {
|
void unlock() {
|
||||||
|
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 <thread>
|
||||||
|
|
||||||
|
#include "../../src/util/thread.h"
|
||||||
#include "../test_utils.h"
|
#include "../test_utils.h"
|
||||||
|
|
||||||
using namespace dxvk;
|
using namespace dxvk;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user