[d3d11] Introduce D3D11DeviceFeatures

This commit is contained in:
Philip Rebohle 2022-09-03 22:45:58 +02:00
parent 5490aa936b
commit 71d6e8f849
3 changed files with 358 additions and 0 deletions

View File

@ -0,0 +1,268 @@
#include <array>
#include "d3d11_features.h"
namespace dxvk {
D3D11DeviceFeatures::D3D11DeviceFeatures() {
}
D3D11DeviceFeatures::D3D11DeviceFeatures(
const Rc<DxvkInstance>& Instance,
const Rc<DxvkAdapter>& Adapter,
D3D_FEATURE_LEVEL FeatureLevel)
: m_features (Adapter->features()),
m_properties (Adapter->devicePropertiesExt()) {
// Assume no TBDR. DXVK does not optimize for TBDR architectures
// anyway, and D3D11 does not really provide meaningful support.
m_architectureInfo.TileBasedDeferredRenderer = FALSE;
// D3D9 options. We unconditionally support all of these.
m_d3d9Options.FullNonPow2TextureSupport = TRUE;
m_d3d9Options1.FullNonPow2TextureSupported = TRUE;
m_d3d9Options1.DepthAsTextureWithLessEqualComparisonFilterSupported = TRUE;
m_d3d9Options1.SimpleInstancingSupported = TRUE;
m_d3d9Options1.TextureCubeFaceRenderTargetWithNonCubeDepthStencilSupported = TRUE;
m_d3d9Shadow.SupportsDepthAsTextureWithLessEqualComparisonFilter = TRUE;
m_d3d9SimpleInstancing.SimpleInstancingSupported = TRUE;
// D3D10 options. We unconditionally support compute shaders.
m_d3d10Options.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = TRUE;
// D3D11.1 options. All of these are required for Feature Level 11_1.
bool hasDoublePrecisionSupport = m_features.core.features.shaderFloat64
&& m_features.core.features.shaderInt64;
m_d3d11Options.DiscardAPIsSeenByDriver = TRUE;
m_d3d11Options.FlagsForUpdateAndCopySeenByDriver = TRUE;
m_d3d11Options.ClearView = TRUE;
m_d3d11Options.CopyWithOverlap = TRUE;
m_d3d11Options.ConstantBufferPartialUpdate = TRUE;
m_d3d11Options.ConstantBufferOffsetting = TRUE;
m_d3d11Options.MapNoOverwriteOnDynamicConstantBuffer = TRUE;
m_d3d11Options.MapNoOverwriteOnDynamicBufferSRV = TRUE;
m_d3d11Options.ExtendedResourceSharing = TRUE;
if (FeatureLevel >= D3D_FEATURE_LEVEL_10_0) {
m_d3d11Options.OutputMergerLogicOp = m_features.core.features.logicOp;
m_d3d11Options.MultisampleRTVWithForcedSampleCountOne = TRUE; // Not really
}
if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0) {
m_d3d11Options.UAVOnlyRenderingForcedSampleCount = TRUE;
m_d3d11Options.SAD4ShaderInstructions = TRUE;
m_d3d11Options.ExtendedDoublesShaderInstructions = hasDoublePrecisionSupport;
}
// D3D11.2 options.
auto tiledResourcesTier = DetermineTiledResourcesTier(FeatureLevel);
m_d3d11Options1.TiledResourcesTier = tiledResourcesTier;
m_d3d11Options1.MinMaxFiltering = tiledResourcesTier >= D3D11_TILED_RESOURCES_TIER_2;
m_d3d11Options1.ClearViewAlsoSupportsDepthOnlyFormats = TRUE;
if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0)
m_d3d11Options1.MapOnDefaultBuffers = TRUE;
// D3D11.3 options
m_d3d11Options2.TypedUAVLoadAdditionalFormats = DetermineUavExtendedTypedLoadSupport(Adapter, FeatureLevel);
m_d3d11Options2.ConservativeRasterizationTier = DetermineConservativeRasterizationTier(FeatureLevel);
m_d3d11Options2.TiledResourcesTier = tiledResourcesTier;
m_d3d11Options2.StandardSwizzle = FALSE;
m_d3d11Options2.UnifiedMemoryArchitecture = FALSE;
if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0)
m_d3d11Options2.MapOnDefaultTextures = TRUE;
if (FeatureLevel >= D3D_FEATURE_LEVEL_11_1) {
m_d3d11Options2.ROVsSupported = FALSE;
m_d3d11Options2.PSSpecifiedStencilRefSupported = m_features.extShaderStencilExport;
}
// More D3D11.3 options
if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0) {
m_d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer =
m_features.vk12.shaderOutputViewportIndex &&
m_features.vk12.shaderOutputLayer;
}
// D3D11.4 options
m_d3d11Options4.ExtendedNV12SharedTextureSupported = TRUE;
// More D3D11.4 options
m_d3d11Options5.SharedResourceTier = DetermineSharedResourceTier(FeatureLevel);
// Double-precision support
if (FeatureLevel >= D3D_FEATURE_LEVEL_11_0)
m_doubles.DoublePrecisionFloatShaderOps = hasDoublePrecisionSupport;
// These numbers are not accurate, but we have no real way to query these
m_gpuVirtualAddress.MaxGPUVirtualAddressBitsPerResource = 32;
m_gpuVirtualAddress.MaxGPUVirtualAddressBitsPerProcess = 40;
// Marker support only depends on the debug utils extension
m_marker.Profile = Instance->extensions().extDebugUtils;
// DXVK will keep all shaders in memory once created, and all Vulkan
// drivers that we know of that can run DXVK have an on-disk cache.
m_shaderCache.SupportFlags = D3D11_SHADER_CACHE_SUPPORT_AUTOMATIC_INPROC_CACHE
| D3D11_SHADER_CACHE_SUPPORT_AUTOMATIC_DISK_CACHE;
// DXVK does not support min precision
m_shaderMinPrecision.PixelShaderMinPrecision = 0;
m_shaderMinPrecision.AllOtherShaderStagesMinPrecision = 0;
// Report native support for command lists here so that we do not actually have
// to re-implement the UpdateSubresource bug from the D3D11 runtime, see MSDN:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx)
m_threading.DriverConcurrentCreates = TRUE;
m_threading.DriverCommandLists = TRUE;
}
D3D11DeviceFeatures::~D3D11DeviceFeatures() {
}
HRESULT D3D11DeviceFeatures::GetFeatureData(
D3D11_FEATURE Feature,
UINT FeatureDataSize,
void* pFeatureData) const {
switch (Feature) {
case D3D11_FEATURE_ARCHITECTURE_INFO:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_architectureInfo);
case D3D11_FEATURE_D3D9_OPTIONS:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d9Options);
case D3D11_FEATURE_D3D9_OPTIONS1:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d9Options1);
case D3D11_FEATURE_D3D9_SHADOW_SUPPORT:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d9Shadow);
case D3D11_FEATURE_D3D9_SIMPLE_INSTANCING_SUPPORT:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d9SimpleInstancing);
case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d10Options);
case D3D11_FEATURE_D3D11_OPTIONS:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d11Options);
case D3D11_FEATURE_D3D11_OPTIONS1:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d11Options1);
case D3D11_FEATURE_D3D11_OPTIONS2:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d11Options2);
case D3D11_FEATURE_D3D11_OPTIONS3:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d11Options3);
case D3D11_FEATURE_D3D11_OPTIONS4:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d11Options4);
case D3D11_FEATURE_D3D11_OPTIONS5:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_d3d11Options5);
case D3D11_FEATURE_DOUBLES:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_doubles);
case D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_gpuVirtualAddress);
case D3D11_FEATURE_MARKER_SUPPORT:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_marker);
case D3D11_FEATURE_SHADER_CACHE:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_shaderCache);
case D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_shaderMinPrecision);
case D3D11_FEATURE_THREADING:
return GetTypedFeatureData(FeatureDataSize, pFeatureData, &m_threading);
default:
Logger::err(str::format("D3D11: Unknown feature: ", Feature));
return E_INVALIDARG;
}
}
D3D11_CONSERVATIVE_RASTERIZATION_TIER D3D11DeviceFeatures::DetermineConservativeRasterizationTier(
D3D_FEATURE_LEVEL FeatureLevel) {
if (FeatureLevel < D3D_FEATURE_LEVEL_11_1
|| !m_features.extConservativeRasterization)
return D3D11_CONSERVATIVE_RASTERIZATION_NOT_SUPPORTED;
// We don't really have a way to query uncertainty regions,
// so just check degenerate triangle behaviour
if (!m_properties.extConservativeRasterization.degenerateTrianglesRasterized)
return D3D11_CONSERVATIVE_RASTERIZATION_TIER_1;
return D3D11_CONSERVATIVE_RASTERIZATION_TIER_2;
}
D3D11_SHARED_RESOURCE_TIER D3D11DeviceFeatures::DetermineSharedResourceTier(
D3D_FEATURE_LEVEL FeatureLevel) {
// Shared resources are all sorts of wonky for obvious
// reasons, so don't over-promise things here for now
return D3D11_SHARED_RESOURCE_TIER_1;
}
D3D11_TILED_RESOURCES_TIER D3D11DeviceFeatures::DetermineTiledResourcesTier(
D3D_FEATURE_LEVEL FeatureLevel) {
if (FeatureLevel < D3D_FEATURE_LEVEL_11_0
|| !m_features.core.features.sparseBinding
|| !m_features.core.features.sparseResidencyBuffer
|| !m_features.core.features.sparseResidencyImage2D
|| !m_features.core.features.sparseResidencyAliased
|| !m_properties.core.properties.sparseProperties.residencyStandard2DBlockShape)
return D3D11_TILED_RESOURCES_NOT_SUPPORTED;
if (FeatureLevel < D3D_FEATURE_LEVEL_11_1
|| !m_features.core.features.shaderResourceResidency
|| !m_features.core.features.shaderResourceMinLod
|| !m_features.vk12.samplerFilterMinmax
|| !m_properties.vk12.filterMinmaxSingleComponentFormats
|| !m_properties.core.properties.sparseProperties.residencyNonResidentStrict
|| m_properties.core.properties.sparseProperties.residencyAlignedMipSize)
return D3D11_TILED_RESOURCES_TIER_1;
if (!m_features.core.features.sparseResidencyImage3D
|| !m_properties.core.properties.sparseProperties.residencyStandard3DBlockShape)
return D3D11_TILED_RESOURCES_TIER_2;
return D3D11_TILED_RESOURCES_TIER_3;
}
BOOL D3D11DeviceFeatures::DetermineUavExtendedTypedLoadSupport(
const Rc<DxvkAdapter>& Adapter,
D3D_FEATURE_LEVEL FeatureLevel) {
static const std::array<VkFormat, 18> s_formats = {{
VK_FORMAT_R32_SFLOAT,
VK_FORMAT_R32_UINT,
VK_FORMAT_R32_SINT,
VK_FORMAT_R32G32B32A32_SFLOAT,
VK_FORMAT_R32G32B32A32_UINT,
VK_FORMAT_R32G32B32A32_SINT,
VK_FORMAT_R16G16B16A16_SFLOAT,
VK_FORMAT_R16G16B16A16_UINT,
VK_FORMAT_R16G16B16A16_SINT,
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8G8B8A8_SINT,
VK_FORMAT_R16_SFLOAT,
VK_FORMAT_R16_UINT,
VK_FORMAT_R16_SINT,
VK_FORMAT_R8_UNORM,
VK_FORMAT_R8_UINT,
VK_FORMAT_R8_SINT,
}};
if (FeatureLevel < D3D_FEATURE_LEVEL_11_0)
return FALSE;
for (auto f : s_formats) {
DxvkFormatFeatures features = Adapter->getFormatFeatures(f);
VkFormatFeatureFlags2 imgFeatures = features.optimal | features.linear;
if (!(imgFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT))
return FALSE;
}
return TRUE;
}
}

