mediafoundation: get device vendor id, device id, and driver version

Reviewed-by: Yubo Xie <yuboxie@microsoft.com>
Reviewed-by: Sil Vilerino <sivileri@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35219>
This commit is contained in:
Pohsiang (John) Hsu 2025-05-20 17:13:02 -07:00 committed by Marge Bot
parent 5ee854c4eb
commit 22d84522ed
7 changed files with 90 additions and 209 deletions

View file

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

View file

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

View file

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

View file

@ -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()

View file

@ -31,185 +31,8 @@
#include "mfd3dmanager.tmh"
static IDXCoreAdapter *
choose_dxcore_adapter( void )
{
HRESULT hr = S_OK;
std::vector<MFTAdapterInfo> adapter_infos;
ComPtr<IDXCoreAdapterFactory> spFactory;
ComPtr<IDXCoreAdapterList> 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<IDXCoreAdapterFactory1> 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<IDXCoreAdapter> 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<uint32_t, std::string> vendor_id_friendly_names = {
{ 0x1002, "AMD" },
{ 0x1414, "Microsoft" },
{ 0x10DE, "NVidia" },
{ 0x8086, "Intel" },
};
const std::vector<uint32_t> vendor_preference_order = {
0x10DE, // NVidia
0x1002, // AMD
0x8086, // Intel
0x1414, // Microsoft
};
std::map<uint32_t, MFAdapterDriverVersion> 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<uint32_t, std::vector<MFAdapterDriverVersion>> 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<IDXGIFactory4> factory;
ComPtr<IDXGIAdapter2> 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<ID3D12Device> spD3D12Device;
ComPtr<IDXCoreAdapter> 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 ) )
{

View file

@ -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<IMFDXGIDeviceManager> m_spDeviceManager;
ComPtr<ID3D11Device5> m_spDevice11;
@ -100,11 +89,16 @@ class CMFD3DManager
ComPtr<IMFVideoSampleAllocatorEx> 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 = {};
};

View file

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