d3d12: Add video encode PSNR output stats
Reviewed-by: Pohsiang (John) Hsu <pohhsu@microsoft.com> Reviewed-by: Jesse Natalie <jenatali@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35263>
This commit is contained in:
@@ -2277,12 +2277,14 @@ void
|
||||
d3d12_video_encoder_update_output_stats_resources(struct d3d12_video_encoder *pD3D12Enc,
|
||||
struct pipe_resource* qpmap,
|
||||
struct pipe_resource* satdmap,
|
||||
struct pipe_resource* rcbitsmap)
|
||||
struct pipe_resource* rcbitsmap,
|
||||
struct pipe_resource* psnrmap)
|
||||
{
|
||||
#if D3D12_VIDEO_USE_NEW_ENCODECMDLIST4_INTERFACE
|
||||
pD3D12Enc->m_currentEncodeConfig.m_GPUQPStatsResource = d3d12_resource(qpmap);
|
||||
pD3D12Enc->m_currentEncodeConfig.m_GPUSATDStatsResource = d3d12_resource(satdmap);
|
||||
pD3D12Enc->m_currentEncodeConfig.m_GPURCBitAllocationStatsResource = d3d12_resource(rcbitsmap);
|
||||
pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource = d3d12_resource(psnrmap);
|
||||
#endif // D3D12_VIDEO_USE_NEW_ENCODECMDLIST4_INTERFACE
|
||||
}
|
||||
|
||||
@@ -2302,7 +2304,8 @@ d3d12_video_encoder_update_current_encoder_config_state(struct d3d12_video_encod
|
||||
d3d12_video_encoder_update_output_stats_resources(pD3D12Enc,
|
||||
((struct pipe_h264_enc_picture_desc *)picture)->gpu_stats_qp_map,
|
||||
((struct pipe_h264_enc_picture_desc *)picture)->gpu_stats_satd_map,
|
||||
((struct pipe_h264_enc_picture_desc *)picture)->gpu_stats_rc_bitallocation_map);
|
||||
((struct pipe_h264_enc_picture_desc *)picture)->gpu_stats_rc_bitallocation_map,
|
||||
((struct pipe_h264_enc_picture_desc *)picture)->gpu_stats_psnr);
|
||||
|
||||
d3d12_video_encoder_update_move_rects(pD3D12Enc, ((struct pipe_h264_enc_picture_desc *)picture)->move_info);
|
||||
d3d12_video_encoder_update_dirty_rects(pD3D12Enc, ((struct pipe_h264_enc_picture_desc *)picture)->dirty_info);
|
||||
@@ -2320,7 +2323,8 @@ d3d12_video_encoder_update_current_encoder_config_state(struct d3d12_video_encod
|
||||
d3d12_video_encoder_update_output_stats_resources(pD3D12Enc,
|
||||
((struct pipe_h265_enc_picture_desc *)picture)->gpu_stats_qp_map,
|
||||
((struct pipe_h265_enc_picture_desc *)picture)->gpu_stats_satd_map,
|
||||
((struct pipe_h265_enc_picture_desc *)picture)->gpu_stats_rc_bitallocation_map);
|
||||
((struct pipe_h265_enc_picture_desc *)picture)->gpu_stats_rc_bitallocation_map,
|
||||
((struct pipe_h264_enc_picture_desc *)picture)->gpu_stats_psnr);
|
||||
|
||||
d3d12_video_encoder_update_move_rects(pD3D12Enc, ((struct pipe_h265_enc_picture_desc *)picture)->move_info);
|
||||
d3d12_video_encoder_update_dirty_rects(pD3D12Enc, ((struct pipe_h265_enc_picture_desc *)picture)->dirty_info);
|
||||
@@ -3641,6 +3645,18 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
|
||||
d12_gpu_stats_rc_bitallocation_map = d3d12_resource_resource(pD3D12Enc->m_currentEncodeConfig.m_GPURCBitAllocationStatsResource);
|
||||
}
|
||||
|
||||
ID3D12Resource* d12_gpu_stats_psnr = NULL;
|
||||
if (pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource) {
|
||||
optionalMetadataFlags |= D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_FRAME_PSNR;
|
||||
d3d12_promote_to_permanent_residency(pD3D12Enc->m_pD3D12Screen, pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource);
|
||||
d3d12_transition_resource_state(d3d12_context(pD3D12Enc->base.context),
|
||||
pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS);
|
||||
d3d12_resource_wait_idle(d3d12_context(pD3D12Enc->base.context), pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource, true /*wantToWrite*/);
|
||||
d12_gpu_stats_psnr = d3d12_resource_resource(pD3D12Enc->m_currentEncodeConfig.m_GPUPSNRAllocationStatsResource);
|
||||
}
|
||||
|
||||
D3D12_VIDEO_ENCODER_FRAME_ANALYSIS FrameAnalysis = {};
|
||||
D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE FrameAnalysisReconstructedPicture = {};
|
||||
std::vector<D3D12_RESOURCE_BARRIER> pTwoPassExtraBarriers;
|
||||
@@ -4005,6 +4021,12 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
|
||||
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE));
|
||||
}
|
||||
|
||||
if (d12_gpu_stats_psnr) {
|
||||
output_stats_barriers.push_back(CD3DX12_RESOURCE_BARRIER::Transition(d12_gpu_stats_psnr,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE));
|
||||
}
|
||||
|
||||
spEncodeCommandList4->ResourceBarrier(static_cast<uint32_t>(output_stats_barriers.size()),
|
||||
output_stats_barriers.data());
|
||||
const D3D12_VIDEO_ENCODER_RESOLVE_METADATA_INPUT_ARGUMENTS1 inputMetadataCmd = {
|
||||
@@ -4030,7 +4052,12 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
|
||||
// ID3D12Resource *pOutputBitAllocationMap;
|
||||
d12_gpu_stats_rc_bitallocation_map,
|
||||
// D3D12_VIDEO_ENCODER_ENCODE_OPERATION_METADATA_BUFFER ResolvedFramePSNRData;
|
||||
{},
|
||||
{
|
||||
// ID3D12Resource *pBuffer;
|
||||
d12_gpu_stats_psnr,
|
||||
// UINT64 Offset;
|
||||
0u,
|
||||
},
|
||||
// D3D12_VIDEO_ENCODER_ENCODE_OPERATION_METADATA_BUFFER ResolvedSubregionsPSNRData;
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -378,6 +378,7 @@ struct D3D12EncodeConfiguration
|
||||
struct d3d12_resource *m_GPUQPStatsResource = NULL;
|
||||
struct d3d12_resource *m_GPUSATDStatsResource = NULL;
|
||||
struct d3d12_resource *m_GPURCBitAllocationStatsResource = NULL;
|
||||
struct d3d12_resource *m_GPUPSNRAllocationStatsResource = NULL;
|
||||
struct
|
||||
{
|
||||
//
|
||||
@@ -737,7 +738,8 @@ void
|
||||
d3d12_video_encoder_update_output_stats_resources(struct d3d12_video_encoder *pD3D12Enc,
|
||||
struct pipe_resource* qpmap,
|
||||
struct pipe_resource* satdmap,
|
||||
struct pipe_resource* rcbitsmap);
|
||||
struct pipe_resource* rcbitsmap,
|
||||
struct pipe_resource* psnrmap);
|
||||
|
||||
bool
|
||||
d3d12_video_encoder_prepare_input_buffers(struct d3d12_video_encoder *pD3D12Enc);
|
||||
|
||||
@@ -1274,11 +1274,13 @@ get_gpu_output_stats_support(D3D12_VIDEO_ENCODER_INPUT_MAP_SESSION_INFO sessionI
|
||||
ID3D12VideoDevice3* pD3D12VideoDevice,
|
||||
union pipe_enc_cap_gpu_stats_map &gpu_stats_qp,
|
||||
union pipe_enc_cap_gpu_stats_map &gpu_stats_satd,
|
||||
union pipe_enc_cap_gpu_stats_map &gpu_stats_rcbits)
|
||||
union pipe_enc_cap_gpu_stats_map &gpu_stats_rcbits,
|
||||
union pipe_enc_cap_gpu_stats_psnr& psnr_support)
|
||||
{
|
||||
gpu_stats_qp.bits.supported = ((capEncoderSupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_PER_BLOCK_QP_MAP_METADATA_AVAILABLE)) ? 1u : 0u;
|
||||
gpu_stats_satd.bits.supported = ((capEncoderSupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_PER_BLOCK_SATD_MAP_METADATA_AVAILABLE)) ? 1u : 0u;
|
||||
gpu_stats_rcbits.bits.supported = ((capEncoderSupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_PER_BLOCK_RC_BIT_ALLOCATION_MAP_METADATA_AVAILABLE )) ? 1u : 0u;
|
||||
psnr_support.bits.supports_y_channel = ((capEncoderSupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_FRAME_PSNR_METADATA_AVAILABLE)) ? 1u : 0u;
|
||||
|
||||
D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAGS optionalMetadataFlags = D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_NONE;
|
||||
if (gpu_stats_qp.bits.supported)
|
||||
@@ -1287,6 +1289,8 @@ get_gpu_output_stats_support(D3D12_VIDEO_ENCODER_INPUT_MAP_SESSION_INFO sessionI
|
||||
optionalMetadataFlags |= D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_SATD_MAP;
|
||||
if (gpu_stats_rcbits.bits.supported)
|
||||
optionalMetadataFlags |= D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_RC_BIT_ALLOCATION_MAP;
|
||||
if (psnr_support.bits.supports_y_channel)
|
||||
optionalMetadataFlags |= D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_FRAME_PSNR;
|
||||
|
||||
D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS1 capStatsResourceReqs =
|
||||
{
|
||||
@@ -1345,6 +1349,13 @@ get_gpu_output_stats_support(D3D12_VIDEO_ENCODER_INPUT_MAP_SESSION_INFO sessionI
|
||||
uint32_t block_size = static_cast<uint32_t>(std::ceil(capStatsResourceReqs.PictureTargetResolution.Width / static_cast<double>(capStatsResourceReqs.EncoderOutputMetadataBitAllocationMapTextureDimensions.Width)));
|
||||
gpu_stats_rcbits.bits.log2_values_block_size = static_cast<uint32_t>(std::log2(block_size));
|
||||
}
|
||||
|
||||
if ((capEncoderSupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_FRAME_PSNR_METADATA_AVAILABLE))
|
||||
{
|
||||
psnr_support.bits.supports_y_channel = (capStatsResourceReqs.EncoderOutputMetadataFramePSNRComponentsNumber >= 1);
|
||||
psnr_support.bits.supports_u_channel = (capStatsResourceReqs.EncoderOutputMetadataFramePSNRComponentsNumber >= 2);
|
||||
psnr_support.bits.supports_u_channel = (capStatsResourceReqs.EncoderOutputMetadataFramePSNRComponentsNumber >= 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1479,7 +1490,8 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
||||
union pipe_enc_cap_dirty_info &dirty_rects_support_gpu,
|
||||
union pipe_enc_cap_qpmap &qpmap_support,
|
||||
union pipe_enc_cap_motion_vector_map &gpu_motion_input_support,
|
||||
union pipe_enc_cap_two_pass &two_pass_support)
|
||||
union pipe_enc_cap_two_pass &two_pass_support,
|
||||
union pipe_enc_cap_gpu_stats_psnr& psnr_support)
|
||||
{
|
||||
ComPtr<ID3D12VideoDevice3> spD3D12VideoDevice;
|
||||
struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
|
||||
@@ -1613,7 +1625,7 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
||||
dirty_rects_support = get_dirty_rects_support(sessionInfo, spD3D12VideoDevice.Get(), D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_CPU_BUFFER);
|
||||
dirty_rects_support_gpu = get_dirty_rects_support(sessionInfo, spD3D12VideoDevice.Get(), D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE);
|
||||
move_rects_support = get_move_rects_support(sessionInfo, spD3D12VideoDevice.Get());
|
||||
get_gpu_output_stats_support(sessionInfo, capEncoderSupportData1.SupportFlags, spD3D12VideoDevice.Get(), gpu_stats_qp, gpu_stats_satd, gpu_stats_rcbits);
|
||||
get_gpu_output_stats_support(sessionInfo, capEncoderSupportData1.SupportFlags, spD3D12VideoDevice.Get(), gpu_stats_qp, gpu_stats_satd, gpu_stats_rcbits, psnr_support);
|
||||
sliced_encode_support = get_sliced_encode_support(capEncoderSupportData1.SupportFlags);
|
||||
qpmap_support = get_qpmap_gpuinput_support(sessionInfo, spD3D12VideoDevice.Get());
|
||||
gpu_motion_input_support = get_motion_gpuinput_support(sessionInfo, spD3D12VideoDevice.Get());
|
||||
@@ -1943,7 +1955,7 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
||||
dirty_rects_support = get_dirty_rects_support(sessionInfo, spD3D12VideoDevice.Get(), D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_CPU_BUFFER);
|
||||
dirty_rects_support_gpu = get_dirty_rects_support(sessionInfo, spD3D12VideoDevice.Get(), D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE);
|
||||
move_rects_support = get_move_rects_support(sessionInfo, spD3D12VideoDevice.Get());
|
||||
get_gpu_output_stats_support(sessionInfo, capEncoderSupportData1.SupportFlags, spD3D12VideoDevice.Get(), gpu_stats_qp, gpu_stats_satd, gpu_stats_rcbits);
|
||||
get_gpu_output_stats_support(sessionInfo, capEncoderSupportData1.SupportFlags, spD3D12VideoDevice.Get(), gpu_stats_qp, gpu_stats_satd, gpu_stats_rcbits, psnr_support);
|
||||
sliced_encode_support = get_sliced_encode_support(capEncoderSupportData1.SupportFlags);
|
||||
gpu_motion_input_support = get_motion_gpuinput_support(sessionInfo, spD3D12VideoDevice.Get());
|
||||
two_pass_support = query_two_pass_support(pscreen, sessionInfo, spD3D12VideoDevice.Get(),
|
||||
@@ -2467,6 +2479,7 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
||||
union pipe_enc_cap_qpmap gpu_qpmap_input = {};
|
||||
union pipe_enc_cap_motion_vector_map gpu_motion_input = {};
|
||||
union pipe_enc_cap_two_pass two_pass_support = {};
|
||||
union pipe_enc_cap_gpu_stats_psnr psnr_support = {};
|
||||
memset(&codec_specific_support, 0, sizeof(codec_specific_support));
|
||||
switch (param) {
|
||||
case PIPE_VIDEO_CAP_REQUIRES_FLUSH_ON_END_FRAME:
|
||||
@@ -2539,6 +2552,7 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
||||
case PIPE_VIDEO_CAP_ENC_QP_MAPS:
|
||||
case PIPE_VIDEO_CAP_ENC_MOTION_VECTOR_MAPS:
|
||||
case PIPE_VIDEO_CAP_ENC_TWO_PASS:
|
||||
case PIPE_VIDEO_CAP_ENC_GPU_STATS_PSNR:
|
||||
{
|
||||
if (d3d12_has_video_encode_support(pscreen,
|
||||
profile,
|
||||
@@ -2568,7 +2582,8 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
||||
dirty_rects_support_gpu,
|
||||
gpu_qpmap_input,
|
||||
gpu_motion_input,
|
||||
two_pass_support)) {
|
||||
two_pass_support,
|
||||
psnr_support)) {
|
||||
|
||||
DXGI_FORMAT format = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
|
||||
auto pipeFmt = d3d12_get_pipe_format(format);
|
||||
@@ -2673,6 +2688,8 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
||||
return gpu_motion_input.value;
|
||||
} else if (param == PIPE_VIDEO_CAP_ENC_TWO_PASS ) {
|
||||
return two_pass_support.value;
|
||||
} else if (param == PIPE_VIDEO_CAP_ENC_GPU_STATS_PSNR ) {
|
||||
return psnr_support.value;
|
||||
}
|
||||
}
|
||||
} else if (param == PIPE_VIDEO_CAP_ENC_QUALITY_LEVEL) {
|
||||
@@ -2751,6 +2768,7 @@ d3d12_video_encode_requires_texture_array_dpb(struct d3d12_screen* pScreen, enum
|
||||
union pipe_enc_cap_qpmap gpu_qpmap_input = {};
|
||||
union pipe_enc_cap_motion_vector_map gpu_motion_input = {};
|
||||
union pipe_enc_cap_two_pass two_pass_support = {};
|
||||
union pipe_enc_cap_gpu_stats_psnr psnr_support = {};
|
||||
if (d3d12_has_video_encode_support(&pScreen->base,
|
||||
profile,
|
||||
maxLvlEncode,
|
||||
@@ -2779,7 +2797,8 @@ d3d12_video_encode_requires_texture_array_dpb(struct d3d12_screen* pScreen, enum
|
||||
dirty_rects_support_gpu,
|
||||
gpu_qpmap_input,
|
||||
gpu_motion_input,
|
||||
two_pass_support))
|
||||
two_pass_support,
|
||||
psnr_support))
|
||||
{
|
||||
return bVideoEncodeRequiresTextureArray;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user