d3d12: Flush stale video encode wait registrations when reusing ID3D12Fence objects

Reviewed-by: Pohsiang (John) Hsu <pohhsu@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41160>
This commit is contained in:
Silvio Vilerino 2026-04-23 11:43:10 -04:00 committed by Marge Bot
parent fb13c044a8
commit e4c9d57ddf

View file

@ -4149,7 +4149,39 @@ d3d12_video_encoder_encode_bitstream_impl(struct pipe_video_codec *codec,
pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].ppSubregionSizes[i] = pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].pspSubregionSizes[i].Get();
if (pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].pspSubregionFences[i] == nullptr)
{
hr = pD3D12Enc->m_pD3D12Screen->dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].pspSubregionFences[i]));
if (FAILED(hr)) {
debug_printf("CreateFence failed with HR %x\n", (unsigned)hr);
pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].encode_result = PIPE_VIDEO_FEEDBACK_METADATA_ENCODE_FLAG_FAILED;
pD3D12Enc->m_spEncodedFrameMetadata[d3d12_video_encoder_metadata_current_index(pD3D12Enc)].encode_result = PIPE_VIDEO_FEEDBACK_METADATA_ENCODE_FLAG_FAILED;
assert(false);
return;
}
}
else if (pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].ppSubregionFenceValues[i] > 0)
{
// The ID3D12Fence objects in pspSubregionFences are reused across frames, but the
// d3d12_fence wrappers (pSubregionPipeFences) are recreated each frame via
// d3d12_create_fence_raw which calls SetEventOnCompletion. When a fence was never
// GPU-signaled (e.g. AUTO slice mode in prev frame produced fewer slices than allocated),
// the previous SetEventOnCompletion registration remains orphaned inside the ID3D12Fence.
// CloseHandle on the event handle (in destroy_fence) does NOT unregister it.
// CPU-signal to (new_value - 1) to flush any stale registration without
// satisfying the upcoming new one.
// At this point, the previous frame is guaranteed to be completed since when
// reusing current_metadata_slot, we only pick slots for frames that are already
// fully completed signaled (i.e. completed) as per the logic in d3d12_video_encoder_begin_frame.
hr = pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].pspSubregionFences[i]->Signal(
pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].ppSubregionFenceValues[i] - 1);
if (FAILED(hr)) {
debug_printf("ID3D12Fence::Signal failed with HR %x\n", (unsigned)hr);
pD3D12Enc->m_inflightResourcesPool[d3d12_video_encoder_pool_current_index(pD3D12Enc)].encode_result = PIPE_VIDEO_FEEDBACK_METADATA_ENCODE_FLAG_FAILED;
pD3D12Enc->m_spEncodedFrameMetadata[d3d12_video_encoder_metadata_current_index(pD3D12Enc)].encode_result = PIPE_VIDEO_FEEDBACK_METADATA_ENCODE_FLAG_FAILED;
assert(false);
return;
}
}
pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].ppSubregionFences[i] = pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].pspSubregionFences[i].Get();
pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].pSubregionPipeFences[i].reset(