// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #ifndef DIRECTX_HEADERS_MOCK_DEVICE_HPP #define DIRECTX_HEADERS_MOCK_DEVICE_HPP #include #ifndef __RPC_FAR #define __RPC_FAR #endif #include #include #include #include "dxguids/dxguids.h" class MockDevice : public ID3D12Device { public: // Constructors and custom functions MockDevice(UINT NodeCount = 1) : m_NodeCount(NodeCount) , m_TileBasedRenderer(m_NodeCount, false) , m_UMA(m_NodeCount, false) , m_CacheCoherentUMA(m_NodeCount, false) , m_IsolatedMMU(m_NodeCount, false) , m_ProtectedResourceSessionSupport(m_NodeCount, D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG_NONE) , m_HeapSerializationTier(m_NodeCount, D3D12_HEAP_SERIALIZATION_TIER_0) , m_ProtectedResourceSessionTypeCount(m_NodeCount, 0) , m_ProtectedResourceSessionTypes(m_NodeCount) { } virtual ~MockDevice() = default; void SetNodeCount(UINT NewCount) { m_NodeCount = NewCount; m_TileBasedRenderer.resize(NewCount); m_UMA.resize(NewCount); m_CacheCoherentUMA.resize(NewCount); m_IsolatedMMU.resize(NewCount); m_ProtectedResourceSessionSupport.resize(NewCount); m_HeapSerializationTier.resize(NewCount); m_ProtectedResourceSessionTypeCount.resize(NewCount); m_ProtectedResourceSessionTypes.resize(NewCount); } public: // ID3D12Device UINT STDMETHODCALLTYPE GetNodeCount() override { return m_NodeCount; } HRESULT STDMETHODCALLTYPE CreateCommandQueue( _In_ const D3D12_COMMAND_QUEUE_DESC *pDesc, REFIID riid, _COM_Outptr_ void **ppCommandQueue ) override { return S_OK; } HRESULT STDMETHODCALLTYPE CreateCommandAllocator( _In_ D3D12_COMMAND_LIST_TYPE type, REFIID riid, _COM_Outptr_ void **ppCommandAllocator ) override { return S_OK; } HRESULT STDMETHODCALLTYPE CreateGraphicsPipelineState( _In_ const D3D12_GRAPHICS_PIPELINE_STATE_DESC *pDesc, REFIID riid, _COM_Outptr_ void **ppPipelineState ) override { return S_OK; } HRESULT STDMETHODCALLTYPE CreateComputePipelineState( _In_ const D3D12_COMPUTE_PIPELINE_STATE_DESC *pDesc, REFIID riid, _COM_Outptr_ void **ppPipelineState ) override { return S_OK; } HRESULT STDMETHODCALLTYPE CreateCommandList( _In_ UINT nodeMask, _In_ D3D12_COMMAND_LIST_TYPE type, _In_ ID3D12CommandAllocator *pCommandAllocator, _In_opt_ ID3D12PipelineState *pInitialState, REFIID riid, _COM_Outptr_ void **ppCommandList ) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE CreateDescriptorHeap( _In_ const D3D12_DESCRIPTOR_HEAP_DESC *pDescriptorHeapDesc, REFIID riid, _COM_Outptr_ void **ppvHeap ) override { return S_OK; } virtual UINT STDMETHODCALLTYPE GetDescriptorHandleIncrementSize( _In_ D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType ) override { return 0; } virtual HRESULT STDMETHODCALLTYPE CreateRootSignature( _In_ UINT nodeMask, _In_reads_(blobLengthInBytes) const void *pBlobWithRootSignature, _In_ SIZE_T blobLengthInBytes, REFIID riid, _COM_Outptr_ void **ppvRootSignature ) override { return S_OK; } virtual void STDMETHODCALLTYPE CreateConstantBufferView( _In_opt_ const D3D12_CONSTANT_BUFFER_VIEW_DESC *pDesc, _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor ) override { return; } virtual void STDMETHODCALLTYPE CreateShaderResourceView( _In_opt_ ID3D12Resource *pResource, _In_opt_ const D3D12_SHADER_RESOURCE_VIEW_DESC *pDesc, _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor ) override { return; } virtual void STDMETHODCALLTYPE CreateUnorderedAccessView( _In_opt_ ID3D12Resource *pResource, _In_opt_ ID3D12Resource *pCounterResource, _In_opt_ const D3D12_UNORDERED_ACCESS_VIEW_DESC *pDesc, _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor ) override { return; } virtual void STDMETHODCALLTYPE CreateRenderTargetView( _In_opt_ ID3D12Resource *pResource, _In_opt_ const D3D12_RENDER_TARGET_VIEW_DESC *pDesc, _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor ) override { return; } virtual void STDMETHODCALLTYPE CreateDepthStencilView( _In_opt_ ID3D12Resource *pResource, _In_opt_ const D3D12_DEPTH_STENCIL_VIEW_DESC *pDesc, _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor) override { return; } virtual void STDMETHODCALLTYPE CreateSampler( _In_ const D3D12_SAMPLER_DESC *pDesc, _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor) override { return; } virtual void STDMETHODCALLTYPE CopyDescriptors( _In_ UINT NumDestDescriptorRanges, _In_reads_(NumDestDescriptorRanges) const D3D12_CPU_DESCRIPTOR_HANDLE *pDestDescriptorRangeStarts, _In_reads_opt_(NumDestDescriptorRanges) const UINT *pDestDescriptorRangeSizes, _In_ UINT NumSrcDescriptorRanges, _In_reads_(NumSrcDescriptorRanges) const D3D12_CPU_DESCRIPTOR_HANDLE *pSrcDescriptorRangeStarts, _In_reads_opt_(NumSrcDescriptorRanges) const UINT *pSrcDescriptorRangeSizes, _In_ D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType) override { return; } virtual void STDMETHODCALLTYPE CopyDescriptorsSimple( _In_ UINT NumDescriptors, _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptorRangeStart, _In_ D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRangeStart, _In_ D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType) override { return; } #if defined(_MSC_VER) || !defined(_WIN32) virtual D3D12_RESOURCE_ALLOCATION_INFO STDMETHODCALLTYPE GetResourceAllocationInfo( _In_ UINT visibleMask, _In_ UINT numResourceDescs, _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC *pResourceDescs) override { D3D12_RESOURCE_ALLOCATION_INFO mockInfo = {}; return mockInfo; } #else virtual D3D12_RESOURCE_ALLOCATION_INFO *STDMETHODCALLTYPE GetResourceAllocationInfo( D3D12_RESOURCE_ALLOCATION_INFO * RetVal, _In_ UINT visibleMask, _In_ UINT numResourceDescs, _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC *pResourceDescs) override { if (RetVal) { *RetVal = {}; } return RetVal; } #endif #if defined(_MSC_VER) || !defined(_WIN32) virtual D3D12_HEAP_PROPERTIES STDMETHODCALLTYPE GetCustomHeapProperties( _In_ UINT nodeMask, D3D12_HEAP_TYPE heapType) override { D3D12_HEAP_PROPERTIES mockProps = {}; return mockProps; } #else virtual D3D12_HEAP_PROPERTIES *STDMETHODCALLTYPE GetCustomHeapProperties( D3D12_HEAP_PROPERTIES * RetVal, _In_ UINT nodeMask, D3D12_HEAP_TYPE heapType) override { if (RetVal) { *RetVal = {}; } return RetVal; } #endif virtual HRESULT STDMETHODCALLTYPE CreateCommittedResource( _In_ const D3D12_HEAP_PROPERTIES *pHeapProperties, D3D12_HEAP_FLAGS HeapFlags, _In_ const D3D12_RESOURCE_DESC *pDesc, D3D12_RESOURCE_STATES InitialResourceState, _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, REFIID riidResource, _COM_Outptr_opt_ void **ppvResource) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE CreateHeap( _In_ const D3D12_HEAP_DESC *pDesc, REFIID riid, _COM_Outptr_opt_ void **ppvHeap) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE CreatePlacedResource( _In_ ID3D12Heap *pHeap, UINT64 HeapOffset, _In_ const D3D12_RESOURCE_DESC *pDesc, D3D12_RESOURCE_STATES InitialState, _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, REFIID riid, _COM_Outptr_opt_ void **ppvResource) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE CreateReservedResource( _In_ const D3D12_RESOURCE_DESC *pDesc, D3D12_RESOURCE_STATES InitialState, _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, REFIID riid, _COM_Outptr_opt_ void **ppvResource) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE CreateSharedHandle( _In_ ID3D12DeviceChild *pObject, _In_opt_ const SECURITY_ATTRIBUTES *pAttributes, DWORD Access, _In_opt_ LPCWSTR Name, _Out_ HANDLE *pHandle) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE OpenSharedHandle( _In_ HANDLE NTHandle, REFIID riid, _COM_Outptr_opt_ void **ppvObj) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE OpenSharedHandleByName( _In_ LPCWSTR Name, DWORD Access, /* [annotation][out] */ _Out_ HANDLE *pNTHandle) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE MakeResident( UINT NumObjects, _In_reads_(NumObjects) ID3D12Pageable *const *ppObjects) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE Evict( UINT NumObjects, _In_reads_(NumObjects) ID3D12Pageable *const *ppObjects) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE CreateFence( UINT64 InitialValue, D3D12_FENCE_FLAGS Flags, REFIID riid, _COM_Outptr_ void **ppFence) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason( void) override { return S_OK; } virtual void STDMETHODCALLTYPE GetCopyableFootprints( _In_ const D3D12_RESOURCE_DESC *pResourceDesc, _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, UINT64 BaseOffset, _Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT *pLayouts, _Out_writes_opt_(NumSubresources) UINT *pNumRows, _Out_writes_opt_(NumSubresources) UINT64 *pRowSizeInBytes, _Out_opt_ UINT64 *pTotalBytes) override { return; } virtual HRESULT STDMETHODCALLTYPE CreateQueryHeap( _In_ const D3D12_QUERY_HEAP_DESC *pDesc, REFIID riid, _COM_Outptr_opt_ void **ppvHeap) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE SetStablePowerState( BOOL Enable) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE CreateCommandSignature( _In_ const D3D12_COMMAND_SIGNATURE_DESC *pDesc, _In_opt_ ID3D12RootSignature *pRootSignature, REFIID riid, _COM_Outptr_opt_ void **ppvCommandSignature) override { return S_OK; } virtual void STDMETHODCALLTYPE GetResourceTiling( _In_ ID3D12Resource *pTiledResource, _Out_opt_ UINT *pNumTilesForEntireResource, _Out_opt_ D3D12_PACKED_MIP_INFO *pPackedMipDesc, _Out_opt_ D3D12_TILE_SHAPE *pStandardTileShapeForNonPackedMips, _Inout_opt_ UINT *pNumSubresourceTilings, _In_ UINT FirstSubresourceTilingToGet, _Out_writes_(*pNumSubresourceTilings) D3D12_SUBRESOURCE_TILING *pSubresourceTilingsForNonPackedMips) override { return; } #if defined(_MSC_VER) || !defined(_WIN32) virtual LUID STDMETHODCALLTYPE GetAdapterLuid( void) override { LUID mockLuid = {}; return mockLuid; } #else virtual LUID *STDMETHODCALLTYPE GetAdapterLuid( LUID * RetVal) override { if (RetVal) { *RetVal = {}; } return RetVal; } #endif public: // ID3D12Object virtual HRESULT STDMETHODCALLTYPE GetPrivateData( _In_ REFGUID guid, _Inout_ UINT *pDataSize, _Out_writes_bytes_opt_( *pDataSize ) void *pData) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE SetPrivateData( _In_ REFGUID guid, _In_ UINT DataSize, _In_reads_bytes_opt_( DataSize ) const void *pData) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( _In_ REFGUID guid, _In_opt_ const IUnknown *pData) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE SetName( _In_z_ LPCWSTR Name) override { return S_OK; } public: // IUnknown virtual HRESULT STDMETHODCALLTYPE QueryInterface( /* [in] */ REFIID riid, /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) override { *ppvObject = this; return S_OK; } virtual ULONG STDMETHODCALLTYPE AddRef() override { // Casual implementation. No actual actions return 0; } virtual ULONG STDMETHODCALLTYPE Release() override { return 0; } // Major function we need to work with virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport( D3D12_FEATURE Feature, _Inout_updates_bytes_(FeatureSupportDataSize) void *pFeatureSupportData, UINT FeatureSupportDataSize ) override { switch( Feature ) { case D3D12_FEATURE_D3D12_OPTIONS: { D3D12_FEATURE_DATA_D3D12_OPTIONS* pD3D12Options = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS)) { return E_INVALIDARG; } pD3D12Options->DoublePrecisionFloatShaderOps = m_DoublePrecisionFloatShaderOps; pD3D12Options->OutputMergerLogicOp = m_OutputMergerLogicOp; pD3D12Options->MinPrecisionSupport = m_ShaderMinPrecisionSupport10Bit | m_ShaderMinPrecisionSupport16Bit; pD3D12Options->TiledResourcesTier = m_TiledResourcesTier; pD3D12Options->ResourceBindingTier = m_ResourceBindingTier; pD3D12Options->PSSpecifiedStencilRefSupported = (m_FeatureLevel >= D3D_FEATURE_LEVEL_11_1) && m_PSSpecifiedStencilRefSupported; pD3D12Options->TypedUAVLoadAdditionalFormats = (m_FeatureLevel >= D3D_FEATURE_LEVEL_11_0) && m_TypedUAVLoadAdditionalFormats; pD3D12Options->ROVsSupported = (m_FeatureLevel >= D3D_FEATURE_LEVEL_11_0) && m_ROVsSupported; pD3D12Options->ConservativeRasterizationTier = (m_FeatureLevel >= D3D_FEATURE_LEVEL_11_1) ? m_ConservativeRasterizationTier : D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED; pD3D12Options->MaxGPUVirtualAddressBitsPerResource = m_MaxGPUVirtualAddressBitsPerResource; pD3D12Options->StandardSwizzle64KBSupported = m_StandardSwizzle64KBSupported; #ifdef DX_ASTC_PROTOTYPE_ENABLED pD3D12Options->ASTCProfile = ASTCProfile(); #endif pD3D12Options->CrossNodeSharingTier = m_CrossNodeSharingTier; pD3D12Options->CrossAdapterRowMajorTextureSupported = m_CrossAdapterRowMajorTextureSupported; pD3D12Options->VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = m_VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation; pD3D12Options->ResourceHeapTier = m_ResourceHeapTier; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS1: { if (!m_Options1Available) { return E_INVALIDARG; } D3D12_FEATURE_DATA_D3D12_OPTIONS1* pD3D12Options1 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS1)) { return E_INVALIDARG; } pD3D12Options1->WaveOps = m_WaveOpsSupported; pD3D12Options1->WaveLaneCountMin = m_WaveLaneCountMin; pD3D12Options1->WaveLaneCountMax = m_WaveLaneCountMax; pD3D12Options1->TotalLaneCount = m_TotalLaneCount; pD3D12Options1->ExpandedComputeResourceStates = m_ExpandedComputeResourceStates; pD3D12Options1->Int64ShaderOps = m_Int64ShaderOpsSupported; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS2: { if (!m_Options2Available) { return E_INVALIDARG; } D3D12_FEATURE_DATA_D3D12_OPTIONS2* pD3D12Options2 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS2)) { return E_INVALIDARG; } pD3D12Options2->DepthBoundsTestSupported = m_DepthBoundsTestSupport; pD3D12Options2->ProgrammableSamplePositionsTier = m_ProgrammableSamplePositionsTier; } return S_OK; case D3D12_FEATURE_ROOT_SIGNATURE: { if (!m_RootSignatureAvailable) { return E_INVALIDARG; } D3D12_FEATURE_DATA_ROOT_SIGNATURE* pRootSig = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(D3D12_FEATURE_DATA_ROOT_SIGNATURE)) { return E_INVALIDARG; } switch (pRootSig->HighestVersion) { case D3D_ROOT_SIGNATURE_VERSION_1_0: case D3D_ROOT_SIGNATURE_VERSION_1_1: break; default: return E_INVALIDARG; } pRootSig->HighestVersion = static_cast(std::min(pRootSig->HighestVersion, m_RootSignatureHighestVersion)); } return S_OK; case D3D12_FEATURE_ARCHITECTURE: { D3D12_FEATURE_DATA_ARCHITECTURE* pFData = static_cast< D3D12_FEATURE_DATA_ARCHITECTURE* >( pFeatureSupportData ); if (FeatureSupportDataSize != sizeof( *pFData )) { return E_INVALIDARG; } // Testing only // If Architecture1 is available, use data from architecture1 if (m_Architecture1Available) { D3D12_FEATURE_DATA_ARCHITECTURE1 CurFData; CurFData.NodeIndex = pFData->NodeIndex; HRESULT hr; if (FAILED( hr = CheckFeatureSupport( D3D12_FEATURE_ARCHITECTURE1, &CurFData, sizeof( CurFData ) ) )) { return hr; } pFData->TileBasedRenderer = CurFData.TileBasedRenderer; pFData->UMA = CurFData.UMA; pFData->CacheCoherentUMA = CurFData.CacheCoherentUMA; } else // Otherwise, load the data directly { // The original procedure will generate and return an E_INVALIDARG error if the NodeIndex is out of scope // Mocking the behavior here by returning the rror if (!(pFData->NodeIndex < m_NodeCount)) { return E_INVALIDARG; } pFData->TileBasedRenderer = m_TileBasedRenderer[pFData->NodeIndex]; pFData->UMA = m_UMA[pFData->NodeIndex]; pFData->CacheCoherentUMA = m_CacheCoherentUMA[pFData->NodeIndex]; // Note that Architecture doesn't have the IsolatedMMU field. } } return S_OK; case D3D12_FEATURE_ARCHITECTURE1: { // Mocking the case where ARCHITECTURE1 is not supported if (!m_Architecture1Available || !m_ArchitectureSucceed) { return E_INVALIDARG; } D3D12_FEATURE_DATA_ARCHITECTURE1* pFData = static_cast< D3D12_FEATURE_DATA_ARCHITECTURE1* >( pFeatureSupportData ); if (FeatureSupportDataSize != sizeof( *pFData )) { return E_INVALIDARG; } // The original procedure will generate and return an E_INVALIDARG error if the NodeIndex is out of scope // Mocking the behavior here by returning the rror if (!(pFData->NodeIndex < m_NodeCount)) { return E_INVALIDARG; } UINT localIndex = pFData->NodeIndex; pFData->TileBasedRenderer = m_TileBasedRenderer[localIndex]; pFData->UMA = m_UMA[localIndex]; pFData->CacheCoherentUMA = m_CacheCoherentUMA[localIndex]; pFData->IsolatedMMU = m_IsolatedMMU[localIndex]; } return S_OK; case D3D12_FEATURE_FEATURE_LEVELS: { D3D12_FEATURE_DATA_FEATURE_LEVELS* pFData = static_cast< D3D12_FEATURE_DATA_FEATURE_LEVELS* >( pFeatureSupportData ); if (FeatureSupportDataSize != sizeof( *pFData )) { return E_INVALIDARG; } if (pFData->NumFeatureLevels == 0 || pFData->pFeatureLevelsRequested == nullptr) { return E_INVALIDARG; } pFData->MaxSupportedFeatureLevel = D3D_FEATURE_LEVEL(0); for (UINT i = 0; i < pFData->NumFeatureLevels; ++i) { if (pFData->pFeatureLevelsRequested[i] <= m_FeatureLevel && pFData->pFeatureLevelsRequested[i] > pFData->MaxSupportedFeatureLevel) { pFData->MaxSupportedFeatureLevel = pFData->pFeatureLevelsRequested[i]; } } return pFData->MaxSupportedFeatureLevel == D3D_FEATURE_LEVEL(0) ? DXGI_ERROR_UNSUPPORTED : S_OK; } case D3D12_FEATURE_FORMAT_SUPPORT: { D3D12_FEATURE_DATA_FORMAT_SUPPORT* pFData = static_cast< D3D12_FEATURE_DATA_FORMAT_SUPPORT* >( pFeatureSupportData ); if (FeatureSupportDataSize != sizeof( *pFData )) { return E_INVALIDARG; } m_FormatReceived = pFData->Format; pFData->Support1 = m_FormatSupport1; pFData->Support2 = m_FormatSupport2; // Based on the original implementation, if there's no support for the format, return an E_FAIL if (m_FormatSupport1 == D3D12_FORMAT_SUPPORT1_NONE && m_FormatSupport2 == D3D12_FORMAT_SUPPORT2_NONE) { return E_FAIL; } } return S_OK; case D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS: { D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS* pFData = static_cast< D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS* >( pFeatureSupportData ); if (FeatureSupportDataSize != sizeof( *pFData )) { return E_INVALIDARG; } m_FormatReceived = pFData->Format; m_SampleCountReceived = pFData->SampleCount; m_MultisampleQualityLevelFlagsReceived = pFData->Flags; // The original check implementation may return E_FAIL // Valid results are non-negative values including 0, smaller than D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT if (!m_MultisampleQualityLevelsSucceed) { // NumQualityLevels will be set to 0 should the check fails pFData->NumQualityLevels = 0; return E_FAIL; } pFData->NumQualityLevels = m_NumQualityLevels; } return S_OK; case D3D12_FEATURE_FORMAT_INFO: { D3D12_FEATURE_DATA_FORMAT_INFO* pFData = static_cast< D3D12_FEATURE_DATA_FORMAT_INFO* > ( pFeatureSupportData ); if (FeatureSupportDataSize != sizeof( *pFData )) { return E_INVALIDARG; } m_FormatReceived = pFData->Format; // If the format is not supported, an E_INVALIDARG will be returned if (!m_DXGIFormatSupported) { return E_INVALIDARG; } pFData->PlaneCount = m_PlaneCount; } return S_OK; case D3D12_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT: { D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT* pFData = static_cast< D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT* >( pFeatureSupportData ); if (FeatureSupportDataSize != sizeof( *pFData )) { return E_INVALIDARG; } pFData->MaxGPUVirtualAddressBitsPerProcess = m_MaxGPUVirtualAddressBitsPerProcess; pFData->MaxGPUVirtualAddressBitsPerResource = m_MaxGPUVirtualAddressBitsPerResource; } return S_OK; case D3D12_FEATURE_SHADER_MODEL: { D3D12_FEATURE_DATA_SHADER_MODEL* pSM = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pSM)) { return E_INVALIDARG; } switch (pSM->HighestShaderModel) { case D3D_SHADER_MODEL_5_1: case D3D_SHADER_MODEL_6_0: case D3D_SHADER_MODEL_6_1: case D3D_SHADER_MODEL_6_2: case D3D_SHADER_MODEL_6_3: case D3D_SHADER_MODEL_6_4: case D3D_SHADER_MODEL_6_5: case D3D_SHADER_MODEL_6_6: case D3D_SHADER_MODEL_6_7: break; default: return E_INVALIDARG; } pSM->HighestShaderModel = static_cast(std::min(pSM->HighestShaderModel,m_HighestSupportedShaderModel)); } return S_OK; case D3D12_FEATURE_SHADER_CACHE: { if (!m_ShaderCacheAvailable) { return E_INVALIDARG; } D3D12_FEATURE_DATA_SHADER_CACHE* pFlags = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pFlags)) { return E_INVALIDARG; } pFlags->SupportFlags = m_ShaderCacheSupportFlags; } return S_OK; case D3D12_FEATURE_COMMAND_QUEUE_PRIORITY: { if (!m_CommandQueuePriorityAvailable) { return E_INVALIDARG; } D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY* pFlags = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pFlags)) { return E_INVALIDARG; } if (pFlags->CommandListType >= D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE+1) { return E_INVALIDARG; } if (pFlags->Priority == D3D12_COMMAND_QUEUE_PRIORITY_NORMAL || pFlags->Priority == D3D12_COMMAND_QUEUE_PRIORITY_HIGH) { pFlags->PriorityForTypeIsSupported = TRUE; } else if (pFlags->Priority == D3D12_COMMAND_QUEUE_PRIORITY_GLOBAL_REALTIME) { pFlags->PriorityForTypeIsSupported = m_GlobalRealtimeCommandQueueSupport; // Simplified } else { return E_INVALIDARG; } } return S_OK; case D3D12_FEATURE_PROTECTED_RESOURCE_SESSION_SUPPORT: { if (!m_ProtectedResourceSessionAvailable) { return E_INVALIDARG; } D3D12_FEATURE_DATA_PROTECTED_RESOURCE_SESSION_SUPPORT* pProtectedResourceSessionSupport = static_cast(pFeatureSupportData); if ( FeatureSupportDataSize != sizeof(*pProtectedResourceSessionSupport) || pProtectedResourceSessionSupport->NodeIndex >= GetNodeCount()) { return E_INVALIDARG; } pProtectedResourceSessionSupport->Support = m_ContentProtectionSupported ? m_ProtectedResourceSessionSupport[pProtectedResourceSessionSupport->NodeIndex] : D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG_NONE; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS3: { if (!m_Options3Available) { return E_INVALIDARG; } D3D12_FEATURE_DATA_D3D12_OPTIONS3* pD3D12Options3 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS3)) { return E_INVALIDARG; } pD3D12Options3->CopyQueueTimestampQueriesSupported = m_CopyQueueTimestampQueriesSupported; pD3D12Options3->CastingFullyTypedFormatSupported = m_CastingFullyTypedFormatsSupported; pD3D12Options3->WriteBufferImmediateSupportFlags = m_GetCachedWriteBufferImmediateSupportFlags; pD3D12Options3->ViewInstancingTier = m_ViewInstancingTier; pD3D12Options3->BarycentricsSupported = m_BarycentricsSupported; } return S_OK; case D3D12_FEATURE_EXISTING_HEAPS: { if (!m_ExistingHeapsAvailable) { return E_INVALIDARG; } auto* pSupport = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pSupport)) { return E_INVALIDARG; } pSupport->Supported = m_ExistingHeapCaps; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS4: { if (!m_Options4Available) { return E_INVALIDARG; } auto* pD3D12Options4 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options4)) { return E_INVALIDARG; } // Reserved Buffer Placement was cut, except for 64KB Aligned MSAA Textures pD3D12Options4->MSAA64KBAlignedTextureSupported = m_MSAA64KBAlignedTextureSupported; pD3D12Options4->SharedResourceCompatibilityTier = m_SharedResourceCompatibilityTier; // Simplified pD3D12Options4->Native16BitShaderOpsSupported = m_Native16BitShaderOpsSupported; } return S_OK; case D3D12_FEATURE_SERIALIZATION: { if (!m_SerializationAvailable) { return E_INVALIDARG; } auto* pSerialization = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pSerialization)) { return E_INVALIDARG; } const UINT NodeIndex = pSerialization->NodeIndex; if (NodeIndex >= m_NodeCount) { return E_INVALIDARG; } pSerialization->HeapSerializationTier = m_HeapSerializationTier[NodeIndex]; } return S_OK; case D3D12_FEATURE_CROSS_NODE: { if (!m_CrossNodeAvailable) { return E_INVALIDARG; } auto* pCrossNode = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pCrossNode)) { return E_INVALIDARG; } pCrossNode->SharingTier = m_CrossNodeSharingTier; pCrossNode->AtomicShaderInstructions = m_AtomicShaderInstructions; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS5: { if (!m_Options5Available) { return E_INVALIDARG; } auto* pD3D12Options5 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options5)) { return E_INVALIDARG; } pD3D12Options5->RaytracingTier = m_RaytracingTier; pD3D12Options5->RenderPassesTier = m_RenderPassesTier; pD3D12Options5->SRVOnlyTiledResourceTier3 = m_SRVOnlyTiledResourceTier3; } return S_OK; case D3D12_FEATURE_DISPLAYABLE: { if (!m_DisplayableAvailable) { return E_INVALIDARG; } auto* pD3D12Displayable = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Displayable)) // Feature_D3D1XDisplayable { return E_INVALIDARG; } pD3D12Displayable->DisplayableTexture = m_DisplayableTexture; pD3D12Displayable->SharedResourceCompatibilityTier = m_SharedResourceCompatibilityTier; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS6: { if (!m_Options6Available) { return E_INVALIDARG; } auto* pD3D12Options6 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options6)) { return E_INVALIDARG; } pD3D12Options6->AdditionalShadingRatesSupported = m_AdditionalShadingRatesSupported; pD3D12Options6->BackgroundProcessingSupported = m_BackgroundProcessingSupported; pD3D12Options6->PerPrimitiveShadingRateSupportedWithViewportIndexing = m_PerPrimitiveShadingRateSupportedWithViewportIndexing; pD3D12Options6->ShadingRateImageTileSize = m_ShadingRateImageTileSize; pD3D12Options6->VariableShadingRateTier = m_VariableShadingRateTier; } return S_OK; case D3D12_FEATURE_QUERY_META_COMMAND: { if (m_QueryMetaCommandAvailable) { if (FeatureSupportDataSize != sizeof(D3D12_FEATURE_DATA_QUERY_META_COMMAND)) { return E_INVALIDARG; } // Only checks inputs and outputs auto* pQueryData = static_cast(pFeatureSupportData); m_CommandID = pQueryData->CommandId; m_pQueryInputData = pQueryData->pQueryInputData; m_NodeMask = pQueryData->NodeMask; m_QueryInputDataSizeInBytes = pQueryData->QueryInputDataSizeInBytes; pQueryData->QueryOutputDataSizeInBytes = m_QueryOutputDataSizeInBytes; pQueryData->pQueryOutputData = m_pQueryOutputData; } else { return E_INVALIDARG; } } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS7: { if (!m_Options7Available) { return E_INVALIDARG; } auto* pD3D12Options7 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options7)) { return E_INVALIDARG; } pD3D12Options7->MeshShaderTier = m_MeshShaderTier; pD3D12Options7->SamplerFeedbackTier = m_SamplerFeedbackTier; } return S_OK; case D3D12_FEATURE_PROTECTED_RESOURCE_SESSION_TYPE_COUNT: { if (!m_ProtectedResourceSessionTypeCountAvailable) { return E_INVALIDARG; } auto* pProtectedResourceSessionTypesCount = static_cast(pFeatureSupportData); if ( FeatureSupportDataSize != sizeof(*pProtectedResourceSessionTypesCount) || pProtectedResourceSessionTypesCount->NodeIndex >= GetNodeCount()) { return E_INVALIDARG; } pProtectedResourceSessionTypesCount->Count = m_ProtectedResourceSessionTypeCount[pProtectedResourceSessionTypesCount->NodeIndex]; } return S_OK; case D3D12_FEATURE_PROTECTED_RESOURCE_SESSION_TYPES: { if (!m_ProtectedResourceSessionTypesAvailable) { return E_INVALIDARG; } auto* pProtectedResourceSessionTypes = static_cast(pFeatureSupportData); if ( FeatureSupportDataSize != sizeof(*pProtectedResourceSessionTypes) || pProtectedResourceSessionTypes->NodeIndex >= GetNodeCount()) { return E_INVALIDARG; } UINT ExpectedCount = m_ProtectedResourceSessionTypeCount[pProtectedResourceSessionTypes->NodeIndex]; if (pProtectedResourceSessionTypes->Count != ExpectedCount) { return E_INVALIDARG; } if (ExpectedCount > 0) { memcpy(pProtectedResourceSessionTypes->pTypes, m_ProtectedResourceSessionTypes[pProtectedResourceSessionTypes->NodeIndex].data(), ExpectedCount * sizeof(*pProtectedResourceSessionTypes->pTypes)); } } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS8: { if (!m_Options8Available) { return E_INVALIDARG; } D3D12_FEATURE_DATA_D3D12_OPTIONS8 *pD3D12Options8 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options8)) { return E_INVALIDARG; } pD3D12Options8->UnalignedBlockTexturesSupported = m_UnalignedBlockTexturesSupported; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS9: { if (!m_Options9Available) { return E_INVALIDARG; } D3D12_FEATURE_DATA_D3D12_OPTIONS9 *pD3D12Options9 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options9)) { return E_INVALIDARG; } pD3D12Options9->AtomicInt64OnGroupSharedSupported = m_AtomicInt64OnGroupSharedSupported; pD3D12Options9->AtomicInt64OnTypedResourceSupported = m_AtomicInt64OnTypedResourceSupported; pD3D12Options9->DerivativesInMeshAndAmplificationShadersSupported = m_DerivativesInMeshAndAmplificationShadersSupported; pD3D12Options9->MeshShaderPipelineStatsSupported = m_MeshShaderPipelineStatsSupported; pD3D12Options9->MeshShaderSupportsFullRangeRenderTargetArrayIndex = m_MeshShaderSupportsFullRangeRenderTargetArrayIndex; pD3D12Options9->WaveMMATier = m_WaveMMATier; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS10: { if (!m_Options10Available) { return E_INVALIDARG; } D3D12_FEATURE_DATA_D3D12_OPTIONS10* pD3D12Options10 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options10)) { return E_INVALIDARG; } pD3D12Options10->MeshShaderPerPrimitiveShadingRateSupported = m_MeshShaderPerPrimitiveShadingRateSupported; pD3D12Options10->VariableRateShadingSumCombinerSupported = m_VariableRateShadingSumCombinerSupported; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS11: { if (!m_Options11Available) { return E_INVALIDARG; } D3D12_FEATURE_DATA_D3D12_OPTIONS11* pD3D12Options11 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options11)) { return E_INVALIDARG; } pD3D12Options11->AtomicInt64OnDescriptorHeapResourceSupported = m_AtomicInt64OnDescriptorHeapResourceSupported; } return S_OK; case D3D12_FEATURE_D3D12_OPTIONS12: { if (!m_Options12Available) { return E_INVALIDARG; } D3D12_FEATURE_DATA_D3D12_OPTIONS12* pD3D12Options12 = static_cast(pFeatureSupportData); if (FeatureSupportDataSize != sizeof(*pD3D12Options12)) { return E_INVALIDARG; } pD3D12Options12->MSPrimitivesPipelineStatisticIncludesCulledPrimitives = m_MSPrimitivesPipelineStatisticIncludesCulledPrimitives; pD3D12Options12->EnhancedBarriersSupported = m_EnhancedBarriersSupported; } return S_OK; default: return E_INVALIDARG; } } public: // For simplicity, allow tests to set the internal state values for this mock class // General UINT m_NodeCount; // Simulated number of computing nodes // 0: Options bool m_D3D12OptionsAvailable = true; BOOL m_DoublePrecisionFloatShaderOps = false; BOOL m_OutputMergerLogicOp = false; D3D12_SHADER_MIN_PRECISION_SUPPORT m_ShaderMinPrecisionSupport10Bit = D3D12_SHADER_MIN_PRECISION_SUPPORT_NONE; D3D12_SHADER_MIN_PRECISION_SUPPORT m_ShaderMinPrecisionSupport16Bit = D3D12_SHADER_MIN_PRECISION_SUPPORT_NONE; D3D12_TILED_RESOURCES_TIER m_TiledResourcesTier = D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED; D3D12_RESOURCE_BINDING_TIER m_ResourceBindingTier = (D3D12_RESOURCE_BINDING_TIER)0; BOOL m_PSSpecifiedStencilRefSupported = false; BOOL m_TypedUAVLoadAdditionalFormats = false; BOOL m_ROVsSupported = false; D3D12_CONSERVATIVE_RASTERIZATION_TIER m_ConservativeRasterizationTier = D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED; UINT m_MaxGPUVirtualAddressBitsPerResource = 0; BOOL m_StandardSwizzle64KBSupported = false; D3D12_CROSS_NODE_SHARING_TIER m_CrossNodeSharingTier = D3D12_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED; BOOL m_CrossAdapterRowMajorTextureSupported = false; BOOL m_VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = false; D3D12_RESOURCE_HEAP_TIER m_ResourceHeapTier = (D3D12_RESOURCE_HEAP_TIER)0; // 1: Architecture & 16: Architecture1 bool m_ArchitectureSucceed = true; bool m_Architecture1Available = false; // Mock the case where Architecture1 is not supported std::vector m_TileBasedRenderer; std::vector m_UMA; std::vector m_CacheCoherentUMA; std::vector m_IsolatedMMU; // 2: Feature Levels bool m_FeatureLevelsAvailable = true; D3D_FEATURE_LEVEL m_FeatureLevel = D3D_FEATURE_LEVEL_12_0; // Set higher to allow other tests to pass correctly // 3: Feature Format Support // Forwarding call only. Make sure that the input parameters are correctly forwarded bool m_FormatSupportAvailable = true; DXGI_FORMAT m_FormatReceived; D3D12_FORMAT_SUPPORT1 m_FormatSupport1 = D3D12_FORMAT_SUPPORT1_NONE; D3D12_FORMAT_SUPPORT2 m_FormatSupport2 = D3D12_FORMAT_SUPPORT2_NONE; // 4: Multisample Quality Levels bool m_MultisampleQualityLevelsSucceed = true; UINT m_SampleCountReceived; D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS m_MultisampleQualityLevelFlagsReceived; UINT m_NumQualityLevels = 0; // 5: Format Info bool m_DXGIFormatSupported = true; UINT m_PlaneCount = 0; // 6: GPU Virtual Address Support bool m_GPUVASupportAvailable = true; UINT m_MaxGPUVirtualAddressBitsPerProcess = 0; // 7: Shader Model D3D_SHADER_MODEL m_HighestSupportedShaderModel = D3D_SHADER_MODEL_5_1; // 8: Options1 bool m_Options1Available = true; bool m_WaveOpsSupported = false; UINT m_WaveLaneCountMin = 0; UINT m_WaveLaneCountMax = 0; UINT m_TotalLaneCount = 0; bool m_ExpandedComputeResourceStates = false; bool m_Int64ShaderOpsSupported = false; // 10: Protected Resource Session Support bool m_ProtectedResourceSessionAvailable = true; bool m_ContentProtectionSupported = true; std::vector m_ProtectedResourceSessionSupport; // 12: Root Signature bool m_RootSignatureAvailable = true; D3D_ROOT_SIGNATURE_VERSION m_RootSignatureHighestVersion = (D3D_ROOT_SIGNATURE_VERSION)0; // 18: D3D12 Options2 bool m_Options2Available = true; bool m_DepthBoundsTestSupport = false; D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER m_ProgrammableSamplePositionsTier = D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED; // 19: Shader Cache bool m_ShaderCacheAvailable = true; D3D12_SHADER_CACHE_SUPPORT_FLAGS m_ShaderCacheSupportFlags = D3D12_SHADER_CACHE_SUPPORT_NONE; // Lazy implementation // 20: Command Queue Priority bool m_CommandQueuePriorityAvailable = true; bool m_GlobalRealtimeCommandQueueSupport = false; // 21: Options3 bool m_Options3Available = true; bool m_CopyQueueTimestampQueriesSupported = false; bool m_CastingFullyTypedFormatsSupported = false; D3D12_COMMAND_LIST_SUPPORT_FLAGS m_GetCachedWriteBufferImmediateSupportFlags = D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE; D3D12_VIEW_INSTANCING_TIER m_ViewInstancingTier = D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED; bool m_BarycentricsSupported = false; // 22: Existing Heaps bool m_ExistingHeapsAvailable = true; bool m_ExistingHeapCaps = false; // 23: Options4 bool m_Options4Available = true; bool m_MSAA64KBAlignedTextureSupported = false; D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER m_SharedResourceCompatibilityTier = D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_0; bool m_Native16BitShaderOpsSupported = false; // 24: Serialization bool m_SerializationAvailable = true; std::vector m_HeapSerializationTier; // 25: Cross Node bool m_CrossNodeAvailable = true; bool m_AtomicShaderInstructions = false; // 27: Options5 bool m_Options5Available = true; bool m_SRVOnlyTiledResourceTier3 = false; D3D12_RENDER_PASS_TIER m_RenderPassesTier = D3D12_RENDER_PASS_TIER_0; D3D12_RAYTRACING_TIER m_RaytracingTier = D3D12_RAYTRACING_TIER_NOT_SUPPORTED; // 28: Displayable bool m_DisplayableAvailable = true; bool m_DisplayableTexture = false; // SharedResourceCompatibilityTier is located in Options4 // 30: Options6 bool m_Options6Available = true; bool m_AdditionalShadingRatesSupported = false; bool m_PerPrimitiveShadingRateSupportedWithViewportIndexing = false; D3D12_VARIABLE_SHADING_RATE_TIER m_VariableShadingRateTier = D3D12_VARIABLE_SHADING_RATE_TIER_NOT_SUPPORTED; UINT m_ShadingRateImageTileSize = 0; bool m_BackgroundProcessingSupported = false; // 31: Query Meta Command bool m_QueryMetaCommandAvailable = true; GUID m_CommandID = {}; UINT m_NodeMask = 0; const void* m_pQueryInputData = nullptr; SIZE_T m_QueryInputDataSizeInBytes = 0; void* m_pQueryOutputData = nullptr; SIZE_T m_QueryOutputDataSizeInBytes = 0; // 32: Options7 bool m_Options7Available = true; D3D12_MESH_SHADER_TIER m_MeshShaderTier = D3D12_MESH_SHADER_TIER_NOT_SUPPORTED; D3D12_SAMPLER_FEEDBACK_TIER m_SamplerFeedbackTier = D3D12_SAMPLER_FEEDBACK_TIER_NOT_SUPPORTED; // 33: Protected Resource Session Type Count bool m_ProtectedResourceSessionTypeCountAvailable = true; std::vector m_ProtectedResourceSessionTypeCount; // 34: Protected Resource Session Types bool m_ProtectedResourceSessionTypesAvailable = true; std::vector> m_ProtectedResourceSessionTypes; // 36: Options8 bool m_Options8Available = true; bool m_UnalignedBlockTexturesSupported = false; // 37: Options9 bool m_Options9Available = true; bool m_MeshShaderPipelineStatsSupported = false; bool m_MeshShaderSupportsFullRangeRenderTargetArrayIndex = false; bool m_AtomicInt64OnTypedResourceSupported = false; bool m_AtomicInt64OnGroupSharedSupported = false; bool m_DerivativesInMeshAndAmplificationShadersSupported = false; D3D12_WAVE_MMA_TIER m_WaveMMATier = D3D12_WAVE_MMA_TIER_NOT_SUPPORTED; // 39: Options10 bool m_Options10Available = true; bool m_VariableRateShadingSumCombinerSupported = false; bool m_MeshShaderPerPrimitiveShadingRateSupported = false; // 40: Options11 bool m_Options11Available = true; bool m_AtomicInt64OnDescriptorHeapResourceSupported = false; // 41: Options12 bool m_Options12Available = true; D3D12_TRI_STATE m_MSPrimitivesPipelineStatisticIncludesCulledPrimitives = D3D12_TRI_STATE_UNKNOWN; bool m_EnhancedBarriersSupported = false; }; #endif