[PATCH vkd3d v2 1/2] vkd3d: Add more features to CheckFeatureSupport().

Conor McCarthy cmccarthy at codeweavers.com
Mon Nov 25 06:12:10 CST 2019


Some games, e.g. Hitman 2, do not check for success, and if the feature
check is unimplemented they will use uninitialised data as the result.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
v2: Fix corrupt patch.
Supersedes 174442.
---
 include/vkd3d_d3d12.idl    | 141 +++++++++++++++++++
 libs/vkd3d/device.c        | 276 +++++++++++++++++++++++++++++++++++++
 libs/vkd3d/vkd3d_private.h |   5 +
 3 files changed, 422 insertions(+)

diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl
index 8246424..3747c8e 100644
--- a/include/vkd3d_d3d12.idl
+++ b/include/vkd3d_d3d12.idl
@@ -1608,6 +1608,141 @@ typedef struct D3D12_FEATURE_DATA_SHADER_MODEL
     D3D_SHADER_MODEL HighestShaderModel;
 } D3D12_FEATURE_DATA_SHADER_MODEL;
 
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS1
+{
+    BOOL WaveOps;
+    UINT WaveLaneCountMin;
+    UINT WaveLaneCountMax;
+    UINT TotalLaneCount;
+    BOOL ExpandedComputeResourceStates;
+    BOOL Int64ShaderOps;
+}  D3D12_FEATURE_DATA_D3D12_OPTIONS1;
+
+typedef enum D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER
+{
+    D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED = 0,
+    D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_1 = 1,
+    D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_2 = 2,
+}  D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS2
+{
+    BOOL DepthBoundsTestSupported;
+    D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER ProgrammableSamplePositionsTier;
+}  D3D12_FEATURE_DATA_D3D12_OPTIONS2;
+
+typedef enum D3D12_SHADER_CACHE_SUPPORT_FLAGS
+{
+    D3D12_SHADER_CACHE_SUPPORT_NONE = 0x0,
+    D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO = 0x1,
+    D3D12_SHADER_CACHE_SUPPORT_LIBRARY = 0x2,
+    D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_INPROC_CACHE = 0x4,
+    D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_DISK_CACHE = 0x8,
+}  D3D12_SHADER_CACHE_SUPPORT_FLAGS;
+
+typedef struct D3D12_FEATURE_DATA_SHADER_CACHE
+{
+    D3D12_SHADER_CACHE_SUPPORT_FLAGS SupportFlags;
+}  D3D12_FEATURE_DATA_SHADER_CACHE;
+
+typedef struct D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY
+{
+    D3D12_COMMAND_LIST_TYPE CommandListType;
+    UINT Priority;
+    BOOL PriorityForTypeIsSupported;
+}  D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY;
+
+typedef struct D3D12_FEATURE_DATA_ARCHITECTURE1
+{
+    UINT NodeIndex;
+    BOOL TileBasedRenderer;
+    BOOL UMA;
+    BOOL CacheCoherentUMA;
+    BOOL IsolatedMMU;
+}  D3D12_FEATURE_DATA_ARCHITECTURE1;
+
+typedef enum D3D12_COMMAND_LIST_SUPPORT_FLAGS
+{
+    D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE = 0x0,
+    D3D12_COMMAND_LIST_SUPPORT_FLAG_DIRECT = 0x1,
+    D3D12_COMMAND_LIST_SUPPORT_FLAG_BUNDLE = 0x2,
+    D3D12_COMMAND_LIST_SUPPORT_FLAG_COMPUTE = 0x4,
+    D3D12_COMMAND_LIST_SUPPORT_FLAG_COPY = 0x8,
+} D3D12_COMMAND_LIST_SUPPORT_FLAGS;
+
+typedef enum D3D12_VIEW_INSTANCING_TIER
+{
+    D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED = 0,
+    D3D12_VIEW_INSTANCING_TIER_1 = 1,
+    D3D12_VIEW_INSTANCING_TIER_2 = 2,
+    D3D12_VIEW_INSTANCING_TIER_3 = 3,
+}  D3D12_VIEW_INSTANCING_TIER;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS3
+{
+    BOOL CopyQueueTimestampQueriesSupported;
+    BOOL CastingFullyTypedFormatSupported;
+    D3D12_COMMAND_LIST_SUPPORT_FLAGS WriteBufferImmediateSupportFlags;
+    D3D12_VIEW_INSTANCING_TIER ViewInstancingTier;
+    BOOL BarycentricsSupported;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS3;
+
+typedef struct D3D12_FEATURE_DATA_EXISTING_HEAPS
+{
+    BOOL Supported;
+}  D3D12_FEATURE_DATA_EXISTING_HEAPS;
+
+typedef enum D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER
+{
+    D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_0 = 0,
+    D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_1 = 1,
+}  D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS4
+{
+    BOOL MSAA64KBAlignedTextureSupported;
+    D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER SharedResourceCompatibilityTier;
+    BOOL Native16BitShaderOpsSupported;
+}  D3D12_FEATURE_DATA_D3D12_OPTIONS4;
+
+typedef enum D3D12_HEAP_SERIALIZATION_TIER
+{
+    D3D12_HEAP_SERIALIZATION_TIER_0 = 0,
+    D3D12_HEAP_SERIALIZATION_TIER_10 = 10,
+}  D3D12_HEAP_SERIALIZATION_TIER;
+
+typedef struct D3D12_FEATURE_DATA_SERIALIZATION
+{
+    UINT NodeIndex;
+    D3D12_HEAP_SERIALIZATION_TIER HeapSerializationTier;
+}  D3D12_FEATURE_DATA_SERIALIZATION;
+
+typedef struct D3D12_FEATURE_DATA_CROSS_NODE
+{
+    D3D12_CROSS_NODE_SHARING_TIER SharingTier;
+    BOOL AtomicShaderInstructions;
+}  D3D12_FEATURE_DATA_CROSS_NODE;
+
+typedef enum D3D12_RENDER_PASS_TIER
+{
+    D3D12_RENDER_PASS_TIER_0 = 0,
+    D3D12_RENDER_PASS_TIER_1 = 1,
+    D3D12_RENDER_PASS_TIER_2 = 2,
+} D3D12_RENDER_PASS_TIER;
+
+typedef enum D3D12_RAYTRACING_TIER
+{
+    D3D12_RAYTRACING_TIER_NOT_SUPPORTED = 0,
+    D3D12_RAYTRACING_TIER_1_0 = 10,
+} D3D12_RAYTRACING_TIER;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS5
+{
+    BOOL SRVOnlyTiledResourceTier3;
+    D3D12_RENDER_PASS_TIER RenderPassesTier;
+    D3D12_RAYTRACING_TIER RaytracingTier;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS5;
+
 typedef enum D3D12_FEATURE
 {
     D3D12_FEATURE_D3D12_OPTIONS = 0,
@@ -1624,6 +1759,12 @@ typedef enum D3D12_FEATURE
     D3D12_FEATURE_D3D12_OPTIONS2 = 18,
     D3D12_FEATURE_SHADER_CACHE = 19,
     D3D12_FEATURE_COMMAND_QUEUE_PRIORITY = 20,
+    D3D12_FEATURE_D3D12_OPTIONS3 = 21,
+    D3D12_FEATURE_EXISTING_HEAPS = 22,
+    D3D12_FEATURE_D3D12_OPTIONS4 = 23,
+    D3D12_FEATURE_SERIALIZATION = 24,
+    D3D12_FEATURE_CROSS_NODE = 25,
+    D3D12_FEATURE_D3D12_OPTIONS5 = 27,
 } D3D12_FEATURE;
 
 typedef struct D3D12_MEMCPY_DEST
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 7ff567d..cd850c9 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1336,6 +1336,33 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
     device->feature_options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = FALSE;
     device->feature_options.ResourceHeapTier = D3D12_RESOURCE_HEAP_TIER_2;
 
+    device->feature_options1.WaveOps = FALSE;
+    device->feature_options1.WaveLaneCountMin = 0;
+    device->feature_options1.WaveLaneCountMax = 0;
+    device->feature_options1.TotalLaneCount = 0;
+    device->feature_options1.ExpandedComputeResourceStates = TRUE;
+    device->feature_options1.Int64ShaderOps = features->shaderInt64;
+
+    /* Depth bounds test is enabled in D3D12_DEPTH_STENCIL_DESC1, which is not supported. */
+    device->feature_options2.DepthBoundsTestSupported = FALSE;
+    /* d3d12_command_list_SetSamplePositions() is not implemented. */
+    device->feature_options2.ProgrammableSamplePositionsTier = D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED;
+
+    device->feature_options3.CopyQueueTimestampQueriesSupported = FALSE;
+    device->feature_options3.CastingFullyTypedFormatSupported = FALSE;
+    device->feature_options3.WriteBufferImmediateSupportFlags = D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE;
+    device->feature_options3.ViewInstancingTier = D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED;
+    device->feature_options3.BarycentricsSupported = FALSE;
+
+    /* Alignment support can be tested later. */
+    device->feature_options4.MSAA64KBAlignedTextureSupported = FALSE;
+    device->feature_options4.SharedResourceCompatibilityTier = D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_0;
+    device->feature_options4.Native16BitShaderOpsSupported = features->shaderInt16;
+
+    device->feature_options5.SRVOnlyTiledResourceTier3 = FALSE;
+    device->feature_options5.RenderPassesTier = D3D12_RENDER_PASS_TIER_0;
+    device->feature_options5.RaytracingTier = D3D12_RAYTRACING_TIER_NOT_SUPPORTED;
+
     if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
     {
         ERR("Failed to enumerate device extensions, vr %d.\n", vr);
@@ -1590,6 +1617,8 @@ static HRESULT d3d12_device_create_vkd3d_queues(struct d3d12_device *device,
     else
         goto out_destroy_queues;
 
+    device->feature_options3.CopyQueueTimestampQueriesSupported = !!device->copy_queue->timestamp_bits;
+
     return S_OK;
 
 out_destroy_queues:
@@ -2433,6 +2462,27 @@ bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent)
     return true;
 }
 
+static bool d3d12_is_64k_msaa_supported(struct d3d12_device *device)
+{
+    D3D12_RESOURCE_ALLOCATION_INFO info;
+    D3D12_RESOURCE_DESC resource_desc;
+
+    memset(&resource_desc, 0, sizeof(resource_desc));
+    resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+    resource_desc.Width = 1024;
+    resource_desc.Height = 1024;
+    resource_desc.DepthOrArraySize = 1;
+    resource_desc.MipLevels = 1;
+    resource_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+    resource_desc.SampleDesc.Count = 4;
+    resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+
+    /* FIXME: is some cases Vulkan requires 0x20000 or more for non-MSAA resources which must have
+     * 0x10000 in their description, so we might resonably return true here for 0x20000 or 0x40000. */
+    return SUCCEEDED(vkd3d_get_image_allocation_info(device, &resource_desc, &info))
+            && info.Alignment <= 0x10000;
+}
+
 static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *iface,
         D3D12_FEATURE feature, void *feature_data, UINT feature_data_size)
 {
@@ -2683,6 +2733,27 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
             return S_OK;
         }
 
+        case D3D12_FEATURE_D3D12_OPTIONS1:
+        {
+            D3D12_FEATURE_DATA_D3D12_OPTIONS1 *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            *data = device->feature_options1;
+
+            TRACE("Wave ops %#x.\n", data->WaveOps);
+            TRACE("Min wave lane count %#x.\n", data->WaveLaneCountMin);
+            TRACE("Max wave lane count %#x.\n", data->WaveLaneCountMax);
+            TRACE("Total lane count %#x.\n", data->TotalLaneCount);
+            TRACE("Expanded compute resource states %#x.\n", data->ExpandedComputeResourceStates);
+            TRACE("Int64 shader ops %#x.\n", data->Int64ShaderOps);
+            return S_OK;
+        }
+
         case D3D12_FEATURE_ROOT_SIGNATURE:
         {
             D3D12_FEATURE_DATA_ROOT_SIGNATURE *data = feature_data;
@@ -2700,6 +2771,211 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
             return S_OK;
         }
 
+        case D3D12_FEATURE_ARCHITECTURE1:
+        {
+            D3D12_FEATURE_DATA_ARCHITECTURE1 *data = feature_data;
+            bool coherent;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            if (data->NodeIndex)
+            {
+                FIXME("Multi-adapter not supported.\n");
+                return E_INVALIDARG;
+            }
+
+            WARN("Assuming device does not support tile based rendering.\n");
+            data->TileBasedRenderer = FALSE;
+
+            data->UMA = d3d12_device_is_uma(device, &coherent);
+            data->CacheCoherentUMA = data->UMA ? coherent : FALSE;
+
+            WARN("Assuming device does not have an isolated memory management unit.\n");
+            data->IsolatedMMU = FALSE;
+
+            TRACE("Tile based renderer %#x, UMA %#x, cache coherent UMA %#x, isolated MMU %#x.\n",
+                    data->TileBasedRenderer, data->UMA, data->CacheCoherentUMA, data->IsolatedMMU);
+            return S_OK;
+        }
+
+        case D3D12_FEATURE_D3D12_OPTIONS2:
+        {
+            D3D12_FEATURE_DATA_D3D12_OPTIONS2 *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            *data = device->feature_options2;
+
+            TRACE("Depth bounds test %#x.\n", data->DepthBoundsTestSupported);
+            TRACE("Programmable sample positions tier %#x.\n", data->ProgrammableSamplePositionsTier);
+            return S_OK;
+        }
+
+        case D3D12_FEATURE_SHADER_CACHE:
+        {
+            D3D12_FEATURE_DATA_SHADER_CACHE *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            /* FIXME: The D3D12 documentation states that D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO is
+             * always supported, but the CachedPSO field of D3D12_GRAPHICS_PIPELINE_STATE_DESC is
+             * ignored and GetCachedBlob() is a stub. */
+            data->SupportFlags = D3D12_SHADER_CACHE_SUPPORT_NONE;
+
+            TRACE("Shader cache support %#x.\n", data->SupportFlags);
+            return S_OK;
+        }
+
+        case D3D12_FEATURE_COMMAND_QUEUE_PRIORITY:
+        {
+            D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            switch (data->CommandListType)
+            {
+                case D3D12_COMMAND_LIST_TYPE_DIRECT:
+                case D3D12_COMMAND_LIST_TYPE_COMPUTE:
+                case D3D12_COMMAND_LIST_TYPE_COPY:
+                    data->PriorityForTypeIsSupported = FALSE;
+                    TRACE("Command list type %#x, priority %u, supported %#x.\n",
+                            data->CommandListType, data->Priority, data->PriorityForTypeIsSupported);
+                    return S_OK;
+
+                default:
+                    FIXME("Unhandled command list type %#x.\n", data->CommandListType);
+                    return E_INVALIDARG;
+            }
+        }
+
+        case D3D12_FEATURE_D3D12_OPTIONS3:
+        {
+            D3D12_FEATURE_DATA_D3D12_OPTIONS3 *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            *data = device->feature_options3;
+
+            TRACE("Copy queue timestamp queries %#x.\n", data->CopyQueueTimestampQueriesSupported);
+            TRACE("Casting fully typed format %#x.\n", data->CastingFullyTypedFormatSupported);
+            TRACE("Write buffer immediate %#x.\n", data->WriteBufferImmediateSupportFlags);
+            TRACE("View instancing tier %#x.\n", data->ViewInstancingTier);
+            TRACE("Barycentrics %#x.\n", data->BarycentricsSupported);
+            return S_OK;
+        }
+
+        case D3D12_FEATURE_EXISTING_HEAPS:
+        {
+            D3D12_FEATURE_DATA_EXISTING_HEAPS *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            data->Supported = FALSE;
+
+            TRACE("Existing heaps %#x.\n", data->Supported);
+            return S_OK;
+        }
+
+        case D3D12_FEATURE_D3D12_OPTIONS4:
+        {
+            D3D12_FEATURE_DATA_D3D12_OPTIONS4 *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            *data = device->feature_options4;
+            data->MSAA64KBAlignedTextureSupported = d3d12_is_64k_msaa_supported(device);
+
+            TRACE("64KB aligned MSAA textures %#x.\n", data->MSAA64KBAlignedTextureSupported);
+            TRACE("Shared resource compatibility tier %#x.\n", data->SharedResourceCompatibilityTier);
+            TRACE("Native 16-bit shader ops %#x.\n", data->Native16BitShaderOpsSupported);
+            return S_OK;
+        }
+
+        case D3D12_FEATURE_SERIALIZATION:
+        {
+            D3D12_FEATURE_DATA_SERIALIZATION *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+            if (data->NodeIndex)
+            {
+                FIXME("Multi-adapter not supported.\n");
+                return E_INVALIDARG;
+            }
+
+            data->HeapSerializationTier = D3D12_HEAP_SERIALIZATION_TIER_0;
+
+            TRACE("Heap serialization tier %#x.\n", data->HeapSerializationTier);
+            return S_OK;
+        }
+
+        case D3D12_FEATURE_CROSS_NODE:
+        {
+            D3D12_FEATURE_DATA_CROSS_NODE *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            data->SharingTier = D3D12_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED;
+            data->AtomicShaderInstructions = FALSE;
+
+            TRACE("Cross node sharing tier %#x.\n", data->SharingTier);
+            TRACE("Cross node shader atomics %#x.\n", data->AtomicShaderInstructions);
+            return S_OK;
+        }
+
+        case D3D12_FEATURE_D3D12_OPTIONS5:
+        {
+            D3D12_FEATURE_DATA_D3D12_OPTIONS5 *data = feature_data;
+
+            if (feature_data_size != sizeof(*data))
+            {
+                WARN("Invalid size %u.\n", feature_data_size);
+                return E_INVALIDARG;
+            }
+
+            *data = device->feature_options5;
+
+            TRACE("SRV tiled resource tier 3 only %#x.\n", data->SRVOnlyTiledResourceTier3);
+            TRACE("Render pass tier %#x.\n", data->RenderPassesTier);
+            TRACE("Ray tracing tier %#x.\n", data->RaytracingTier);
+            return S_OK;
+        }
+
         default:
             FIXME("Unhandled feature %#x.\n", feature);
             return E_NOTIMPL;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 9edf96e..7ba1db4 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -1086,6 +1086,11 @@ struct d3d12_device
     PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback;
 
     D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options;
+    D3D12_FEATURE_DATA_D3D12_OPTIONS1 feature_options1;
+    D3D12_FEATURE_DATA_D3D12_OPTIONS2 feature_options2;
+    D3D12_FEATURE_DATA_D3D12_OPTIONS3 feature_options3;
+    D3D12_FEATURE_DATA_D3D12_OPTIONS4 feature_options4;
+    D3D12_FEATURE_DATA_D3D12_OPTIONS5 feature_options5;
 
     struct vkd3d_vulkan_info vk_info;
 
-- 
2.24.0




More information about the wine-devel mailing list