summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO31
-rw-r--r--PKGBUILD132
-rw-r--r--dxvk-async.patch446
-rw-r--r--dxvk-extraopts.patch34
-rw-r--r--extraopts.patch70
-rw-r--r--setup_dxvk2
-rwxr-xr-xsetup_dxvk.sh236
7 files changed, 358 insertions, 593 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 519797156c5f..70bf2e92bc7d 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,7 +1,7 @@
pkgbase = dxvk-mingw
pkgdesc = Vulkan-based implementation of D3D9, D3D10 and D3D11 for Linux / Wine, MingW version
- pkgver = 1.6.1
- pkgrel = 2
+ pkgver = 2.3.1
+ pkgrel = 1
url = https://github.com/doitsujin/dxvk
arch = x86_64
license = zlib/libpng
@@ -10,23 +10,24 @@ pkgbase = dxvk-mingw
makedepends = glslang
makedepends = git
makedepends = mingw-w64-gcc
- depends = vulkan-icd-loader
- depends = wine>=4.0rc1
- depends = lib32-vulkan-icd-loader
- depends = bash
provides = dxvk
provides = d9vk
- provides = dxvk=1.6.1
+ provides = dxvk=2.3.1
conflicts = dxvk
conflicts = d9vk
- source = git+https://github.com/doitsujin/dxvk.git#tag=v1.6.1
+ options = !lto
+ options = !staticlibs
+ source = git+https://github.com/doitsujin/dxvk.git#tag=v2.3.1
+ source = dxvk-extraopts.patch
+ source = setup_dxvk.sh
source = setup_dxvk
- source = dxvk-async.patch
- source = extraopts.patch
- sha256sums = SKIP
- sha256sums = b2413cabd8cca56e2d308ef5513edf1c7f909036ed2ccfeae17536a0e864dc96
- sha256sums = 6ff286091c20327e67252e1e6812830a42c990d1ee56541023eb217712209f3c
- sha256sums = acde3a23166f79fa87ab090200be2aabaf16e5876ce19b8270ad1179bb0bc7a5
+ sha256sums = 203b336366b16612b01bc5c220bdeeee633e6fdbf15f23559c826eac7b59beeb
+ sha256sums = bcc15521e4c7f966a0192a1dabb7fb4935b33db39344ab5b861f9d81486f1362
+ sha256sums = c3daf448a0460f36ac471d2d4982874207888148ac3f03fbc2f003eccc2c2a45
+ sha256sums = c1f6a18b03d1612b60f8081428f00cfac5e66315fe9d42719f01cf5564deeeff
pkgname = dxvk-mingw
-
+ depends = vulkan-icd-loader
+ depends = lib32-vulkan-icd-loader
+ depends = wine
+ depends = bash
diff --git a/PKGBUILD b/PKGBUILD
index 68866a736724..52074e362ded 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,102 +1,112 @@
# Maintainer: loathingkernel <loathingkernel @at gmail .dot com>
pkgname=dxvk-mingw
-pkgver=1.6.1
-pkgrel=2
+pkgver=2.3.1
+pkgrel=1
pkgdesc='Vulkan-based implementation of D3D9, D3D10 and D3D11 for Linux / Wine, MingW version'
arch=('x86_64')
url="https://github.com/doitsujin/dxvk"
license=('zlib/libpng')
-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 !staticlibs)
source=(
"git+https://github.com/doitsujin/dxvk.git#tag=v$pkgver"
+ "dxvk-extraopts.patch"
+ "setup_dxvk.sh"
"setup_dxvk"
- "dxvk-async.patch"
- "extraopts.patch"
-)
-sha256sums=(
- "SKIP"
- "b2413cabd8cca56e2d308ef5513edf1c7f909036ed2ccfeae17536a0e864dc96"
- "6ff286091c20327e67252e1e6812830a42c990d1ee56541023eb217712209f3c"
- "acde3a23166f79fa87ab090200be2aabaf16e5876ce19b8270ad1179bb0bc7a5"
)
prepare() {
cd dxvk
+ # Explicitly set origin URL for submodules using relative paths
+ git remote set-url origin https://github.com/doitsujin/dxvk.git
+ git submodule update --init --filter=tree:0 --recursive
+
# Uncomment to enable extra optimizations
# Patch crossfiles with extra optimizations from makepkg.conf
- patch -p1 -i "$srcdir"/extraopts.patch
- local dxvk_cflags="$CFLAGS"
- local dxvk_ldflags="$LDFLAGS"
- # Filter known bad flags before applying optimizations
- # If using -march=native and the CPU supports AVX, launching a d3d9
- # game can cause an Unhandled exception. The cause seems to be the
- # combination of AVX instructions and tree vectorization (implied by O3),
- # all tested archictures from sandybridge to haswell are affected.
- # Disabling AVX (and AVX2 as a side-effect).
- # Relevant Wine issues
- # https://bugs.winehq.org/show_bug.cgi?id=45289
- # https://bugs.winehq.org/show_bug.cgi?id=43516
- dxvk_cflags+=" -mno-avx"
- # Filter fstack-protector{ ,-all,-strong} flag for MingW.
- # https://github.com/Joshua-Ashton/d9vk/issues/476
- #dxvk_cflags+=" -fno-stack-protector"
- dxvk_cflags="${dxvk_cflags// -fstack-protector*([\-all|\-strong])/}"
- # Adjust optimization level in meson arguments. This is ignored
- # anyway because meson sets its own optimization level.
- dxvk_cflags="${dxvk_cflags// -O+([0-3s]|fast)/}"
- # Doesn't compile with these flags in MingW so remove them.
- # They are also filtered in Wine PKGBUILDs so remove them
- # for winelib versions too.
- dxvk_cflags="${dxvk_cflags/ -fno-plt/}"
- dxvk_ldflags="${dxvk_ldflags/,-z,now/}"
- dxvk_ldflags="${dxvk_ldflags/,-z,relro/}"
+ patch -p1 -i "$srcdir"/dxvk-extraopts.patch
+
+ # By default export FLAGS used by proton and ignore makepkg
+ # This overrides FLAGS from makepkg.conf, if you comment these you are on your own
+ # If you want the "best" possible optimizations for your system you can use
+ # `-march=native` and remove the `-mtune=core-avx2` option.
+
+ local -a split=($CFLAGS)
+ local -A flags
+ for opt in "${split[@]}"; do flags["${opt%%=*}"]="${opt##*=}"; done
+ local march="${flags["-march"]:-nocona}"
+ local mtune="generic" #"${flags["-mtune"]:-core-avx2}"
+
+ CFLAGS="-O3 -march=$march -mtune=$mtune -pipe"
+ CXXFLAGS="-O3 -march=$march -mtune=$mtune -pipe"
+ LDFLAGS="-Wl,-O1,--sort-common,--as-needed"
+
+ # These flags are taken from Proton
+ CFLAGS+=" -mfpmath=sse -fwrapv -fno-strict-aliasing"
+ CXXFLAGS+=" -mfpmath=sse -fwrapv -fno-strict-aliasing -std=c++17"
+ LDFLAGS+=" -Wl,--file-alignment,4096"
+
+ # AVX is "hard" disabled for 32bit in any case.
+ # AVX/AVX2 for 64bit is disabled below.
+ # Seems unnecessery for 64bit if -mtune=generic is used
+ #CFLAGS+=" -mno-avx2 -mno-avx"
+ #CXXFLAGS+=" -mno-avx2 -mno-avx"
+
+ export CFLAGS CXXFLAGS LDFLAGS
+
+ local cross_ldflags="$LDFLAGS"
+
+ local cross_cflags="$CFLAGS -mcmodel=small"
+ local cross_cxxflags="$CXXFLAGS -mcmodel=small"
sed -i build-win64.txt \
- -e "s|@CARGS@|\'${dxvk_cflags// /\',\'}\'|g" \
- -e "s|@LDARGS@|\'${dxvk_ldflags// /\',\'}\'|g"
+ -e "s|@CARGS@|\'${cross_cflags// /\',\'}\'|g" \
+ -e "s|@CXXARGS@|\'${cross_cxxflags// /\',\'}\'|g" \
+ -e "s|@LDARGS@|\'${cross_ldflags// /\',\'}\'|g"
+
+ local cross_cflags="$CFLAGS -mstackrealign -mno-avx"
+ local cross_cxxflags="$CXXFLAGS -mstackrealign -mno-avx"
sed -i build-win32.txt \
- -e "s|@CARGS@|\'${dxvk_cflags// /\',\'}\'|g" \
- -e "s|@LDARGS@|\'${dxvk_ldflags// /\',\'}\'|g"
-
- # 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 enables async by default. YOU HAVE BEEN WARNED.
- #patch -p1 -i "$srcdir"/dxvk-async.patch
+ -e "s|@CARGS@|\'${cross_cflags// /\',\'}\'|g" \
+ -e "s|@CXXARGS@|\'${cross_cxxflags// /\',\'}\'|g" \
+ -e "s|@LDARGS@|\'${cross_ldflags// /\',\'}\'|g"
}
build() {
- meson dxvk "build/x64" \
+ meson setup dxvk "build/x64" \
--cross-file dxvk/build-win64.txt \
--prefix "/usr/share/dxvk/x64" \
--bindir "" --libdir "" \
- --buildtype "release" \
- --optimization=3 \
- --strip \
- -Denable_tests=false
+ --buildtype "plain" \
+ --force-fallback-for=libdisplay-info \
+ --strip
ninja -C "build/x64" -v
- meson dxvk "build/x32" \
+ meson setup dxvk "build/x32" \
--cross-file dxvk/build-win32.txt \
--prefix "/usr/share/dxvk/x32" \
--bindir "" --libdir "" \
- --buildtype "release" \
- --optimization=3 \
- --strip \
- -Denable_tests=false
+ --buildtype "plain" \
+ --force-fallback-for=libdisplay-info \
+ --strip
ninja -C "build/x32" -v
}
package() {
+ depends=('vulkan-icd-loader' 'lib32-vulkan-icd-loader' 'wine' 'bash')
+
DESTDIR="$pkgdir" ninja -C "build/x32" install
DESTDIR="$pkgdir" ninja -C "build/x64" install
- install -Dm 755 -t "$pkgdir/usr/share/dxvk" dxvk/setup_dxvk.sh
- install -Dm 644 -t "$pkgdir/usr/share/doc/dxvk" dxvk/dxvk.conf
- install -Dm 644 -t "$pkgdir/usr/share/$pkgname" dxvk/LICENSE
+ install -Dm 755 -t "$pkgdir/usr/share/dxvk" setup_dxvk.sh
+ install -Dm 644 -t "$pkgdir/usr/share/dxvk" dxvk/dxvk.conf
+ install -Dm 644 -t "$pkgdir/usr/share/doc/$pkgname" dxvk/README.md
+ install -Dm 644 -t "$pkgdir/usr/share/licenses/$pkgname" dxvk/LICENSE
install -Dm 755 -t "$pkgdir/usr/bin" setup_dxvk
}
+
+sha256sums=('203b336366b16612b01bc5c220bdeeee633e6fdbf15f23559c826eac7b59beeb'
+ 'bcc15521e4c7f966a0192a1dabb7fb4935b33db39344ab5b861f9d81486f1362'
+ 'c3daf448a0460f36ac471d2d4982874207888148ac3f03fbc2f003eccc2c2a45'
+ 'c1f6a18b03d1612b60f8081428f00cfac5e66315fe9d42719f01cf5564deeeff')
diff --git a/dxvk-async.patch b/dxvk-async.patch
deleted file mode 100644
index 19c506c4964f..000000000000
--- a/dxvk-async.patch
+++ /dev/null
@@ -1,446 +0,0 @@
-From dfac76f528d0fc88ecbfe27ccb87483840828b9b Mon Sep 17 00:00:00 2001
-From: Tk-Glitch <ti3nou@gmail.com>
-Date: Sat, 28 Sep 2019 18:59:04 +0200
-Subject: Async pipecompiler rebase against DXVK
- d128d776ad906d6b8d3941eda7b7ee679346dbaf
-
-
-diff --git a/meson.build b/meson.build
-index 9a519e46..dea82ee1 100644
---- a/meson.build
-+++ b/meson.build
-@@ -101,7 +101,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 b4f679fa..13c86d8f 100644
---- a/src/dxvk/dxvk_context.cpp
-+++ b/src/dxvk/dxvk_context.cpp
-@@ -606,7 +606,7 @@ namespace dxvk {
- const Rc<DxvkImageView>& imageView,
- VkImageAspectFlags clearAspects,
- VkClearValue clearValue) {
-- this->updateFramebuffer();
-+ this->updateFramebuffer(false);
-
- // Prepare attachment ops
- DxvkColorAttachmentOps colorOp;
-@@ -2433,7 +2433,7 @@ namespace dxvk {
- VkExtent3D extent,
- VkImageAspectFlags aspect,
- VkClearValue value) {
-- this->updateFramebuffer();
-+ this->updateFramebuffer(false);
-
- // Find out if the render target view is currently bound,
- // so that we can avoid spilling the render pass if it is.
-@@ -3652,7 +3652,7 @@ 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;
-@@ -3969,7 +3969,7 @@ namespace dxvk {
- }
-
-
-- void DxvkContext::updateFramebuffer() {
-+ void DxvkContext::updateFramebuffer(bool isDraw) {
- if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) {
- m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer);
-
-@@ -3988,6 +3988,11 @@ namespace dxvk {
- : VkComponentMapping();
- }
-
-+ if (isDraw) {
-+ for (uint32_t i = 0; i < fb->numAttachments(); i++)
-+ fb->getAttachment(i).view->setRtBindingFrameId(m_device->getCurrentFrameId());
-+ }
-+
- m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
- }
- }
-@@ -4205,7 +4210,7 @@ namespace dxvk {
- template<bool Indexed>
- void DxvkContext::commitGraphicsState() {
- if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer))
-- this->updateFramebuffer();
-+ this->updateFramebuffer(true);
-
- if (!m_flags.test(DxvkContextFlag::GpRenderPassBound))
- this->startRenderPass();
-@@ -4465,4 +4470,13 @@ namespace dxvk {
- }
- }
-
--}
-\ No newline at end of file
-+
-+ 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;
-+ }
-+}
-diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h
-index f54f5321..0984d085 100644
---- a/src/dxvk/dxvk_context.h
-+++ b/src/dxvk/dxvk_context.h
-@@ -1141,7 +1141,7 @@ namespace dxvk {
- VkDescriptorSet set,
- const DxvkPipelineLayout* layout);
-
-- void updateFramebuffer();
-+ void updateFramebuffer(bool isDraw);
-
- void updateIndexBufferBinding();
- void updateVertexBufferBindings();
-@@ -1180,6 +1180,7 @@ namespace dxvk {
-
- void trackDrawBuffer();
-
-+ bool checkAsyncCompilationCompat();
- };
-
--}
-\ No newline at end of file
-+}
-diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp
-index 5e05b425..8586c794 100644
---- a/src/dxvk/dxvk_graphics.cpp
-+++ b/src/dxvk/dxvk_graphics.cpp
-@@ -75,8 +75,6 @@ namespace dxvk {
-
-
- DxvkGraphicsPipeline::~DxvkGraphicsPipeline() {
-- for (const auto& instance : m_pipelines)
-- this->destroyPipeline(instance.pipeline());
- }
-
-
-@@ -96,7 +94,8 @@ 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);
-@@ -105,10 +104,13 @@ namespace dxvk {
-
- 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)
- return VK_NULL_HANDLE;
-
-diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h
-index 168e9714..07f0883d 100644
---- a/src/dxvk/dxvk_graphics.h
-+++ b/src/dxvk/dxvk_graphics.h
-@@ -247,11 +247,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
-diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h
-index 8f82d65a..156f6054 100644
---- a/src/dxvk/dxvk_image.h
-+++ b/src/dxvk/dxvk_image.h
-@@ -442,6 +442,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;
-@@ -450,6 +481,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 394feabb..df05ecd8 100644
---- a/src/dxvk/dxvk_options.cpp
-+++ b/src/dxvk/dxvk_options.cpp
-@@ -5,6 +5,7 @@ namespace dxvk {
- DxvkOptions::DxvkOptions(const Config& config) {
- enableStateCache = config.getOption<bool> ("dxvk.enableStateCache", true);
- enableOpenVR = config.getOption<bool> ("dxvk.enableOpenVR", true);
-+ useAsync = config.getOption<bool> ("dxvk.useAsync", true);
- numCompilerThreads = config.getOption<int32_t> ("dxvk.numCompilerThreads", 0);
- asyncPresent = config.getOption<Tristate>("dxvk.asyncPresent", Tristate::Auto);
- useRawSsbo = config.getOption<Tristate>("dxvk.useRawSsbo", Tristate::Auto);
-diff --git a/src/dxvk/dxvk_options.h b/src/dxvk/dxvk_options.h
-index 447294b5..571d6c15 100644
---- a/src/dxvk/dxvk_options.h
-+++ b/src/dxvk/dxvk_options.h
-@@ -10,6 +10,7 @@ namespace dxvk {
-
- /// Enable state cache
- bool enableStateCache;
-+ bool useAsync;
-
- /// Use transfer queue if available
- bool enableTransferQueue;
-diff --git a/src/dxvk/dxvk_pipecompiler.cpp b/src/dxvk/dxvk_pipecompiler.cpp
-new file mode 100644
-index 00000000..cfef228a
---- /dev/null
-+++ b/src/dxvk/dxvk_pipecompiler.cpp
-@@ -0,0 +1,69 @@
-+#include "dxvk_graphics.h"
-+#include "dxvk_pipecompiler.h"
-+
-+namespace dxvk {
-+
-+ DxvkPipelineCompiler::DxvkPipelineCompiler() {
-+ uint32_t sysCpuCount = dxvk::thread::hardware_concurrency();
-+ uint32_t threadCount = sysCpuCount > 2 ? sysCpuCount - 2 : 1;
-+
-+ Logger::info(str::format(
-+ "DxvkPipelineCompiler: Using ",
-+ threadCount, " workers"));
-+
-+ // Start the compiler threads
-+ m_compilerThreads.resize(threadCount);
-+
-+ for (uint32_t i = 0; i < threadCount; i++) {
-+ m_compilerThreads.at(i) = dxvk::thread(
-+ [this] { this->runCompilerThread(); });
-+ }
-+ }
-+
-+
-+ DxvkPipelineCompiler::~DxvkPipelineCompiler() {
-+ { std::unique_lock<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::unique_lock<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);
-+ }
-+ }
-+
-+}
-diff --git a/src/dxvk/dxvk_pipecompiler.h b/src/dxvk/dxvk_pipecompiler.h
-new file mode 100644
-index 00000000..a82fff60
---- /dev/null
-+++ b/src/dxvk/dxvk_pipecompiler.h
-@@ -0,0 +1,60 @@
-+#pragma once
-+
-+#include <atomic>
-+#include <condition_variable>
-+#include <mutex>
-+#include <queue>
-+
-+#include "../util/thread.h"
-+#include "dxvk_include.h"
-+
-+namespace dxvk {
-+
-+ class DxvkGraphicsPipeline;
-+ class DxvkGraphicsPipelineStateInfo;
-+
-+ /**
-+ * \brief Pipeline compiler
-+ *
-+ * Asynchronous pipeline compiler
-+ */
-+ class DxvkPipelineCompiler : public RcObject {
-+
-+ public:
-+
-+ DxvkPipelineCompiler();
-+ ~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 378bb3d1..3323f926 100644
---- a/src/dxvk/dxvk_pipemanager.cpp
-+++ b/src/dxvk/dxvk_pipemanager.cpp
-@@ -45,9 +45,13 @@ namespace dxvk {
- : m_device (device),
- m_cache (new DxvkPipelineCache(device->vkd())) {
- std::string useStateCache = env::getEnvVar("DXVK_STATE_CACHE");
-+ std::string useAsync = env::getEnvVar("DXVK_ASYNC");
-
- if (useStateCache != "0" && device->config().enableStateCache)
- m_stateCache = new DxvkStateCache(device, this, passManager);
-+
-+ if (useAsync != "0" || device->config().useAsync)
-+ m_compiler = new DxvkPipelineCompiler();
- }
-
-
-diff --git a/src/dxvk/dxvk_pipemanager.h b/src/dxvk/dxvk_pipemanager.h
-index f0087d15..29e758c7 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 {
-
-@@ -107,6 +108,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 867f3002..f4c4336c 100644
---- a/src/dxvk/meson.build
-+++ b/src/dxvk/meson.build
-@@ -82,6 +82,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-extraopts.patch b/dxvk-extraopts.patch
new file mode 100644
index 000000000000..49a77f486f42
--- /dev/null
+++ b/dxvk-extraopts.patch
@@ -0,0 +1,34 @@
+diff --git a/build-win32.txt b/build-win32.txt
+index a1406832..748f5c1e 100644
+--- a/build-win32.txt
++++ b/build-win32.txt
+@@ -4,6 +4,12 @@ cpp = 'i686-w64-mingw32-g++'
+ ar = 'i686-w64-mingw32-ar'
+ strip = 'i686-w64-mingw32-strip'
+
++[built-in options]
++c_args=[@CARGS@]
++cpp_args=[@CXXARGS@]
++c_link_args = [@LDARGS@]
++cpp_link_args = [@LDARGS@]
++
+ [properties]
+ needs_exe_wrapper = true
+
+diff --git a/build-win64.txt b/build-win64.txt
+index 1aee4626..7d2e84f4 100644
+--- a/build-win64.txt
++++ b/build-win64.txt
+@@ -4,6 +4,12 @@ cpp = 'x86_64-w64-mingw32-g++'
+ ar = 'x86_64-w64-mingw32-ar'
+ strip = 'x86_64-w64-mingw32-strip'
+
++[built-in options]
++c_args=[@CARGS@]
++cpp_args=[@CXXARGS@]
++c_link_args = [@LDARGS@]
++cpp_link_args = [@LDARGS@]
++
+ [properties]
+ needs_exe_wrapper = true
+
diff --git a/extraopts.patch b/extraopts.patch
deleted file mode 100644
index 43a8fd6d10ec..000000000000
--- a/extraopts.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-diff --git a/build-win32.txt b/build-win32.txt
-index 0865fc5e..b93a280f 100644
---- a/build-win32.txt
-+++ b/build-win32.txt
-@@ -5,10 +5,10 @@ ar = 'i686-w64-mingw32-ar'
- strip = 'i686-w64-mingw32-strip'
-
- [properties]
--c_args=['-msse', '-msse2']
--cpp_args=['-msse', '-msse2']
--c_link_args = ['-static', '-static-libgcc']
--cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++']
-+c_args=['-msse', '-msse2', @CARGS@]
-+cpp_args=['-msse', '-msse2', @CARGS@]
-+c_link_args = ['-static', '-static-libgcc', @LDARGS@]
-+cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++', @LDARGS@]
- needs_exe_wrapper = true
-
- [host_machine]
-diff --git a/build-win64.txt b/build-win64.txt
-index 2a7fbee3..9e3bfc2e 100644
---- a/build-win64.txt
-+++ b/build-win64.txt
-@@ -5,8 +5,10 @@ ar = 'x86_64-w64-mingw32-ar'
- strip = 'x86_64-w64-mingw32-strip'
-
- [properties]
--c_link_args = ['-static', '-static-libgcc']
--cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++']
-+c_args=[@CARGS@]
-+cpp_args=[@CARGS@]
-+c_link_args = ['-static', '-static-libgcc', @LDARGS@]
-+cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++', @LDARGS@]
- needs_exe_wrapper = true
-
- [host_machine]
-diff --git a/build-wine32.txt b/build-wine32.txt
-index ba8d34a8..ecec2eb4 100644
---- a/build-wine32.txt
-+++ b/build-wine32.txt
-@@ -7,9 +7,9 @@ strip = 'strip'
- [properties]
- needs_exe_wrapper = true
-
--c_args=['-m32', '-msse', '-msse2', '-fvisibility=hidden']
--cpp_args=['-m32', '-msse', '-msse2', '-fvisibility=hidden', '-fvisibility-inlines-hidden', '-D__WIDL_objidl_generated_name_0000000C=']
--cpp_link_args=['-m32', '-mwindows']
-+c_args=['-m32', '-msse', '-msse2', '-fvisibility=hidden', @CARGS@]
-+cpp_args=['-m32', '-msse', '-msse2', '-fvisibility=hidden', '-fvisibility-inlines-hidden', '-D__WIDL_objidl_generated_name_0000000C=', @CARGS@]
-+cpp_link_args=['-m32', '-mwindows', @LDARGS@]
-
- [host_machine]
- system = 'linux'
-diff --git a/build-wine64.txt b/build-wine64.txt
-index b3e028bb..fb9d98fd 100644
---- a/build-wine64.txt
-+++ b/build-wine64.txt
-@@ -7,9 +7,9 @@ strip = 'strip'
- [properties]
- needs_exe_wrapper = true
-
--c_args=['-m64', '-fvisibility=hidden']
--cpp_args=['-m64', '-fvisibility=hidden', '-fvisibility-inlines-hidden', '-D__WIDL_objidl_generated_name_0000000C=']
--cpp_link_args=['-m64', '-mwindows']
-+c_args=['-m64', '-fvisibility=hidden', @CARGS@]
-+cpp_args=['-m64', '-fvisibility=hidden', '-fvisibility-inlines-hidden', '-D__WIDL_objidl_generated_name_0000000C=', @CARGS@]
-+cpp_link_args=['-m64', '-mwindows', @LDARGS@]
-
- [host_machine]
- system = 'linux'
diff --git a/setup_dxvk b/setup_dxvk
index 01a7b908b232..e162b8da6e84 100644
--- a/setup_dxvk
+++ b/setup_dxvk
@@ -1,2 +1,2 @@
#!/bin/sh
-/usr/share/dxvk/setup_dxvk.sh $1 --symlink
+/usr/share/dxvk/setup_dxvk.sh $@
diff --git a/setup_dxvk.sh b/setup_dxvk.sh
new file mode 100755
index 000000000000..773a141b697c
--- /dev/null
+++ b/setup_dxvk.sh
@@ -0,0 +1,236 @@
+#!/usr/bin/env bash
+
+# default directories
+dxvk_lib32=${dxvk_lib32:-"x32"}
+dxvk_lib64=${dxvk_lib64:-"x64"}
+
+# figure out where we are
+basedir="$(dirname "$(readlink -f "$0")")"
+
+# figure out which action to perform
+action="$1"
+
+case "$action" in
+install)
+ ;;
+uninstall)
+ ;;
+*)
+ echo "Unrecognized action: $action"
+ echo "Usage: $0 [install|uninstall] [--without-dxgi] [--symlink]"
+ exit 1
+esac
+
+# process arguments
+shift
+
+with_dxgi=true
+file_cmd="cp -v --reflink=auto"
+
+while (($# > 0)); do
+ case "$1" in
+ "--without-dxgi")
+ with_dxgi=false
+ ;;
+ "--symlink")
+ file_cmd="ln -s -v"
+ ;;
+ esac
+ shift
+done
+
+# check wine prefix before invoking wine, so that we
+# don't accidentally create one if the user screws up
+if [ -n "$WINEPREFIX" ] && ! [ -f "$WINEPREFIX/system.reg" ]; then
+ echo "$WINEPREFIX:"' Not a valid wine prefix.' >&2
+ exit 1
+fi
+
+# find wine executable
+export WINEDEBUG=-all
+# disable mscoree and mshtml to avoid downloading
+# wine gecko and mono
+export WINEDLLOVERRIDES="mscoree,mshtml="
+
+wineserver="wineserver"
+
+# $PATH is the way for user to control where wine is located (including custom Wine versions).
+# Pure 64-bit Wine (non Wow64) requires skipping 32-bit steps.
+# In such case, wine64 and winebooot will be present, but wine binary will be missing,
+# however it can be present in other PATHs, so it shouldn't be used, to avoid versions mixing.
+wine_path=$(dirname "$(which $wineserver)")
+wine="$wine_path/wine"
+wine64="$wine_path/wine64"
+wineboot="$wine_path/wineboot"
+
+# Thank you winetricks!
+get_file_arch()
+{
+ _W_file="$1"
+ # Assume ELF binaries for everything else
+ _W_ob_output="$(od -An -t x1 -j 0x12 -N 1 "${_W_file}" | tr -d "[:space:]")"
+ case "${_W_ob_output}" in
+ "3e") _W_file_arch="x86_64" ;;
+ "03"|"06") _W_file_arch="i386" ;;
+ *) _W_file_arch="" ;;
+ esac
+
+ echo "${_W_file_arch}"
+}
+
+if [ -z "$WINEARCH" ]; then
+ wine_arch=$(get_file_arch "$wine")
+ wine64_arch=$(get_file_arch "$wine64")
+ if [ "$wine_arch" == "x86_64" ] || [ "$wine64_arch" == "x86_64" ]; then
+ arch=win64
+ elif [ "$wine_arch" == "i386" ] && [ "$wine64_arch" == "" ]; then
+ arch=win32
+ fi
+else
+ arch="$WINEARCH"
+fi
+
+if ! [ -f "$wine64" ]; then
+ wine64="$wine"
+fi
+
+if [ "$arch" == "win32" ]; then
+ wine64="$wine"
+fi
+
+# resolve 32-bit and 64-bit system32 path
+wine_ver="$($wineserver --version 2>&1 >/dev/null | grep Wine)"
+if [ -z "$wine_ver" ]; then
+ echo "$wineserver:"' Not a wine executable. Check your wine install.' >&2
+ exit 1
+fi
+
+# ensure wine placeholder dlls are recreated
+# if they are missing
+$wineboot -u
+
+system32_path=$($wine64 winepath.exe -u 'C:\windows\system32' 2> /dev/null)
+system32_path="${system32_path/$'\r'/}"
+syswow64_path=$($wine64 winepath.exe -u 'C:\windows\syswow64' 2> /dev/null)
+syswow64_path="${syswow64_path/$'\r'/}"
+
+if [ -z "$syswow64_path" ] && [ -z "$system32_path" ]; then
+ echo 'Failed to resolve C:\windows\system32.' >&2
+ exit 1
+fi
+
+# create native dll override
+overrideDll() {
+ if ! $wine64 reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v "$1" /d native /f >/dev/null 2>&1; then
+ echo -e "Failed to add override for $1"
+ exit 1
+ fi
+}
+
+# remove dll override
+restoreDll() {
+ if ! $wine64 reg delete 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v "$1" /f >/dev/null 2>&1; then
+ echo "Failed to remove override for $1"
+ fi
+}
+
+# copy or link dxvk dll, back up original file
+installFile() {
+ dstfile="${1}/${3}.dll"
+ srcfile="${basedir}/${2}/${3}.dll"
+
+ if ! [ -f "${srcfile}" ]; then
+ echo "${srcfile}: File not found. Skipping." >&2
+ return 1
+ fi
+
+ if [ -n "$1" ]; then
+ if [ -f "${dstfile}" ] || [ -h "${dstfile}" ]; then
+ if ! [ -f "${dstfile}.old" ]; then
+ mv -v "${dstfile}" "${dstfile}.old"
+ else
+ rm -v "${dstfile}"
+ fi
+ else
+ touch "${dstfile}.old_none"
+ fi
+ $file_cmd "${srcfile}" "${dstfile}"
+ fi
+ return 0
+}
+
+# remove dxvk dll, restore original file
+uninstallFile() {
+ dstfile="${1}/${3}.dll"
+ srcfile="${basedir}/${2}/${3}.dll"
+
+ if ! [ -f "${srcfile}" ]; then
+ echo "${srcfile}: File not found. Skipping." >&2
+ return 1
+ fi
+
+ if ! [ -f "${dstfile}" ] && ! [ -h "${dstfile}" ]; then
+ echo "${dstfile}: File not found. Skipping." >&2
+ return 1
+ fi
+
+ if [ -f "${dstfile}.old" ]; then
+ rm -v "${dstfile}"
+ mv -v "${dstfile}.old" "${dstfile}"
+ return 0
+ elif [ -f "${dstfile}.old_none" ]; then
+ rm -v "${dstfile}.old_none"
+ rm -v "${dstfile}"
+ return 0
+ else
+ return 1
+ fi
+}
+
+install() {
+ if [ "$arch" == "win32" ]; then
+ lib="$dxvk_lib32"
+ dll="${1}"
+ else
+ lib="$dxvk_lib64"
+ dll="${1}"
+ fi
+ if installFile "$system32_path" "$lib" "$dll"; then
+ overrideDll "$dll"
+ fi
+
+ if [ -d "$syswow64_path" ]; then
+ if installFile "$syswow64_path" "$dxvk_lib32" "$1"; then
+ overrideDll "$1"
+ fi
+ fi
+}
+
+uninstall() {
+ if [ "$arch" == "win32" ]; then
+ lib="$dxvk_lib32"
+ dll="${1}"
+ else
+ lib="$dxvk_lib64"
+ dll="${1}"
+ fi
+ if uninstallFile "$system32_path" "$lib" "$dll"; then
+ restoreDll "$dll"
+ fi
+
+ if [ -d "$syswow64_path" ]; then
+ if uninstallFile "$syswow64_path" "$dxvk_lib32" "$1"; then
+ restoreDll "$1"
+ fi
+ fi
+}
+
+# skip dxgi during install if not explicitly
+# enabled, but always try to uninstall it
+if $with_dxgi || [ "$action" == "uninstall" ]; then
+ $action dxgi
+fi
+
+$action d3d9
+$action d3d10core
+$action d3d11