diff --git a/src/dxvk/dxvk_pipecompiler.cpp b/src/dxvk/dxvk_pipecompiler.cpp new file mode 100644 index 00000000..0134527a --- /dev/null +++ b/src/dxvk/dxvk_pipecompiler.cpp @@ -0,0 +1,65 @@ +#include "dxvk_pipecompiler.h" + +namespace dxvk { + + DxvkPipelineCompiler::DxvkPipelineCompiler() { + // Use ~half the CPU cores for pipeline compilation + const uint32_t threadCount = std::max( + 1u, std::thread::hardware_concurrency() / 2); + + Logger::debug(str::format( + "DxvkPipelineCompiler: Using ", threadCount, " threads")); + + // Start the compiler threads + m_compilerThreads.resize(threadCount); + + for (uint32_t i = 0; i < threadCount; i++) { + m_compilerThreads.at(i) = std::thread( + [this] { this->runCompilerThread(); }); + } + } + + + DxvkPipelineCompiler::~DxvkPipelineCompiler() { + { std::unique_lock lock(m_compilerLock); + m_compilerStop.store(true); + m_compilerCond.notify_all(); + } + + for (auto& thread : m_compilerThreads) + thread.join(); + } + + + void DxvkPipelineCompiler::queueCompilation( + const Rc& pipeline, + const Rc& instance) { + std::unique_lock lock(m_compilerLock); + m_compilerQueue.push({ pipeline, instance }); + m_compilerCond.notify_one(); + } + + + void DxvkPipelineCompiler::runCompilerThread() { + while (!m_compilerStop.load()) { + PipelineEntry entry; + + { std::unique_lock lock(m_compilerLock); + + m_compilerCond.wait(lock, [this] { + return m_compilerStop.load() + || m_compilerQueue.size() != 0; + }); + + if (m_compilerQueue.size() != 0) { + entry = std::move(m_compilerQueue.front()); + m_compilerQueue.pop(); + } + } + + if (entry.pipeline != nullptr && entry.instance != nullptr) + entry.pipeline->compileInstance(entry.instance); + } + } + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_pipecompiler.h b/src/dxvk/dxvk_pipecompiler.h new file mode 100644 index 00000000..428ad209 --- /dev/null +++ b/src/dxvk/dxvk_pipecompiler.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "dxvk_graphics.h" + +namespace dxvk { + + /** + * \brief Pipeline compiler + * + * asynchronous pipeline compiler, which is used + * to compile optimized versions of pipelines. + */ + class DxvkPipelineCompiler : public RcObject { + + public: + + DxvkPipelineCompiler(); + ~DxvkPipelineCompiler(); + + /** + * \brief Compiles a pipeline asynchronously + * + * This should be used to compile optimized + * graphics pipeline instances asynchronously. + * \param [in] pipeline The pipeline object + * \param [in] instance The pipeline instance + */ + void queueCompilation( + const Rc& pipeline, + const Rc& instance); + + private: + + struct PipelineEntry { + Rc pipeline; + Rc instance; + }; + + std::atomic m_compilerStop = { false }; + std::mutex m_compilerLock; + std::condition_variable m_compilerCond; + std::queue m_compilerQueue; + std::vector m_compilerThreads; + + void runCompilerThread(); + + }; + +} \ No newline at end of file diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index 234d1f61..1c563df9 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -43,6 +43,7 @@ dxvk_src = files([ 'dxvk_meta_clear.cpp', 'dxvk_meta_resolve.cpp', 'dxvk_pipecache.cpp', + 'dxvk_pipecompiler.cpp', 'dxvk_pipelayout.cpp', 'dxvk_pipemanager.cpp', 'dxvk_query.cpp',