mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 15:40:11 +01:00
mediafoundation: Implement d3d12_context_queue_priority_manager and related ICodecAPI
Reviewed-by: Pohsiang (John) Hsu <pohhsu@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37376>
This commit is contained in:
parent
11db73820f
commit
4b203d361e
7 changed files with 262 additions and 2 deletions
|
|
@ -282,6 +282,14 @@ StringFromCodecAPI( const GUID *Api )
|
|||
{
|
||||
return "CODECAPI_AVEncVideoInputAbsoluteQPBlockSettings";
|
||||
}
|
||||
else if( *Api == CODECAPI_AVEncWorkGlobalPriority )
|
||||
{
|
||||
return "CODECAPI_AVEncWorkGlobalPriority";
|
||||
}
|
||||
else if( *Api == CODECAPI_AVEncWorkProcessPriority )
|
||||
{
|
||||
return "CODECAPI_AVEncWorkProcessPriority";
|
||||
}
|
||||
return "Unknown CodecAPI";
|
||||
}
|
||||
|
||||
|
|
@ -405,6 +413,17 @@ CDX12EncHMFT::IsSupported( const GUID *Api )
|
|||
}
|
||||
}
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
if( (*Api == CODECAPI_AVEncWorkGlobalPriority) || (*Api == CODECAPI_AVEncWorkProcessPriority) )
|
||||
{
|
||||
if(m_EncoderCapabilities.m_bHWSupportsQueuePriorityManagement)
|
||||
{
|
||||
hr = S_OK;
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
if( m_EncoderCapabilities.m_TwoPassSupport.bits.supports_1pass_recon_writing_skip )
|
||||
{
|
||||
if( *Api == CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale )
|
||||
|
|
@ -890,6 +909,18 @@ CDX12EncHMFT::GetValue( const GUID *Api, VARIANT *Value )
|
|||
Value->vt = VT_BOOL;
|
||||
Value->boolVal = m_bRateControlFramePreAnalysisExternalReconDownscale ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
}
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
else if( *Api == CODECAPI_AVEncWorkGlobalPriority )
|
||||
{
|
||||
Value->vt = VT_UI4;
|
||||
Value->ulVal = (UINT32) m_WorkGlobalPriority;
|
||||
}
|
||||
else if( *Api == CODECAPI_AVEncWorkProcessPriority )
|
||||
{
|
||||
Value->vt = VT_UI4;
|
||||
Value->ulVal = (UINT32) m_WorkProcessPriority;
|
||||
}
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
else if( *Api == CODECAPI_AVEncVideoInputDeltaQPBlockSettings )
|
||||
{
|
||||
InputQPSettings hevcDeltaQPSettings;
|
||||
|
|
@ -1567,6 +1598,40 @@ CDX12EncHMFT::SetValue( const GUID *Api, VARIANT *Value )
|
|||
}
|
||||
m_bVideoEnableSpatialAdaptiveQuantization = Value->ulVal ? TRUE : FALSE;
|
||||
}
|
||||
else if( *Api == CODECAPI_AVEncWorkProcessPriority )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] SET CODECAPI_AVEncWorkProcessPriority - %u\n", this, Value->ulVal );
|
||||
if( Value->vt != VT_UI4 )
|
||||
{
|
||||
CHECKHR_GOTO( E_INVALIDARG, done );
|
||||
}
|
||||
|
||||
if(!m_EncoderCapabilities.m_bHWSupportsQueuePriorityManagement)
|
||||
{
|
||||
CHECKHR_GOTO( E_INVALIDARG, done );
|
||||
}
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
m_WorkProcessPriority = (D3D12_COMMAND_QUEUE_PROCESS_PRIORITY) (Value->ulVal);;
|
||||
m_bWorkProcessPrioritySet = TRUE;
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
}
|
||||
else if( *Api == CODECAPI_AVEncWorkGlobalPriority )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] SET CODECAPI_AVEncWorkGlobalPriority - %u\n", this, Value->ulVal );
|
||||
if( Value->vt != VT_UI4 )
|
||||
{
|
||||
CHECKHR_GOTO( E_INVALIDARG, done );
|
||||
}
|
||||
|
||||
if(!m_EncoderCapabilities.m_bHWSupportsQueuePriorityManagement)
|
||||
{
|
||||
CHECKHR_GOTO( E_INVALIDARG, done );
|
||||
}
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
m_WorkGlobalPriority = (D3D12_COMMAND_QUEUE_GLOBAL_PRIORITY) Value->ulVal;
|
||||
m_bWorkGlobalPrioritySet = TRUE;
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
}
|
||||
else if( *Api == CODECAPI_AVEncVideoOutputQPMapBlockSize )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] SET CODECAPI_AVEncVideoOutputQPMapBlockSize - %u\n", this, Value->ulVal );
|
||||
|
|
|
|||
|
|
@ -456,6 +456,40 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
|
|||
|
||||
pDX12EncodeContext->pVlScreen = m_pVlScreen; // weakref
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
//
|
||||
// Update the encoder priorities (if any set)
|
||||
//
|
||||
|
||||
#if 0 // For testing priorities
|
||||
{
|
||||
m_bWorkProcessPrioritySet = ((pipeEncoderInputFenceHandleValue % 2) == 0) ? TRUE : FALSE;
|
||||
m_WorkGlobalPriority = static_cast<D3D12_COMMAND_QUEUE_GLOBAL_PRIORITY>((pipeEncoderInputFenceHandleValue % 14) + 18); // 18-31 range (no hard realtime privileges)
|
||||
m_bWorkGlobalPrioritySet = ((pipeEncoderInputFenceHandleValue % 2) == 0) ? TRUE : FALSE;
|
||||
m_WorkProcessPriority = static_cast<D3D12_COMMAND_QUEUE_PROCESS_PRIORITY>(pipeEncoderInputFenceHandleValue % 2); // 0-1 range
|
||||
}
|
||||
#endif // For testing priorities
|
||||
|
||||
if (m_bWorkProcessPrioritySet || m_bWorkGlobalPrioritySet)
|
||||
{
|
||||
for (ID3D12CommandQueue* queue : m_ContextPriorityMgr.m_registeredQueues)
|
||||
{
|
||||
mtx_lock(&m_ContextPriorityMgr.m_lock);
|
||||
int result = m_ContextPriorityMgr.base.set_queue_priority(&m_ContextPriorityMgr.base, queue, reinterpret_cast<uint32_t*>(&m_WorkGlobalPriority), reinterpret_cast<uint32_t*>(&m_WorkProcessPriority));
|
||||
mtx_unlock(&m_ContextPriorityMgr.m_lock);
|
||||
|
||||
CHECKBOOL_GOTO(result == 0, MF_E_UNEXPECTED, done);
|
||||
}
|
||||
|
||||
// Once set in the underlying pipe context, don't set them again
|
||||
// until they're modified by the CodecAPI SetValue function.
|
||||
m_bWorkProcessPrioritySet = FALSE;
|
||||
m_bWorkGlobalPrioritySet = FALSE;
|
||||
}
|
||||
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
// Call the helper for encoder specific work
|
||||
pDX12EncodeContext->encoderPicInfo.base.in_fence = pPipeEncoderInputFenceHandle;
|
||||
pDX12EncodeContext->encoderPicInfo.base.in_fence_value = pipeEncoderInputFenceHandleValue;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
#include <utility>
|
||||
#include <encoder_capabilities.h>
|
||||
#include "gallium/drivers/d3d12/d3d12_interop_public.h"
|
||||
|
||||
// Initializes encoder capabilities by querying hardware-specific parameters from pipe given the video profile.
|
||||
void
|
||||
|
|
@ -153,4 +154,10 @@ encoder_capabilities::initialize( pipe_screen *pScreen, pipe_video_profile video
|
|||
|
||||
m_PSNRStatsSupport.value =
|
||||
pScreen->get_video_param( pScreen, videoProfile, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_ENC_GPU_STATS_PSNR );
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
d3d12_interop_device_info1 screen_interop_info = {};
|
||||
bool successQuery = pScreen->interop_query_device_info(pScreen, sizeof(d3d12_interop_device_info1), &screen_interop_info) != 0;
|
||||
m_bHWSupportsQueuePriorityManagement = successQuery && screen_interop_info.set_context_queue_priority_manager != NULL;
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,4 +134,7 @@ class encoder_capabilities
|
|||
|
||||
// PSNR frame stats
|
||||
union pipe_enc_cap_gpu_stats_psnr m_PSNRStatsSupport = {};
|
||||
|
||||
// Driver supports queue priority management
|
||||
bool m_bHWSupportsQueuePriorityManagement = false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -504,6 +504,45 @@ DEFINE_CODECAPI_GUID( AVEncVideoRateControlFramePreAnalysisExternalReconDownscal
|
|||
DEFINE_CODECAPI_GUIDNAMED( AVEncVideoRateControlFramePreAnalysisExternalReconDownscale )
|
||||
#endif
|
||||
|
||||
#ifndef CODECAPI_AVEncWorkGlobalPriority
|
||||
// AVEncWorkGlobalPriority (VT_UI4) (Experimental, Testing only)
|
||||
// Indicates global priority for all work submitted by the encoder to the GPU
|
||||
// VARIANT_FALSE: disable; VARIANT_TRUE: enable
|
||||
DEFINE_CODECAPI_GUID( AVEncWorkGlobalPriority,
|
||||
"CA123CAA-A17B-4BBA-9E08-269F3CF5D636",
|
||||
0xca123caa,
|
||||
0xa17b,
|
||||
0x4bba,
|
||||
0x9e,
|
||||
0x8,
|
||||
0x26,
|
||||
0x9f,
|
||||
0x3c,
|
||||
0xf5,
|
||||
0xd6,
|
||||
0x36 )
|
||||
#define CODECAPI_AVEncWorkGlobalPriority DEFINE_CODECAPI_GUIDNAMED( AVEncWorkGlobalPriority )
|
||||
#endif
|
||||
|
||||
#ifndef CODECAPI_AVEncWorkProcessPriority
|
||||
// AVEncWorkProcessPriority (VT_UI4) (Experimental, Testing only)
|
||||
// Indicates global priority for all work submitted by the encoder to the GPU
|
||||
// VARIANT_FALSE: disable; VARIANT_TRUE: enable
|
||||
DEFINE_CODECAPI_GUID( AVEncWorkProcessPriority,
|
||||
"FB123CAA-B778-4BBA-9E08-269F3CF5D125",
|
||||
0xfb123caa,
|
||||
0xb778,
|
||||
0x4bba,
|
||||
0x9e,
|
||||
0x8,
|
||||
0x26,
|
||||
0x9f,
|
||||
0x3c,
|
||||
0xf5,
|
||||
0xd1,
|
||||
0x25 )
|
||||
#define CODECAPI_AVEncWorkProcessPriority DEFINE_CODECAPI_GUIDNAMED( AVEncWorkProcessPriority )
|
||||
#endif
|
||||
|
||||
#if MFT_CODEC_H264ENC
|
||||
#define HMFT_GUID "8994db7c-288a-4c62-a136-a3c3c2a208a8"
|
||||
|
|
@ -695,6 +734,13 @@ class __declspec( uuid( HMFT_GUID ) ) CDX12EncHMFT : CMFD3DManager,
|
|||
BOOL m_bRateControlFramePreAnalysis = FALSE;
|
||||
BOOL m_bRateControlFramePreAnalysisExternalReconDownscale = FALSE;
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
D3D12_COMMAND_QUEUE_PROCESS_PRIORITY m_WorkProcessPriority = {};
|
||||
BOOL m_bWorkProcessPrioritySet = FALSE;
|
||||
D3D12_COMMAND_QUEUE_GLOBAL_PRIORITY m_WorkGlobalPriority = {};
|
||||
BOOL m_bWorkGlobalPrioritySet = FALSE;
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
struct pipe_video_codec *m_pPipeVideoCodec = nullptr;
|
||||
struct pipe_video_codec *m_pPipeVideoBlitter = nullptr;
|
||||
reference_frames_tracker *m_pGOPTracker = nullptr;
|
||||
|
|
|
|||
|
|
@ -248,12 +248,71 @@ CMFD3DManager::UpdateGPUFeatureFlags()
|
|||
*/
|
||||
}
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
int MFTRegisterWorkQueue(struct d3d12_context_queue_priority_manager* manager, ID3D12CommandQueue* queue)
|
||||
{
|
||||
mft_context_queue_priority_manager* mft_mgr = (mft_context_queue_priority_manager*) manager;
|
||||
mtx_lock(&mft_mgr->m_lock);
|
||||
|
||||
ComPtr<IUnknown> queue_unknown;
|
||||
if (FAILED(queue->QueryInterface(IID_PPV_ARGS( &queue_unknown ))))
|
||||
{
|
||||
mtx_unlock(&mft_mgr->m_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Only register the queue if not already registered
|
||||
auto it = std::find(mft_mgr->m_registeredQueues.begin(), mft_mgr->m_registeredQueues.end(), queue);
|
||||
if (it == mft_mgr->m_registeredQueues.end())
|
||||
{
|
||||
//
|
||||
// Register the queue_unknown with the MFT.
|
||||
//
|
||||
|
||||
mft_mgr->m_registeredQueues.push_back(queue);
|
||||
}
|
||||
|
||||
mtx_unlock(&mft_mgr->m_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MFTUnregisterWorkQueue(struct d3d12_context_queue_priority_manager* manager, ID3D12CommandQueue* queue)
|
||||
{
|
||||
mft_context_queue_priority_manager* mft_mgr = (mft_context_queue_priority_manager*) manager;
|
||||
mtx_lock(&mft_mgr->m_lock);
|
||||
|
||||
ComPtr<IUnknown> queue_unknown;
|
||||
if (FAILED(queue->QueryInterface(IID_PPV_ARGS( &queue_unknown ))))
|
||||
{
|
||||
mtx_unlock(&mft_mgr->m_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Unregister the queue_unknown with the MFT.
|
||||
//
|
||||
|
||||
auto it = std::find(mft_mgr->m_registeredQueues.begin(), mft_mgr->m_registeredQueues.end(), queue);
|
||||
if (it != mft_mgr->m_registeredQueues.end())
|
||||
mft_mgr->m_registeredQueues.erase(it);
|
||||
|
||||
mtx_unlock(&mft_mgr->m_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
HRESULT
|
||||
CMFD3DManager::xOnSetD3DManager( ULONG_PTR ulParam )
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
Shutdown();
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
d3d12_interop_device_info1 screen_interop_info = {};
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
if( ulParam == 0 )
|
||||
{
|
||||
return hr;
|
||||
|
|
@ -273,6 +332,36 @@ CMFD3DManager::xOnSetD3DManager( ULONG_PTR ulParam )
|
|||
CHECKNULL_GOTO( m_pPipeContext = pipe_create_multimedia_context( m_pVlScreen->pscreen, false ),
|
||||
MF_E_DXGI_DEVICE_NOT_INITIALIZED,
|
||||
done );
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
if ((m_pVlScreen->pscreen->interop_query_device_info(m_pVlScreen->pscreen, sizeof(d3d12_interop_device_info1), &screen_interop_info) != 0) &&
|
||||
(screen_interop_info.set_context_queue_priority_manager != NULL))
|
||||
{
|
||||
CHECKBOOL_GOTO( thrd_success == mtx_init(&m_ContextPriorityMgr.m_lock, mtx_plain),
|
||||
MF_E_DXGI_DEVICE_NOT_INITIALIZED,
|
||||
done );
|
||||
|
||||
m_ContextPriorityMgr.base.register_work_queue = MFTRegisterWorkQueue;
|
||||
m_ContextPriorityMgr.base.unregister_work_queue = MFTUnregisterWorkQueue;
|
||||
|
||||
CHECKBOOL_GOTO( screen_interop_info.set_context_queue_priority_manager( m_pPipeContext, &m_ContextPriorityMgr.base ) == 0,
|
||||
MF_E_DXGI_DEVICE_NOT_INITIALIZED,
|
||||
done );
|
||||
|
||||
//
|
||||
// Verify that the callbacks have been filled by the driver
|
||||
//
|
||||
CHECKNULL_GOTO( m_ContextPriorityMgr.base.context,
|
||||
MF_E_DXGI_DEVICE_NOT_INITIALIZED,
|
||||
done );
|
||||
CHECKNULL_GOTO( m_ContextPriorityMgr.base.set_queue_priority,
|
||||
MF_E_DXGI_DEVICE_NOT_INITIALIZED,
|
||||
done );
|
||||
CHECKNULL_GOTO( m_ContextPriorityMgr.base.get_queue_priority,
|
||||
MF_E_DXGI_DEVICE_NOT_INITIALIZED,
|
||||
done );
|
||||
}
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
CHECKHR_GOTO( MFCreateVideoSampleAllocatorEx( IID_PPV_ARGS( &m_spVideoSampleAllocator ) ), done );
|
||||
|
||||
CHECKHR_GOTO( GetDeviceInfo(), done );
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@
|
|||
#include <mutex>
|
||||
#include <wrl/client.h>
|
||||
#include <wrl/implements.h>
|
||||
#include <c11/threads.h>
|
||||
#include <vector>
|
||||
#include "gallium/drivers/d3d12/d3d12_interop_public.h"
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
|
|
@ -65,6 +68,15 @@ typedef union
|
|||
uint64_t version; // bits field
|
||||
} MFAdapterDriverVersion;
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
struct mft_context_queue_priority_manager
|
||||
{
|
||||
struct d3d12_context_queue_priority_manager base;
|
||||
std::vector<ID3D12CommandQueue*> m_registeredQueues;
|
||||
mtx_t m_lock;
|
||||
};
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
class CMFD3DManager
|
||||
{
|
||||
public:
|
||||
|
|
@ -94,6 +106,10 @@ class CMFD3DManager
|
|||
struct sw_winsys *m_pWinsys = nullptr;
|
||||
struct pipe_context *m_pPipeContext = nullptr;
|
||||
|
||||
#if ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
struct mft_context_queue_priority_manager m_ContextPriorityMgr = {};
|
||||
#endif // ( USE_D3D12_PREVIEW_HEADERS && ( D3D12_PREVIEW_SDK_VERSION >= 717 ) )
|
||||
|
||||
uint32_t m_deviceVendorId {};
|
||||
uint32_t m_deviceDeviceId {};
|
||||
MFAdapterDriverVersion m_deviceDriverVersion {};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue