diff --git a/media/gpu/windows/d3d12_video_processor_wrapper.cc b/media/gpu/windows/d3d12_video_processor_wrapper.cc --- a/media/gpu/windows/d3d12_video_processor_wrapper.cc +++ b/media/gpu/windows/d3d12_video_processor_wrapper.cc @@ -147,6 +147,18 @@ D3D12FenceAndValue D3D12VideoProcessorWrapper::ProcessFrames( output_stream_desc_ = output_stream_desc; } + // The previous ProcessFrames() submission is normally drained transitively + // via D3D12VideoEncoderWrapper::Encode() -> SignalAndWaitCPU(). If the codec + // delegate's EncodeImpl() bails out before reaching that wait, the previous + // command list may still be executing on the GPU when we get back here. + // Resetting an allocator backing an in-flight list is D3D12 UB, so block + // until the last signalled value has been reached on the GPU. + if (fence_->GetCompletedValue() < fence_->Value() && + !fence_->WaitCPU(fence_->Value()).is_ok()) { + DLOG(ERROR) << "WaitCPU on previous video-process fence failed"; + return {}; + } + hr = command_allocator_->Reset(); if (FAILED(hr)) { DLOG(ERROR) << "Reset video process command allocator failed:"