66 for (
i = 0;
i <
ctx->max_num_ref;
i++) {
67 if (
ctx->ref_resources[
i] && res ==
ctx->ref_resources[
i]) {
68 ctx->used_mask |= 1 <<
i;
74 for (
i = 0;
i <
ctx->max_num_ref;
i++) {
75 if (!((
ctx->used_mask >>
i) & 0x1)) {
76 ctx->ref_resources[
i] = res;
88 ID3D12Resource **ppBuffer)
93 D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
95 D3D12_RESOURCE_DESC
desc = {
96 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
97 .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
98 .Width =
ctx->bitstream_size,
100 .DepthOrArraySize = 1,
102 .Format = DXGI_FORMAT_UNKNOWN,
103 .SampleDesc = { .Count = 1, .Quality = 0 },
104 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
105 .Flags = D3D12_RESOURCE_FLAG_NONE,
109 uint64_t completion = ID3D12Fence_GetCompletedValue(
ctx->sync_ctx.fence);
118 hr = ID3D12Device_CreateCommandAllocator(
ctx->device_ctx->device, D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
119 &IID_ID3D12CommandAllocator, (
void **)ppAllocator);
125 hr = ID3D12Device_CreateCommittedResource(
ctx->device_ctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
126 &
desc, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL,
127 &IID_ID3D12Resource, (
void **)ppBuffer);
138 ID3D12Resource *pBuffer, uint64_t fence_value)
145 .fence_value = fence_value,
159 uint64_t completion = ID3D12Fence_GetCompletedValue(psync_ctx->
fence);
160 if (completion < psync_ctx->fence_value) {
161 if (FAILED(ID3D12Fence_SetEventOnCompletion(psync_ctx->
fence, psync_ctx->
fence_value, psync_ctx->
event)))
164 WaitForSingleObjectEx(psync_ctx->
event, INFINITE, FALSE);
184 DX_CHECK(ID3D12CommandQueue_Signal(
ctx->command_queue,
ctx->sync_ctx.fence, ++
ctx->sync_ctx.fence_value));
198 D3D12_VIDEO_DECODER_HEAP_DESC
desc = {
200 .Configuration =
ctx->cfg,
201 .DecodeWidth = frames_ctx->
width,
202 .DecodeHeight = frames_ctx->
height,
203 .Format = frames_hwctx->
format,
206 .MaxDecodePictureBufferCount =
ctx->max_num_ref,
210 &IID_ID3D12VideoDecoderHeap, (
void **)&
ctx->decoder_heap));
217 "[width(%d), height(%d)], on your device!\n", frames_ctx->
width, frames_ctx->
height);
225 D3D12_VIDEO_DECODER_DESC
desc;
231 D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT feature = {
233 .Configuration =
ctx->cfg,
234 .Width = frames_ctx->
width,
235 .Height = frames_ctx->
height,
236 .DecodeFormat = frames_hwctx->
format,
241 DX_CHECK(ID3D12VideoDevice_CheckFeatureSupport(device_hwctx->
video_device, D3D12_FEATURE_VIDEO_DECODE_SUPPORT,
242 &feature,
sizeof(feature)));
243 if (!(feature.SupportFlags & D3D12_VIDEO_DECODE_SUPPORT_FLAG_SUPPORTED)) {
247 if (!(feature.DecodeTier >= D3D12_VIDEO_DECODE_TIER_2)) {
248 av_log(avctx,
AV_LOG_ERROR,
"D3D12 video decode on this device requires tier %d support, "
249 "but it is not implemented.\n", feature.DecodeTier);
253 desc = (D3D12_VIDEO_DECODER_DESC) {
255 .Configuration =
ctx->cfg,
259 (
void **)&
ctx->decoder));
262 if (!
ctx->decoder_ref)
289 ID3D12CommandAllocator *command_allocator =
NULL;
290 D3D12_COMMAND_QUEUE_DESC queue_desc = {
291 .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
293 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
322 if (!
ctx->ref_resources)
326 if (!
ctx->ref_subresources)
331 if (!
ctx->objects_queue)
334 DX_CHECK(ID3D12Device_CreateFence(
ctx->device_ctx->device, 0, D3D12_FENCE_FLAG_NONE,
335 &IID_ID3D12Fence, (
void **)&
ctx->sync_ctx.fence));
337 ctx->sync_ctx.event = CreateEvent(
NULL, FALSE, FALSE,
NULL);
338 if (!
ctx->sync_ctx.event)
345 DX_CHECK(ID3D12Device_CreateCommandQueue(
ctx->device_ctx->device, &queue_desc,
346 &IID_ID3D12CommandQueue, (
void **)&
ctx->command_queue));
348 DX_CHECK(ID3D12Device_CreateCommandList(
ctx->device_ctx->device, 0, queue_desc.Type,
349 command_allocator,
NULL, &IID_ID3D12CommandList, (
void **)&
ctx->command_list));
351 DX_CHECK(ID3D12VideoDecodeCommandList_Close(
ctx->command_list));
353 ID3D12CommandQueue_ExecuteCommandLists(
ctx->command_queue, 1, (ID3D12CommandList **)&
ctx->command_list);
375 int num_allocator = 0;
379 if (
ctx->sync_ctx.fence)
388 if (
ctx->objects_queue) {
395 av_log(avctx,
AV_LOG_VERBOSE,
"Total number of command allocators reused: %d\n", num_allocator);
401 if (
ctx->sync_ctx.event)
402 CloseHandle(
ctx->sync_ctx.event);
412 ID3D12Resource *current_resource,
int state_before,
int state_end)
417 for (
int i = 0;
i <
ctx->max_num_ref;
i++) {
418 if (((
ctx->used_mask >>
i) & 0x1) &&
ctx->ref_resources[
i] &&
ctx->ref_resources[
i] != current_resource) {
419 barriers[num_barrier].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
420 barriers[num_barrier].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
421 barriers[num_barrier].Transition = (D3D12_RESOURCE_TRANSITION_BARRIER){
422 .pResource =
ctx->ref_resources[
i],
423 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
424 .StateBefore = state_before,
425 .StateAfter = state_end,
435 const void *pp,
unsigned pp_size,
436 const void *qm,
unsigned qm_size,
442 ID3D12CommandAllocator *command_allocator =
NULL;
444 ID3D12Resource *resource = (ID3D12Resource *)
f->texture;
446 ID3D12VideoDecodeCommandList *cmd_list =
ctx->command_list;
447 D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
449 D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS input_args = {
450 .NumFrameArguments = 2,
453 .Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_PICTURE_PARAMETERS,
458 .Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_INVERSE_QUANTIZATION_MATRIX,
463 .pHeap =
ctx->decoder_heap,
466 D3D12_VIDEO_DECODE_OUTPUT_STREAM_ARGUMENTS output_args = {
467 .ConversionArguments = { 0 },
468 .OutputSubresource = 0,
469 .pOutputTexture2D = resource,
472 UINT num_barrier = 1;
473 barriers[0] = (D3D12_RESOURCE_BARRIER) {
474 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
475 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
477 .pResource = resource,
478 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
479 .StateBefore = D3D12_RESOURCE_STATE_COMMON,
480 .StateAfter = D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE,
484 memset(
ctx->ref_subresources, 0,
sizeof(UINT) *
ctx->max_num_ref);
485 input_args.ReferenceFrames.NumTexture2Ds =
ctx->max_num_ref;
486 input_args.ReferenceFrames.ppTexture2Ds =
ctx->ref_resources;
487 input_args.ReferenceFrames.pSubresources =
ctx->ref_subresources;
494 input_args.NumFrameArguments = 1;
504 DX_CHECK(ID3D12CommandAllocator_Reset(command_allocator));
506 DX_CHECK(ID3D12VideoDecodeCommandList_Reset(cmd_list, command_allocator));
510 ID3D12VideoDecodeCommandList_ResourceBarrier(cmd_list, num_barrier, barriers);
512 ID3D12VideoDecodeCommandList_DecodeFrame(cmd_list,
ctx->decoder, &output_args, &input_args);
514 for (
int i = 0;
i < num_barrier;
i++)
515 FFSWAP(D3D12_RESOURCE_STATES, barriers[
i].Transition.StateBefore, barriers[
i].Transition.StateAfter);
517 ID3D12VideoDecodeCommandList_ResourceBarrier(cmd_list, num_barrier, barriers);
519 DX_CHECK(ID3D12VideoDecodeCommandList_Close(cmd_list));
521 ID3D12CommandQueue_ExecuteCommandLists(
ctx->command_queue, 1, (ID3D12CommandList **)&
ctx->command_list);
523 DX_CHECK(ID3D12CommandQueue_Signal(
ctx->command_queue,
f->sync_ctx.fence, ++
f->sync_ctx.fence_value));
525 DX_CHECK(ID3D12CommandQueue_Signal(
ctx->command_queue,
ctx->sync_ctx.fence, ++
ctx->sync_ctx.fence_value));
534 if (command_allocator)