d3d12: Add get_video_enc_last_slice_completion_fence interop

Reviewed-by: Pohsiang (John) Hsu <pohhsu@microsoft.com>
Reviewed-by: Yubo Xie <yuboxie@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38144>
This commit is contained in:
Silvio Vilerino 2025-10-25 00:02:29 -04:00 committed by Marge Bot
parent a22334e632
commit e55b2b5064
4 changed files with 62 additions and 0 deletions

View file

@ -336,6 +336,11 @@ d3d12_context_set_queue_priority_manager(struct pipe_context *ctx, struct d3d12_
int
d3d12_video_encoder_set_max_async_queue_depth(struct pipe_context *ctx, uint32_t max_async_depth);
int
d3d12_video_encoder_get_last_slice_completion_fence(struct pipe_video_codec *codec,
void *feedback,
pipe_fence_handle **last_slice_completion_fence);
bool
d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor);

View file

@ -189,6 +189,26 @@ struct d3d12_interop_device_info1 {
* Returns int (0 for success, error code otherwise)
*/
int (*set_video_encoder_max_async_queue_depth)(struct pipe_context *context, uint32_t max_async_queue_depth);
/*
* Function pointer to get the last slice completion fence for a video encoder,
* which may happen before the entire frame is complete, including the stats.
* If this function is NULL, the driver does not support getting the last slice completion fence.
*
* Parameters:
* - pipe_video_codec*: codec to query
* - void*: feedback data to provide to the driver to indicate the frame feedback
* from which to get the last slice completion fence returned by
* pipe_video_codec::encode_bitstream/encode_bitstream_sliced.
* - pipe_fence_handle**: pointer to a fence handle to be filled in by the driver
*
* The caller must call pipe_video_codec::destroy_fence to destroy the returned fence handle
*
* Returns int (0 for success, error code otherwise)
*/
int (*get_video_enc_last_slice_completion_fence)(struct pipe_video_codec *codec,
void *feedback,
struct pipe_fence_handle **fence);
};
#ifdef __cplusplus

View file

@ -1162,6 +1162,7 @@ d3d12_interop_query_device_info(struct pipe_screen *pscreen, uint32_t data_size,
d3d12_interop_device_info1 *info1 = (d3d12_interop_device_info1 *)data;
info1->set_context_queue_priority_manager = d3d12_context_set_queue_priority_manager;
info1->set_video_encoder_max_async_queue_depth = d3d12_video_encoder_set_max_async_queue_depth;
info1->get_video_enc_last_slice_completion_fence = d3d12_video_encoder_get_last_slice_completion_fence;
return sizeof(*info1);
}

View file

@ -5018,3 +5018,39 @@ d3d12_video_encoder_fence_wait(struct pipe_video_codec *codec,
// ret != 0 -> Encode completed
return wait_res ? 1 : 0;
}
int
d3d12_video_encoder_get_last_slice_completion_fence(struct pipe_video_codec *codec,
void *feedback,
pipe_fence_handle **last_slice_completion_fence)
{
struct d3d12_video_encoder *pD3D12Enc = (struct d3d12_video_encoder *) codec;
assert(pD3D12Enc);
if (!pD3D12Enc || !feedback || !last_slice_completion_fence) {
return -1;
}
struct d3d12_fence *feedback_fence = (struct d3d12_fence *) feedback;
uint64_t requested_metadata_fence = feedback_fence->value;
size_t current_metadata_slot = static_cast<size_t>(requested_metadata_fence % pD3D12Enc->m_MaxMetadataBuffersCount);
// Check if the requested metadata is valid
if ((pD3D12Enc->m_fenceValue - requested_metadata_fence) > pD3D12Enc->m_MaxMetadataBuffersCount) {
debug_printf("[d3d12_video_encoder_get_last_slice_completion_fence] Requested metadata for fence %" PRIu64 " at current fence %" PRIu64
" is too far back in time for the ring buffer of size %" PRIu64 "\n",
requested_metadata_fence,
pD3D12Enc->m_fenceValue,
static_cast<uint64_t>(pD3D12Enc->m_MaxMetadataBuffersCount));
return -1;
}
// Get the last slice completion fence for this frame
if (pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].m_LastSliceFence) {
d3d12_fence_reference((struct d3d12_fence **)last_slice_completion_fence,
pD3D12Enc->m_spEncodedFrameMetadata[current_metadata_slot].m_LastSliceFence.get());
return 0;
}
return -1;
}