diff --git a/dxvk.conf b/dxvk.conf index fea5b5ce..6863d05a 100644 --- a/dxvk.conf +++ b/dxvk.conf @@ -334,13 +334,16 @@ # Force enable/disable floating point quirk emulation -# +# # Force toggle anything * 0 emulation -# Tristate +# Setting it to True will use a faster but less accurate approach that works for most games. # Supported values: -# - True/False +# - True: Use a faster but less accurate approach. Good enough for most games +# - False: Disable float emulation completely +# - Strict: Use a slower but more correct approach. Necessary for some games +# - Auto: DXVK will pick automatically -# d3d9.floatEmulation = +# d3d9.floatEmulation = True # Enable dialog box mode diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index e6261368..3b7e3392 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -6479,7 +6479,7 @@ namespace dxvk { StartRegister, pConstantData, Count, - m_d3d9Options.d3d9FloatEmulation); + m_d3d9Options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled); return D3D_OK; } diff --git a/src/d3d9/d3d9_options.cpp b/src/d3d9/d3d9_options.cpp index b99deec2..33f53058 100644 --- a/src/d3d9/d3d9_options.cpp +++ b/src/d3d9/d3d9_options.cpp @@ -81,8 +81,14 @@ namespace dxvk { 0, 0); applyTristate(this->generalHazards, config.getOption("d3d9.generalHazards", Tristate::Auto)); - this->d3d9FloatEmulation = true; // <-- Future Extension? - applyTristate(this->d3d9FloatEmulation, config.getOption("d3d9.floatEmulation", Tristate::Auto)); + std::string floatEmulation = Config::toLower(config.getOption("d3d9.floatEmulation", "true")); + if (floatEmulation == "strict") { + d3d9FloatEmulation = D3D9FloatEmulation::Strict; + } else if (floatEmulation == "false") { + d3d9FloatEmulation = D3D9FloatEmulation::Disabled; + } else { + d3d9FloatEmulation = D3D9FloatEmulation::Enabled; + } } } \ No newline at end of file diff --git a/src/d3d9/d3d9_options.h b/src/d3d9/d3d9_options.h index 79e00f84..3a004174 100644 --- a/src/d3d9/d3d9_options.h +++ b/src/d3d9/d3d9_options.h @@ -7,6 +7,12 @@ namespace dxvk { + enum class D3D9FloatEmulation { + Disabled, + Enabled, + Strict + }; + struct D3D9Options { D3D9Options(const Rc& device, const Config& config); @@ -83,7 +89,7 @@ namespace dxvk { uint32_t maxAvailableMemory; /// D3D9 Floating Point Emulation (anything * 0 = 0) - bool d3d9FloatEmulation; + D3D9FloatEmulation d3d9FloatEmulation; /// Support the DF16 & DF24 texture format bool supportDFFormats; diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp index 8675c31c..baf3f450 100644 --- a/src/dxso/dxso_compiler.cpp +++ b/src/dxso/dxso_compiler.cpp @@ -1439,7 +1439,7 @@ namespace dxvk { DxsoRegisterValue DxsoCompiler::emitMulOperand( DxsoRegisterValue operand, DxsoRegisterValue other) { - if (!m_moduleInfo.options.d3d9FloatEmulation) + if (m_moduleInfo.options.d3d9FloatEmulation != D3D9FloatEmulation::Strict) return operand; uint32_t boolId = getVectorTypeId({ DxsoScalarType::Bool, other.type.ccount }); @@ -1966,7 +1966,7 @@ namespace dxvk { m_module.constfReplicant(1.0f, result.type.ccount), emitRegisterLoad(src[0], mask).id); - if (m_moduleInfo.options.d3d9FloatEmulation) { + if (m_moduleInfo.options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled) { result.id = m_module.opNMin(typeId, result.id, m_module.constfReplicant(FLT_MAX, result.type.ccount)); } @@ -1978,7 +1978,7 @@ namespace dxvk { result.id = m_module.opInverseSqrt(typeId, result.id); - if (m_moduleInfo.options.d3d9FloatEmulation) { + if (m_moduleInfo.options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled) { result.id = m_module.opNMin(typeId, result.id, m_module.constfReplicant(FLT_MAX, result.type.ccount)); } @@ -2052,7 +2052,7 @@ namespace dxvk { result.id = m_module.opPow(typeId, base, exponent); - if (m_moduleInfo.options.strictPow && m_moduleInfo.options.d3d9FloatEmulation) { + if (m_moduleInfo.options.strictPow && m_moduleInfo.options.d3d9FloatEmulation != D3D9FloatEmulation::Disabled) { DxsoRegisterValue cmp; cmp.type = { DxsoScalarType::Bool, result.type.ccount }; cmp.id = m_module.opFOrdEqual(getVectorTypeId(cmp.type), @@ -2097,7 +2097,7 @@ namespace dxvk { DxsoRegisterValue dot = emitDot(vec3, vec3); dot.id = m_module.opInverseSqrt (scalarTypeId, dot.id); - if (m_moduleInfo.options.d3d9FloatEmulation) { + if (m_moduleInfo.options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled) { dot.id = m_module.opNMin (scalarTypeId, dot.id, m_module.constf32(FLT_MAX)); } @@ -2214,7 +2214,7 @@ namespace dxvk { case DxsoOpcode::Log: result.id = m_module.opFAbs(typeId, emitRegisterLoad(src[0], mask).id); result.id = m_module.opLog2(typeId, result.id); - if (m_moduleInfo.options.d3d9FloatEmulation) { + if (m_moduleInfo.options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled) { result.id = m_module.opNMax(typeId, result.id, m_module.constfReplicant(-FLT_MAX, result.type.ccount)); } diff --git a/src/dxso/dxso_options.h b/src/dxso/dxso_options.h index 39104cc3..c977ce8a 100644 --- a/src/dxso/dxso_options.h +++ b/src/dxso/dxso_options.h @@ -27,7 +27,7 @@ namespace dxvk { /// Whether to emulate d3d9 float behaviour using clampps /// True: Perform emulation to emulate behaviour (ie. anything * 0 = 0) /// False: Don't do anything. - bool d3d9FloatEmulation; + D3D9FloatEmulation d3d9FloatEmulation; /// Whether or not we should care about pow(0, 0) = 1 bool strictPow;