56 ID3D12Resource *resource =
NULL;
57 D3D12_HEAP_PROPERTIES props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
58 D3D12_RESOURCE_DESC
desc;
60 if (reference_only_map ==
NULL) {
66 for (
i = 0;
i <
ctx->max_num_ref;
i++) {
67 if (!reference_only_map[
i].used && reference_only_map[
i].resource !=
NULL) {
68 reference_only_map[
i].
used = 1;
69 resource = reference_only_map[
i].
resource;
76 for (
i = 0;
i <
ctx->max_num_ref;
i++) {
77 if (reference_only_map[
i].resource ==
NULL)
81 if (
i ==
ctx->max_num_ref) {
87 output_resource->lpVtbl->GetDesc(output_resource, &
desc);
88 desc.Flags = D3D12_RESOURCE_FLAG_VIDEO_DECODE_REFERENCE_ONLY | D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
90 if (FAILED(ID3D12Device_CreateCommittedResource(device_hwctx->
device, &props, D3D12_HEAP_FLAG_NONE, &
desc,
91 D3D12_RESOURCE_STATE_COMMON,
NULL, &IID_ID3D12Resource, (
void **)&reference_only_map[
i].
resource))) {
96 reference_only_map[
i].
used = 1;
97 resource = reference_only_map[
i].
resource;
108 if (reference_only_map !=
NULL) {
109 for (
i = 0;
i <
ctx->max_num_ref;
i++) {
110 if (reference_only_map[
i].resource !=
NULL) {
124 if (reference_only_map ==
NULL)
126 memset(
ctx->ref_only_resources, 0,
ctx->max_num_ref *
sizeof(*(
ctx->ref_only_resources)));
127 for (j = 0; j <
ctx->max_num_ref; j++) {
128 for (
i = 0;
i <
ctx->max_num_ref;
i++) {
129 if (reference_only_map[j].used && reference_only_map[j].output_resource ==
ctx->ref_resources[
i]) {
130 ctx->ref_only_resources[
i] = reference_only_map[j].
resource;
134 if (
i ==
ctx->max_num_ref)
135 reference_only_map[j].
used = 0;
161 for (
i = 0;
i <
ctx->max_num_ref;
i++) {
162 if (
ctx->ref_resources[
i] && res ==
ctx->ref_resources[
i]) {
163 ctx->used_mask |= 1 <<
i;
169 for (
i = 0;
i <
ctx->max_num_ref;
i++) {
170 if (!((
ctx->used_mask >>
i) & 0x1)) {
171 ctx->ref_resources[
i] = res;
183 ID3D12Resource **ppBuffer)
188 D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
190 D3D12_RESOURCE_DESC
desc = {
191 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
192 .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
193 .Width =
ctx->bitstream_size,
195 .DepthOrArraySize = 1,
197 .Format = DXGI_FORMAT_UNKNOWN,
198 .SampleDesc = { .Count = 1, .Quality = 0 },
199 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
200 .Flags = D3D12_RESOURCE_FLAG_NONE,
204 uint64_t completion = ID3D12Fence_GetCompletedValue(
ctx->sync_ctx.fence);
213 hr = ID3D12Device_CreateCommandAllocator(
ctx->device_ctx->device, D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
214 &IID_ID3D12CommandAllocator, (
void **)ppAllocator);
220 hr = ID3D12Device_CreateCommittedResource(
ctx->device_ctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
221 &
desc, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL,
222 &IID_ID3D12Resource, (
void **)ppBuffer);
233 ID3D12Resource *pBuffer, uint64_t fence_value)
240 .fence_value = fence_value,
254 uint64_t completion = ID3D12Fence_GetCompletedValue(psync_ctx->
fence);
255 if (completion < psync_ctx->fence_value) {
256 if (FAILED(ID3D12Fence_SetEventOnCompletion(psync_ctx->
fence, psync_ctx->
fence_value, psync_ctx->
event)))
259 WaitForSingleObjectEx(psync_ctx->
event, INFINITE, FALSE);
279 DX_CHECK(ID3D12CommandQueue_Signal(
ctx->command_queue,
ctx->sync_ctx.fence, ++
ctx->sync_ctx.fence_value));
293 D3D12_VIDEO_DECODER_HEAP_DESC
desc = {
295 .Configuration =
ctx->cfg,
296 .DecodeWidth = frames_ctx->
width,
297 .DecodeHeight = frames_ctx->
height,
298 .Format = frames_hwctx->
format,
301 .MaxDecodePictureBufferCount =
ctx->max_num_ref,
305 &IID_ID3D12VideoDecoderHeap, (
void **)&
ctx->decoder_heap));
312 "[width(%d), height(%d)], on your device!\n", frames_ctx->
width, frames_ctx->
height);
320 D3D12_VIDEO_DECODER_DESC
desc;
326 D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT feature = {
328 .Configuration =
ctx->cfg,
329 .Width = frames_ctx->
width,
330 .Height = frames_ctx->
height,
331 .DecodeFormat = frames_hwctx->
format,
336 DX_CHECK(ID3D12VideoDevice_CheckFeatureSupport(device_hwctx->
video_device, D3D12_FEATURE_VIDEO_DECODE_SUPPORT,
337 &feature,
sizeof(feature)));
338 if (!(feature.SupportFlags & D3D12_VIDEO_DECODE_SUPPORT_FLAG_SUPPORTED)) {
342 if (!(feature.DecodeTier >= D3D12_VIDEO_DECODE_TIER_2)) {
343 av_log(avctx,
AV_LOG_ERROR,
"D3D12 video decode on this device requires tier %d support, "
344 "but it is not implemented.\n", feature.DecodeTier);
348 ctx->reference_only_map =
NULL;
349 ctx->ref_only_resources =
NULL;
350 if (feature.ConfigurationFlags & D3D12_VIDEO_DECODE_CONFIGURATION_FLAG_REFERENCE_ONLY_ALLOCATIONS_REQUIRED) {
351 av_log(avctx,
AV_LOG_VERBOSE,
"Reference-Only Allocations are required for this D3D12 decoder configuration.\n");
353 if (!
ctx->reference_only_map)
355 ctx->ref_only_resources =
av_calloc(
ctx->max_num_ref,
sizeof(*
ctx->ref_only_resources));
356 if (!
ctx->ref_only_resources)
360 desc = (D3D12_VIDEO_DECODER_DESC) {
362 .Configuration =
ctx->cfg,
366 (
void **)&
ctx->decoder));
369 if (!
ctx->decoder_ref)
396 ID3D12CommandAllocator *command_allocator =
NULL;
397 D3D12_COMMAND_QUEUE_DESC queue_desc = {
398 .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
400 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
429 if (!
ctx->ref_resources)
433 if (!
ctx->ref_subresources)
438 if (!
ctx->objects_queue)
441 DX_CHECK(ID3D12Device_CreateFence(
ctx->device_ctx->device, 0, D3D12_FENCE_FLAG_NONE,
442 &IID_ID3D12Fence, (
void **)&
ctx->sync_ctx.fence));
444 ctx->sync_ctx.event = CreateEvent(
NULL, FALSE, FALSE,
NULL);
445 if (!
ctx->sync_ctx.event)
452 DX_CHECK(ID3D12Device_CreateCommandQueue(
ctx->device_ctx->device, &queue_desc,
453 &IID_ID3D12CommandQueue, (
void **)&
ctx->command_queue));
455 DX_CHECK(ID3D12Device_CreateCommandList(
ctx->device_ctx->device, 0, queue_desc.Type,
456 command_allocator,
NULL, &IID_ID3D12CommandList, (
void **)&
ctx->command_list));
458 DX_CHECK(ID3D12VideoDecodeCommandList_Close(
ctx->command_list));
460 ID3D12CommandQueue_ExecuteCommandLists(
ctx->command_queue, 1, (ID3D12CommandList **)&
ctx->command_list);
482 int num_allocator = 0;
486 if (
ctx->sync_ctx.fence)
495 if (
ctx->objects_queue) {
502 av_log(avctx,
AV_LOG_VERBOSE,
"Total number of command allocators reused: %d\n", num_allocator);
509 if (
ctx->sync_ctx.event)
510 CloseHandle(
ctx->sync_ctx.event);
520 ID3D12Resource *current_resource,
int state_before,
int state_end)
523 ID3D12Resource **ref_resources =
ctx->ref_only_resources ?
ctx->ref_only_resources :
ctx->ref_resources;
526 for (
int i = 0;
i <
ctx->max_num_ref;
i++) {
527 if (((
ctx->used_mask >>
i) & 0x1) && ref_resources[
i] && ref_resources[
i] != current_resource) {
528 barriers[num_barrier].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
529 barriers[num_barrier].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
530 barriers[num_barrier].Transition = (D3D12_RESOURCE_TRANSITION_BARRIER) {
531 .pResource = ref_resources[
i],
532 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
533 .StateBefore = state_before,
534 .StateAfter = state_end,
544 const void *pp,
unsigned pp_size,
545 const void *qm,
unsigned qm_size,
551 ID3D12CommandAllocator *command_allocator =
NULL;
553 ID3D12Resource *output_resource = (ID3D12Resource*)
f->texture;
554 ID3D12Resource *ref_resource =
NULL;
556 ID3D12VideoDecodeCommandList *cmd_list =
ctx->command_list;
557 D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
559 D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS input_args = {
560 .NumFrameArguments = 2,
563 .Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_PICTURE_PARAMETERS,
568 .Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_INVERSE_QUANTIZATION_MATRIX,
573 .pHeap =
ctx->decoder_heap,
576 D3D12_VIDEO_DECODE_OUTPUT_STREAM_ARGUMENTS output_args = {
577 .ConversionArguments = { 0 },
578 .OutputSubresource = 0,
579 .pOutputTexture2D = output_resource,
582 memset(
ctx->ref_subresources, 0,
sizeof(UINT) *
ctx->max_num_ref);
583 input_args.ReferenceFrames.NumTexture2Ds =
ctx->max_num_ref;
584 input_args.ReferenceFrames.pSubresources =
ctx->ref_subresources;
586 if (
ctx->reference_only_map) {
588 if (ref_resource ==
NULL) {
594 output_args.ConversionArguments.Enable = 1;
595 input_args.ReferenceFrames.ppTexture2Ds =
ctx->ref_only_resources;
596 output_args.ConversionArguments.pReferenceTexture2D = ref_resource;
597 output_args.ConversionArguments.ReferenceSubresource = 0;
599 ref_resource = output_resource;
600 input_args.ReferenceFrames.ppTexture2Ds =
ctx->ref_resources;
603 UINT num_barrier = 1;
604 barriers[0] = (D3D12_RESOURCE_BARRIER) {
605 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
606 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
608 .pResource = output_resource,
609 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
610 .StateBefore = D3D12_RESOURCE_STATE_COMMON,
611 .StateAfter = D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE,
615 if (
ctx->reference_only_map) {
616 barriers[1] = (D3D12_RESOURCE_BARRIER) {
617 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
618 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
620 .pResource = ref_resource,
621 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
622 .StateBefore = D3D12_RESOURCE_STATE_COMMON,
623 .StateAfter = D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE,
634 input_args.NumFrameArguments = 1;
644 DX_CHECK(ID3D12CommandAllocator_Reset(command_allocator));
646 DX_CHECK(ID3D12VideoDecodeCommandList_Reset(cmd_list, command_allocator));
650 ID3D12VideoDecodeCommandList_ResourceBarrier(cmd_list, num_barrier, barriers);
652 ID3D12VideoDecodeCommandList_DecodeFrame(cmd_list,
ctx->decoder, &output_args, &input_args);
654 for (
int i = 0;
i < num_barrier;
i++)
655 FFSWAP(D3D12_RESOURCE_STATES, barriers[
i].Transition.StateBefore, barriers[
i].Transition.StateAfter);
657 ID3D12VideoDecodeCommandList_ResourceBarrier(cmd_list, num_barrier, barriers);
659 DX_CHECK(ID3D12VideoDecodeCommandList_Close(cmd_list));
661 ID3D12CommandQueue_ExecuteCommandLists(
ctx->command_queue, 1, (ID3D12CommandList **)&
ctx->command_list);
663 DX_CHECK(ID3D12CommandQueue_Signal(
ctx->command_queue,
f->sync_ctx.fence, ++
f->sync_ctx.fence_value));
665 DX_CHECK(ID3D12CommandQueue_Signal(
ctx->command_queue,
ctx->sync_ctx.fence, ++
ctx->sync_ctx.fence_value));
674 if (command_allocator)