View File

@ -0,0 +1,89 @@
#pragma once
#include "d3d11_include.h"
#include "../dxvk/dxvk_adapter.h"
#include "../dxvk/dxvk_instance.h"
namespace dxvk {
/**
* \brief Device features
*
* Stores D3D device feature structs.
*/
class D3D11DeviceFeatures {
public:
D3D11DeviceFeatures();
D3D11DeviceFeatures(
const Rc<DxvkInstance>& Instance,
const Rc<DxvkAdapter>& Adapter,
D3D_FEATURE_LEVEL FeatureLevel);
~D3D11DeviceFeatures();
/**
* \brief Retrieves feature support data
*
* \param [in] Feature D3D feature to query
* \param [in] FeatureDataSize Data size, in bytes
* \param [out] pFeatureData Data
* \returns Status of the operation
*/
HRESULT GetFeatureData(
D3D11_FEATURE Feature,
UINT FeatureDataSize,
void* pFeatureData) const;
private:
DxvkDeviceFeatures m_features;
DxvkDeviceInfo m_properties;
D3D11_FEATURE_DATA_ARCHITECTURE_INFO m_architectureInfo = { };
D3D11_FEATURE_DATA_D3D9_OPTIONS m_d3d9Options = { };
D3D11_FEATURE_DATA_D3D9_OPTIONS1 m_d3d9Options1 = { };
D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT m_d3d9Shadow = { };
D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT m_d3d9SimpleInstancing = { };
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS m_d3d10Options = { };
D3D11_FEATURE_DATA_D3D11_OPTIONS m_d3d11Options = { };
D3D11_FEATURE_DATA_D3D11_OPTIONS1 m_d3d11Options1 = { };
D3D11_FEATURE_DATA_D3D11_OPTIONS2 m_d3d11Options2 = { };
D3D11_FEATURE_DATA_D3D11_OPTIONS3 m_d3d11Options3 = { };
D3D11_FEATURE_DATA_D3D11_OPTIONS4 m_d3d11Options4 = { };
D3D11_FEATURE_DATA_D3D11_OPTIONS5 m_d3d11Options5 = { };
D3D11_FEATURE_DATA_DOUBLES m_doubles = { };
D3D11_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT m_gpuVirtualAddress = { };
D3D11_FEATURE_DATA_MARKER_SUPPORT m_marker = { };
D3D11_FEATURE_DATA_SHADER_CACHE m_shaderCache = { };
D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT m_shaderMinPrecision = { };
D3D11_FEATURE_DATA_THREADING m_threading = { };
template<typename T>
static HRESULT GetTypedFeatureData(UINT Size, void* pDstData, const T* pSrcData) {
if (Size != sizeof(T))
return E_INVALIDARG;
*(reinterpret_cast<T*>(pDstData)) = *pSrcData;
return S_OK;
}
D3D11_CONSERVATIVE_RASTERIZATION_TIER DetermineConservativeRasterizationTier(
D3D_FEATURE_LEVEL FeatureLevel);
D3D11_SHARED_RESOURCE_TIER DetermineSharedResourceTier(
D3D_FEATURE_LEVEL FeatureLevel);
D3D11_TILED_RESOURCES_TIER DetermineTiledResourcesTier(
D3D_FEATURE_LEVEL FeatureLevel);
BOOL DetermineUavExtendedTypedLoadSupport(
const Rc<DxvkAdapter>& Adapter,
D3D_FEATURE_LEVEL FeatureLevel);
};
}

View File

@ -37,6 +37,7 @@ d3d11_src = [
'd3d11_depth_stencil.cpp',
'd3d11_device.cpp',
'd3d11_enums.cpp',
'd3d11_features.cpp',
'd3d11_fence.cpp',
'd3d11_gdi.cpp',
'd3d11_initializer.cpp',