From e53cb72e39610915a4fce49253e61635369281c4 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 22 Apr 2018 23:49:41 +0200 Subject: [PATCH] [dxbc] Make DxbcOptions a set of flags This allows for game-specific workarounds and driver-specific workarounds to be applied in an easier fashion. --- src/d3d11/d3d11_device.cpp | 3 ++- src/dxbc/dxbc_compiler.cpp | 14 +++++------ src/dxbc/dxbc_options.cpp | 36 ++++++++++++++++++++-------- src/dxbc/dxbc_options.h | 49 +++++++++++++++++++++++--------------- 4 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index dc9fba044..248b2c33f 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -86,7 +86,8 @@ namespace dxvk { m_dxvkDevice (pDxgiDevice->GetDXVKDevice()), m_dxvkAdapter (m_dxvkDevice->adapter()), m_d3d11Options (D3D11GetAppOptions(env::getExeName())), - m_dxbcOptions (m_dxvkDevice) { + m_dxbcOptions (getDxbcAppOptions(env::getExeName()) | + getDxbcDeviceOptions(m_dxvkDevice)) { Com adapter; if (FAILED(pDxgiDevice->GetAdapter(&adapter)) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index b1045d6ee..fda78d9f4 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -769,7 +769,7 @@ namespace dxvk { const bool isUav = ins.op == DxbcOpcode::DclUavTyped; if (isUav) { - if (m_options.useStorageImageReadWithoutFormat) + if (m_options.test(DxbcOption::UseStorageImageReadWithoutFormat)) m_module.enableCapability(spv::CapabilityStorageImageReadWithoutFormat); m_module.enableCapability(spv::CapabilityStorageImageWriteWithoutFormat); } @@ -846,7 +846,7 @@ namespace dxvk { if (isUav) { if ((m_analysis->uavInfos[registerId].accessAtomicOp) || (m_analysis->uavInfos[registerId].accessTypedLoad - && !m_options.useStorageImageReadWithoutFormat)) + && !m_options.test(DxbcOption::UseStorageImageReadWithoutFormat))) imageFormat = getScalarImageFormat(sampledType); } @@ -1391,13 +1391,13 @@ namespace dxvk { break; case DxbcOpcode::Max: - dst.id = m_options.useSimpleMinMaxClamp + dst.id = m_options.test(DxbcOption::UseSimpleMinMaxClamp) ? m_module.opFMax(typeId, src.at(0).id, src.at(1).id) : m_module.opNMax(typeId, src.at(0).id, src.at(1).id); break; case DxbcOpcode::Min: - dst.id = m_options.useSimpleMinMaxClamp + dst.id = m_options.test(DxbcOption::UseSimpleMinMaxClamp) ? m_module.opFMin(typeId, src.at(0).id, src.at(1).id) : m_module.opNMin(typeId, src.at(0).id, src.at(1).id); break; @@ -2952,7 +2952,7 @@ namespace dxvk { DxbcRegMask(true, false, false, false)) : DxbcRegisterValue(); - if (isDepthCompare && m_options.addExtraDrefCoordComponent && coord.type.ccount < 4) + if (isDepthCompare && m_options.test(DxbcOption::AddExtraDrefCoordComponent) && coord.type.ccount < 4) coord = emitRegisterConcat(coord, referenceValue); // Determine the sampled image type based on the opcode. @@ -3064,7 +3064,7 @@ namespace dxvk { ? emitRegisterLoad(ins.src[3], DxbcRegMask(true, false, false, false)) : DxbcRegisterValue(); - if (isDepthCompare && m_options.addExtraDrefCoordComponent && coord.type.ccount < 4) + if (isDepthCompare && m_options.test(DxbcOption::AddExtraDrefCoordComponent) && coord.type.ccount < 4) coord = emitRegisterConcat(coord, referenceValue); // Load explicit gradients for sample operations that require them @@ -3952,7 +3952,7 @@ namespace dxvk { const DxbcRegisterValue vec0 = emitBuildConstVecf32(0.0f, 0.0f, 0.0f, 0.0f, mask); const DxbcRegisterValue vec1 = emitBuildConstVecf32(1.0f, 1.0f, 1.0f, 1.0f, mask); - value.id = m_options.useSimpleMinMaxClamp + value.id = m_options.test(DxbcOption::UseSimpleMinMaxClamp) ? m_module.opFClamp(typeId, value.id, vec0.id, vec1.id) : m_module.opNClamp(typeId, value.id, vec0.id, vec1.id); } diff --git a/src/dxbc/dxbc_options.cpp b/src/dxbc/dxbc_options.cpp index a5ea3f8a9..6ccfd5656 100644 --- a/src/dxbc/dxbc_options.cpp +++ b/src/dxbc/dxbc_options.cpp @@ -1,25 +1,41 @@ +#include + #include "dxbc_options.h" namespace dxvk { - DxbcOptions::DxbcOptions(const Rc& device) { + const static std::unordered_map g_dxbcAppOptions = {{ + + }}; + + + DxbcOptions getDxbcAppOptions(const std::string& appName) { + auto appOptions = g_dxbcAppOptions.find(appName); + + return appOptions != g_dxbcAppOptions.end() + ? appOptions->second + : DxbcOptions(); + } + + + DxbcOptions getDxbcDeviceOptions(const Rc& device) { + DxbcOptions flags; + const VkPhysicalDeviceProperties devProps = device->adapter()->deviceProperties(); const VkPhysicalDeviceFeatures devFeatures = device->features(); - // Apply driver-specific workarounds const DxvkGpuVendor vendor = static_cast(devProps.vendorID); if (vendor == DxvkGpuVendor::Nvidia) { - // Older versions of the driver expect the - // coordinate vector to have an extra component - this->addExtraDrefCoordComponent = true; - - // From vkd3d: NMin/NMax/NClamp may crash the driver. - this->useSimpleMinMaxClamp = true; + flags.set( + DxbcOption::AddExtraDrefCoordComponent, + DxbcOption::UseSimpleMinMaxClamp); } - // Enable certain features if they are supported by the device - this->useStorageImageReadWithoutFormat = devFeatures.shaderStorageImageReadWithoutFormat; + if (devFeatures.shaderStorageImageReadWithoutFormat) + flags.set(DxbcOption::UseStorageImageReadWithoutFormat); + + return flags; } } \ No newline at end of file diff --git a/src/dxbc/dxbc_options.h b/src/dxbc/dxbc_options.h index 74b8db2f5..1a8e575c6 100644 --- a/src/dxbc/dxbc_options.h +++ b/src/dxbc/dxbc_options.h @@ -4,26 +4,37 @@ namespace dxvk { - /** - * \brief DXBC compiler options - * - * Defines driver- or device-specific options, - * which are mostly workarounds for driver bugs. - */ - struct DxbcOptions { - DxbcOptions() { } - DxbcOptions( - const Rc& device); - - /// Add extra component to dref coordinate vector - bool addExtraDrefCoordComponent = false; - - /// Use Fmin/Fmax instead of Nmin/Nmax. - bool useSimpleMinMaxClamp = false; + enum class DxbcOption : uint64_t { + /// Use the ShaderImageReadWithoutFormat capability. + /// Enabled by default on GPUs which support this. + UseStorageImageReadWithoutFormat, - /// If \c false, image read operations can only be performed - /// on storage images with a scalar 32-bit image formats. - bool useStorageImageReadWithoutFormat = false; + /// Adds an extra component to the depth reference + /// vector for depth-compare operations. Workaround + /// for bugs in Nvidia drivers prior to 396.18. + AddExtraDrefCoordComponent, + + /// Use FMin/FMax/FClamp instead of NMin/NMax/NClamp. + /// Workaround for bugs in older Nvidia drivers. + UseSimpleMinMaxClamp, }; + using DxbcOptions = Flags; + + /** + * \brief Gets app-specific DXBC options + * + * \param [in] appName Application name + * \returns DXBC options for this application + */ + DxbcOptions getDxbcAppOptions(const std::string& appName); + + /** + * \brief Gets device-specific options + * + * \param [in] device The device + * \returns Device options + */ + DxbcOptions getDxbcDeviceOptions(const Rc& device); + } \ No newline at end of file