From c3cff09c4f029ed015ce73d7aac3059f8cc7fa62 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Wed, 8 Apr 2020 23:20:57 +0100 Subject: [PATCH] [d3d9] Implement d3d9.longMad option --- dxvk.conf | 11 +++++++++++ src/d3d9/d3d9_options.cpp | 1 + src/d3d9/d3d9_options.h | 5 +++++ src/dxso/dxso_compiler.cpp | 19 +++++++++++++++---- src/dxso/dxso_options.cpp | 2 ++ src/dxso/dxso_options.h | 5 +++++ 6 files changed, 39 insertions(+), 4 deletions(-) diff --git a/dxvk.conf b/dxvk.conf index 626b50e3..1b5d8b50 100644 --- a/dxvk.conf +++ b/dxvk.conf @@ -304,3 +304,14 @@ # d3d9.forceSwapchainMSAA = -1 + +# Long Mad +# +# Should we make our Mads a FFma or do it the long way with an FMul and an FAdd? +# This solves some rendering bugs in games that have z-pass shaders which +# don't match entirely to the regular vertex shader in this way. +# +# Supported values: +# - True/False + +# d3d9.longMad = False \ No newline at end of file diff --git a/src/d3d9/d3d9_options.cpp b/src/d3d9/d3d9_options.cpp index bc06dde6..939f4f4b 100644 --- a/src/d3d9/d3d9_options.cpp +++ b/src/d3d9/d3d9_options.cpp @@ -69,6 +69,7 @@ namespace dxvk { this->allowDoNotWait = config.getOption ("d3d9.allowDoNotWait", true); this->allowDiscard = config.getOption ("d3d9.allowDiscard", true); this->enumerateByDisplays = config.getOption ("d3d9.enumerateByDisplays", true); + this->longMad = config.getOption ("d3d9.longMad", false); // If we are not Nvidia, enable general hazards. this->generalHazards = adapter == nullptr || !adapter->matchesDriver(DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0); diff --git a/src/d3d9/d3d9_options.h b/src/d3d9/d3d9_options.h index bdfe0c8e..b5742f9c 100644 --- a/src/d3d9/d3d9_options.h +++ b/src/d3d9/d3d9_options.h @@ -138,6 +138,11 @@ namespace dxvk { /// Enumerate adapters by displays bool enumerateByDisplays; + + /// Should we make our Mads a FFma or do it the long way with an FMul and an FAdd? + /// This solves some rendering bugs in games that have z-pass shaders which + /// don't match entirely to the regular vertex shader in this way. + bool longMad; }; } \ No newline at end of file diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp index 134de1c3..ba7ad2a2 100644 --- a/src/dxso/dxso_compiler.cpp +++ b/src/dxso/dxso_compiler.cpp @@ -1774,10 +1774,21 @@ namespace dxvk { emitRegisterLoad(src[1], mask).id); break; case DxsoOpcode::Mad: - result.id = m_module.opFFma(typeId, - emitRegisterLoad(src[0], mask).id, - emitRegisterLoad(src[1], mask).id, - emitRegisterLoad(src[2], mask).id); + if (!m_moduleInfo.options.longMad) { + result.id = m_module.opFFma(typeId, + emitRegisterLoad(src[0], mask).id, + emitRegisterLoad(src[1], mask).id, + emitRegisterLoad(src[2], mask).id); + } + else { + result.id = m_module.opFMul(typeId, + emitRegisterLoad(src[0], mask).id, + emitRegisterLoad(src[1], mask).id); + + result.id = m_module.opFAdd(typeId, + result.id, + emitRegisterLoad(src[2], mask).id); + } break; case DxsoOpcode::Mul: result.id = m_module.opFMul(typeId, diff --git a/src/dxso/dxso_options.cpp b/src/dxso/dxso_options.cpp index 41d5fb4c..e8cd5407 100644 --- a/src/dxso/dxso_options.cpp +++ b/src/dxso/dxso_options.cpp @@ -45,6 +45,8 @@ namespace dxvk { forceSamplerTypeSpecConstants = options.forceSamplerTypeSpecConstants; vertexConstantBufferAsSSBO = pDevice->GetVertexConstantLayout().totalSize() > devInfo.core.properties.limits.maxUniformBufferRange; + + longMad = options.longMad; } } \ No newline at end of file diff --git a/src/dxso/dxso_options.h b/src/dxso/dxso_options.h index efc87719..4e02d4bd 100644 --- a/src/dxso/dxso_options.h +++ b/src/dxso/dxso_options.h @@ -45,6 +45,11 @@ namespace dxvk { /// Should the VS constant buffer be an SSBO (swvp on NV) bool vertexConstantBufferAsSSBO; + + /// Should we make our Mads a FFma or do it the long way with an FMul and an FAdd? + /// This solves some rendering bugs in games that have z-pass shaders which + /// don't match entirely to the regular vertex shader in this way. + bool longMad; }; } \ No newline at end of file