mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 02:28:10 +02:00
d3d12: Implement GPU Input Motion vectors
Reviewed-By: Pohsiang Hsu <pohhsu@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34844>
This commit is contained in:
parent
143087dadd
commit
1c31fc3091
3 changed files with 301 additions and 42 deletions
|
|
@ -337,50 +337,86 @@ d3d12_video_encoder_friendly_frame_type_h264(D3D12_VIDEO_ENCODER_FRAME_TYPE_H264
|
|||
}
|
||||
}
|
||||
|
||||
#if D3D12_VIDEO_USE_NEW_ENCODECMDLIST4_INTERFACE
|
||||
static D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION
|
||||
d3d12_video_encoder_convert_move_precision(enum pipe_enc_move_info_precision_unit precision)
|
||||
{
|
||||
switch (precision)
|
||||
{
|
||||
case PIPE_ENC_MOVE_INFO_PRECISION_UNIT_FULL_PIXEL:
|
||||
{
|
||||
return D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_FULL_PIXEL;
|
||||
} break;
|
||||
case PIPE_ENC_MOVE_INFO_PRECISION_UNIT_HALF_PIXEL:
|
||||
{
|
||||
return D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_HALF_PIXEL;
|
||||
} break;
|
||||
case PIPE_ENC_MOVE_INFO_PRECISION_UNIT_QUARTER_PIXEL:
|
||||
{
|
||||
return D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_QUARTER_PIXEL;
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
unreachable("Unsupported pipe_enc_move_info");
|
||||
return D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_FULL_PIXEL;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
#endif // D3D12_VIDEO_USE_NEW_ENCODECMDLIST4_INTERFACE
|
||||
|
||||
void
|
||||
d3d12_video_encoder_update_move_rects(struct d3d12_video_encoder *pD3D12Enc,
|
||||
const struct pipe_enc_move_info& rects)
|
||||
{
|
||||
#if D3D12_VIDEO_USE_NEW_ENCODECMDLIST4_INTERFACE
|
||||
assert(rects.num_rects <= PIPE_ENC_MOVE_RECTS_NUM_MAX);
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.NumMoveRegions = std::min(rects.num_rects, static_cast<uint32_t>(PIPE_ENC_MOVE_RECTS_NUM_MAX));
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray.resize(pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.NumMoveRegions);
|
||||
for (uint32_t i = 0; i < pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.NumMoveRegions; i++) {
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].SourcePoint.x = rects.rects[i].source_point.x;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].SourcePoint.y = rects.rects[i].source_point.y;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].DestRect.top = rects.rects[i].dest_rect.top;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].DestRect.left = rects.rects[i].dest_rect.left;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].DestRect.right = rects.rects[i].dest_rect.right;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].DestRect.bottom = rects.rects[i].dest_rect.bottom;
|
||||
}
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.pMoveRegions = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray.data();
|
||||
memset(&pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc, 0, sizeof(pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc));
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapSource = rects.input_mode == PIPE_ENC_MOVE_INFO_INPUT_MODE_RECTS ?
|
||||
D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_CPU_BUFFER : D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE;
|
||||
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MotionSearchModeConfiguration.MotionSearchMode = D3D12_VIDEO_ENCODER_FRAME_MOTION_SEARCH_MODE_FULL_SEARCH;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MotionSearchModeConfiguration.SearchDeviationLimit = 0u;
|
||||
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.SourceDPBFrameReference = rects.dpb_reference_index;
|
||||
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.Flags = rects.overlapping_rects ? D3D12_VIDEO_ENCODER_MOVEREGION_INFO_FLAG_MULTIPLE_HINTS :
|
||||
D3D12_VIDEO_ENCODER_MOVEREGION_INFO_FLAG_NONE;
|
||||
|
||||
switch (rects.precision)
|
||||
if (rects.input_mode == PIPE_ENC_MOVE_INFO_INPUT_MODE_RECTS)
|
||||
{
|
||||
case PIPE_ENC_MOVE_INFO_PRECISION_UNIT_FULL_PIXEL:
|
||||
assert(rects.num_rects <= PIPE_ENC_MOVE_RECTS_NUM_MAX);
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.NumMoveRegions = std::min(rects.num_rects, static_cast<uint32_t>(PIPE_ENC_MOVE_RECTS_NUM_MAX));
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray.resize(pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.NumMoveRegions);
|
||||
for (uint32_t i = 0; i < pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.NumMoveRegions; i++) {
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].SourcePoint.x = rects.rects[i].source_point.x;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].SourcePoint.y = rects.rects[i].source_point.y;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].DestRect.top = rects.rects[i].dest_rect.top;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].DestRect.left = rects.rects[i].dest_rect.left;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].DestRect.right = rects.rects[i].dest_rect.right;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray[i].DestRect.bottom = rects.rects[i].dest_rect.bottom;
|
||||
}
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.pMoveRegions = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsArray.data();
|
||||
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.MotionSearchModeConfiguration.MotionSearchMode = D3D12_VIDEO_ENCODER_FRAME_MOTION_SEARCH_MODE_FULL_SEARCH;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.MotionSearchModeConfiguration.SearchDeviationLimit = 0u;
|
||||
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.SourceDPBFrameReference = rects.dpb_reference_index;
|
||||
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.Flags = rects.overlapping_rects ? D3D12_VIDEO_ENCODER_MOVEREGION_INFO_FLAG_MULTIPLE_HINTS :
|
||||
D3D12_VIDEO_ENCODER_MOVEREGION_INFO_FLAG_NONE;
|
||||
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.MotionUnitPrecision = d3d12_video_encoder_convert_move_precision(rects.precision);
|
||||
}
|
||||
else if (rects.input_mode == PIPE_ENC_MOVE_INFO_INPUT_MODE_MAP)
|
||||
{
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.MotionSearchModeConfiguration.MotionSearchMode = D3D12_VIDEO_ENCODER_FRAME_MOTION_SEARCH_MODE_FULL_SEARCH;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.MotionSearchModeConfiguration.SearchDeviationLimit = 0u;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.NumHintsPerPixel = rects.num_hints;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.ppMotionVectorMaps.resize(rects.num_hints);
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.ppMotionVectorMapsMetadata.resize(rects.num_hints);
|
||||
for (unsigned i = 0; i < rects.num_hints; i++)
|
||||
{
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MotionUnitPrecision = D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_FULL_PIXEL;
|
||||
} break;
|
||||
case PIPE_ENC_MOVE_INFO_PRECISION_UNIT_HALF_PIXEL:
|
||||
{
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MotionUnitPrecision = D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_HALF_PIXEL;
|
||||
} break;
|
||||
case PIPE_ENC_MOVE_INFO_PRECISION_UNIT_QUARTER_PIXEL:
|
||||
{
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MotionUnitPrecision = D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_QUARTER_PIXEL;
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
unreachable("Unsupported pipe_enc_move_info");
|
||||
} break;
|
||||
assert(i < PIPE_ENC_MOVE_MAP_MAX_HINTS);
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.ppMotionVectorMaps[i] = d3d12_resource_resource(d3d12_resource(rects.gpu_motion_vectors_map[i]));
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.pMotionVectorMapsSubresources = NULL;
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.ppMotionVectorMapsMetadata[i] = d3d12_resource_resource(d3d12_resource(rects.gpu_motion_metadata_map[i]));
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.pMotionVectorMapsMetadataSubresources = NULL;
|
||||
}
|
||||
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.MotionUnitPrecision = d3d12_video_encoder_convert_move_precision(rects.precision);
|
||||
// pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.PictureControlConfiguration is set later as not all the params are ready at this stage
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1385,6 +1421,24 @@ d3d12_video_encoder_disable_rc_minmaxqp(struct D3D12EncodeRateControlState & rcS
|
|||
}
|
||||
}
|
||||
|
||||
static bool d3d12_video_encoder_is_move_regions_feature_enabled(struct d3d12_video_encoder* pD3D12Enc, D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE mapSource)
|
||||
{
|
||||
if (pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapSource != mapSource)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mapSource == D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_CPU_BUFFER)
|
||||
{
|
||||
return pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo.NumMoveRegions > 0;
|
||||
}
|
||||
else if (mapSource == D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE)
|
||||
{
|
||||
return pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.NumHintsPerPixel > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool d3d12_video_encoder_is_dirty_regions_feature_enabled(struct d3d12_video_encoder* pD3D12Enc, D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE mapSource)
|
||||
{
|
||||
if (pD3D12Enc->m_currentEncodeConfig.m_DirtyRectsDesc.MapSource != mapSource)
|
||||
|
|
@ -1618,6 +1672,14 @@ bool d3d12_video_encoder_query_d3d12_driver_caps(struct d3d12_video_encoder *pD3
|
|||
|
||||
d3d12_video_encoder_is_gpu_qmap_input_feature_enabled(pD3D12Enc, /*output param*/ capEncoderSupportData1.QPMap.Enabled, /*output param*/ capEncoderSupportData1.QPMap.MapSource);
|
||||
|
||||
capEncoderSupportData1.MotionSearch.MapSource = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapSource;
|
||||
capEncoderSupportData1.MotionSearch.Enabled = d3d12_video_encoder_is_move_regions_feature_enabled(pD3D12Enc, pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapSource);
|
||||
if (capEncoderSupportData1.MotionSearch.Enabled)
|
||||
{
|
||||
capEncoderSupportData1.MotionSearch.MotionSearchMode = D3D12_VIDEO_ENCODER_FRAME_MOTION_SEARCH_MODE_FULL_SEARCH;
|
||||
capEncoderSupportData1.MotionSearch.BidirectionalRefFrameEnabled = TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
enum pipe_video_format codec = u_reduce_video_profile(pD3D12Enc->base.profile);
|
||||
|
|
@ -1814,6 +1876,43 @@ bool d3d12_video_encoder_query_d3d12_driver_caps(struct d3d12_video_encoder *pD3
|
|||
}
|
||||
}
|
||||
|
||||
if ((capEncoderSupportData1.MotionSearch.MapSource == D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE) &&
|
||||
(capEncoderSupportData1.MotionSearch.Enabled))
|
||||
{
|
||||
// Query specifics of staging resource for move regions
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.capInputLayoutMotionVectors =
|
||||
{
|
||||
// UINT NodeIndex;
|
||||
0u,
|
||||
// D3D12_VIDEO_ENCODER_INPUT_MAP_SESSION_INFO SessionInfo;
|
||||
{
|
||||
capEncoderSupportData1.Codec,
|
||||
d3d12_video_encoder_get_current_profile_desc(pD3D12Enc),
|
||||
d3d12_video_encoder_get_current_level_desc(pD3D12Enc),
|
||||
pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo.Format,
|
||||
// D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC
|
||||
pD3D12Enc->m_currentEncodeConfig.m_currentResolution,
|
||||
d3d12_video_encoder_get_current_codec_config_desc(pD3D12Enc),
|
||||
capEncoderSupportData1.SubregionFrameEncoding,
|
||||
capEncoderSupportData1.SubregionFrameEncodingData
|
||||
},
|
||||
// D3D12_VIDEO_ENCODER_INPUT_MAP_TYPE MapType;
|
||||
D3D12_VIDEO_ENCODER_INPUT_MAP_TYPE_MOTION_VECTORS,
|
||||
// BOOL IsSupported;
|
||||
FALSE,
|
||||
// UINT64 MaxResolvedBufferAllocationSize;
|
||||
0u,
|
||||
};
|
||||
|
||||
hr = pD3D12Enc->m_spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_RESOLVE_INPUT_PARAM_LAYOUT,
|
||||
&pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.capInputLayoutMotionVectors,
|
||||
sizeof(pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.capInputLayoutMotionVectors));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
debug_printf("CheckFeatureSupport D3D12_FEATURE_VIDEO_ENCODER_RESOLVE_INPUT_PARAM_LAYOUT failed with HR %x\n", hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2289,6 +2388,28 @@ d3d12_video_encoder_prepare_input_buffers(struct d3d12_video_encoder *pD3D12Enc)
|
|||
}
|
||||
}
|
||||
|
||||
if (d3d12_video_encoder_is_move_regions_feature_enabled(pD3D12Enc, D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE))
|
||||
{
|
||||
bool bNeedsCreation = (pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].m_spMotionVectorsResolvedOpaqueMap == NULL) ||
|
||||
(GetDesc(pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].m_spMotionVectorsResolvedOpaqueMap.Get()).Width <
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.capInputLayoutMotionVectors.MaxResolvedBufferAllocationSize);
|
||||
if (bNeedsCreation)
|
||||
{
|
||||
pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].m_spMotionVectorsResolvedOpaqueMap.Reset();
|
||||
CD3DX12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.capInputLayoutMotionVectors.MaxResolvedBufferAllocationSize);
|
||||
hr = pD3D12Enc->m_pD3D12Screen->dev->CreateCommittedResource(&Properties,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].m_spMotionVectorsResolvedOpaqueMap));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
debug_printf("CreateCommittedResource for m_spMotionVectorsResolvedOpaqueMap failed with HR %x\n", hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
|
|
@ -3132,10 +3253,64 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
|
|||
}
|
||||
|
||||
D3D12_VIDEO_ENCODER_FRAME_MOTION_VECTORS motionRegions = { };
|
||||
motionRegions.MapSource = D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_CPU_BUFFER;
|
||||
motionRegions.pCPUBuffer = &pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc;
|
||||
if (motionRegions.pCPUBuffer->NumMoveRegions > 0)
|
||||
motionRegions.MapSource = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapSource;
|
||||
if (d3d12_video_encoder_is_move_regions_feature_enabled(pD3D12Enc, motionRegions.MapSource))
|
||||
{
|
||||
picCtrlFlags |= D3D12_VIDEO_ENCODER_PICTURE_CONTROL_FLAG_ENABLE_MOTION_VECTORS_INPUT;
|
||||
if (motionRegions.MapSource == D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_CPU_BUFFER)
|
||||
{
|
||||
motionRegions.MapSource = D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_CPU_BUFFER;
|
||||
motionRegions.pCPUBuffer = &pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.RectsInfo;
|
||||
}
|
||||
else if (motionRegions.MapSource == D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE)
|
||||
{
|
||||
motionRegions.pOpaqueLayoutBuffer = pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].m_spMotionVectorsResolvedOpaqueMap.Get();
|
||||
pResolveInputDataBarriers.push_back(CD3DX12_RESOURCE_BARRIER::Transition(motionRegions.pOpaqueLayoutBuffer,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE));
|
||||
|
||||
for (unsigned i = 0; i < pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.NumHintsPerPixel; i++)
|
||||
{
|
||||
pResolveInputDataBarriers.push_back(CD3DX12_RESOURCE_BARRIER::Transition(pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.ppMotionVectorMaps[i],
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ));
|
||||
pResolveInputDataBarriers.push_back(CD3DX12_RESOURCE_BARRIER::Transition(pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.ppMotionVectorMapsMetadata[i],
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ));
|
||||
}
|
||||
|
||||
// see below std::swap for reversal to common after ResolveInputParamLayout is done
|
||||
pD3D12Enc->m_spEncodeCommandList->ResourceBarrier(static_cast<uint32_t>(pResolveInputDataBarriers.size()),
|
||||
pResolveInputDataBarriers.data());
|
||||
D3D12_VIDEO_ENCODER_INPUT_MAP_DATA ResolveInputData = {};
|
||||
ResolveInputData.MapType = D3D12_VIDEO_ENCODER_INPUT_MAP_TYPE_MOTION_VECTORS;
|
||||
ResolveInputData.MotionVectors.MotionSearchModeConfiguration = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.MotionSearchModeConfiguration;
|
||||
ResolveInputData.MotionVectors.NumHintsPerPixel = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.NumHintsPerPixel;
|
||||
ResolveInputData.MotionVectors.ppMotionVectorMaps = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.ppMotionVectorMaps.data();
|
||||
ResolveInputData.MotionVectors.ppMotionVectorMapsMetadata = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.ppMotionVectorMapsMetadata.data();
|
||||
ResolveInputData.MotionVectors.pMotionVectorMapsSubresources = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.pMotionVectorMapsSubresources;
|
||||
ResolveInputData.MotionVectors.pMotionVectorMapsMetadataSubresources = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.pMotionVectorMapsMetadataSubresources;
|
||||
ResolveInputData.MotionVectors.MotionUnitPrecision = pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.MotionUnitPrecision;
|
||||
ResolveInputData.MotionVectors.PictureControlConfiguration = currentPicParams;
|
||||
|
||||
D3D12_VIDEO_ENCODER_RESOLVE_INPUT_PARAM_LAYOUT_INPUT_ARGUMENTS resolveInputParamLayoutInput =
|
||||
{
|
||||
pD3D12Enc->m_currentEncodeConfig.m_MoveRectsDesc.MapInfo.capInputLayoutMotionVectors.SessionInfo,
|
||||
ResolveInputData,
|
||||
};
|
||||
D3D12_VIDEO_ENCODER_RESOLVE_INPUT_PARAM_LAYOUT_OUTPUT_ARGUMENTS resolveInputParamLayoutOutput =
|
||||
{
|
||||
motionRegions.pOpaqueLayoutBuffer,
|
||||
};
|
||||
|
||||
pD3D12Enc->m_spEncodeCommandList->ResolveInputParamLayout(&resolveInputParamLayoutInput, &resolveInputParamLayoutOutput);
|
||||
for (auto &BarrierDesc : pResolveInputDataBarriers) {
|
||||
std::swap(BarrierDesc.Transition.StateBefore, BarrierDesc.Transition.StateAfter);
|
||||
}
|
||||
pD3D12Enc->m_spEncodeCommandList->ResourceBarrier(static_cast<uint32_t>(pResolveInputDataBarriers.size()),
|
||||
pResolveInputDataBarriers.data());
|
||||
}
|
||||
}
|
||||
|
||||
ID3D12Resource* d12_gpu_stats_qp_map = NULL;
|
||||
D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAGS optionalMetadataFlags = D3D12_VIDEO_ENCODER_OPTIONAL_METADATA_ENABLE_FLAG_NONE;
|
||||
|
|
|
|||
|
|
@ -349,8 +349,27 @@ struct D3D12EncodeConfiguration
|
|||
std::vector<int16_t> m_pRateControlQPMap16Bit;
|
||||
} CPUInput;
|
||||
} m_QuantizationMatrixDesc = {};
|
||||
struct{
|
||||
D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE MapSource;
|
||||
struct { // union doesn't play well with std::vector
|
||||
// D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_CPU_BUFFER
|
||||
D3D12_VIDEO_ENCODER_MOVEREGION_INFO RectsInfo;
|
||||
// D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE
|
||||
struct
|
||||
{
|
||||
D3D12_VIDEO_ENCODER_FRAME_MOTION_SEARCH_MODE_CONFIG MotionSearchModeConfiguration;
|
||||
UINT NumHintsPerPixel;
|
||||
std::vector<ID3D12Resource*> ppMotionVectorMaps;
|
||||
UINT* pMotionVectorMapsSubresources;
|
||||
std::vector<ID3D12Resource*> ppMotionVectorMapsMetadata;
|
||||
UINT* pMotionVectorMapsMetadataSubresources;
|
||||
D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION MotionUnitPrecision;
|
||||
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA PictureControlConfiguration;
|
||||
D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLVE_INPUT_PARAM_LAYOUT capInputLayoutMotionVectors;
|
||||
} MapInfo;
|
||||
};
|
||||
} m_MoveRectsDesc = {};
|
||||
std::vector<RECT> m_DirtyRectsArray;
|
||||
D3D12_VIDEO_ENCODER_MOVEREGION_INFO m_MoveRectsDesc = {};
|
||||
std::vector<D3D12_VIDEO_ENCODER_MOVE_RECT> m_MoveRectsArray;
|
||||
struct d3d12_resource *m_GPUQPStatsResource = NULL;
|
||||
struct d3d12_resource *m_GPUSATDStatsResource = NULL;
|
||||
|
|
@ -533,6 +552,7 @@ struct d3d12_video_encoder
|
|||
|
||||
ComPtr<ID3D12Resource> m_spDirtyRectsResolvedOpaqueMap; // output of ID3D12VideoEncodeCommandList::ResolveInputParamLayout
|
||||
ComPtr<ID3D12Resource> m_spQPMapResolvedOpaqueMap; // output of ID3D12VideoEncodeCommandList::ResolveInputParamLayout
|
||||
ComPtr<ID3D12Resource> m_spMotionVectorsResolvedOpaqueMap; // output of ID3D12VideoEncodeCommandList::ResolveInputParamLayout
|
||||
};
|
||||
|
||||
std::vector<InFlightEncodeResources> m_inflightResourcesPool;
|
||||
|
|
|
|||
|
|
@ -1069,6 +1069,60 @@ get_sliced_encode_support(D3D12_VIDEO_ENCODER_SUPPORT_FLAGS capEncoderSupportFla
|
|||
return sliced_encode_support;
|
||||
}
|
||||
|
||||
static
|
||||
union pipe_enc_cap_motion_vector_map
|
||||
get_motion_gpuinput_support(D3D12_VIDEO_ENCODER_INPUT_MAP_SESSION_INFO sessionInfo,
|
||||
ID3D12VideoDevice3* pD3D12VideoDevice)
|
||||
{
|
||||
D3D12_FEATURE_DATA_VIDEO_ENCODER_MOTION_SEARCH capMotionInput =
|
||||
{
|
||||
// UINT NodeIndex;
|
||||
0u,
|
||||
// D3D12_VIDEO_ENCODER_INPUT_MAP_SESSION_INFO SessionInfo;
|
||||
sessionInfo,
|
||||
// D3D12_VIDEO_ENCODER_FRAME_MOTION_SEARCH_MODE MotionSearchMode;
|
||||
D3D12_VIDEO_ENCODER_FRAME_MOTION_SEARCH_MODE_FULL_SEARCH,
|
||||
// D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE MapSource;
|
||||
D3D12_VIDEO_ENCODER_INPUT_MAP_SOURCE_GPU_TEXTURE,
|
||||
// BOOL BidirectionalRefFrameEnabled;
|
||||
false,
|
||||
// D3D12_VIDEO_ENCODER_MOTION_SEARCH_SUPPORT_FLAGS SupportFlags;
|
||||
D3D12_VIDEO_ENCODER_MOTION_SEARCH_SUPPORT_FLAG_NONE,
|
||||
// UINT MaxMotionHints;
|
||||
0u,
|
||||
// UINT MinDeviation;
|
||||
0u,
|
||||
// UINT MaxDeviation;
|
||||
0u,
|
||||
// UINT MapSourcePreferenceRanking;
|
||||
0u,
|
||||
// D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_SUPPORT_FLAGS MotionUnitPrecisionSupport;
|
||||
D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_SUPPORT_FLAG_NONE
|
||||
};
|
||||
|
||||
union pipe_enc_cap_motion_vector_map motion_gpu_support = {};
|
||||
if (SUCCEEDED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_MOTION_SEARCH, &capMotionInput, sizeof(capMotionInput))))
|
||||
{
|
||||
|
||||
if (capMotionInput.SupportFlags & D3D12_VIDEO_ENCODER_MOTION_SEARCH_SUPPORT_FLAG_SUPPORTED)
|
||||
{
|
||||
motion_gpu_support.bits.max_motion_hints = std::min(31u, capMotionInput.MaxMotionHints);
|
||||
assert(motion_gpu_support.bits.max_motion_hints <= PIPE_ENC_MOVE_MAP_MAX_HINTS);
|
||||
if (motion_gpu_support.bits.max_motion_hints > 0)
|
||||
{
|
||||
motion_gpu_support.bits.supports_precision_full_pixel = (capMotionInput.MotionUnitPrecisionSupport & D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_SUPPORT_FLAG_FULL_PIXEL) ? 1u : 0u;
|
||||
motion_gpu_support.bits.supports_precision_half_pixel = (capMotionInput.MotionUnitPrecisionSupport & D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_SUPPORT_FLAG_HALF_PIXEL) ? 1u : 0u;
|
||||
motion_gpu_support.bits.supports_precision_quarter_pixel = (capMotionInput.MotionUnitPrecisionSupport & D3D12_VIDEO_ENCODER_FRAME_INPUT_MOTION_UNIT_PRECISION_SUPPORT_FLAG_QUARTER_PIXEL) ? 1u : 0u;
|
||||
motion_gpu_support.bits.support_multiple_dpb_refs = 0u; // (capMotionInput.SupportFlags & D3D12_VIDEO_ENCODER_MOTION_SEARCH_SUPPORT_FLAG_GPU_TEXTURE_MULTIPLE_REFERENCES) ? 1u : 0u;
|
||||
motion_gpu_support.bits.pipe_pixel_vectors_map_format = PIPE_FORMAT_R16G16_SINT; // As per DX12 spec
|
||||
motion_gpu_support.bits.pipe_pixel_vectors_metadata_map_format = PIPE_FORMAT_R8_UINT; // As per DX12 spec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return motion_gpu_support;
|
||||
}
|
||||
|
||||
static
|
||||
union pipe_enc_cap_qpmap
|
||||
get_qpmap_gpuinput_support(D3D12_VIDEO_ENCODER_INPUT_MAP_SESSION_INFO sessionInfo,
|
||||
|
|
@ -1133,7 +1187,8 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
|||
union pipe_enc_cap_gpu_stats_map &gpu_stats_rcbits,
|
||||
union pipe_enc_cap_sliced_notifications &sliced_encode_support,
|
||||
union pipe_enc_cap_dirty_info &dirty_rects_support_gpu,
|
||||
union pipe_enc_cap_qpmap &qpmap_support)
|
||||
union pipe_enc_cap_qpmap &qpmap_support,
|
||||
union pipe_enc_cap_motion_vector_map &gpu_motion_input_support)
|
||||
{
|
||||
ComPtr<ID3D12VideoDevice3> spD3D12VideoDevice;
|
||||
struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
|
||||
|
|
@ -1270,6 +1325,7 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
|||
get_gpu_output_stats_support(sessionInfo, capEncoderSupportData1.SupportFlags, spD3D12VideoDevice.Get(), gpu_stats_qp, gpu_stats_satd, gpu_stats_rcbits);
|
||||
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());
|
||||
#endif
|
||||
}
|
||||
} break;
|
||||
|
|
@ -1580,6 +1636,7 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
|||
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);
|
||||
sliced_encode_support = get_sliced_encode_support(capEncoderSupportData1.SupportFlags);
|
||||
gpu_motion_input_support = get_motion_gpuinput_support(sessionInfo, spD3D12VideoDevice.Get());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -2169,6 +2226,7 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
|||
union pipe_enc_cap_gpu_stats_map gpu_stats_rcbits = {};
|
||||
union pipe_enc_cap_sliced_notifications sliced_encode_support = {};
|
||||
union pipe_enc_cap_qpmap gpu_qpmap_input = {};
|
||||
union pipe_enc_cap_motion_vector_map gpu_motion_input = {};
|
||||
memset(&codec_specific_support, 0, sizeof(codec_specific_support));
|
||||
switch (param) {
|
||||
case PIPE_VIDEO_CAP_REQUIRES_FLUSH_ON_END_FRAME:
|
||||
|
|
@ -2239,6 +2297,7 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
|||
case PIPE_VIDEO_CAP_ENC_SLICED_NOTIFICATIONS:
|
||||
case PIPE_VIDEO_CAP_ENC_DIRTY_MAPS:
|
||||
case PIPE_VIDEO_CAP_ENC_QP_MAPS:
|
||||
case PIPE_VIDEO_CAP_ENC_MOTION_VECTOR_MAPS:
|
||||
{
|
||||
if (d3d12_has_video_encode_support(pscreen,
|
||||
profile,
|
||||
|
|
@ -2266,7 +2325,8 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
|||
gpu_stats_rcbits,
|
||||
sliced_encode_support,
|
||||
dirty_rects_support_gpu,
|
||||
gpu_qpmap_input)) {
|
||||
gpu_qpmap_input,
|
||||
gpu_motion_input)) {
|
||||
|
||||
DXGI_FORMAT format = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
|
||||
auto pipeFmt = d3d12_get_pipe_format(format);
|
||||
|
|
@ -2367,6 +2427,8 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
|||
return dirty_rects_support_gpu.value;
|
||||
} else if (param == PIPE_VIDEO_CAP_ENC_QP_MAPS) {
|
||||
return gpu_qpmap_input.value;
|
||||
} else if (param == PIPE_VIDEO_CAP_ENC_MOTION_VECTOR_MAPS) {
|
||||
return gpu_motion_input.value;
|
||||
}
|
||||
}
|
||||
} else if (param == PIPE_VIDEO_CAP_ENC_QUALITY_LEVEL) {
|
||||
|
|
@ -2443,6 +2505,7 @@ d3d12_video_encode_requires_texture_array_dpb(struct d3d12_screen* pScreen, enum
|
|||
union pipe_enc_cap_gpu_stats_map gpu_stats_rcbits = {};
|
||||
union pipe_enc_cap_sliced_notifications sliced_encode_support = {};
|
||||
union pipe_enc_cap_qpmap gpu_qpmap_input = {};
|
||||
union pipe_enc_cap_motion_vector_map gpu_motion_input = {};
|
||||
if (d3d12_has_video_encode_support(&pScreen->base,
|
||||
profile,
|
||||
maxLvlEncode,
|
||||
|
|
@ -2469,7 +2532,8 @@ d3d12_video_encode_requires_texture_array_dpb(struct d3d12_screen* pScreen, enum
|
|||
gpu_stats_rcbits,
|
||||
sliced_encode_support,
|
||||
dirty_rects_support_gpu,
|
||||
gpu_qpmap_input))
|
||||
gpu_qpmap_input,
|
||||
gpu_motion_input))
|
||||
{
|
||||
return bVideoEncodeRequiresTextureArray;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue