Submitted by: Zeckma Date: 2026-08-21 Initial Package Version: 0.11.1 Origin: Upstream, https://gitlab.freedesktop.org/mstoeckl/waypipe/-/commit/5fc8a456f14499052a4888a25719c462a4cd1b9a Upstream Status: Applied Description: Uses the new libavutil API in FFmpeg-9.0. diff --git a/meson.build b/meson.build index c95d5e88ed03cd28b8f78857fdef4326c4a225bb..0ebb8ba3088f6971a0d51f84b2cc91099dbf16f2 100644 --- a/meson.build +++ b/meson.build @@ -103,7 +103,7 @@ if get_option('build_rs') ) libavutil = dependency( 'libavutil', - version: '>=58.11.100', + version: '>=60.13.100', required: get_option('with_video'), ) libavcodec = dependency( diff --git a/src/dmabuf.rs b/src/dmabuf.rs index 99f44ecc8a540e5f7daa80d4babd02aadf761dbf..3db5ec76a0d5f1d7e8ad8d6e1eab5ab8b023c876 100644 --- a/src/dmabuf.rs +++ b/src/dmabuf.rs @@ -65,8 +65,8 @@ pub struct VulkanDevice { _instance: Arc, dev_info: DeviceInfo, - /** Queue family indices. Order: [compute+transfer, graphics+transfer, encode, decode] */ - qfis: [Option; 4], + /** Information about the queues that were bound. (flags, video operations, index, number bound) */ + queue_info: Vec<(vk::QueueFlags, vk::VideoCodecOperationFlagsKHR, i32, i32)>, /** Timeline semaphore; when it reaches 'queue.last_semaphore_value', all preceding work using * the semaphore is done */ @@ -1362,81 +1362,120 @@ pub fn setup_vulkan_device_base( let memory_properties = instance .instance .get_physical_device_memory_properties(physdev); - let queue_families = instance + + let num_families = instance .instance - .get_physical_device_queue_family_properties(physdev); + .get_physical_device_queue_family_properties2_len(physdev); + assert!(num_families <= i32::MAX as usize); + + let mut vid_props = vec![vk::QueueFamilyVideoPropertiesKHR::default(); num_families]; + let mut qf_props: Vec = vid_props + .iter_mut() + .map(|vid_prop| vk::QueueFamilyProperties2::default().push_next(vid_prop)) + .collect(); + instance + .instance + .get_physical_device_queue_family_properties2(physdev, &mut qf_props[..]); + + let mut first_ct = None; + let mut first_gt = None; + let mut vid_queues = Vec::new(); + let mut has_vid_enc = false; + let mut has_vid_dec = false; - let mut qfis = [None, None, None, None]; - let mut nqis = [0, 0, 0, 0]; - for (u, family) in queue_families.iter().enumerate().rev() { - let i: u32 = u.try_into().unwrap(); - if family + for (u, qf_prop) in qf_props.iter().enumerate() { + if qf_prop + .queue_family_properties .queue_flags .contains(vk::QueueFlags::COMPUTE | vk::QueueFlags::TRANSFER) + && first_ct.is_none() { - qfis[0] = Some(i); - nqis[0] = family.queue_count; + first_ct = Some(u); } - if family + if qf_prop + .queue_family_properties .queue_flags .contains(vk::QueueFlags::GRAPHICS | vk::QueueFlags::TRANSFER) + && first_gt.is_none() { - qfis[1] = Some(i); - nqis[1] = family.queue_count; + first_gt = Some(u); } - if family + + // TODO: match the queues to what codecs are listed as being supported, + // in particular, to allow for earlier error messages + let enc = qf_prop + .queue_family_properties .queue_flags - .contains(vk::QueueFlags::VIDEO_ENCODE_KHR) - { - qfis[2] = Some(i); - nqis[2] = family.queue_count; - } - if family + .contains(vk::QueueFlags::VIDEO_ENCODE_KHR); + let dec = qf_prop + .queue_family_properties .queue_flags - .contains(vk::QueueFlags::VIDEO_DECODE_KHR) - { - qfis[3] = Some(i); - nqis[3] = family.queue_count; + .contains(vk::QueueFlags::VIDEO_DECODE_KHR); + + has_vid_enc |= enc; + has_vid_dec |= dec; + if enc || dec { + vid_queues.push(u); } } - let Some(queue_family) = qfis[0] else { + let Some(queue_family) = first_ct else { return Err(tag!("No compute+transfer queue available")); }; let prio = &[1.0]; - let chosen_queues: Vec> = if using_hw_video { - if qfis[1].is_none() { + let qf_indices = if using_hw_video { + let Some(gt) = first_gt else { return Err(tag!("No graphics+transfer queue available")); - } + }; - if using_hw_video_enc && qfis[2].is_none() { - return Err(tag!("No encode queue available")); + if using_hw_video_enc && !has_vid_enc { + return Err(tag!("No video encode queue available")); } - if using_hw_video_dec && qfis[3].is_none() { - return Err(tag!("No decode queue available")); + if using_hw_video_dec && !has_vid_dec { + return Err(tag!("No video decode queue available")); } - // Only create one queue out of each family that we need. - let mut qfis = qfis.to_vec(); - qfis.retain(Option::is_some); - qfis.sort_unstable(); - qfis.dedup(); - qfis.into_iter() - .map(|qf| { - vk::DeviceQueueCreateInfo::default() - .queue_family_index(qf.unwrap()) - .queue_priorities(prio) - }) - .collect() + let mut all_queues = vid_queues; + all_queues.insert(0, queue_family); + all_queues.insert(0, gt); + all_queues.sort_unstable(); + all_queues.dedup(); + all_queues } else { - vec![vk::DeviceQueueCreateInfo::default() - .queue_family_index(queue_family) - .queue_priorities(prio)] + vec![queue_family] }; + let queue_family: u32 = queue_family.try_into().unwrap(); + + let queue_info: Vec<(vk::QueueFlags, vk::VideoCodecOperationFlagsKHR, i32, i32)> = + qf_indices + .iter() + .map(|u| { + let qf_prop = &qf_props[*u]; + // SAFTEY: accessing vid_prop through the (implicit) &mut reference that qf_prop holds + // The type matches the only next item that was pushed. + let vid_prop = *qf_prop.p_next.cast::(); + ( + qf_prop.queue_family_properties.queue_flags, + vid_prop.video_codec_operations, + i32::try_from(*u).unwrap(), + 1, + ) + }) + .collect(); + + let chosen_queues: Vec> = qf_indices + .into_iter() + .map(|qf| { + vk::DeviceQueueCreateInfo::default() + .queue_family_index(qf.try_into().unwrap()) + .queue_priorities(prio) + }) + .collect(); + let enabled_exts = get_enabled_exts(dev_info); let mut featuresv11 = @@ -1695,7 +1734,7 @@ pub fn setup_vulkan_device_base( _instance: instance.clone(), dev_info: *dev_info, - qfis, + queue_info, queue: Mutex::new(VulkanQueue { queue, last_semaphore_value: init_sem_value, @@ -1745,7 +1784,7 @@ pub fn setup_vulkan_device( &dev.dev, &dev.dev_info, debug, - dev.qfis, + &dev.queue_info[..], &enabled_exts, INSTANCE_EXTS, )? diff --git a/src/video.rs b/src/video.rs index 7663efc74abeba727b579189ae344388ab31a64f..f3469f9f83c8f207a8f430df4e7704f1795d8e02 100644 --- a/src/video.rs +++ b/src/video.rs @@ -596,7 +596,7 @@ pub unsafe fn setup_video( dev: &Device, pdev_info: &DeviceInfo, debug: bool, - qfis: [Option; 4], + queue_info: &[(vk::QueueFlags, vk::VideoCodecOperationFlagsKHR, i32, i32)], device_exts: &[*const c_char], instance_exts: &[*const c_char], ) -> Result, String> { @@ -663,16 +663,16 @@ pub unsafe fn setup_video( /* Note: the queue_family_indices are deprecated and will be replaced * by `.qf`/`.nb_qf` */ - ctx.queue_family_tx_index = qfis[0].map_or(-1, |v| v.try_into().unwrap()); - ctx.queue_family_comp_index = qfis[0].map_or(-1, |v| v.try_into().unwrap()); - ctx.queue_family_index = qfis[1].map_or(-1, |v| v.try_into().unwrap()); - ctx.queue_family_encode_index = qfis[2].map_or(-1, |v| v.try_into().unwrap()); - ctx.queue_family_decode_index = qfis[3].map_or(-1, |v| v.try_into().unwrap()); - ctx.nb_graphics_queues = 1; - ctx.nb_tx_queues = 1; - ctx.nb_comp_queues = 1; - ctx.nb_encode_queues = 1; - ctx.nb_decode_queues = 1; + for (i, (flags, codec_ops, index, nbound)) in queue_info.iter().enumerate() { + let Some(qf) = ctx.qf.get_mut(i) else { + continue; + }; + qf.idx = *index; + qf.num = *nbound; + qf.flags = flags.as_raw(); + qf.video_caps = codec_ops.as_raw(); + } + ctx.nb_qf = i32::try_from(queue_info.len().min(ctx.qf.len())).unwrap(); av_hwdevice_ctx_init(&lib, device_ref)?;