From 22d84522edc8a21b67f95f662b6d9202d8d69008 Mon Sep 17 00:00:00 2001 From: "Pohsiang (John) Hsu" Date: Tue, 20 May 2025 17:13:02 -0700 Subject: [PATCH] mediafoundation: get device vendor id, device id, and driver version Reviewed-by: Yubo Xie Reviewed-by: Sil Vilerino Part-of: --- .../frontends/mediafoundation/codecapi.cpp | 2 +- .../mediafoundation/encoder_capabilities.cpp | 2 - .../mediafoundation/encoder_capabilities.h | 2 - .../mediafoundation/hmft_entrypoints.cpp | 2 +- .../mediafoundation/mfd3dmanager.cpp | 267 ++++++------------ .../frontends/mediafoundation/mfd3dmanager.h | 22 +- .../frontends/mediafoundation/mftransform.cpp | 2 +- 7 files changed, 90 insertions(+), 209 deletions(-) diff --git a/src/gallium/frontends/mediafoundation/codecapi.cpp b/src/gallium/frontends/mediafoundation/codecapi.cpp index f437583da0d..074daf21dfa 100644 --- a/src/gallium/frontends/mediafoundation/codecapi.cpp +++ b/src/gallium/frontends/mediafoundation/codecapi.cpp @@ -925,7 +925,7 @@ CDX12EncHMFT::SetValue( const GUID *Api, VARIANT *Value ) else if( *Api == CODECAPI_AVLowLatencyMode ) { // TODO: remove this code path when we clarify whether this is supported on AMD. - if( m_EncoderCapabilities.m_deviceVendor == "AMD" ) + if( m_deviceVendor == "AMD" ) { debug_printf( "[dx12 hmft 0x%p] Device vendor is AMD, ignore LowLatency Settings\n", this ); m_bLowLatency = TRUE; diff --git a/src/gallium/frontends/mediafoundation/encoder_capabilities.cpp b/src/gallium/frontends/mediafoundation/encoder_capabilities.cpp index d4f96926763..8595c5290f2 100644 --- a/src/gallium/frontends/mediafoundation/encoder_capabilities.cpp +++ b/src/gallium/frontends/mediafoundation/encoder_capabilities.cpp @@ -27,8 +27,6 @@ void encoder_capabilities::initialize( pipe_screen *pScreen, pipe_video_profile videoProfile ) { - m_deviceVendor = pScreen->get_device_vendor( pScreen ); - m_uiMaxWidth = pScreen->get_video_param( pScreen, videoProfile, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_MAX_WIDTH ); m_uiMaxHeight = pScreen->get_video_param( pScreen, videoProfile, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_MAX_HEIGHT ); diff --git a/src/gallium/frontends/mediafoundation/encoder_capabilities.h b/src/gallium/frontends/mediafoundation/encoder_capabilities.h index 8821e1e2dce..db4b31104c6 100644 --- a/src/gallium/frontends/mediafoundation/encoder_capabilities.h +++ b/src/gallium/frontends/mediafoundation/encoder_capabilities.h @@ -38,8 +38,6 @@ class encoder_capabilities void initialize( pipe_screen *pScreen, pipe_video_profile profile ); // Cached underlying backend pipe caps (avoid querying on each frame) - std::string m_deviceVendor {}; - // PIPE_VIDEO_CAP_MAX_WIDTH UINT m_uiMaxWidth = 0; diff --git a/src/gallium/frontends/mediafoundation/hmft_entrypoints.cpp b/src/gallium/frontends/mediafoundation/hmft_entrypoints.cpp index 98c3365b8e2..2d93f987d12 100644 --- a/src/gallium/frontends/mediafoundation/hmft_entrypoints.cpp +++ b/src/gallium/frontends/mediafoundation/hmft_entrypoints.cpp @@ -35,7 +35,7 @@ all the entrypoints/stubs in this file would help organize the DLL public interface */ -CDX12EncHMFT::CDX12EncHMFT() +CDX12EncHMFT::CDX12EncHMFT() : CMFD3DManager( this ) { } CDX12EncHMFT::~CDX12EncHMFT() diff --git a/src/gallium/frontends/mediafoundation/mfd3dmanager.cpp b/src/gallium/frontends/mediafoundation/mfd3dmanager.cpp index 7ac8acee042..83a3011d4d4 100644 --- a/src/gallium/frontends/mediafoundation/mfd3dmanager.cpp +++ b/src/gallium/frontends/mediafoundation/mfd3dmanager.cpp @@ -31,185 +31,8 @@ #include "mfd3dmanager.tmh" -static IDXCoreAdapter * -choose_dxcore_adapter( void ) -{ - HRESULT hr = S_OK; - std::vector adapter_infos; - ComPtr spFactory; - ComPtr spAdapterList; - adapter_infos.reserve( 2 ); - hr = DXCoreCreateAdapterFactory( IID_IDXCoreAdapterFactory, (void **) spFactory.GetAddressOf() ); - if( FAILED( hr ) ) - { - debug_printf( "CMFD3DManager: DXCoreCreateAdapterFactory failed: %08x\n", hr ); - return NULL; - } - -#ifdef NTDDI_WIN11_GA - // Get all media adapters (e.g including MCDM using latest DXCore APIs) - ComPtr spFactory1; - if( SUCCEEDED( spFactory.As( &spFactory1 ) ) && - SUCCEEDED( spFactory1->CreateAdapterListByWorkload( DXCoreWorkload::Media, - DXCoreRuntimeFilterFlags::D3D12, - DXCoreHardwareTypeFilterFlags::None, - spAdapterList.GetAddressOf() ) ) ) - { - debug_printf( "CMFD3DManager: Using IDXCoreAdapterFactory1::CreateAdapterListByWorkload\n" ); - } -#endif // NTDDI_WIN11_GA - - // Fallback to older DXCore enumeration APIs - if( !spAdapterList && - SUCCEEDED( spFactory->CreateAdapterList( 1, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE, spAdapterList.GetAddressOf() ) ) ) - { - debug_printf( "CMFD3DManager: Fallback to IDXCoreAdapterFactory::CreateAdapterList since " - "IDXCoreAdapterFactory1::CreateAdapterListByWorkload was not available\n" ); - } - - // Validate we enumerated one way or another - if( !spAdapterList ) - { - debug_printf( "CMFD3DManager: Couldn't create an adapter list\n" ); - return NULL; - } - - adapter_infos.clear(); - for( unsigned i = 0; i < spAdapterList->GetAdapterCount(); i++ ) - { - ComPtr spAdapter; - MFTAdapterInfo adapter_info = {}; - uint64_t driver_version = 0; - if( SUCCEEDED( spAdapterList->GetAdapter( i, spAdapter.GetAddressOf() ) ) ) - { - if( FAILED( spAdapter->GetProperty( DXCoreAdapterProperty::IsIntegrated, &adapter_info.is_integrated ) ) ) - continue; - if( FAILED( spAdapter->GetProperty( DXCoreAdapterProperty::HardwareID, &adapter_info.hardware_id ) ) ) - continue; - if( FAILED( spAdapter->GetProperty( DXCoreAdapterProperty::InstanceLuid, &adapter_info.adapter_luid ) ) ) - continue; - if( FAILED( spAdapter->GetProperty( DXCoreAdapterProperty::DriverVersion, &driver_version ) ) ) - continue; - - // Read into driver_version variable first since the parts in the struct are in high to low bits order - adapter_info.driver_version.part1 = ( ( driver_version >> 48 ) & 0xFFFF ); - adapter_info.driver_version.part2 = ( ( driver_version >> 32 ) & 0xFFFF ); - adapter_info.driver_version.part3 = ( ( driver_version >> 16 ) & 0xFFFF ); - adapter_info.driver_version.part4 = ( driver_version & 0xFFFF ); - adapter_infos.push_back( adapter_info ); - } - } - - std::map vendor_id_friendly_names = { - { 0x1002, "AMD" }, - { 0x1414, "Microsoft" }, - { 0x10DE, "NVidia" }, - { 0x8086, "Intel" }, - }; - - const std::vector vendor_preference_order = { - 0x10DE, // NVidia - 0x1002, // AMD - 0x8086, // Intel - 0x1414, // Microsoft - }; - - std::map driver_min_versions; - { - // Min driver versions - driver_min_versions[0x1002 /* AMD */] = { 31, 0, 0, 0 }; - driver_min_versions[0x1414 /* Microsoft */] = { 10, 0, 26000, 0 }; // OS version for MSFT SW driver - driver_min_versions[0x10DE /* NVidia */] = { 31, 0, 0, 0 }; - driver_min_versions[0x8086 /* Intel */] = { 31, 0, 0, 0 }; - } - - adapter_infos.erase( - std::remove_if( adapter_infos.begin(), - adapter_infos.end(), - [&driver_min_versions]( const MFTAdapterInfo &adapter ) { - return ( adapter.driver_version.part1 < driver_min_versions[adapter.hardware_id.vendorID].part1 ) || - ( adapter.driver_version.part2 < driver_min_versions[adapter.hardware_id.vendorID].part2 ) || - ( adapter.driver_version.part3 < driver_min_versions[adapter.hardware_id.vendorID].part3 ) || - ( adapter.driver_version.part4 < driver_min_versions[adapter.hardware_id.vendorID].part4 ); - } ), - adapter_infos.end() ); - - std::map> driver_denylist; - { - // Blocked driver versions - driver_denylist[0x1002 /* AMD */] = { { 31, 0, 0, 0 } }; - driver_denylist[0x1414 /* Microsoft */] = { { 10, 0, 26000, 0 } }; // OS version for MSFT SW driver - driver_denylist[0x10DE /* NVidia */] = { { 31, 0, 0, 0 } }; - driver_denylist[0x8086 /* Intel */] = { { 31, 0, 0, 0 } }; - } - - adapter_infos.erase( std::remove_if( adapter_infos.begin(), - adapter_infos.end(), - [&driver_denylist]( const MFTAdapterInfo &adapter ) { - return std::find_if( driver_denylist[adapter.hardware_id.vendorID].begin(), - driver_denylist[adapter.hardware_id.vendorID].end(), - [&adapter]( const MFAdapterDriverVersion &x ) { - return x.version == adapter.driver_version.version; - } ) != driver_denylist[adapter.hardware_id.vendorID].end(); - } ), - adapter_infos.end() ); - - std::sort( adapter_infos.begin(), adapter_infos.end(), [vendor_preference_order]( MFTAdapterInfo a, MFTAdapterInfo b ) { - // First criteria: iGPU first - if( a.is_integrated > b.is_integrated ) - return true; - if( a.is_integrated < b.is_integrated ) - return false; - - // Second criteria: IHV preference - size_t preferenceOrderA = - std::distance( vendor_preference_order.begin(), - std::find( vendor_preference_order.begin(), vendor_preference_order.end(), a.hardware_id.vendorID ) ); - size_t preferenceOrderB = - std::distance( vendor_preference_order.begin(), - std::find( vendor_preference_order.begin(), vendor_preference_order.end(), b.hardware_id.vendorID ) ); - if( preferenceOrderA < preferenceOrderB ) - return true; - if( preferenceOrderA > preferenceOrderB ) - return false; - - // Third criteria: driver version - if( a.driver_version.version > b.driver_version.version ) - return true; - if( a.driver_version.version < b.driver_version.version ) - return false; - - return false; - } ); - - debug_printf( "CMFD3DManager: Selecting adapter from adapter list...\n" ); - for( size_t i = 0; i < adapter_infos.size(); i++ ) - { - debug_printf( "CMFD3DManager: %s Adapter LUID (%d %d) - is_integrated %d - vendor_id 0x%x (%s) - driver_version " - "%d.%d.%d.%d \n", - ( i == 0 ) ? "[SELECTED]" : "", - adapter_infos[i].adapter_luid.LowPart, - adapter_infos[i].adapter_luid.HighPart, - adapter_infos[i].is_integrated, - adapter_infos[i].hardware_id.vendorID, - vendor_id_friendly_names.count( adapter_infos[i].hardware_id.vendorID ) > 0 ? - vendor_id_friendly_names[adapter_infos[i].hardware_id.vendorID].c_str() : - "Unknown", - adapter_infos[i].driver_version.part1, - adapter_infos[i].driver_version.part2, - adapter_infos[i].driver_version.part3, - adapter_infos[i].driver_version.part4 ); - } - - IDXCoreAdapter *selected_adapter = NULL; - if( ( adapter_infos.size() == 0 ) || FAILED( spFactory->GetAdapterByLuid( adapter_infos[0].adapter_luid, &selected_adapter ) ) ) - debug_printf( "CMFD3DManager: Error, no adapters found.\n" ); - - return selected_adapter; -} - -CMFD3DManager::CMFD3DManager() +CMFD3DManager::CMFD3DManager( void *logId ) : m_logId( logId ) { } CMFD3DManager::~CMFD3DManager() @@ -270,6 +93,10 @@ CMFD3DManager::Shutdown( bool bReleaseDeviceManager ) { m_pVlScreen->destroy( this->m_pVlScreen ); m_pVlScreen = nullptr; + m_deviceVendor = {}; + m_deviceVendorId = {}; + m_deviceDeviceId = {}; + m_deviceDriverVersion = {}; } if( m_pWinsys ) @@ -329,6 +156,77 @@ done: return hr; } +enum +{ + MFT_HW_VENDOR_AMD = 0x1002, + MFT_HW_VENDOR_INTEL = 0x8086, + MFT_HW_VENDOR_MICROSOFT = 0x1414, + MFT_HW_VENDOR_NVIDIA = 0x10de, +}; + +static const char * +VendorIDToString( uint32_t vendorId ) +{ + switch( vendorId ) + { + case MFT_HW_VENDOR_MICROSOFT: + return "Microsoft"; + case MFT_HW_VENDOR_AMD: + return "AMD"; + case MFT_HW_VENDOR_NVIDIA: + return "NVIDIA"; + case MFT_HW_VENDOR_INTEL: + return "Intel"; + default: + return "Unknown"; + } +} + +inline UINT16 +ExtractDriverVersionComponent( const size_t index, const LARGE_INTEGER &driverVersion ) +{ + return (UINT16) ( driverVersion.QuadPart >> ( index * 8 * 2 ) ) & 0xffff; +} + +// retrieve device information such as vendor id, device id, driver version. we'll use this info later on +// to do block list and driver version dependent operations. +HRESULT +CMFD3DManager::GetDeviceInfo() +{ + HRESULT hr = S_OK; + ComPtr factory; + ComPtr adaptor; + DXGI_ADAPTER_DESC desc; + LARGE_INTEGER driverVersion; + LUID luid = m_spDevice->GetAdapterLuid(); + + CHECKHR_GOTO( CreateDXGIFactory( IID_PPV_ARGS( &factory ) ), done ); + CHECKHR_GOTO( factory->EnumAdapterByLuid( luid, IID_PPV_ARGS( &adaptor ) ), done ); + CHECKHR_GOTO( adaptor->GetDesc( &desc ), done ); + CHECKHR_GOTO( adaptor->CheckInterfaceSupport( __uuidof( IDXGIDevice ), &driverVersion ), done ); + + m_deviceVendorId = desc.VendorId; + m_deviceDeviceId = desc.DeviceId; + m_deviceVendor = VendorIDToString( m_deviceVendorId ); + m_deviceDriverVersion.part1 = ExtractDriverVersionComponent( 3, driverVersion ); + m_deviceDriverVersion.part2 = ExtractDriverVersionComponent( 2, driverVersion ); + m_deviceDriverVersion.part3 = ExtractDriverVersionComponent( 1, driverVersion ); + m_deviceDriverVersion.part4 = ExtractDriverVersionComponent( 0, driverVersion ); + + MFE_INFO( "[dx12 hmft 0x%p] D3DManager: device vendor = %s\n", m_logId, m_deviceVendor.c_str() ); + MFE_INFO( "[dx12 hmft 0x%p] D3DManager: device vendor id = %x\n", m_logId, m_deviceVendorId ); + MFE_INFO( "[dx12 hmft 0x%p] D3DManager: device device id = %x\n", m_logId, m_deviceDeviceId ); + MFE_INFO( "[dx12 hmft 0x%p] D3DManager: %S", m_logId, desc.Description ); + MFE_INFO( "[dx12 hmft 0x%p] D3DManager: device driver version = %d.%d.%d.%d\n", + m_logId, + m_deviceDriverVersion.part1, + m_deviceDriverVersion.part2, + m_deviceDriverVersion.part3, + m_deviceDriverVersion.part4 ); +done: + return hr; +} + HRESULT CMFD3DManager::xOnSetD3DManager( ULONG_PTR ulParam ) { @@ -337,17 +235,7 @@ CMFD3DManager::xOnSetD3DManager( ULONG_PTR ulParam ) if( ulParam == 0 ) { -#if 0 - // Treat 0 as "pick a default" - ComPtr spD3D12Device; - ComPtr dxcore_adapter = choose_dxcore_adapter(); - CHECKNULL_GOTO(dxcore_adapter, MF_E_DXGI_DEVICE_NOT_INITIALIZED, done); - CHECKHR_GOTO(MFCreateDXGIDeviceManager(&m_uiResetToken, &m_spDeviceManager), done); - CHECKHR_GOTO(CreateD3D12DeviceWithMinimumSupportedFeatureLevel(dxcore_adapter.Get(), spD3D12Device), done); - CHECKHR_GOTO(m_spDeviceManager->ResetDevice(spD3D12Device.Get(), m_uiResetToken), done); -#else return hr; -#endif } else { @@ -365,6 +253,9 @@ CMFD3DManager::xOnSetD3DManager( ULONG_PTR ulParam ) MF_E_DXGI_DEVICE_NOT_INITIALIZED, done ); CHECKHR_GOTO( MFCreateVideoSampleAllocatorEx( IID_PPV_ARGS( &m_spVideoSampleAllocator ) ), done ); + + CHECKHR_GOTO( GetDeviceInfo(), done ); + done: if( FAILED( hr ) ) { diff --git a/src/gallium/frontends/mediafoundation/mfd3dmanager.h b/src/gallium/frontends/mediafoundation/mfd3dmanager.h index e5cca4a97b4..7a6b5037e08 100644 --- a/src/gallium/frontends/mediafoundation/mfd3dmanager.h +++ b/src/gallium/frontends/mediafoundation/mfd3dmanager.h @@ -65,22 +65,10 @@ typedef union uint64_t version; // bits field } MFAdapterDriverVersion; -typedef struct MFTAdapterInfo -{ - // DXCoreAdapterProperty::InstanceLuid - LUID adapter_luid; - // DXCoreAdapterProperty::IsIntegrated - uint32_t is_integrated; - // DXCoreAdapterProperty::HardwareID - DXCoreHardwareID hardware_id; - // DXCoreAdapterProperty::DriverVersion - MFAdapterDriverVersion driver_version; -} MFTAdapterInfo; - class CMFD3DManager { public: - CMFD3DManager(); + CMFD3DManager( void *logId ); ~CMFD3DManager(); HRESULT Initialize( D3D12_VIDEO_ENCODER_CODEC codec ); @@ -91,6 +79,7 @@ class CMFD3DManager protected: HRESULT xReopenDeviceManager( bool bNewDevice ); + HRESULT GetDeviceInfo(); ComPtr m_spDeviceManager; ComPtr m_spDevice11; @@ -100,11 +89,16 @@ class CMFD3DManager ComPtr m_spVideoSampleAllocator; // Used for software input samples that need to be copied UINT32 m_uiResetToken = 0; HANDLE m_hDevice = NULL; - LUID m_currentDXAdapterLuid = { 0 }; struct vl_screen *m_pVlScreen = nullptr; struct sw_winsys *m_pWinsys = nullptr; struct pipe_context *m_pPipeContext = nullptr; + std::string m_deviceVendor {}; + uint32_t m_deviceVendorId {}; + uint32_t m_deviceDeviceId {}; + MFAdapterDriverVersion m_deviceDriverVersion {}; + private: D3D12_VIDEO_ENCODER_CODEC m_codec; + const void *m_logId = {}; }; diff --git a/src/gallium/frontends/mediafoundation/mftransform.cpp b/src/gallium/frontends/mediafoundation/mftransform.cpp index 609e7918732..2c32eddced2 100644 --- a/src/gallium/frontends/mediafoundation/mftransform.cpp +++ b/src/gallium/frontends/mediafoundation/mftransform.cpp @@ -544,7 +544,7 @@ CDX12EncHMFT::OnOutputTypeChanged() CHECKHR_GOTO( InitializeEncoder( m_outputPipeProfile, m_uiOutputWidth, m_uiOutputHeight ), done ); // TODO: remove this code path when we clarify whether this is supported on AMD. - if( m_EncoderCapabilities.m_deviceVendor == "AMD" ) + if( m_deviceVendor == "AMD" ) { MFE_INFO( "[dx12 hmft 0x%p] Device vendor is AMD, turn off async mode until issue is worked out", this ); m_bLowLatency = TRUE;