1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-07 16:54:14 +01:00

[dxbc] Make DxbcOptions a set of flags

This allows for game-specific workarounds and driver-specific
workarounds to be applied in an easier fashion.
This commit is contained in:
Philip Rebohle 2018-04-22 23:49:41 +02:00
parent cfcca11fc5
commit e53cb72e39
4 changed files with 65 additions and 37 deletions

View File

@ -86,7 +86,8 @@ namespace dxvk {
m_dxvkDevice (pDxgiDevice->GetDXVKDevice()), m_dxvkDevice (pDxgiDevice->GetDXVKDevice()),
m_dxvkAdapter (m_dxvkDevice->adapter()), m_dxvkAdapter (m_dxvkDevice->adapter()),
m_d3d11Options (D3D11GetAppOptions(env::getExeName())), m_d3d11Options (D3D11GetAppOptions(env::getExeName())),
m_dxbcOptions (m_dxvkDevice) { m_dxbcOptions (getDxbcAppOptions(env::getExeName()) |
getDxbcDeviceOptions(m_dxvkDevice)) {
Com<IDXGIAdapter> adapter; Com<IDXGIAdapter> adapter;
if (FAILED(pDxgiDevice->GetAdapter(&adapter)) if (FAILED(pDxgiDevice->GetAdapter(&adapter))

View File

@ -769,7 +769,7 @@ namespace dxvk {
const bool isUav = ins.op == DxbcOpcode::DclUavTyped; const bool isUav = ins.op == DxbcOpcode::DclUavTyped;
if (isUav) { if (isUav) {
if (m_options.useStorageImageReadWithoutFormat) if (m_options.test(DxbcOption::UseStorageImageReadWithoutFormat))
m_module.enableCapability(spv::CapabilityStorageImageReadWithoutFormat); m_module.enableCapability(spv::CapabilityStorageImageReadWithoutFormat);
m_module.enableCapability(spv::CapabilityStorageImageWriteWithoutFormat); m_module.enableCapability(spv::CapabilityStorageImageWriteWithoutFormat);
} }
@ -846,7 +846,7 @@ namespace dxvk {
if (isUav) { if (isUav) {
if ((m_analysis->uavInfos[registerId].accessAtomicOp) if ((m_analysis->uavInfos[registerId].accessAtomicOp)
|| (m_analysis->uavInfos[registerId].accessTypedLoad || (m_analysis->uavInfos[registerId].accessTypedLoad
&& !m_options.useStorageImageReadWithoutFormat)) && !m_options.test(DxbcOption::UseStorageImageReadWithoutFormat)))
imageFormat = getScalarImageFormat(sampledType); imageFormat = getScalarImageFormat(sampledType);
} }
@ -1391,13 +1391,13 @@ namespace dxvk {
break; break;
case DxbcOpcode::Max: 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.opFMax(typeId, src.at(0).id, src.at(1).id)
: m_module.opNMax(typeId, src.at(0).id, src.at(1).id); : m_module.opNMax(typeId, src.at(0).id, src.at(1).id);
break; break;
case DxbcOpcode::Min: 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.opFMin(typeId, src.at(0).id, src.at(1).id)
: m_module.opNMin(typeId, src.at(0).id, src.at(1).id); : m_module.opNMin(typeId, src.at(0).id, src.at(1).id);
break; break;
@ -2952,7 +2952,7 @@ namespace dxvk {
DxbcRegMask(true, false, false, false)) DxbcRegMask(true, false, false, false))
: DxbcRegisterValue(); : 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); coord = emitRegisterConcat(coord, referenceValue);
// Determine the sampled image type based on the opcode. // Determine the sampled image type based on the opcode.
@ -3064,7 +3064,7 @@ namespace dxvk {
? emitRegisterLoad(ins.src[3], DxbcRegMask(true, false, false, false)) ? emitRegisterLoad(ins.src[3], DxbcRegMask(true, false, false, false))
: DxbcRegisterValue(); : 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); coord = emitRegisterConcat(coord, referenceValue);
// Load explicit gradients for sample operations that require them // 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 vec0 = emitBuildConstVecf32(0.0f, 0.0f, 0.0f, 0.0f, mask);
const DxbcRegisterValue vec1 = emitBuildConstVecf32(1.0f, 1.0f, 1.0f, 1.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.opFClamp(typeId, value.id, vec0.id, vec1.id)
: m_module.opNClamp(typeId, value.id, vec0.id, vec1.id); : m_module.opNClamp(typeId, value.id, vec0.id, vec1.id);
} }

View File

@ -1,25 +1,41 @@
#include <unordered_map>
#include "dxbc_options.h" #include "dxbc_options.h"
namespace dxvk { namespace dxvk {
DxbcOptions::DxbcOptions(const Rc<DxvkDevice>& device) { const static std::unordered_map<std::string, DxbcOptions> 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<DxvkDevice>& device) {
DxbcOptions flags;
const VkPhysicalDeviceProperties devProps = device->adapter()->deviceProperties(); const VkPhysicalDeviceProperties devProps = device->adapter()->deviceProperties();
const VkPhysicalDeviceFeatures devFeatures = device->features(); const VkPhysicalDeviceFeatures devFeatures = device->features();
// Apply driver-specific workarounds
const DxvkGpuVendor vendor = static_cast<DxvkGpuVendor>(devProps.vendorID); const DxvkGpuVendor vendor = static_cast<DxvkGpuVendor>(devProps.vendorID);
if (vendor == DxvkGpuVendor::Nvidia) { if (vendor == DxvkGpuVendor::Nvidia) {
// Older versions of the driver expect the flags.set(
// coordinate vector to have an extra component DxbcOption::AddExtraDrefCoordComponent,
this->addExtraDrefCoordComponent = true; DxbcOption::UseSimpleMinMaxClamp);
// From vkd3d: NMin/NMax/NClamp may crash the driver.
this->useSimpleMinMaxClamp = true;
} }
// Enable certain features if they are supported by the device if (devFeatures.shaderStorageImageReadWithoutFormat)
this->useStorageImageReadWithoutFormat = devFeatures.shaderStorageImageReadWithoutFormat; flags.set(DxbcOption::UseStorageImageReadWithoutFormat);
return flags;
} }
} }

View File

@ -4,26 +4,37 @@
namespace dxvk { namespace dxvk {
/** enum class DxbcOption : uint64_t {
* \brief DXBC compiler options /// Use the ShaderImageReadWithoutFormat capability.
* /// Enabled by default on GPUs which support this.
* Defines driver- or device-specific options, UseStorageImageReadWithoutFormat,
* which are mostly workarounds for driver bugs.
*/
struct DxbcOptions {
DxbcOptions() { }
DxbcOptions(
const Rc<DxvkDevice>& device);
/// Add extra component to dref coordinate vector
bool addExtraDrefCoordComponent = false;
/// Use Fmin/Fmax instead of Nmin/Nmax.
bool useSimpleMinMaxClamp = false;
/// If \c false, image read operations can only be performed /// Adds an extra component to the depth reference
/// on storage images with a scalar 32-bit image formats. /// vector for depth-compare operations. Workaround
bool useStorageImageReadWithoutFormat = false; /// 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<DxbcOption>;
/**
* \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<DxvkDevice>& device);
} }