From 0107d94632ebdec21fbee6d0caeca8007b8ecdee Mon Sep 17 00:00:00 2001 From: "Pohsiang (John) Hsu" Date: Wed, 21 May 2025 17:01:20 -0700 Subject: [PATCH] mediafoundation: add mechanism to disable async and h.264 unwrapped POC (commented out for now) according to gpu/version Reviewed-by: Yubo Xie Reviewed-by: Sil Vilerino Part-of: --- .../frontends/mediafoundation/codecapi.cpp | 5 ++-- .../frontends/mediafoundation/encode_h264.cpp | 3 +- .../mediafoundation/mfd3dmanager.cpp | 29 +++++++++++++++++-- .../frontends/mediafoundation/mfd3dmanager.h | 11 ++++++- .../frontends/mediafoundation/mftransform.cpp | 5 ++-- .../reference_frames_tracker_h264.cpp | 22 ++++++++++++-- .../reference_frames_tracker_h264.h | 13 +++++---- .../reference_frames_tracker_hevc.cpp | 2 +- 8 files changed, 70 insertions(+), 20 deletions(-) diff --git a/src/gallium/frontends/mediafoundation/codecapi.cpp b/src/gallium/frontends/mediafoundation/codecapi.cpp index 074daf21dfa..d6bbaed9f76 100644 --- a/src/gallium/frontends/mediafoundation/codecapi.cpp +++ b/src/gallium/frontends/mediafoundation/codecapi.cpp @@ -924,10 +924,9 @@ 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_deviceVendor == "AMD" ) + if( m_gpuFeatureFlags.m_bDisableAsync ) { - debug_printf( "[dx12 hmft 0x%p] Device vendor is AMD, ignore LowLatency Settings\n", this ); + debug_printf( "[dx12 hmft 0x%p] Async is disabled due to lack of GPU support \n", this ); m_bLowLatency = TRUE; } else diff --git a/src/gallium/frontends/mediafoundation/encode_h264.cpp b/src/gallium/frontends/mediafoundation/encode_h264.cpp index ef68bdbb663..8aca2c5ef69 100644 --- a/src/gallium/frontends/mediafoundation/encode_h264.cpp +++ b/src/gallium/frontends/mediafoundation/encode_h264.cpp @@ -1174,7 +1174,8 @@ CDX12EncHMFT::CreateGOPTracker( uint32_t textureWidth, uint32_t textureHeight ) MaxHWL0Ref, MaxHWL1Ref, m_pPipeVideoCodec->max_references, - m_uiMaxLongTermReferences ); + m_uiMaxLongTermReferences, + m_gpuFeatureFlags.m_bH264SendUnwrappedPOC ); CHECKNULL_GOTO( m_pGOPTracker, MF_E_INVALIDMEDIATYPE, done ); diff --git a/src/gallium/frontends/mediafoundation/mfd3dmanager.cpp b/src/gallium/frontends/mediafoundation/mfd3dmanager.cpp index 83a3011d4d4..d5b597ac12d 100644 --- a/src/gallium/frontends/mediafoundation/mfd3dmanager.cpp +++ b/src/gallium/frontends/mediafoundation/mfd3dmanager.cpp @@ -93,10 +93,10 @@ CMFD3DManager::Shutdown( bool bReleaseDeviceManager ) { m_pVlScreen->destroy( this->m_pVlScreen ); m_pVlScreen = nullptr; - m_deviceVendor = {}; m_deviceVendorId = {}; m_deviceDeviceId = {}; m_deviceDriverVersion = {}; + m_gpuFeatureFlags = {}; } if( m_pWinsys ) @@ -207,13 +207,12 @@ CMFD3DManager::GetDeviceInfo() 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 = %s\n", m_logId, VendorIDToString( m_deviceVendorId ) ); 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 ); @@ -227,6 +226,28 @@ done: return hr; } +void +CMFD3DManager::UpdateGPUFeatureFlags() +{ + if( m_deviceVendorId == MFT_HW_VENDOR_AMD ) + { + m_gpuFeatureFlags.m_bDisableAsync = true; + MFE_INFO( "[dx12 hmft 0x%p] D3DManager: GPUFeature m_bDisableAsync is set to true\n", m_logId ); + } + + /* + if( m_deviceVendorId == MFT_HW_VENDOR_NVIDIA ) + { + if( m_deviceDriverVersion.part1 >= 32 && m_deviceDriverVersion.part2 >= 0 && m_deviceDriverVersion.part3 >= 15 && + m_deviceDriverVersion.part4 >= 9002 ) + { + m_gpuFeatureFlags.m_bH264SendUnwrappedPOC = true; + MFE_INFO( "[dx12 hmft 0x%p] D3DManager: GPUFeature m_bH264SendUnwrappedPOC is set to true\n", m_logId ); + } + } + */ +} + HRESULT CMFD3DManager::xOnSetD3DManager( ULONG_PTR ulParam ) { @@ -256,6 +277,8 @@ CMFD3DManager::xOnSetD3DManager( ULONG_PTR ulParam ) CHECKHR_GOTO( GetDeviceInfo(), done ); + UpdateGPUFeatureFlags(); + done: if( FAILED( hr ) ) { diff --git a/src/gallium/frontends/mediafoundation/mfd3dmanager.h b/src/gallium/frontends/mediafoundation/mfd3dmanager.h index 7a6b5037e08..cfb2f17856b 100644 --- a/src/gallium/frontends/mediafoundation/mfd3dmanager.h +++ b/src/gallium/frontends/mediafoundation/mfd3dmanager.h @@ -80,6 +80,7 @@ class CMFD3DManager protected: HRESULT xReopenDeviceManager( bool bNewDevice ); HRESULT GetDeviceInfo(); + void UpdateGPUFeatureFlags(); ComPtr m_spDeviceManager; ComPtr m_spDevice11; @@ -93,11 +94,19 @@ class CMFD3DManager 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 {}; + // MFT features that are dependent on GPU / version (ensure these are named to be false by default so we can easily reset this + // struct) + struct GPUFeatureFlags + { + bool m_bDisableAsync = false; + bool m_bH264SendUnwrappedPOC = false; + }; + GPUFeatureFlags m_gpuFeatureFlags; + 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 2c32eddced2..a54651dacd9 100644 --- a/src/gallium/frontends/mediafoundation/mftransform.cpp +++ b/src/gallium/frontends/mediafoundation/mftransform.cpp @@ -543,10 +543,9 @@ 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_deviceVendor == "AMD" ) + if( m_gpuFeatureFlags.m_bDisableAsync ) { - MFE_INFO( "[dx12 hmft 0x%p] Device vendor is AMD, turn off async mode until issue is worked out", this ); + MFE_INFO( "[dx12 hmft 0x%p] Async is disabled due to lack of GPU support.", this ); m_bLowLatency = TRUE; } else diff --git a/src/gallium/frontends/mediafoundation/reference_frames_tracker_h264.cpp b/src/gallium/frontends/mediafoundation/reference_frames_tracker_h264.cpp index 44cf0fc77d5..50f3c3ab78e 100644 --- a/src/gallium/frontends/mediafoundation/reference_frames_tracker_h264.cpp +++ b/src/gallium/frontends/mediafoundation/reference_frames_tracker_h264.cpp @@ -43,12 +43,14 @@ reference_frames_tracker_h264::reference_frames_tracker_h264( struct pipe_video_ uint32_t MaxL0References, uint32_t MaxL1References, uint32_t MaxDPBCapacity, - uint32_t MaxLongTermReferences ) + uint32_t MaxLongTermReferences, + bool bSendUnwrappedPOC ) : m_codec( codec ), m_MaxL0References( MaxL0References ), m_MaxL1References( MaxL1References ), m_MaxDPBCapacity( MaxDPBCapacity ), m_MaxLongTermReferences( MaxLongTermReferences ), + m_bSendUnwrappedPOC( bSendUnwrappedPOC ), m_ALL_LTR_VALID_MASK( ( 1 << m_MaxLongTermReferences ) - 1 ), m_DPBManager( m_codec, @@ -595,14 +597,28 @@ reference_frames_tracker_h264::GOPStateBeginFrame( bool forceKey ) { m_gop_state.reference_type = frame_descriptor_reference_type_short_term; m_gop_state.temporal_id = 0; - m_gop_state.picture_order_count = ( 2 * m_gop_state.frame_num ) % ( 2 * m_max_frame_num ); + if( m_bSendUnwrappedPOC ) + { + m_gop_state.picture_order_count = ( 2 * m_gop_state.frame_num_no_wrap ); + } + else + { + m_gop_state.picture_order_count = ( 2 * m_gop_state.frame_num ) % ( 2 * m_max_frame_num ); + } m_gop_state.current_reference_frame_count++; } else { m_gop_state.reference_type = frame_descriptor_reference_type_none; m_gop_state.temporal_id = 1; - m_gop_state.picture_order_count = ( 2 * m_gop_state.frame_num - 1 ) % ( 2 * m_max_frame_num ); + if( m_bSendUnwrappedPOC ) + { + m_gop_state.picture_order_count = ( 2 * m_gop_state.frame_num_no_wrap - 1 ); + } + else + { + m_gop_state.picture_order_count = ( 2 * m_gop_state.frame_num - 1 ) % ( 2 * m_max_frame_num ); + } } } } diff --git a/src/gallium/frontends/mediafoundation/reference_frames_tracker_h264.h b/src/gallium/frontends/mediafoundation/reference_frames_tracker_h264.h index 3bd88004e1b..b0836d12a30 100644 --- a/src/gallium/frontends/mediafoundation/reference_frames_tracker_h264.h +++ b/src/gallium/frontends/mediafoundation/reference_frames_tracker_h264.h @@ -37,8 +37,8 @@ typedef struct frame_descriptor_h264 uint32_t ip_period; pipe_h2645_enc_picture_type frame_type; uint32_t frame_num; // H264: frame_num % max_frame_num, reset on IDR - uint64_t frame_num_no_wrap; - uint64_t current_reference_frame_count; + uint32_t frame_num_no_wrap; + uint32_t current_reference_frame_count; uint32_t picture_order_count; frame_descriptor_reference_type reference_type; uint32_t ltr_index; @@ -68,7 +68,7 @@ class reference_frames_tracker_h264 : public reference_frames_tracker { uint32_t picture_order_count; uint32_t frame_num; - uint64_t frame_num_no_wrap; + uint32_t frame_num_no_wrap; bool is_ltr; uint32_t ltr_index; uint8_t temporal_id; @@ -81,7 +81,7 @@ class reference_frames_tracker_h264 : public reference_frames_tracker { uint8_t pos; // index into location in the PrevFrameInfo array // below are from PrevFrameInfo - uint64_t frame_num_no_wrap; + uint32_t frame_num_no_wrap; bool is_ltr; uint32_t ltr_index; uint8_t temporal_id; @@ -114,7 +114,8 @@ class reference_frames_tracker_h264 : public reference_frames_tracker uint32_t MaxL0References, uint32_t MaxL1References, uint32_t MaxDPBCapacity, - uint32_t MaxLongTermReferences ); + uint32_t MaxLongTermReferences, + bool bSendUnwrappedPOC ); private: uint32_t PrepareFrameRefLists( bool useLTR, uint32_t useLTRBitmap ); @@ -136,6 +137,8 @@ class reference_frames_tracker_h264 : public reference_frames_tracker uint32_t m_MaxDPBCapacity = 0; uint32_t m_MaxLongTermReferences = 0; + bool m_bSendUnwrappedPOC = false; + bool m_bSendMaxLongTermReferences = false; uint32_t m_ActiveLTRBitmap = 0; diff --git a/src/gallium/frontends/mediafoundation/reference_frames_tracker_hevc.cpp b/src/gallium/frontends/mediafoundation/reference_frames_tracker_hevc.cpp index 019859c0e0b..dd89f952afa 100644 --- a/src/gallium/frontends/mediafoundation/reference_frames_tracker_hevc.cpp +++ b/src/gallium/frontends/mediafoundation/reference_frames_tracker_hevc.cpp @@ -154,7 +154,7 @@ reference_frames_tracker_hevc::begin_frame( reference_frames_tracker_dpb_async_t } } - m_ActiveLTRBitmap = useLTRBitmap & 0xFFFF; // synchronize active LTR bitmap with useLTRBitmap + m_ActiveLTRBitmap = useLTRBitmap & 0xFFFF; // synchronize active LTR bitmap with useLTRBitmap } ltrUsedBitMask = PrepareFrameRefLists();