mediafoundation: fix slice capability check, and fix the slice mb mode, remove slice mode 2

Reviewed-by: Sil Vilerino <sivileri@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35554>
This commit is contained in:
Pohsiang (John) Hsu
2025-06-10 15:22:01 -07:00
committed by Marge Bot
parent 8b15d0f31f
commit 2bb9f691e8
7 changed files with 72 additions and 116 deletions
@@ -383,53 +383,40 @@ CDX12EncHMFT::GetParameterRange( const GUID *Api, VARIANT *ValueMin, VARIANT *Va
}
else if( *Api == CODECAPI_AVEncSliceControlMode )
{
static_assert( PIPE_VIDEO_SLICE_MODE_BLOCKS == 0 );
static_assert( PIPE_VIDEO_SLICE_MODE_MAX_SLICE_SIZE == 1 );
static_assert( PIPE_VIDEO_SLICE_MODE_AUTO == 2 );
bool bSliceModeMB = m_EncoderCapabilities.m_bHWSupportSliceModeMB;
bool bSliceModeMBRow = m_EncoderCapabilities.m_bHWSupportSliceModeMBRow;
// If PIPE_VIDEO_SLICE_MODE_BLOCKS is not supported, return error.
if( m_EncoderCapabilities.m_HWSupportedSliceModes.HasAll( PIPE_VIDEO_SLICE_MODE_BLOCKS,
PIPE_VIDEO_SLICE_MODE_MAX_SLICE_SIZE,
PIPE_VIDEO_SLICE_MODE_AUTO ) )
if( !( bSliceModeMB || bSliceModeMBRow ) )
{
ValueMin->vt = VT_UI4;
ValueMin->ulVal = 0;
ValueMax->vt = VT_UI4;
ValueMax->ulVal = 2;
SteppingDelta->vt = VT_UI4;
SteppingDelta->ulVal = 1;
}
else if( m_EncoderCapabilities.m_HWSupportedSliceModes.HasAll( PIPE_VIDEO_SLICE_MODE_BLOCKS,
PIPE_VIDEO_SLICE_MODE_MAX_SLICE_SIZE ) )
{
ValueMin->vt = VT_UI4;
ValueMin->ulVal = 0;
ValueMax->vt = VT_UI4;
ValueMax->ulVal = 1;
SteppingDelta->vt = VT_UI4;
SteppingDelta->ulVal = 1;
}
else if( m_EncoderCapabilities.m_HWSupportedSliceModes.HasAll( PIPE_VIDEO_SLICE_MODE_BLOCKS ) )
{
ValueMin->vt = VT_UI4;
ValueMin->ulVal = 0;
ValueMax->vt = VT_UI4;
ValueMax->ulVal = 0;
SteppingDelta->vt = VT_UI4;
SteppingDelta->ulVal = 0;
}
else
{
// Nothing is supported.
return E_NOTIMPL;
}
ULONG min = 0;
ULONG max = 2;
ULONG delta = 2;
if( bSliceModeMB && !bSliceModeMBRow )
{
min = 0;
max = 0;
delta = 1;
}
else if( !bSliceModeMB && bSliceModeMBRow )
{
min = 2;
max = 2;
delta = 1;
}
ValueMin->vt = VT_UI4;
ValueMin->ulVal = min;
ValueMax->vt = VT_UI4;
ValueMax->ulVal = max;
SteppingDelta->vt = VT_UI4;
SteppingDelta->ulVal = delta;
return S_OK;
}
else if( *Api == CODECAPI_AVEncSliceControlSize )
@@ -436,17 +436,24 @@ CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bo
{
pPicInfo->slice_mode = PIPE_VIDEO_SLICE_MODE_BLOCKS;
uint32_t blocks_per_slice = m_uiSliceControlSize;
pPicInfo->num_slice_descriptors = ( height_in_blocks * width_in_blocks ) / blocks_per_slice;
pPicInfo->num_slice_descriptors = static_cast<uint32_t>(
std::ceil( ( height_in_blocks * width_in_blocks ) / static_cast<double>( blocks_per_slice ) ) );
uint32_t slice_starting_mb = 0;
CHECKBOOL_GOTO( pPicInfo->num_slice_descriptors <= m_EncoderCapabilities.m_uiMaxHWSupportedMaxSlices,
MF_E_UNEXPECTED,
done );
for( uint32_t i = 0; i < pPicInfo->num_slice_descriptors; i++ )
CHECKBOOL_GOTO( pPicInfo->num_slice_descriptors >= 1, MF_E_UNEXPECTED, done );
uint32_t total_blocks = height_in_blocks * width_in_blocks;
uint32_t i = 0;
for( i = 0; i < pPicInfo->num_slice_descriptors - 1; i++ )
{
pPicInfo->slices_descriptors[i].macroblock_address = slice_starting_mb;
pPicInfo->slices_descriptors[i].num_macroblocks = blocks_per_slice;
slice_starting_mb += blocks_per_slice;
}
pPicInfo->slices_descriptors[i].macroblock_address = slice_starting_mb;
pPicInfo->slices_descriptors[i].num_macroblocks = total_blocks - slice_starting_mb;
}
else if( SLICE_CONTROL_MODE_BITS == m_uiSliceControlMode )
{
@@ -463,12 +470,18 @@ CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bo
CHECKBOOL_GOTO( pPicInfo->num_slice_descriptors <= m_EncoderCapabilities.m_uiMaxHWSupportedMaxSlices,
MF_E_UNEXPECTED,
done );
for( uint32_t i = 0; i < pPicInfo->num_slice_descriptors; i++ )
CHECKBOOL_GOTO( pPicInfo->num_slice_descriptors >= 1, MF_E_UNEXPECTED, done );
uint32_t total_blocks = height_in_blocks * width_in_blocks;
uint32_t i = 0;
for( i = 0; i < pPicInfo->num_slice_descriptors - 1; i++ )
{
pPicInfo->slices_descriptors[i].macroblock_address = slice_starting_mb;
pPicInfo->slices_descriptors[i].num_macroblocks = blocks_per_slice;
slice_starting_mb += blocks_per_slice;
}
pPicInfo->slices_descriptors[i].macroblock_address = slice_starting_mb;
pPicInfo->slices_descriptors[i].num_macroblocks = total_blocks - slice_starting_mb;
}
}
}
@@ -434,17 +434,24 @@ CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bo
{
pPicInfo->slice_mode = PIPE_VIDEO_SLICE_MODE_BLOCKS;
uint32_t blocks_per_slice = m_uiSliceControlSize;
pPicInfo->num_slice_descriptors = ( height_in_blocks * width_in_blocks ) / blocks_per_slice;
pPicInfo->num_slice_descriptors = static_cast<uint32_t>(
std::ceil( ( height_in_blocks * width_in_blocks ) / static_cast<double>( blocks_per_slice ) ) );
uint32_t slice_starting_mb = 0;
CHECKBOOL_GOTO( pPicInfo->num_slice_descriptors <= m_EncoderCapabilities.m_uiMaxHWSupportedMaxSlices,
MF_E_UNEXPECTED,
done );
for( uint32_t i = 0; i < pPicInfo->num_slice_descriptors; i++ )
CHECKBOOL_GOTO( pPicInfo->num_slice_descriptors >= 1, MF_E_UNEXPECTED, done );
uint32_t total_blocks = height_in_blocks * width_in_blocks;
uint32_t i = 0;
for( i = 0; i < pPicInfo->num_slice_descriptors; i++ )
{
pPicInfo->slices_descriptors[i].slice_segment_address = slice_starting_mb;
pPicInfo->slices_descriptors[i].num_ctu_in_slice = blocks_per_slice;
slice_starting_mb += blocks_per_slice;
}
pPicInfo->slices_descriptors[i].slice_segment_address = slice_starting_mb;
pPicInfo->slices_descriptors[i].num_ctu_in_slice = total_blocks - slice_starting_mb;
}
else if( SLICE_CONTROL_MODE_BITS == m_uiSliceControlMode )
{
@@ -141,10 +141,12 @@ encoder_capabilities::initialize( pipe_screen *pScreen, pipe_video_profile video
m_HWSupportMotionGPUMaps.value =
pScreen->get_video_param( pScreen, videoProfile, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_ENC_MOTION_VECTOR_MAPS );
// TODO: We should get the supported slice mode from pipe, but currently, it doesn't support.
// Currently, dx12MFT only support mode_blocks, so we initialize it like this.
m_HWSupportedSliceModes = EnumMask<pipe_video_slice_mode> { PIPE_VIDEO_SLICE_MODE_BLOCKS };
uint32_t supportedSliceStructures =
pScreen->get_video_param( pScreen, videoProfile, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_ENC_SLICES_STRUCTURE );
m_bHWSupportSliceModeMB = ( ( supportedSliceStructures & PIPE_VIDEO_CAP_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS ) != 0 );
m_bHWSupportSliceModeBits = ( ( supportedSliceStructures & PIPE_VIDEO_CAP_SLICE_STRUCTURE_MAX_SLICE_SIZE ) != 0 );
m_bHWSupportSliceModeMBRow = ( ( supportedSliceStructures & PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS ) != 0 );
m_TwoPassSupport.value =
pScreen->get_video_param( pScreen, videoProfile, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_ENC_TWO_PASS );
@@ -26,7 +26,6 @@
#include <string>
#include <wtypes.h>
#include "enum_mask.h"
#include "pipe_headers.h"
class encoder_capabilities
@@ -126,7 +125,9 @@ class encoder_capabilities
union pipe_enc_cap_motion_vector_map m_HWSupportMotionGPUMaps = {};
// Supported slice mode
EnumMask<pipe_video_slice_mode> m_HWSupportedSliceModes {};
bool m_bHWSupportSliceModeMB = false;
bool m_bHWSupportSliceModeBits = false;
bool m_bHWSupportSliceModeMBRow = false;
// Two pass encode
union pipe_enc_cap_two_pass m_TwoPassSupport = {};
@@ -1,64 +0,0 @@
/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#pragma once
#include <initializer_list>
#include <type_traits>
template <typename T>
concept EnumType = std::is_enum_v<T>;
template <EnumType Enum>
class EnumMask
{
using UnderlyingType = std::underlying_type_t<Enum>;
public:
explicit constexpr EnumMask( std::initializer_list<Enum> values )
{
for( auto v : values )
{
m_mask |= MakeValue( v );
}
}
constexpr bool HasAll( Enum v )
{
return m_mask & MakeValue( v );
}
template <EnumType... Enums>
constexpr bool HasAll( Enum v, Enums... values )
{
return HasAll( v ) && HasAll( values... );
}
private:
constexpr UnderlyingType MakeValue( Enum v )
{
return 1 << (UnderlyingType) v;
}
UnderlyingType m_mask {};
};
@@ -60,6 +60,16 @@ TEST( MediaFoundationEntrypoint, VerifyBasicCodecAPI )
ULONG ulValuesCount;
CHECKHR_GOTO( spCodecAPI->GetParameterValues( &CODECAPI_AVEncVideoLTRBufferControl, &pValues, &ulValuesCount ), done );
}
{
VARIANT vMin;
VARIANT vMax;
VARIANT vDelta;
CHECKHR_GOTO( spCodecAPI->GetParameterRange( &CODECAPI_AVEncSliceControlMode, &vMin, &vMax, &vDelta ), done );
ASSERT_TRUE( vMin.vt == VT_UI4 && vMax.vt == VT_UI4 && vDelta.vt == VT_UI4 );
ASSERT_TRUE( vMin.ulVal <= 2u && vMax.ulVal <= 2u );
ASSERT_TRUE( vMin.ulVal <= vMax.ulVal );
ASSERT_TRUE( vDelta.ulVal >= 1u && vDelta.ulVal <= 2u );
}
done:
ASSERT_HRESULT_SUCCEEDED( hr );