mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 09:38:07 +02:00
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:
parent
5ee854c4eb
commit
22d84522ed
7 changed files with 90 additions and 209 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 ) )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 = {};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue