d3d12: Implement last slice signal by splitting Encode/Resolve in two ECL

Reviewed-by: Pohsiang (John) Hsu <pohhsu@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37982>
This commit is contained in:
Silvio Vilerino 2025-10-16 15:52:31 -04:00 committed by Pohsiang (John) Hsu
parent 134274488d
commit f4f619e26e
2 changed files with 99 additions and 11 deletions

View file

@ -155,10 +155,19 @@ d3d12_video_encoder_flush(struct pipe_video_codec *codec)
goto flush_fail;
}
hr = pD3D12Enc->m_spResolveCommandList->Close();
if (FAILED(hr)) {
debug_printf("[d3d12_video_encoder] d3d12_video_encoder_flush - Can't close command list with HR %x\n", (unsigned)hr);
goto flush_fail;
}
ID3D12CommandList *ppCommandLists[1] = { pD3D12Enc->m_spEncodeCommandList.Get() };
pD3D12Enc->m_spEncodeCommandQueue->ExecuteCommandLists(1, ppCommandLists);
pD3D12Enc->m_spEncodeCommandQueue->Signal(pD3D12Enc->m_spLastSliceFence.Get(), pD3D12Enc->m_LastSliceFenceValue);
ID3D12CommandList *ppCommandLists2[1] = { pD3D12Enc->m_spResolveCommandList.Get() };
pD3D12Enc->m_spEncodeCommandQueue->ExecuteCommandLists(1, ppCommandLists2);
pD3D12Enc->m_spEncodeCommandQueue->Signal(pD3D12Enc->m_spFence.Get(), pD3D12Enc->m_fenceValue);
// Validate device was not removed
hr = pD3D12Enc->m_pD3D12Screen->dev->GetDeviceRemovedReason();
if (hr != S_OK) {
@ -170,6 +179,7 @@ d3d12_video_encoder_flush(struct pipe_video_codec *codec)
}
pD3D12Enc->m_fenceValue++;
pD3D12Enc->m_LastSliceFenceValue++;
pD3D12Enc->m_bPendingWorkNotFlushed = false;
}
return;
@ -204,6 +214,14 @@ d3d12_video_encoder_sync_completion(struct pipe_video_codec *codec,
goto sync_with_token_fail;
}
debug_printf("[d3d12_video_encoder] d3d12_video_encoder_sync_completion - resetting ID3D12CommandAllocator %p...\n",
pool_entry.m_spResolveCommandAllocator.Get());
hr = pool_entry.m_spResolveCommandAllocator->Reset();
if(FAILED(hr)) {
debug_printf("failed with %x.\n", (unsigned)hr);
goto sync_with_token_fail;
}
// Release references granted on end_frame for this inflight operations
pool_entry.m_spEncoder.Reset();
pool_entry.m_spEncoderHeap.Reset();
@ -2343,6 +2361,14 @@ d3d12_video_encoder_create_command_objects(struct d3d12_video_encoder *pD3D12Enc
return false;
}
hr = pD3D12Enc->m_pD3D12Screen->dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&pD3D12Enc->m_spLastSliceFence));
if (FAILED(hr)) {
debug_printf(
"[d3d12_video_encoder] d3d12_video_encoder_create_command_objects - Call to CreateFence failed with HR %x\n",
(unsigned)hr);
return false;
}
uint64_t CompletionFenceValue = pD3D12Enc->m_fenceValue;
for (auto& inputResource : pD3D12Enc->m_inflightResourcesPool)
{
@ -2357,8 +2383,21 @@ d3d12_video_encoder_create_command_objects(struct d3d12_video_encoder *pD3D12Enc
return false;
}
// Create associated command allocator for Resolve operations
hr = pD3D12Enc->m_pD3D12Screen->dev->CreateCommandAllocator(
D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
IID_PPV_ARGS(inputResource.m_spResolveCommandAllocator.GetAddressOf()));
if (FAILED(hr)) {
debug_printf("[d3d12_video_encoder] d3d12_video_encoder_create_command_objects - Call to "
"CreateCommandAllocator failed with HR %x\n",
(unsigned)hr);
return false;
}
// Initialize fence for the in flight resource pool slot
inputResource.m_CompletionFence.reset(d3d12_create_fence_raw(pD3D12Enc->m_spFence.Get(), CompletionFenceValue++));
inputResource.m_CompletionFence.reset(d3d12_create_fence_raw(pD3D12Enc->m_spFence.Get(), CompletionFenceValue));
inputResource.m_CompletionFence.reset(d3d12_create_fence_raw(pD3D12Enc->m_spLastSliceFence.Get(), CompletionFenceValue));
CompletionFenceValue++;
}
ComPtr<ID3D12Device4> spD3D12Device4;
@ -2381,6 +2420,18 @@ d3d12_video_encoder_create_command_objects(struct d3d12_video_encoder *pD3D12Enc
return false;
}
hr = spD3D12Device4->CreateCommandList1(0,
D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
D3D12_COMMAND_LIST_FLAG_NONE,
IID_PPV_ARGS(pD3D12Enc->m_spResolveCommandList.GetAddressOf()));
if (FAILED(hr)) {
debug_printf("[d3d12_video_encoder] d3d12_video_encoder_create_command_objects - Call to CreateCommandList "
"failed with HR %x\n",
(unsigned)hr);
return false;
}
return true;
}
@ -2825,6 +2876,14 @@ d3d12_video_encoder_begin_frame(struct pipe_video_codec * codec,
goto fail;
}
hr = pD3D12Enc->m_spResolveCommandList->Reset(pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].m_spResolveCommandAllocator.Get());
if (FAILED(hr)) {
debug_printf(
"[d3d12_video_encoder] d3d12_video_encoder_flush - resetting ID3D12GraphicsCommandList failed with HR %x\n",
(unsigned)hr);
goto fail;
}
pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].m_InputSurfaceFence = d3d12_fence(picture->in_fence);
pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].m_InputSurfaceFenceValue = picture->in_fence_value;
pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].encode_result = PIPE_VIDEO_FEEDBACK_METADATA_ENCODE_FLAG_OK;
@ -3319,6 +3378,9 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
*feedback = (void*)pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].m_fence.get();
pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].m_LastSliceFence.reset(d3d12_create_fence_raw(pD3D12Enc->m_spLastSliceFence.Get(), pD3D12Enc->m_LastSliceFenceValue));
d3d12_fence_reference((struct d3d12_fence **)last_slice_completion_fence, pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].m_LastSliceFence.get());
std::vector<D3D12_RESOURCE_BARRIER> rgCurrentFrameStateTransitions = {
CD3DX12_RESOURCE_BARRIER::Transition(pInputVideoD3D12Res,
D3D12_RESOURCE_STATE_COMMON,
@ -3489,8 +3551,11 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
#endif
ComPtr<ID3D12VideoEncodeCommandList4> spEncodeCommandList4;
if (SUCCEEDED(pD3D12Enc->m_spEncodeCommandList->QueryInterface(
IID_PPV_ARGS(spEncodeCommandList4.GetAddressOf())))) {
ComPtr<ID3D12VideoEncodeCommandList4> spResolveCommandList4;
if ((SUCCEEDED(pD3D12Enc->m_spEncodeCommandList->QueryInterface(
IID_PPV_ARGS(spEncodeCommandList4.GetAddressOf())))) &&
(SUCCEEDED(pD3D12Enc->m_spResolveCommandList->QueryInterface(
IID_PPV_ARGS(spResolveCommandList4.GetAddressOf()))))) {
// Update current frame pic params state after reconfiguring above.
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA1 currentPicParams =
@ -4049,7 +4114,7 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
D3D12_RESOURCE_STATE_COMMON));
}
spEncodeCommandList4->ResourceBarrier(static_cast<uint32_t>(rgResolveMetadataStateTransitions.size()),
spResolveCommandList4->ResourceBarrier(static_cast<uint32_t>(rgResolveMetadataStateTransitions.size()),
rgResolveMetadataStateTransitions.data());
std::vector<D3D12_RESOURCE_BARRIER> output_stats_barriers;
@ -4077,7 +4142,7 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE));
}
spEncodeCommandList4->ResourceBarrier(static_cast<uint32_t>(output_stats_barriers.size()),
spResolveCommandList4->ResourceBarrier(static_cast<uint32_t>(output_stats_barriers.size()),
output_stats_barriers.data());
const D3D12_VIDEO_ENCODER_RESOLVE_METADATA_INPUT_ARGUMENTS1 inputMetadataCmd = {
pD3D12Enc->m_currentEncodeConfig.m_encoderCodecDesc,
@ -4112,7 +4177,7 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
{},
};
spEncodeCommandList4->ResolveEncoderOutputMetadata1(&inputMetadataCmd, &outputMetadataCmd);
spResolveCommandList4->ResolveEncoderOutputMetadata1(&inputMetadataCmd, &outputMetadataCmd);
debug_printf("[d3d12_video_encoder_encode_bitstream] EncodeFrame slot %" PRIu64 " encoder %p encoderheap %p input tex %p output bitstream %p raw metadata buf %p resolved metadata buf %p Command allocator %p\n",
static_cast<uint64_t>(d3d12_video_encoder_pool_current_index(pD3D12Enc)),
@ -4146,14 +4211,14 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
D3D12_RESOURCE_STATE_COMMON),
};
spEncodeCommandList4->ResourceBarrier(_countof(rgRevertResolveMetadataStateTransitions),
spResolveCommandList4->ResourceBarrier(_countof(rgRevertResolveMetadataStateTransitions),
rgRevertResolveMetadataStateTransitions);
// Revert output_stats_barriers
for (auto &BarrierDesc : output_stats_barriers) {
std::swap(BarrierDesc.Transition.StateBefore, BarrierDesc.Transition.StateAfter);
}
spEncodeCommandList4->ResourceBarrier(static_cast<uint32_t>(output_stats_barriers.size()),
spResolveCommandList4->ResourceBarrier(static_cast<uint32_t>(output_stats_barriers.size()),
output_stats_barriers.data());
for (auto &BarrierDesc : pSlicedEncodingExtraBarriers) {
@ -4218,6 +4283,24 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
&inputStreamArguments,
&outputStreamArguments);
std::vector<D3D12_RESOURCE_BARRIER> rgResolveMetadataStateTransitions = {
CD3DX12_RESOURCE_BARRIER::Transition(pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].spBuffer.Get(),
D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE),
CD3DX12_RESOURCE_BARRIER::Transition(pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].m_spMetadataOutputBuffer.Get(),
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ),
CD3DX12_RESOURCE_BARRIER::Transition(pInputVideoD3D12Res,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
D3D12_RESOURCE_STATE_COMMON),
CD3DX12_RESOURCE_BARRIER::Transition(pOutputBufferD3D12Resources[0],
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
D3D12_RESOURCE_STATE_COMMON),
};
pD3D12Enc->m_spResolveCommandList->ResourceBarrier(static_cast<uint32_t>(rgResolveMetadataStateTransitions.size()),
rgResolveMetadataStateTransitions.data());
const D3D12_VIDEO_ENCODER_RESOLVE_METADATA_INPUT_ARGUMENTS inputMetadataCmd = {
pD3D12Enc->m_currentEncodeConfig.m_encoderCodecDesc,
d3d12_video_encoder_get_current_profile_desc(pD3D12Enc),
@ -4232,7 +4315,7 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
{ pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].spBuffer.Get(), 0 }
};
pD3D12Enc->m_spEncodeCommandList->ResolveEncoderOutputMetadata(&inputMetadataCmd, &outputMetadataCmd);
pD3D12Enc->m_spResolveCommandList->ResolveEncoderOutputMetadata(&inputMetadataCmd, &outputMetadataCmd);
debug_printf("[d3d12_video_encoder_encode_bitstream] EncodeFrame slot %" PRIu64 " encoder %p encoderheap %p input tex %p output bitstream %p raw metadata buf %p resolved metadata buf %p Command allocator %p\n",
static_cast<uint64_t>(d3d12_video_encoder_pool_current_index(pD3D12Enc)),
@ -4266,7 +4349,7 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
D3D12_RESOURCE_STATE_COMMON),
};
pD3D12Enc->m_spEncodeCommandList->ResourceBarrier(_countof(rgRevertResolveMetadataStateTransitions),
pD3D12Enc->m_spResolveCommandList->ResourceBarrier(_countof(rgRevertResolveMetadataStateTransitions),
rgRevertResolveMetadataStateTransitions);
}
debug_printf("[d3d12_video_encoder] d3d12_video_encoder_encode_bitstream finalized for fenceValue: %" PRIu64 "\n",

View file

@ -546,6 +546,7 @@ struct EncodedBitstreamResolvedMetadata
/* Pending fence data for this frame */
d3d12_unique_fence m_fence;
d3d12_unique_fence m_LastSliceFence;
};
enum d3d12_video_encoder_driver_workarounds
@ -580,7 +581,9 @@ struct d3d12_video_encoder
size_t m_MaxMetadataBuffersCount = 0;
ComPtr<ID3D12Fence> m_spFence;
ComPtr<ID3D12Fence> m_spLastSliceFence;
uint64_t m_fenceValue = 1u;
uint64_t m_LastSliceFenceValue = 1u;
bool m_bPendingWorkNotFlushed = false;
ComPtr<ID3D12VideoDevice3> m_spD3D12VideoDevice;
@ -588,6 +591,7 @@ struct d3d12_video_encoder
ComPtr<ID3D12VideoEncoderHeap> m_spVideoEncoderHeap;
ComPtr<ID3D12CommandQueue> m_spEncodeCommandQueue;
ComPtr<ID3D12VideoEncodeCommandList2> m_spEncodeCommandList;
ComPtr<ID3D12VideoEncodeCommandList2> m_spResolveCommandList;
std::vector<D3D12_RESOURCE_BARRIER> m_transitionsBeforeCloseCmdList;
std::unique_ptr<d3d12_video_encoder_references_manager_interface> m_upDPBManager;
@ -614,6 +618,7 @@ struct d3d12_video_encoder
std::shared_ptr<d3d12_video_dpb_storage_manager_interface> m_References;
ComPtr<ID3D12CommandAllocator> m_spCommandAllocator;
ComPtr<ID3D12CommandAllocator> m_spResolveCommandAllocator;
struct d3d12_fence* m_InputSurfaceFence = NULL;
uint64_t m_InputSurfaceFenceValue = 0;