1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +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_dxvkAdapter (m_dxvkDevice->adapter()),
m_d3d11Options (D3D11GetAppOptions(env::getExeName())),
m_dxbcOptions (m_dxvkDevice) {
m_dxbcOptions (getDxbcAppOptions(env::getExeName()) |
getDxbcDeviceOptions(m_dxvkDevice)) {
Com<IDXGIAdapter> adapter;
if (FAILED(pDxgiDevice->GetAdapter(&adapter))

View File

@ -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);
}

View File

@ -1,25 +1,41 @@
#include <unordered_map>
#include "dxbc_options.h"
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 VkPhysicalDeviceFeatures devFeatures = device->features();
// Apply driver-specific workarounds
const DxvkGpuVendor vendor = static_cast<DxvkGpuVendor>(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;
}
}

View File

@ -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<DxvkDevice>& device);
enum class DxbcOption : uint64_t {
/// Use the ShaderImageReadWithoutFormat capability.
/// Enabled by default on GPUs which support this.
UseStorageImageReadWithoutFormat,
/// Add extra component to dref coordinate vector
bool addExtraDrefCoordComponent = 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 instead of Nmin/Nmax.
bool useSimpleMinMaxClamp = false;
/// If \c false, image read operations can only be performed
/// on storage images with a scalar 32-bit image formats.
bool useStorageImageReadWithoutFormat = false;
/// 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);
}