diff --git a/pkgs/misc/dxvk/darwin-dxvk-compat.patch b/pkgs/misc/dxvk/darwin-dxvk-compat.patch new file mode 100644 index 000000000000..1c68659215f0 --- /dev/null +++ b/pkgs/misc/dxvk/darwin-dxvk-compat.patch @@ -0,0 +1,35 @@ +Source: https://github.com/marzent/dxvk/commit/65247afe2de5dd6b555b8fdd46dddcdc6325e1d6 +--- + src/d3d11/d3d11_device.cpp | 12 +- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp +index 21f0d1b4a..5b1d05335 100644 +--- a/src/d3d11/d3d11_device.cpp ++++ b/src/d3d11/d3d11_device.cpp +@@ -799,8 +799,12 @@ namespace dxvk { + InitReturnPtr(ppGeometryShader); + D3D11CommonShader module; + +- if (!m_dxvkDevice->features().extTransformFeedback.transformFeedback) +- return DXGI_ERROR_INVALID_CALL; ++ if (!m_dxvkDevice->features().extTransformFeedback.transformFeedback) { ++ Logger::err( ++ "D3D11: CreateGeometryShaderWithStreamOutput:" ++ "\n Transform feedback not supported by device"); ++ return S_OK; ++ } + + // Zero-init some counterss so that we can increment + // them while walking over the stream output entries +@@ -1973,8 +1977,8 @@ namespace dxvk { + enabled.core.features.logicOp = supported.core.features.logicOp; + enabled.core.features.shaderImageGatherExtended = VK_TRUE; + enabled.core.features.variableMultisampleRate = supported.core.features.variableMultisampleRate; +- enabled.extTransformFeedback.transformFeedback = VK_TRUE; +- enabled.extTransformFeedback.geometryStreams = VK_TRUE; ++ enabled.extTransformFeedback.transformFeedback = supported.extTransformFeedback.transformFeedback; ++ enabled.extTransformFeedback.geometryStreams = supported.extTransformFeedback.geometryStreams; + } + + if (featureLevel >= D3D_FEATURE_LEVEL_10_1) { diff --git a/pkgs/misc/dxvk/darwin-moltenvk-compat.patch b/pkgs/misc/dxvk/darwin-moltenvk-compat.patch new file mode 100644 index 000000000000..7d16fdf70331 --- /dev/null +++ b/pkgs/misc/dxvk/darwin-moltenvk-compat.patch @@ -0,0 +1,59 @@ +Source: https://github.com/Gcenx/MoltenVK/commit/1f268bd45f6c928784d7cb90dedce382895f10ae + +Fake extensions for DXVK; +- _features.geometryShader +- _features.tessellationShader +- _features.shaderCullDistance + +Enabled defaults; +- MVK_ALLOW_METAL_FENCES=1 +- MVK_CONFIG_RESUME_LOST_DEVICE=1 +--- + MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 3 +++ + MoltenVK/MoltenVK/Utility/MVKEnvironment.h | 4 ++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +index bc6d19df..e1959c6e 100644 +--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm ++++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +@@ -1656,6 +1656,8 @@ + _features.robustBufferAccess = true; // XXX Required by Vulkan spec + _features.fullDrawIndexUint32 = true; + _features.independentBlend = true; ++ _features.geometryShader = true; // XXX Required by DXVK for D3D10 ++ _features.tessellationShader = true; // XXX Required by DXVK for D3D11 + _features.sampleRateShading = true; + _features.depthBiasClamp = true; + _features.fillModeNonSolid = true; +@@ -1669,6 +1671,7 @@ + _features.shaderUniformBufferArrayDynamicIndexing = true; + _features.shaderStorageBufferArrayDynamicIndexing = true; + _features.shaderClipDistance = true; ++ _features.shaderCullDistance = true; // XXX Required by DXVK for 10level9 + _features.shaderInt16 = true; + _features.multiDrawIndirect = true; + _features.inheritedQueries = true; +diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h +index 81d0defc..80c414d3 100644 +--- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h ++++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h +@@ -240,7 +240,7 @@ void mvkSetConfig(const MVKConfiguration& mvkConfig); + # define MVK_ALLOW_METAL_EVENTS 1 + #endif + #ifndef MVK_ALLOW_METAL_FENCES +-# define MVK_ALLOW_METAL_FENCES 0 ++# define MVK_ALLOW_METAL_FENCES 1 // XXX Required by DXVK for Apple/NVidia GPUs (better FPS than CPU Emulation) + #endif + + /** Substitute Metal 2D textures for Vulkan 1D images. Enabled by default. */ +@@ -275,7 +275,7 @@ void mvkSetConfig(const MVKConfiguration& mvkConfig); + + /** Resume MVKDevice VK_ERROR_DEVICE_LOST errors that do not cause MVKPhysicalDevice errors. Disabled by default. */ + #ifndef MVK_CONFIG_RESUME_LOST_DEVICE +-# define MVK_CONFIG_RESUME_LOST_DEVICE 0 ++# define MVK_CONFIG_RESUME_LOST_DEVICE 1 + #endif + + /** Support Metal argument buffers. Disabled by default. */ + \ No newline at end of file diff --git a/pkgs/misc/dxvk/default.nix b/pkgs/misc/dxvk/default.nix new file mode 100644 index 000000000000..61e2d78b45c0 --- /dev/null +++ b/pkgs/misc/dxvk/default.nix @@ -0,0 +1,80 @@ +{ lib +, pkgs +, stdenv +, fetchFromGitHub +, pkgsCross +}: + +let + # DXVK needs to be a separate derivation because it’s actually a set of DLLs for Windows that + # needs to be built with a cross-compiler. + dxvk32 = pkgsCross.mingw32.callPackage ./dxvk.nix { inherit (self) src version dxvkPatches; }; + dxvk64 = pkgsCross.mingwW64.callPackage ./dxvk.nix { inherit (self) src version dxvkPatches; }; + + # Use the self pattern to support overriding `src` and `version` via `overrideAttrs`. A recursive + # attrset wouldn’t work. + self = stdenv.mkDerivation { + name = "dxvk"; + version = "1.10"; + + src = fetchFromGitHub { + owner = "doitsujin"; + repo = "dxvk"; + rev = "v${self.version}"; + hash = "sha256-/zH6vER/6s/d+Tt181UJOa97sqdkJyKGw6E36+1owzQ="; + }; + + # Patch DXVK to work with MoltenVK even though it doesn’t support some required features. + # Some games will work poorly (particularly Unreal Engine 4 games), but others work pretty well. + # Override this to patch DXVK itself (rather than the setup script). + dxvkPatches = lib.optional stdenv.isDarwin ./darwin-dxvk-compat.patch; + + outputs = [ "out" "bin" "lib" ]; + + # Also copy `mcfgthread-12.dll` due to DXVK’s being built in a MinGW cross environment. + patches = [ ./mcfgthread.patch ]; + + dontConfigure = true; + dontBuild = true; + + installPhase = '' + mkdir -p $out/bin $bin $lib + substitute setup_dxvk.sh $out/bin/setup_dxvk.sh \ + --subst-var-by mcfgthreads32 "${pkgsCross.mingw32.windows.mcfgthreads}" \ + --subst-var-by mcfgthreads64 "${pkgsCross.mingwW64.windows.mcfgthreads}" \ + --replace 'basedir=$(dirname "$(readlink -f $0)")' "basedir=$bin" + chmod a+x $out/bin/setup_dxvk.sh + declare -A dxvks=( [x32]=${dxvk32} [x64]=${dxvk64} ) + for arch in "''${!dxvks[@]}"; do + ln -s "''${dxvks[$arch]}/bin" $bin/$arch + ln -s "''${dxvks[$arch]}/lib" $lib/$arch + done + ''; + + # DXVK with MoltenVK requires a patched MoltenVK in addition to its own patches. Provide a + # convenience function to handle the necessary patching. + # Usage: + # let + # patchedMoltenVK = dxvk.patchMoltenVK darwin.moltenvk; + # in + # wine64Packages.full.override { moltenvk = patchedMoltenVK; vkd3dSupport = false; } + passthru.patchMoltenVK = moltenvk: + moltenvk.overrideAttrs (old: { + patches = old.patches or [ ] ++ [ + # Lie to DXVK about certain features that DXVK expects to be available and set defaults + # for better performance/compatability on certain hardware. + ./darwin-moltenvk-compat.patch + ]; + }); + + meta = { + description = "A Vulkan-based translation layer for Direct3D 9/10/11"; + homepage = "https://github.com/doitsujin/dxvk"; + changelog = "https://github.com/doitsujin/dxvk/releases"; + maintainers = [ lib.maintainers.reckenrode ]; + license = lib.licenses.zlib; + platforms = lib.platforms.unix; + }; + }; +in +self diff --git a/pkgs/misc/dxvk/dxvk.nix b/pkgs/misc/dxvk/dxvk.nix new file mode 100644 index 000000000000..40b674df9225 --- /dev/null +++ b/pkgs/misc/dxvk/dxvk.nix @@ -0,0 +1,52 @@ +{ lib +, stdenv +, fetchFromGitHub +, glslang +, meson +, ninja +, windows +, src +, version +, dxvkPatches +}: + +stdenv.mkDerivation { + pname = "dxvk"; + inherit src version; + + nativeBuildInputs = [ glslang meson ninja ]; + buildInputs = [ windows.pthreads ]; + + patches = dxvkPatches; + + # Replace use of DXVK’s threading classes with the ones from the C++ standard library, which uses + # mcfgthreads in nixpkgs. + postPatch = '' + for class in mutex recursive_mutex condition_variable; do + for file in $(grep -rl dxvk::$class *); do + if [ "$(basename "$file")" != "thread.h" ]; then + substituteInPlace "$file" --replace dxvk::$class std::$class + fi + done + done + ''; + + mesonFlags = + let + arch = if stdenv.is32bit then "32" else "64"; + in + [ + "--buildtype" "release" + "--cross-file" "build-win${arch}.txt" + "--prefix" "${placeholder "out"}" + ]; + + meta = { + description = "A Vulkan-based translation layer for Direct3D 9/10/11"; + homepage = "https://github.com/doitsujin/dxvk"; + changelog = "https://github.com/doitsujin/dxvk/releases"; + maintainers = [ lib.maintainers.reckenrode ]; + license = lib.licenses.zlib; + platforms = lib.platforms.windows; + }; +} diff --git a/pkgs/misc/dxvk/mcfgthread.patch b/pkgs/misc/dxvk/mcfgthread.patch new file mode 100644 index 000000000000..037071630172 --- /dev/null +++ b/pkgs/misc/dxvk/mcfgthread.patch @@ -0,0 +1,34 @@ +diff --git a/setup_dxvk.sh b/setup_dxvk.sh +index 3e63ecf0..87c04f23 100755 +--- a/setup_dxvk.sh ++++ b/setup_dxvk.sh +@@ -133,6 +133,8 @@ + rm -v "${dstfile}" + fi + $file_cmd "${srcfile}" "${dstfile}" ++ elif [ "${4}" = "--force" ]; then ++ $file_cmd "${srcfile}" "${dstfile}" + else + echo "${dstfile}: File not found in wine prefix" >&2 + return 1 +@@ -170,12 +172,12 @@ + } + + install() { +- installFile "$win64_sys_path" "$dxvk_lib64" "$1" ++ installFile "$win64_sys_path" "$dxvk_lib64" "$1" "${2-}" + inst64_ret="$?" + + inst32_ret=-1 + if $wow64; then +- installFile "$win32_sys_path" "$dxvk_lib32" "$1" ++ installFile "$win32_sys_path" "$dxvk_lib32" "$1" "${2-}" + inst32_ret="$?" + fi + +@@ -214,3 +216,5 @@ + + $action d3d10core + $action d3d11 ++ ++basedir="" dxvk_lib32=@mcfgthreads32@/bin dxvk_lib64=@mcfgthreads64@/bin $action mcfgthread-12 --force diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 389e1c038d32..e95201baf93e 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -33079,6 +33079,8 @@ with pkgs; dump = callPackage ../tools/backup/dump { }; + dxvk = callPackage ../misc/dxvk { }; + ecdsatool = callPackage ../tools/security/ecdsatool { }; emulationstation = callPackage ../applications/emulators/emulationstation { };