diff options
author | Stelios Tsampas | 2021-10-31 17:01:09 +0200 |
---|---|---|
committer | Stelios Tsampas | 2021-10-31 17:01:09 +0200 |
commit | 466758f18b09d6b2c096ffdcb4f1624c1ef63763 (patch) | |
tree | 0eae700411baefe268097b43b3106b505487d66b | |
parent | 620fc31a23bf53edafe9481d575d4f5c79551dce (diff) | |
download | aur-466758f18b09d6b2c096ffdcb4f1624c1ef63763.tar.gz |
Use external async patch
-rw-r--r-- | .SRCINFO | 11 | ||||
-rw-r--r-- | PKGBUILD | 29 | ||||
-rw-r--r-- | dxvk-async-conf.patch | 29 | ||||
-rw-r--r-- | dxvk-async.patch | 523 |
4 files changed, 53 insertions, 539 deletions
@@ -20,13 +20,16 @@ pkgbase = dxvk-mingw conflicts = dxvk conflicts = d9vk options = !lto + options = !staticlibs source = git+https://github.com/doitsujin/dxvk.git#tag=v1.9.2 - source = setup_dxvk - source = dxvk-async.patch + source = https://raw.githubusercontent.com/Sporif/dxvk-async/1.9.2/dxvk-async.patch + source = dxvk-async-conf.patch source = dxvk-extraopts.patch + source = setup_dxvk sha256sums = SKIP - sha256sums = b2413cabd8cca56e2d308ef5513edf1c7f909036ed2ccfeae17536a0e864dc96 - sha256sums = acdb652830d642829057a035ebc69481697078a734f57ac974ee5b54454470ff + sha256sums = 9212a9c42ac8c9c7b9ba7378685b27e7ea0e7a8a8aaac1f3f4d37590ada3e991 + sha256sums = c9c2f02bce1e1e93d511aff73484208456835d4d7601a36ab4524939472fc401 sha256sums = 2bf3515ce9a3ee426c2632aa3355b2556ee8fe5dd8d88e088f90803e3d5f10a6 + sha256sums = b2413cabd8cca56e2d308ef5513edf1c7f909036ed2ccfeae17536a0e864dc96 pkgname = dxvk-mingw @@ -1,7 +1,8 @@ # Maintainer: loathingkernel <loathingkernel @at gmail .dot com> pkgname=dxvk-mingw -pkgver=1.9.2 +_dxvkver=1.9.2 +pkgver=$_dxvkver pkgrel=1 pkgdesc='Vulkan-based implementation of D3D9, D3D10 and D3D11 for Linux / Wine, MingW version' arch=('x86_64') @@ -11,23 +12,32 @@ depends=('vulkan-icd-loader' 'wine>=4.0rc1' 'lib32-vulkan-icd-loader' 'bash') makedepends=('ninja' 'meson>=0.43' 'glslang' 'git' 'mingw-w64-gcc') provides=('dxvk' 'd9vk' "dxvk=$pkgver") conflicts=('dxvk' 'd9vk') -options=(!lto) +options=(!lto !staticlibs) source=( - "git+https://github.com/doitsujin/dxvk.git#tag=v$pkgver" - "setup_dxvk" - "dxvk-async.patch" + "git+https://github.com/doitsujin/dxvk.git#tag=v$_dxvkver" + "https://raw.githubusercontent.com/Sporif/dxvk-async/$_dxvkver/dxvk-async.patch" + "dxvk-async-conf.patch" "dxvk-extraopts.patch" + "setup_dxvk" ) sha256sums=( 'SKIP' - 'b2413cabd8cca56e2d308ef5513edf1c7f909036ed2ccfeae17536a0e864dc96' - 'acdb652830d642829057a035ebc69481697078a734f57ac974ee5b54454470ff' + '9212a9c42ac8c9c7b9ba7378685b27e7ea0e7a8a8aaac1f3f4d37590ada3e991' + 'c9c2f02bce1e1e93d511aff73484208456835d4d7601a36ab4524939472fc401' '2bf3515ce9a3ee426c2632aa3355b2556ee8fe5dd8d88e088f90803e3d5f10a6' + 'b2413cabd8cca56e2d308ef5513edf1c7f909036ed2ccfeae17536a0e864dc96' ) prepare() { cd dxvk + # Uncomment to enable dxvk async patch. + # Enable at your own risk. If you don't know what it is, + # and its implications, leave it as is. You have been warned. + # I am not liable if anything happens to you by using it. + #patch -p1 -i "$srcdir"/dxvk-async.patch + #patch -p1 -i "$srcdir"/dxvk-async-conf.patch + # Export CFLAGS used by proton # -O2 is adjusted to -O3 since AVX is disabled # This overrides CFLAGS from makepkg.conf, if you comment these you are on your own @@ -36,11 +46,6 @@ prepare() { export CFLAGS="-O3 -march=nocona -mtune=core-avx2 -pipe" export CXXFLAGS="-O3 -march=nocona -mtune=core-avx2 -pipe" - # Uncomment to enable dxvk async patch. - # Enable at your own risk. If you don't know what it is, - # and its implications, leave it as is. You have been warned. - # I am not liable if anything happens to you by using it. - #patch -p1 -i "$srcdir"/dxvk-async.patch # Uncomment to enable extra optimizations # Patch crossfiles with extra optimizations from makepkg.conf patch -p1 -i "$srcdir"/dxvk-extraopts.patch diff --git a/dxvk-async-conf.patch b/dxvk-async-conf.patch new file mode 100644 index 000000000000..83b715546b6c --- /dev/null +++ b/dxvk-async-conf.patch @@ -0,0 +1,29 @@ +diff --git a/dxvk.conf b/dxvk.conf +index 9ca21a5e..abf0f2bf 100644 +--- a/dxvk.conf ++++ b/dxvk.conf +@@ -214,6 +214,24 @@ + # dxvk.hud = + + ++# Compile pipelines asynchronously if possible. This may reduce stuttering ++# in some games, but may also introduce rendering issues that might become ++# apparent over time. Do not report bugs with this option enabled. ++# ++# Supported values: True, False ++ ++# dxvk.enableAsync = True ++ ++ ++# Sets number of async compiler threads. ++# ++# Supported values: ++# - 0 to automatically determine the number of threads to use ++# - any positive number to enforce the thread count ++ ++# dxvk.numAsyncThreads = 0 ++ ++ + # Reported shader model + # + # The shader model to state that we support in the device diff --git a/dxvk-async.patch b/dxvk-async.patch deleted file mode 100644 index 016f8f06a122..000000000000 --- a/dxvk-async.patch +++ /dev/null @@ -1,523 +0,0 @@ -diff --git a/meson.build b/meson.build -index 8fa3ce61..5e4d32d1 100644 ---- a/meson.build -+++ b/meson.build -@@ -103,7 +103,7 @@ else - endif - - dxvk_version = vcs_tag( -- command: ['git', 'describe', '--dirty=+'], -+ command: ['git', 'describe', '--dirty=-async'], - input: 'version.h.in', - output: 'version.h') - -diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp -index 797c4e20..bda90275 100644 ---- a/src/dxvk/dxvk_context.cpp -+++ b/src/dxvk/dxvk_context.cpp -@@ -3837,7 +3837,9 @@ namespace dxvk { - : DxvkContextFlag::GpDirtyStencilRef); - - // Retrieve and bind actual Vulkan pipeline handle -- m_gpActivePipeline = m_state.gp.pipeline->getPipelineHandle(m_state.gp.state, m_state.om.framebuffer->getRenderPass()); -+ m_gpActivePipeline = m_state.gp.pipeline->getPipelineHandle(m_state.gp.state, -+ m_state.om.framebuffer->getRenderPass(), -+ this->checkAsyncCompilationCompat()); - - if (unlikely(!m_gpActivePipeline)) - return false; -@@ -4093,7 +4095,7 @@ namespace dxvk { - } - - -- void DxvkContext::updateFramebuffer() { -+ void DxvkContext::updateFramebuffer(bool isDraw) { - if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) { - m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer); - -@@ -4114,6 +4116,11 @@ namespace dxvk { - m_state.gp.state.omSwizzle[i] = DxvkOmAttachmentSwizzle(mapping); - } - -+ if (isDraw) { -+ for (uint32_t i = 0; i < fb->numAttachments(); i++) -+ fb->getAttachment(i).view->setRtBindingFrameId(m_device->getCurrentFrameId()); -+ } -+ - m_flags.set(DxvkContextFlag::GpDirtyPipelineState); - } - } -@@ -4343,7 +4350,7 @@ namespace dxvk { - } - - if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) -- this->updateFramebuffer(); -+ this->updateFramebuffer(true); - - if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)) - this->startRenderPass(); -@@ -4772,6 +4779,14 @@ namespace dxvk { - } - } - -+ bool DxvkContext::checkAsyncCompilationCompat() { -+ bool fbCompat = true; -+ for (uint32_t i = 0; fbCompat && i < m_state.om.framebuffer->numAttachments(); i++) { -+ const auto& attachment = m_state.om.framebuffer->getAttachment(i); -+ fbCompat &= attachment.view->getRtBindingAsyncCompilationCompat(); -+ } -+ return fbCompat; -+ } - - DxvkGraphicsPipeline* DxvkContext::lookupGraphicsPipeline( - const DxvkGraphicsPipelineShaders& shaders) { -diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h -index 2456b20a..d58f1021 100644 ---- a/src/dxvk/dxvk_context.h -+++ b/src/dxvk/dxvk_context.h -@@ -1159,7 +1159,7 @@ namespace dxvk { - VkDescriptorSet set, - const DxvkPipelineLayout* layout); - -- void updateFramebuffer(); -+ void updateFramebuffer(bool isDraw = false); - - void updateIndexBufferBinding(); - void updateVertexBufferBindings(); -@@ -1211,6 +1211,8 @@ namespace dxvk { - - void trackDrawBuffer(); - -+ bool checkAsyncCompilationCompat(); -+ - DxvkGraphicsPipeline* lookupGraphicsPipeline( - const DxvkGraphicsPipelineShaders& shaders); - -diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp -index 192e340b..96826600 100644 ---- a/src/dxvk/dxvk_graphics.cpp -+++ b/src/dxvk/dxvk_graphics.cpp -@@ -62,17 +62,21 @@ namespace dxvk { - - VkPipeline DxvkGraphicsPipeline::getPipelineHandle( - const DxvkGraphicsPipelineStateInfo& state, -- const DxvkRenderPass* renderPass) { -+ const DxvkRenderPass* renderPass, -+ bool async) { - DxvkGraphicsPipelineInstance* instance = nullptr; - -- { std::lock_guard<sync::Spinlock> lock(m_mutex); -+ { //std::lock_guard<sync::Spinlock> lock(m_mutex); - - instance = this->findInstance(state, renderPass); - - if (instance) - return instance->pipeline(); - -- instance = this->createInstance(state, renderPass); -+ if (async && m_pipeMgr->m_compiler != nullptr) -+ m_pipeMgr->m_compiler->queueCompilation(this, state, renderPass); -+ else -+ instance = this->createInstance(state, renderPass); - } - - if (!instance) -@@ -83,13 +87,13 @@ namespace dxvk { - } - - -- void DxvkGraphicsPipeline::compilePipeline( -+ bool DxvkGraphicsPipeline::compilePipeline( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass) { - std::lock_guard<sync::Spinlock> lock(m_mutex); - -- if (!this->findInstance(state, renderPass)) -- this->createInstance(state, renderPass); -+ return (this->findInstance(state, renderPass) == nullptr) && -+ (this->createInstance(state, renderPass) != nullptr); - } - - -@@ -103,6 +107,7 @@ namespace dxvk { - - VkPipeline newPipelineHandle = this->createPipeline(state, renderPass); - -+ std::lock_guard<sync::Spinlock> lock(m_mutex2); - m_pipeMgr->m_numGraphicsPipelines += 1; - return &m_pipelines.emplace_back(state, renderPass, newPipelineHandle); - } -@@ -111,6 +116,7 @@ namespace dxvk { - DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass) { -+ std::lock_guard<sync::Spinlock> lock(m_mutex2); - for (auto& instance : m_pipelines) { - if (instance.isCompatible(state, renderPass)) - return &instance; -diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h -index 4194599d..c48ee3ed 100644 ---- a/src/dxvk/dxvk_graphics.h -+++ b/src/dxvk/dxvk_graphics.h -@@ -185,11 +185,13 @@ namespace dxvk { - * state. If necessary, a new pipeline will be created. - * \param [in] state Pipeline state vector - * \param [in] renderPass The render pass -+ * \param [in] async Compile asynchronously - * \returns Pipeline handle - */ - VkPipeline getPipelineHandle( - const DxvkGraphicsPipelineStateInfo& state, -- const DxvkRenderPass* renderPass); -+ const DxvkRenderPass* renderPass, -+ bool async); - - /** - * \brief Compiles a pipeline -@@ -198,11 +200,16 @@ namespace dxvk { - * and stores the result for future use. - * \param [in] state Pipeline state vector - * \param [in] renderPass The render pass -+ * \returns \c true if compile succeeded - */ -- void compilePipeline( -+ bool compilePipeline( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass); - -+ void writePipelineStateToCache( -+ const DxvkGraphicsPipelineStateInfo& state, -+ const DxvkRenderPassFormat& format) const; -+ - private: - - Rc<vk::DeviceFn> m_vkd; -@@ -221,6 +228,7 @@ namespace dxvk { - - // List of pipeline instances, shared between threads - alignas(CACHE_LINE_SIZE) sync::Spinlock m_mutex; -+ alignas(CACHE_LINE_SIZE) sync::Spinlock m_mutex2; - std::vector<DxvkGraphicsPipelineInstance> m_pipelines; - - DxvkGraphicsPipelineInstance* createInstance( -@@ -248,10 +256,6 @@ namespace dxvk { - bool validatePipelineState( - const DxvkGraphicsPipelineStateInfo& state) const; - -- void writePipelineStateToCache( -- const DxvkGraphicsPipelineStateInfo& state, -- const DxvkRenderPassFormat& format) const; -- - void logPipelineState( - LogLevel level, - const DxvkGraphicsPipelineStateInfo& state) const; -diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h -index 19b5d85f..3da24c49 100644 ---- a/src/dxvk/dxvk_image.h -+++ b/src/dxvk/dxvk_image.h -@@ -465,6 +465,37 @@ namespace dxvk { - return result; - } - -+ /** -+ * \brief Sets render target usage frame number -+ * -+ * The image view will track internally when -+ * it was last used as a render target. This -+ * info is used for async shader compilation. -+ * \param [in] frameId Frame number -+ */ -+ void setRtBindingFrameId(uint32_t frameId) { -+ if (frameId != m_rtBindingFrameId) { -+ if (frameId == m_rtBindingFrameId + 1) -+ m_rtBindingFrameCount += 1; -+ else -+ m_rtBindingFrameCount = 0; -+ -+ m_rtBindingFrameId = frameId; -+ } -+ } -+ -+ /** -+ * \brief Checks for async pipeline compatibility -+ * -+ * Asynchronous pipeline compilation may be enabled if the -+ * render target has been drawn to in the previous frames. -+ * \param [in] frameId Current frame ID -+ * \returns \c true if async compilation is supported -+ */ -+ bool getRtBindingAsyncCompilationCompat() const { -+ return m_rtBindingFrameCount >= 5; -+ } -+ - private: - - Rc<vk::DeviceFn> m_vkd; -@@ -473,6 +504,9 @@ namespace dxvk { - DxvkImageViewCreateInfo m_info; - VkImageView m_views[ViewCount]; - -+ uint32_t m_rtBindingFrameId = 0; -+ uint32_t m_rtBindingFrameCount = 0; -+ - void createView(VkImageViewType type, uint32_t numLayers); - - }; -diff --git a/src/dxvk/dxvk_options.cpp b/src/dxvk/dxvk_options.cpp -index 73dd69d1..c3da6bb5 100644 ---- a/src/dxvk/dxvk_options.cpp -+++ b/src/dxvk/dxvk_options.cpp -@@ -10,6 +10,8 @@ namespace dxvk { - useRawSsbo = config.getOption<Tristate>("dxvk.useRawSsbo", Tristate::Auto); - useEarlyDiscard = config.getOption<Tristate>("dxvk.useEarlyDiscard", Tristate::Auto); - hud = config.getOption<std::string>("dxvk.hud", ""); -+ enableAsync = config.getOption<bool> ("dxvk.enableAsync", false); -+ numAsyncThreads = config.getOption<int32_t> ("dxvk.numAsyncThreads", 0); - } - - } -\ No newline at end of file -diff --git a/src/dxvk/dxvk_options.h b/src/dxvk/dxvk_options.h -index 3c5dde91..52a7be04 100644 ---- a/src/dxvk/dxvk_options.h -+++ b/src/dxvk/dxvk_options.h -@@ -21,6 +21,13 @@ namespace dxvk { - /// when using the state cache - int32_t numCompilerThreads; - -+ // Enable async pipelines -+ bool enableAsync; -+ -+ /// Number of compiler threads -+ /// when using async pipelines -+ int32_t numAsyncThreads; -+ - /// Shader-related options - Tristate useRawSsbo; - Tristate useEarlyDiscard; -diff --git a/src/dxvk/dxvk_pipecompiler.cpp b/src/dxvk/dxvk_pipecompiler.cpp -new file mode 100644 -index 00000000..40218acd ---- /dev/null -+++ b/src/dxvk/dxvk_pipecompiler.cpp -@@ -0,0 +1,76 @@ -+#include "dxvk_device.h" -+#include "dxvk_graphics.h" -+#include "dxvk_pipecompiler.h" -+ -+namespace dxvk { -+ -+ DxvkPipelineCompiler::DxvkPipelineCompiler(const DxvkDevice* device) { -+ 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 (device->config().numAsyncThreads > 0) -+ numWorkers = device->config().numAsyncThreads; -+ -+ Logger::info(str::format("DXVK: Using ", numWorkers, " async compiler threads")); -+ -+ // Start the compiler threads -+ m_compilerThreads.resize(numWorkers); -+ -+ for (uint32_t i = 0; i < numWorkers; i++) { -+ m_compilerThreads.at(i) = dxvk::thread( -+ [this] { this->runCompilerThread(); }); -+ } -+ } -+ -+ -+ DxvkPipelineCompiler::~DxvkPipelineCompiler() { -+ { std::lock_guard<std::mutex> lock(m_compilerLock); -+ m_compilerStop.store(true); -+ } -+ -+ m_compilerCond.notify_all(); -+ for (auto& thread : m_compilerThreads) -+ thread.join(); -+ } -+ -+ -+ void DxvkPipelineCompiler::queueCompilation( -+ DxvkGraphicsPipeline* pipeline, -+ const DxvkGraphicsPipelineStateInfo& state, -+ const DxvkRenderPass* renderPass) { -+ std::lock_guard<std::mutex> lock(m_compilerLock); -+ m_compilerQueue.push({ pipeline, state, renderPass }); -+ m_compilerCond.notify_one(); -+ } -+ -+ -+ void DxvkPipelineCompiler::runCompilerThread() { -+ env::setThreadName("dxvk-pcompiler"); -+ -+ while (!m_compilerStop.load()) { -+ PipelineEntry entry; -+ -+ { std::unique_lock<std::mutex> 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.renderPass != nullptr && -+ entry.pipeline->compilePipeline(entry.state, entry.renderPass)) { -+ entry.pipeline->writePipelineStateToCache(entry.state, entry.renderPass->format()); -+ } -+ } -+ } -+ -+} -diff --git a/src/dxvk/dxvk_pipecompiler.h b/src/dxvk/dxvk_pipecompiler.h -new file mode 100644 -index 00000000..d7fcc2cf ---- /dev/null -+++ b/src/dxvk/dxvk_pipecompiler.h -@@ -0,0 +1,61 @@ -+#pragma once -+ -+#include <atomic> -+#include <condition_variable> -+#include <mutex> -+#include <queue> -+ -+#include "../util/thread.h" -+#include "dxvk_include.h" -+ -+namespace dxvk { -+ -+ class DxvkDevice; -+ class DxvkGraphicsPipeline; -+ class DxvkGraphicsPipelineStateInfo; -+ -+ /** -+ * \brief Pipeline compiler -+ * -+ * Asynchronous pipeline compiler -+ */ -+ class DxvkPipelineCompiler : public RcObject { -+ -+ public: -+ -+ DxvkPipelineCompiler(const DxvkDevice* device); -+ ~DxvkPipelineCompiler(); -+ -+ /** -+ * \brief Compiles a pipeline asynchronously -+ * -+ * This should be used to compile graphics -+ * pipeline instances asynchronously. -+ * \param [in] pipeline The pipeline object -+ * \param [in] state The pipeline state info object -+ * \param [in] renderPass -+ */ -+ void queueCompilation( -+ DxvkGraphicsPipeline* pipeline, -+ const DxvkGraphicsPipelineStateInfo& state, -+ const DxvkRenderPass* renderPass); -+ -+ private: -+ -+ struct PipelineEntry { -+ DxvkGraphicsPipeline* pipeline = nullptr; -+ DxvkGraphicsPipelineStateInfo state; -+ const DxvkRenderPass* renderPass = nullptr; -+ }; -+ -+ std::atomic<bool> m_compilerStop = { false }; -+ std::mutex m_compilerLock; -+ std::condition_variable m_compilerCond; -+ std::queue<PipelineEntry> m_compilerQueue; -+ std::vector<dxvk::thread> m_compilerThreads; -+ -+ void runCompilerThread(); -+ -+ }; -+ -+} -diff --git a/src/dxvk/dxvk_pipemanager.cpp b/src/dxvk/dxvk_pipemanager.cpp -index 2e29202e..1e767381 100644 ---- a/src/dxvk/dxvk_pipemanager.cpp -+++ b/src/dxvk/dxvk_pipemanager.cpp -@@ -9,7 +9,11 @@ namespace dxvk { - DxvkRenderPassPool* passManager) - : m_device (device), - m_cache (new DxvkPipelineCache(device->vkd())) { -+ std::string useAsync = env::getEnvVar("DXVK_ASYNC"); - std::string useStateCache = env::getEnvVar("DXVK_STATE_CACHE"); -+ -+ if (useAsync == "1" || device->config().enableAsync) -+ m_compiler = new DxvkPipelineCompiler(device); - - if (useStateCache != "0" && device->config().enableStateCache) - m_stateCache = new DxvkStateCache(device, this, passManager); -diff --git a/src/dxvk/dxvk_pipemanager.h b/src/dxvk/dxvk_pipemanager.h -index 858928ca..4c12a4dc 100644 ---- a/src/dxvk/dxvk_pipemanager.h -+++ b/src/dxvk/dxvk_pipemanager.h -@@ -6,6 +6,7 @@ - - #include "dxvk_compute.h" - #include "dxvk_graphics.h" -+#include "dxvk_pipecompiler.h" - - namespace dxvk { - -@@ -95,6 +96,7 @@ namespace dxvk { - const DxvkDevice* m_device; - Rc<DxvkPipelineCache> m_cache; - Rc<DxvkStateCache> m_stateCache; -+ Rc<DxvkPipelineCompiler> m_compiler; - - std::atomic<uint32_t> m_numComputePipelines = { 0 }; - std::atomic<uint32_t> m_numGraphicsPipelines = { 0 }; -diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build -index 1dc113c3..003fb1a7 100644 ---- a/src/dxvk/meson.build -+++ b/src/dxvk/meson.build -@@ -83,6 +83,7 @@ dxvk_src = files([ - 'dxvk_openvr.cpp', - 'dxvk_options.cpp', - 'dxvk_pipecache.cpp', -+ 'dxvk_pipecompiler.cpp', - 'dxvk_pipelayout.cpp', - 'dxvk_pipemanager.cpp', - 'dxvk_queue.cpp', -diff --git a/dxvk.conf b/dxvk.conf -index 9ca21a5e..abf0f2bf 100644 ---- a/dxvk.conf -+++ b/dxvk.conf -@@ -214,6 +214,24 @@ - # dxvk.hud = - - -+# Compile pipelines asynchronously if possible. This may reduce stuttering -+# in some games, but may also introduce rendering issues that might become -+# apparent over time. Do not report bugs with this option enabled. -+# -+# Supported values: True, False -+ -+# dxvk.enableAsync = True -+ -+ -+# Sets number of async compiler threads. -+# -+# Supported values: -+# - 0 to automatically determine the number of threads to use -+# - any positive number to enforce the thread count -+ -+# dxvk.numAsyncThreads = 0 -+ -+ - # Reported shader model - # - # The shader model to state that we support in the device |