diff --git a/src/gallium/frontends/mediafoundation/codecapi.cpp b/src/gallium/frontends/mediafoundation/codecapi.cpp index ae572e551af..683d48b457a 100644 --- a/src/gallium/frontends/mediafoundation/codecapi.cpp +++ b/src/gallium/frontends/mediafoundation/codecapi.cpp @@ -1824,6 +1824,14 @@ CDX12EncHMFT::SetValue( const GUID *Api, VARIANT *Value ) { CHECKHR_GOTO(E_INVALIDARG, done); } + + if ((Value->ulVal > 0) && (!m_EncoderCapabilities.m_HWSupportSlicedFences.bits.supported)) + { + MFE_ERROR("[dx12 hmft 0x%p] User tried to set CODECAPI_AVEncSliceGenerationMode: %d, but this encoder does NOT support sliced fence generation.", + this, Value->ulVal); + CHECKHR_GOTO(E_INVALIDARG, done); + } + debug_printf("[dx12 hmft 0x%p] SET CODECAPI_AVEncSliceGenerationMode - %u\n", this, Value->ulVal); m_uiSliceGenerationMode = Value->ulVal; m_bSliceGenerationModeSet = TRUE; diff --git a/src/gallium/frontends/mediafoundation/encode.cpp b/src/gallium/frontends/mediafoundation/encode.cpp index 7e5ef77fc0c..93a686f9edd 100644 --- a/src/gallium/frontends/mediafoundation/encode.cpp +++ b/src/gallium/frontends/mediafoundation/encode.cpp @@ -554,7 +554,7 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E #endif pDX12EncodeContext->sliceNotificationMode = D3D12_VIDEO_ENCODER_COMPRESSED_BITSTREAM_NOTIFICATION_MODE_FULL_FRAME; - if( m_EncoderCapabilities.m_HWSupportSlicedFences.bits.supported && ( num_output_buffers > 1 ) ) + if( m_bSliceGenerationModeSet && (m_uiSliceGenerationMode > 0) && ( num_output_buffers > 1 ) /* IHV driver requires > 1 slices */ ) { pDX12EncodeContext->sliceNotificationMode = D3D12_VIDEO_ENCODER_COMPRESSED_BITSTREAM_NOTIFICATION_MODE_SUBREGIONS; if( m_EncoderCapabilities.m_HWSupportSlicedFences.bits.multiple_buffers_required ) diff --git a/src/gallium/frontends/mediafoundation/mftransform.cpp b/src/gallium/frontends/mediafoundation/mftransform.cpp index e2723cc7f54..dd0e5fc1a2d 100644 --- a/src/gallium/frontends/mediafoundation/mftransform.cpp +++ b/src/gallium/frontends/mediafoundation/mftransform.cpp @@ -1443,11 +1443,19 @@ CDX12EncHMFT::xThreadProc( void *pCtx ) return result; }; - // If slice generation mode is explicitly set to 1 (1 slice per output sample) and auto mode is off - // emit multiple output samples, one per slice - if (pThis->m_bSliceGenerationModeSet && - (pThis->m_uiSliceGenerationMode == 1) && - (!pDX12EncodeContext->IsSliceAutoModeEnabled())) // We cannot know if the last slice is actually the last one on time to set the last MFSample properties + // + // We can assume pLastSliceFence is signaled after the last pSliceFences[slice_idx] is signaled + // but there may still be a race condition there in between these last two signals + // + // If we are using PIPE_SLICE_AUTO_MODE, we need to wait on pLastSliceFence to know when all actual slices are done + // and what pSliceFences[] after that point are unused and must not be waited on. + // + // When emitting the MFSamples asynchronously for each slice, we need to mark MFSample_LastSlice + // on the last actual slice. In auto mode, we only know which one is the last actual slice after pLastSliceFence is signaled + // and by that time, it is too late to mark MFSample_LastSlice on the last slice only (as it may have been already emitted), + // so in PIPE_SLICE_AUTO_MODE, we gather all completed slices here and emit them together after pLastSliceFence is signaled. + // + if (!pDX12EncodeContext->IsSliceAutoModeEnabled()) { std::vector codec_unit_metadata; codec_unit_metadata.reserve( 16 );