174 D3D12_FEATURE_DATA_VIDEO_MOTION_ESTIMATOR feature_data = {0};
175 D3D12_VIDEO_MOTION_ESTIMATOR_DESC me_desc = {0};
176 D3D12_VIDEO_MOTION_VECTOR_HEAP_DESC heap_desc = {0};
180 feature_data.NodeIndex = 0;
181 feature_data.InputFormat =
s->frames_ctx->format;
182 feature_data.BlockSizeFlags = 0;
183 feature_data.PrecisionFlags = 0;
184 feature_data.SizeRange.MaxWidth =
width;
185 feature_data.SizeRange.MaxHeight =
height;
186 feature_data.SizeRange.MinWidth =
width;
187 feature_data.SizeRange.MinHeight =
height;
189 hr = ID3D12VideoDevice1_CheckFeatureSupport(
s->video_device,
190 D3D12_FEATURE_VIDEO_MOTION_ESTIMATOR,
191 &feature_data,
sizeof(feature_data));
198 D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE_FLAGS requested_block_flag =
199 (
s->d3d12_block_size == D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE_8X8) ?
200 D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE_FLAG_8X8 :
201 D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE_FLAG_16X16;
203 if (!(feature_data.BlockSizeFlags & requested_block_flag)) {
204 av_log(
ctx,
AV_LOG_ERROR,
"Requested block size (%dx%d) not supported by device (supported flags: 0x%x)\n",
205 s->block_size,
s->block_size, feature_data.BlockSizeFlags);
209 if (!(feature_data.PrecisionFlags & D3D12_VIDEO_MOTION_ESTIMATOR_VECTOR_PRECISION_FLAG_QUARTER_PEL)) {
211 feature_data.PrecisionFlags);
216 s->block_size,
s->block_size);
219 me_desc.NodeMask = 0;
220 me_desc.InputFormat =
s->frames_ctx->format;
221 me_desc.BlockSize =
s->d3d12_block_size;
222 me_desc.Precision =
s->precision;
223 me_desc.SizeRange = feature_data.SizeRange;
225 hr = ID3D12VideoDevice1_CreateVideoMotionEstimator(
s->video_device, &me_desc,
NULL,
226 &IID_ID3D12VideoMotionEstimator,
227 (
void **)&
s->motion_estimator);
234 heap_desc.NodeMask = 0;
235 heap_desc.InputFormat =
s->frames_ctx->format;
236 heap_desc.BlockSize =
s->d3d12_block_size;
237 heap_desc.Precision =
s->precision;
238 heap_desc.SizeRange = feature_data.SizeRange;
240 hr = ID3D12VideoDevice1_CreateVideoMotionVectorHeap(
s->video_device, &heap_desc,
NULL,
241 &IID_ID3D12VideoMotionVectorHeap,
242 (
void **)&
s->motion_vector_heap);
250 int mb_width = (
width +
s->block_size - 1) /
s->block_size;
251 int mb_height = (
height +
s->block_size - 1) /
s->block_size;
253 D3D12_HEAP_PROPERTIES heap_props_default = {.Type = D3D12_HEAP_TYPE_DEFAULT};
254 D3D12_RESOURCE_DESC texture_desc = {
255 .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
259 .DepthOrArraySize = 1,
261 .Format = DXGI_FORMAT_R16G16_SINT,
262 .SampleDesc = {.Count = 1, .Quality = 0},
263 .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
264 .Flags = D3D12_RESOURCE_FLAG_NONE,
267 hr = ID3D12Device_CreateCommittedResource(
s->device, &heap_props_default, D3D12_HEAP_FLAG_NONE,
268 &texture_desc, D3D12_RESOURCE_STATE_COMMON,
NULL,
269 &IID_ID3D12Resource, (
void **)&
s->resolved_mv_texture_back);
275 hr = ID3D12Device_CreateCommittedResource(
s->device, &heap_props_default, D3D12_HEAP_FLAG_NONE,
276 &texture_desc, D3D12_RESOURCE_STATE_COMMON,
NULL,
277 &IID_ID3D12Resource, (
void **)&
s->resolved_mv_texture_fwd);
286 D3D12_PLACED_SUBRESOURCE_FOOTPRINT temp_layout;
287 UINT64 temp_total_size;
289 ID3D12Device_GetCopyableFootprints(
s->device, &texture_desc, 0, 1, 0,
290 &temp_layout,
NULL,
NULL, &temp_total_size);
292 s->readback_buffer_size = temp_total_size;
295 (
unsigned long long)
s->readback_buffer_size, mb_width, mb_height, temp_layout.Footprint.RowPitch);
297 D3D12_HEAP_PROPERTIES heap_props_readback = {.Type = D3D12_HEAP_TYPE_READBACK};
298 D3D12_RESOURCE_DESC buffer_desc = {
299 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
301 .Width =
s->readback_buffer_size,
303 .DepthOrArraySize = 1,
305 .Format = DXGI_FORMAT_UNKNOWN,
306 .SampleDesc = {.Count = 1, .Quality = 0},
307 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
308 .Flags = D3D12_RESOURCE_FLAG_NONE,
311 hr = ID3D12Device_CreateCommittedResource(
s->device, &heap_props_readback, D3D12_HEAP_FLAG_NONE,
312 &buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
313 &IID_ID3D12Resource, (
void **)&
s->readback_buffer_back);
319 hr = ID3D12Device_CreateCommittedResource(
s->device, &heap_props_readback, D3D12_HEAP_FLAG_NONE,
320 &buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
321 &IID_ID3D12Resource, (
void **)&
s->readback_buffer_fwd);
328 D3D12_COMMAND_QUEUE_DESC copy_queue_desc = {
329 .Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
331 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
335 hr = ID3D12Device_CreateCommandQueue(
s->device, ©_queue_desc,
336 &IID_ID3D12CommandQueue, (
void **)&
s->copy_command_queue);
342 hr = ID3D12Device_CreateCommandAllocator(
s->device, D3D12_COMMAND_LIST_TYPE_DIRECT,
343 &IID_ID3D12CommandAllocator, (
void **)&
s->copy_command_allocator);
349 hr = ID3D12Device_CreateCommandList(
s->device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
350 s->copy_command_allocator,
NULL, &IID_ID3D12GraphicsCommandList,
351 (
void **)&
s->copy_command_list);
357 hr = ID3D12GraphicsCommandList_Close(
s->copy_command_list);
561 int mb_width, mb_height, mb_count;
563 if (!
s->initialized) {
575 s->prev_frame =
s->cur_frame;
576 s->cur_frame =
s->next_frame;
595 mb_width = (
s->cur_frame->width +
s->block_size - 1) /
s->block_size;
596 mb_height = (
s->cur_frame->height +
s->block_size - 1) /
s->block_size;
597 mb_count = mb_width * mb_height;
599 const int nb_dirs =
s->next_frame ? 2 : 1;
615 hr = ID3D12CommandAllocator_Reset(
s->command_allocator);
622 hr = ID3D12VideoEncodeCommandList_Reset(
s->command_list,
s->command_allocator);
630 D3D12_RESOURCE_BARRIER barriers[3];
631 int barrier_count = 2;
634 D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
636 D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
640 D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
644 ID3D12VideoEncodeCommandList_ResourceBarrier(
s->command_list, barrier_count, barriers);
647 D3D12_VIDEO_MOTION_ESTIMATOR_INPUT input_back = {
648 .pInputTexture2D = cur_hwframe->
texture,
649 .InputSubresourceIndex = 0,
650 .pReferenceTexture2D = prev_hwframe->
texture,
651 .ReferenceSubresourceIndex = 0,
652 .pHintMotionVectorHeap =
NULL,
655 D3D12_VIDEO_MOTION_ESTIMATOR_OUTPUT output = {
656 .pMotionVectorHeap =
s->motion_vector_heap,
659 ID3D12VideoEncodeCommandList_EstimateMotion(
s->command_list,
s->motion_estimator,
660 &output, &input_back);
662 D3D12_RESOLVE_VIDEO_MOTION_VECTOR_HEAP_INPUT resolve_input = {
663 .pMotionVectorHeap =
s->motion_vector_heap,
664 .PixelWidth =
s->cur_frame->width,
665 .PixelHeight =
s->cur_frame->height,
668 D3D12_RESOLVE_VIDEO_MOTION_VECTOR_HEAP_OUTPUT resolve_output_back = {
669 .pMotionVectorTexture2D =
s->resolved_mv_texture_back,
670 .MotionVectorCoordinate = {.X = 0, .Y = 0, .Z = 0, .SubresourceIndex = 0},
673 ID3D12VideoEncodeCommandList_ResolveMotionVectorHeap(
s->command_list,
674 &resolve_output_back, &resolve_input);
682 D3D12_VIDEO_MOTION_ESTIMATOR_INPUT input_fwd = {
683 .pInputTexture2D = cur_hwframe->
texture,
684 .InputSubresourceIndex = 0,
685 .pReferenceTexture2D = next_hwframe->
texture,
686 .ReferenceSubresourceIndex = 0,
687 .pHintMotionVectorHeap =
NULL,
690 ID3D12VideoEncodeCommandList_EstimateMotion(
s->command_list,
s->motion_estimator,
691 &output, &input_fwd);
693 D3D12_RESOLVE_VIDEO_MOTION_VECTOR_HEAP_OUTPUT resolve_output_fwd = {
694 .pMotionVectorTexture2D =
s->resolved_mv_texture_fwd,
695 .MotionVectorCoordinate = {.X = 0, .Y = 0, .Z = 0, .SubresourceIndex = 0},
698 ID3D12VideoEncodeCommandList_ResolveMotionVectorHeap(
s->command_list,
699 &resolve_output_fwd, &resolve_input);
705 for (
int i = 0;
i < barrier_count;
i++)
706 FFSWAP(D3D12_RESOURCE_STATES, barriers[
i].Transition.StateBefore, barriers[
i].Transition.StateAfter);
708 ID3D12VideoEncodeCommandList_ResourceBarrier(
s->command_list, barrier_count, barriers);
711 hr = ID3D12VideoEncodeCommandList_Close(
s->command_list);
719 hr = ID3D12CommandQueue_Wait(
s->command_queue, cur_hwframe->
sync_ctx.
fence,
727 hr = ID3D12CommandQueue_Wait(
s->command_queue, prev_hwframe->
sync_ctx.
fence,
736 hr = ID3D12CommandQueue_Wait(
s->command_queue, next_hwframe->
sync_ctx.
fence,
746 ID3D12CommandQueue_ExecuteCommandLists(
s->command_queue, 1, (ID3D12CommandList **)&
s->command_list);
749 hr = ID3D12CommandQueue_Signal(
s->command_queue,
s->fence, ++
s->fence_value);
764 hr = ID3D12CommandAllocator_Reset(
s->copy_command_allocator);
771 hr = ID3D12GraphicsCommandList_Reset(
s->copy_command_list,
s->copy_command_allocator,
NULL);
779 D3D12_RESOURCE_BARRIER copy_barriers[2];
780 int copy_barrier_count = 1;
783 D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE);
787 D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE);
788 copy_barrier_count = 2;
791 ID3D12GraphicsCommandList_ResourceBarrier(
s->copy_command_list, copy_barrier_count, copy_barriers);
794 D3D12_RESOURCE_DESC texture_desc_back;
795 D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout_back;
796 UINT64 row_size_back, total_size_back;
800 s->resolved_mv_texture_back->lpVtbl->GetDesc(
s->resolved_mv_texture_back, &texture_desc_back);
803 (
unsigned long long)texture_desc_back.Width, texture_desc_back.Height, texture_desc_back.Format);
806 ID3D12Device_GetCopyableFootprints(
s->device, &texture_desc_back, 0, 1, 0,
807 &layout_back, &num_rows_back, &row_size_back, &total_size_back);
810 (
unsigned long long)layout_back.Offset, layout_back.Footprint.Width, layout_back.Footprint.Height,
811 layout_back.Footprint.Depth, layout_back.Footprint.RowPitch);
814 D3D12_TEXTURE_COPY_LOCATION src_back = {
815 .pResource =
s->resolved_mv_texture_back,
816 .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
817 .SubresourceIndex = 0
820 D3D12_TEXTURE_COPY_LOCATION dst_back = {
821 .pResource =
s->readback_buffer_back,
822 .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
825 .Footprint = layout_back.Footprint
830 ID3D12GraphicsCommandList_CopyTextureRegion(
s->copy_command_list, &dst_back, 0, 0, 0, &src_back,
NULL);
835 D3D12_RESOURCE_DESC texture_desc_fwd;
836 D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout_fwd;
837 UINT64 row_size_fwd, total_size_fwd;
841 s->resolved_mv_texture_fwd->lpVtbl->GetDesc(
s->resolved_mv_texture_fwd, &texture_desc_fwd);
844 (
unsigned long long)texture_desc_fwd.Width, texture_desc_fwd.Height, texture_desc_fwd.Format);
847 ID3D12Device_GetCopyableFootprints(
s->device, &texture_desc_fwd, 0, 1, 0,
848 &layout_fwd, &num_rows_fwd, &row_size_fwd, &total_size_fwd);
851 (
unsigned long long)layout_fwd.Offset, layout_fwd.Footprint.Width, layout_fwd.Footprint.Height,
852 layout_fwd.Footprint.Depth, layout_fwd.Footprint.RowPitch);
854 D3D12_TEXTURE_COPY_LOCATION src_fwd = {
855 .pResource =
s->resolved_mv_texture_fwd,
856 .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
857 .SubresourceIndex = 0
860 D3D12_TEXTURE_COPY_LOCATION dst_fwd = {
861 .pResource =
s->readback_buffer_fwd,
862 .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
865 .Footprint = layout_fwd.Footprint
870 ID3D12GraphicsCommandList_CopyTextureRegion(
s->copy_command_list, &dst_fwd, 0, 0, 0, &src_fwd,
NULL);
874 for (
int i = 0;
i < copy_barrier_count;
i++)
875 FFSWAP(D3D12_RESOURCE_STATES, copy_barriers[
i].Transition.StateBefore, copy_barriers[
i].Transition.StateAfter);
877 ID3D12GraphicsCommandList_ResourceBarrier(
s->copy_command_list, copy_barrier_count, copy_barriers);
879 hr = ID3D12GraphicsCommandList_Close(
s->copy_command_list);
887 ID3D12CommandQueue_ExecuteCommandLists(
s->copy_command_queue, 1, (ID3D12CommandList **)&
s->copy_command_list);
890 hr = ID3D12CommandQueue_Signal(
s->copy_command_queue,
s->fence, ++
s->fence_value);