[dxvk] Use new worker thread system in state cache

This commit is contained in:
Philip Rebohle 2022-07-05 18:11:42 +02:00
parent 02e6a212bb
commit f2f1f86500
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 33 additions and 58 deletions

View File

@ -165,7 +165,9 @@ namespace dxvk {
DxvkDevice* device)
: m_device (device),
m_cache (device),
m_stateCache(device, this) {
m_workers (device, &m_cache),
m_stateCache(device, this, &m_workers) {
}
@ -277,13 +279,9 @@ namespace dxvk {
}
bool DxvkPipelineManager::isCompilingShaders() const {
return m_stateCache.isCompilingShaders();
}
void DxvkPipelineManager::stopWorkerThreads() {
m_stateCache.stopWorkerThreads();
m_workers.stopWorkers();
m_stateCache.stopWorkers();
}

View File

@ -201,7 +201,9 @@ namespace dxvk {
* \brief Checks whether async compiler is busy
* \returns \c true if shaders are being compiled
*/
bool isCompilingShaders() const;
bool isCompilingShaders() const {
return m_workers.isBusy();
}
/**
* \brief Stops async compiler threads
@ -212,6 +214,7 @@ namespace dxvk {
DxvkDevice* m_device;
DxvkPipelineCache m_cache;
DxvkPipelineWorkers m_workers;
DxvkStateCache m_stateCache;
std::atomic<uint32_t> m_numComputePipelines = { 0 };

View File

@ -214,9 +214,11 @@ namespace dxvk {
DxvkStateCache::DxvkStateCache(
DxvkDevice* device,
DxvkPipelineManager* pipeManager)
DxvkPipelineManager* pipeManager,
DxvkPipelineWorkers* pipeWorkers)
: m_device (device),
m_pipeManager (pipeManager) {
m_pipeManager (pipeManager),
m_pipeWorkers (pipeWorkers) {
std::string useStateCache = env::getEnvVar("DXVK_STATE_CACHE");
m_enable = useStateCache != "0" && device->config().enableStateCache;
@ -253,7 +255,7 @@ namespace dxvk {
DxvkStateCache::~DxvkStateCache() {
this->stopWorkerThreads();
this->stopWorkers();
}
@ -346,12 +348,12 @@ namespace dxvk {
if (workerLock) {
m_workerCond.notify_all();
createWorkers();
createWorker();
}
}
void DxvkStateCache::stopWorkerThreads() {
void DxvkStateCache::stopWorkers() {
{ std::lock_guard<dxvk::mutex> workerLock(m_workerLock);
std::lock_guard<dxvk::mutex> writerLock(m_writerLock);
@ -362,8 +364,8 @@ namespace dxvk {
m_writerCond.notify_all();
}
for (auto& worker : m_workerThreads)
worker.join();
if (m_workerThread.joinable())
m_workerThread.join();
if (m_writerThread.joinable())
m_writerThread.join();
@ -420,7 +422,7 @@ namespace dxvk {
for (auto e = entries.first; e != entries.second; e++) {
const auto& entry = m_entries[e->second];
pipeline->compilePipeline(entry.gpState);
m_pipeWorkers->compileGraphicsPipeline(pipeline, entry.gpState);
}
} else {
auto pipeline = m_pipeManager->createComputePipeline(item.cp);
@ -428,7 +430,7 @@ namespace dxvk {
for (auto e = entries.first; e != entries.second; e++) {
const auto& entry = m_entries[e->second];
pipeline->compilePipeline(entry.cpState);
m_pipeWorkers->compileComputePipeline(pipeline, entry.cpState);
}
}
}
@ -704,7 +706,7 @@ namespace dxvk {
void DxvkStateCache::workerFunc() {
env::setThreadName("dxvk-shader");
env::setThreadName("dxvk-worker");
while (!m_stopThreads.load()) {
WorkerItem item;
@ -712,14 +714,10 @@ namespace dxvk {
{ std::unique_lock<dxvk::mutex> lock(m_workerLock);
if (m_workerQueue.empty()) {
m_workerBusy -= 1;
m_workerCond.wait(lock, [this] () {
return m_workerQueue.size()
|| m_stopThreads.load();
});
if (!m_workerQueue.empty())
m_workerBusy += 1;
}
if (m_workerQueue.empty())
@ -767,28 +765,9 @@ namespace dxvk {
}
void DxvkStateCache::createWorkers() {
if (m_workerThreads.empty()) {
// Use half the available CPU cores for pipeline compilation
uint32_t numCpuCores = dxvk::thread::hardware_concurrency();
uint32_t numWorkers = ((std::max(1u, numCpuCores) - 1) * 5) / 7;
if (numWorkers < 1) numWorkers = 1;
if (numWorkers > 32) numWorkers = 32;
if (m_device->config().numCompilerThreads > 0)
numWorkers = m_device->config().numCompilerThreads;
Logger::info(str::format("DXVK: Using ", numWorkers, " compiler threads"));
// Start the worker threads and the file writer
m_workerBusy.store(numWorkers);
for (uint32_t i = 0; i < numWorkers; i++) {
m_workerThreads.emplace_back([this] () { workerFunc(); });
m_workerThreads[i].set_priority(ThreadPriority::Lowest);
}
}
void DxvkStateCache::createWorker() {
if (!m_workerThread.joinable())
m_workerThread = dxvk::thread([this] () { workerFunc(); });
}

View File

@ -13,6 +13,8 @@
namespace dxvk {
class DxvkDevice;
class DxvkPipelineManager;
class DxvkPipelineWorkers;
/**
* \brief State cache
@ -29,8 +31,9 @@ namespace dxvk {
DxvkStateCache(
DxvkDevice* device,
DxvkPipelineManager* pipeManager);
DxvkPipelineManager* pipeManager,
DxvkPipelineWorkers* pipeWorkers);
~DxvkStateCache();
/**
@ -72,15 +75,7 @@ namespace dxvk {
/**
* \brief Explicitly stops worker threads
*/
void stopWorkerThreads();
/**
* \brief Checks whether compiler threads are busy
* \returns \c true if we're compiling shaders
*/
bool isCompilingShaders() const {
return m_workerBusy.load() > 0;
}
void stopWorkers();
private:
@ -93,6 +88,7 @@ namespace dxvk {
DxvkDevice* m_device;
DxvkPipelineManager* m_pipeManager;
DxvkPipelineWorkers* m_pipeWorkers;
bool m_enable = false;
std::vector<DxvkStateCacheEntry> m_entries;
@ -115,8 +111,7 @@ namespace dxvk {
dxvk::mutex m_workerLock;
dxvk::condition_variable m_workerCond;
std::queue<WorkerItem> m_workerQueue;
std::atomic<uint32_t> m_workerBusy;
std::vector<dxvk::thread> m_workerThreads;
dxvk::thread m_workerThread;
dxvk::mutex m_writerLock;
dxvk::condition_variable m_writerCond;
@ -160,7 +155,7 @@ namespace dxvk {
void writerFunc();
void createWorkers();
void createWorker();
void createWriter();