use multi-threaded capture if vk queues ≥ 2
This commit is contained in:
@@ -229,7 +229,7 @@ where
|
|||||||
has_wlr_dmabuf,
|
has_wlr_dmabuf,
|
||||||
has_wlr_screencopy,
|
has_wlr_screencopy,
|
||||||
pw_token_store,
|
pw_token_store,
|
||||||
&app.session,
|
&app,
|
||||||
) {
|
) {
|
||||||
overlay.backend.set_renderer(Box::new(renderer));
|
overlay.backend.set_renderer(Box::new(renderer));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,10 @@ pub(super) struct LinePool {
|
|||||||
|
|
||||||
impl LinePool {
|
impl LinePool {
|
||||||
pub fn new(graphics: Arc<WlxGraphics>) -> anyhow::Result<Self> {
|
pub fn new(graphics: Arc<WlxGraphics>) -> anyhow::Result<Self> {
|
||||||
let mut command_buffer =
|
let mut command_buffer = graphics.create_uploads_command_buffer(
|
||||||
graphics.create_uploads_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
graphics.transfer_queue.clone(),
|
||||||
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)?;
|
||||||
|
|
||||||
let buf = vec![255; 16];
|
let buf = vec![255; 16];
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ pub(super) struct Skybox {
|
|||||||
|
|
||||||
impl Skybox {
|
impl Skybox {
|
||||||
pub fn new(app: &AppState) -> anyhow::Result<Self> {
|
pub fn new(app: &AppState) -> anyhow::Result<Self> {
|
||||||
let mut command_buffer = app
|
let mut command_buffer = app.graphics.create_uploads_command_buffer(
|
||||||
.graphics
|
app.graphics.transfer_queue.clone(),
|
||||||
.create_uploads_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut maybe_image = None;
|
let mut maybe_image = None;
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ pub struct WlxGraphics {
|
|||||||
pub device: Arc<Device>,
|
pub device: Arc<Device>,
|
||||||
pub graphics_queue: Arc<Queue>,
|
pub graphics_queue: Arc<Queue>,
|
||||||
pub transfer_queue: Arc<Queue>,
|
pub transfer_queue: Arc<Queue>,
|
||||||
pub capture_queue: Arc<Queue>,
|
pub capture_queue: Option<Arc<Queue>>,
|
||||||
|
|
||||||
pub native_format: Format,
|
pub native_format: Format,
|
||||||
pub texture_filtering: Filter,
|
pub texture_filtering: Filter,
|
||||||
@@ -247,21 +247,8 @@ impl WlxGraphics {
|
|||||||
physical_device.properties().device_name,
|
physical_device.properties().device_name,
|
||||||
);
|
);
|
||||||
|
|
||||||
let queue_family_index_gfx = physical_device
|
let queue_families = try_all_queue_families(physical_device.as_ref())
|
||||||
.queue_family_properties()
|
.expect("vkPhysicalDevice does not have a GRAPHICS / TRANSFER queue.");
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.position(|(_, q)| q.queue_flags.intersects(QueueFlags::GRAPHICS))
|
|
||||||
.expect("Vulkan device has no graphics queue")
|
|
||||||
as u32;
|
|
||||||
|
|
||||||
let queue_family_index_xfer = physical_device
|
|
||||||
.queue_family_properties()
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.position(|(_, q)| q.queue_flags.intersects(QueueFlags::TRANSFER))
|
|
||||||
.expect("Vulkan device has no transfer queue")
|
|
||||||
as u32;
|
|
||||||
|
|
||||||
let mut device_extensions = DeviceExtensions::empty();
|
let mut device_extensions = DeviceExtensions::empty();
|
||||||
let dmabuf_extensions = get_dmabuf_extensions();
|
let dmabuf_extensions = get_dmabuf_extensions();
|
||||||
@@ -276,9 +263,12 @@ impl WlxGraphics {
|
|||||||
.ext_image_drm_format_modifier;
|
.ext_image_drm_format_modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
if physical_device.supported_extensions().ext_filter_cubic {
|
let texture_filtering = if physical_device.supported_extensions().ext_filter_cubic {
|
||||||
device_extensions.ext_filter_cubic = true;
|
device_extensions.ext_filter_cubic = true;
|
||||||
}
|
Filter::Cubic
|
||||||
|
} else {
|
||||||
|
Filter::Linear
|
||||||
|
};
|
||||||
|
|
||||||
let device_extensions_raw = device_extensions
|
let device_extensions_raw = device_extensions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -297,19 +287,14 @@ impl WlxGraphics {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let queue_priorities = vec![1.0];
|
let queue_create_infos = queue_families
|
||||||
|
.iter()
|
||||||
let queue_create_infos = [
|
.map(|fam| {
|
||||||
vk::DeviceQueueCreateInfo::default()
|
vk::DeviceQueueCreateInfo::default()
|
||||||
.queue_family_index(queue_family_index_gfx)
|
.queue_family_index(fam.queue_family_index)
|
||||||
.queue_priorities(&queue_priorities),
|
.queue_priorities(&fam.priorities)
|
||||||
vk::DeviceQueueCreateInfo::default()
|
})
|
||||||
.queue_family_index(queue_family_index_xfer)
|
.collect::<Vec<_>>();
|
||||||
.queue_priorities(&queue_priorities),
|
|
||||||
vk::DeviceQueueCreateInfo::default()
|
|
||||||
.queue_family_index(queue_family_index_xfer)
|
|
||||||
.queue_priorities(&queue_priorities),
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut device_create_info = vk::DeviceCreateInfo::default()
|
let mut device_create_info = vk::DeviceCreateInfo::default()
|
||||||
.queue_create_infos(&queue_create_infos)
|
.queue_create_infos(&queue_create_infos)
|
||||||
@@ -321,13 +306,7 @@ impl WlxGraphics {
|
|||||||
dynamic_rendering.p_next = device_create_info.p_next.cast_mut();
|
dynamic_rendering.p_next = device_create_info.p_next.cast_mut();
|
||||||
device_create_info.p_next = &raw mut dynamic_rendering as *const c_void;
|
device_create_info.p_next = &raw mut dynamic_rendering as *const c_void;
|
||||||
|
|
||||||
let texture_filtering = if physical_device.supported_extensions().ext_filter_cubic {
|
let (device, queues) = unsafe {
|
||||||
Filter::Cubic
|
|
||||||
} else {
|
|
||||||
Filter::Linear
|
|
||||||
};
|
|
||||||
|
|
||||||
let (device, mut queues) = unsafe {
|
|
||||||
let vk_device = xr_instance
|
let vk_device = xr_instance
|
||||||
.create_vulkan_device(
|
.create_vulkan_device(
|
||||||
system,
|
system,
|
||||||
@@ -343,23 +322,14 @@ impl WlxGraphics {
|
|||||||
physical_device,
|
physical_device,
|
||||||
vk::Device::from_raw(vk_device as _),
|
vk::Device::from_raw(vk_device as _),
|
||||||
DeviceCreateInfo {
|
DeviceCreateInfo {
|
||||||
queue_create_infos: vec![
|
queue_create_infos: queue_families
|
||||||
QueueCreateInfo {
|
.iter()
|
||||||
queue_family_index: queue_family_index_gfx,
|
.map(|fam| QueueCreateInfo {
|
||||||
queues: queue_priorities.clone(),
|
queue_family_index: fam.queue_family_index,
|
||||||
|
queues: fam.priorities.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
})
|
||||||
QueueCreateInfo {
|
.collect::<Vec<_>>(),
|
||||||
queue_family_index: queue_family_index_xfer,
|
|
||||||
queues: queue_priorities.clone(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
QueueCreateInfo {
|
|
||||||
queue_family_index: queue_family_index_xfer,
|
|
||||||
queues: queue_priorities,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
],
|
|
||||||
enabled_extensions: device_extensions,
|
enabled_extensions: device_extensions,
|
||||||
enabled_features: features,
|
enabled_features: features,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -383,15 +353,7 @@ impl WlxGraphics {
|
|||||||
let _ = CString::from_raw(c_string.cast_mut());
|
let _ = CString::from_raw(c_string.cast_mut());
|
||||||
});
|
});
|
||||||
|
|
||||||
let graphics_queue = queues
|
let (graphics_queue, transfer_queue, capture_queue) = unwrap_queues(queues.collect());
|
||||||
.next()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("no graphics queues available"))?;
|
|
||||||
let transfer_queue = queues
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("no transfer queues available"))?;
|
|
||||||
let capture_queue = queues
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("not enough transfer queues available"))?;
|
|
||||||
|
|
||||||
let memory_allocator = memory_allocator(device.clone());
|
let memory_allocator = memory_allocator(device.clone());
|
||||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||||
@@ -459,65 +421,48 @@ impl WlxGraphics {
|
|||||||
|
|
||||||
let dmabuf_extensions = get_dmabuf_extensions();
|
let dmabuf_extensions = get_dmabuf_extensions();
|
||||||
|
|
||||||
let (physical_device, my_extensions, queue_family_index_gfx, queue_family_index_xfer) =
|
let (physical_device, my_extensions, queue_families) = instance
|
||||||
instance
|
.enumerate_physical_devices()?
|
||||||
.enumerate_physical_devices()?
|
.filter_map(|p| {
|
||||||
.filter_map(|p| {
|
let mut my_extensions = vk_device_extensions_fn(&p);
|
||||||
let mut my_extensions = vk_device_extensions_fn(&p);
|
|
||||||
|
|
||||||
if !p.supported_extensions().contains(&my_extensions) {
|
|
||||||
log::debug!(
|
|
||||||
"Not using {} due to missing extensions:",
|
|
||||||
p.properties().device_name,
|
|
||||||
);
|
|
||||||
for (ext, missing) in p.supported_extensions().difference(&my_extensions) {
|
|
||||||
if missing {
|
|
||||||
log::debug!(" {ext}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.supported_extensions().contains(&dmabuf_extensions) {
|
|
||||||
my_extensions = my_extensions.union(&dmabuf_extensions);
|
|
||||||
my_extensions.ext_image_drm_format_modifier =
|
|
||||||
p.supported_extensions().ext_image_drm_format_modifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.supported_extensions().ext_filter_cubic {
|
|
||||||
my_extensions.ext_filter_cubic = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if !p.supported_extensions().contains(&my_extensions) {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Device exts for {}: {:?}",
|
"Not using {} due to missing extensions:",
|
||||||
p.properties().device_name,
|
p.properties().device_name,
|
||||||
&my_extensions
|
|
||||||
);
|
);
|
||||||
Some((p, my_extensions))
|
for (ext, missing) in p.supported_extensions().difference(&my_extensions) {
|
||||||
})
|
if missing {
|
||||||
.filter_map(|(p, my_extensions)| {
|
log::debug!(" {ext}");
|
||||||
p.queue_family_properties()
|
}
|
||||||
.iter()
|
}
|
||||||
.enumerate()
|
return None;
|
||||||
.position(|(_, q)| q.queue_flags.intersects(QueueFlags::GRAPHICS))
|
}
|
||||||
.map(|i| (p, my_extensions, i as u32))
|
|
||||||
})
|
if p.supported_extensions().contains(&dmabuf_extensions) {
|
||||||
.filter_map(|(p, my_extensions, queue_family_index)| {
|
my_extensions = my_extensions.union(&dmabuf_extensions);
|
||||||
p.queue_family_properties()
|
my_extensions.ext_image_drm_format_modifier =
|
||||||
.iter()
|
p.supported_extensions().ext_image_drm_format_modifier;
|
||||||
.enumerate()
|
}
|
||||||
.position(|(_, q)| q.queue_flags.intersects(QueueFlags::TRANSFER))
|
|
||||||
.map(|i| (p, my_extensions, queue_family_index, i as u32))
|
if p.supported_extensions().ext_filter_cubic {
|
||||||
})
|
my_extensions.ext_filter_cubic = true;
|
||||||
.min_by_key(|(p, _, _, _)| match p.properties().device_type {
|
}
|
||||||
PhysicalDeviceType::DiscreteGpu => 0,
|
|
||||||
PhysicalDeviceType::IntegratedGpu => 1,
|
log::debug!(
|
||||||
PhysicalDeviceType::VirtualGpu => 2,
|
"Device exts for {}: {:?}",
|
||||||
PhysicalDeviceType::Cpu => 3,
|
p.properties().device_name,
|
||||||
PhysicalDeviceType::Other => 4,
|
&my_extensions
|
||||||
_ => 5,
|
);
|
||||||
})
|
Some((p, my_extensions))
|
||||||
.expect("no suitable physical device found");
|
})
|
||||||
|
.filter_map(|(p, my_extensions)| {
|
||||||
|
try_all_queue_families(p.as_ref()).map(|families| (p, my_extensions, families))
|
||||||
|
})
|
||||||
|
.min_by_key(|(p, _, families)| {
|
||||||
|
prio_from_device_type(p) * 10 + prio_from_families(families)
|
||||||
|
})
|
||||||
|
.expect("no suitable physical device found");
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"Using vkPhysicalDevice: {}",
|
"Using vkPhysicalDevice: {}",
|
||||||
@@ -530,7 +475,7 @@ impl WlxGraphics {
|
|||||||
Filter::Linear
|
Filter::Linear
|
||||||
};
|
};
|
||||||
|
|
||||||
let (device, mut queues) = Device::new(
|
let (device, queues) = Device::new(
|
||||||
physical_device,
|
physical_device,
|
||||||
DeviceCreateInfo {
|
DeviceCreateInfo {
|
||||||
enabled_extensions: my_extensions,
|
enabled_extensions: my_extensions,
|
||||||
@@ -538,23 +483,14 @@ impl WlxGraphics {
|
|||||||
dynamic_rendering: true,
|
dynamic_rendering: true,
|
||||||
..DeviceFeatures::empty()
|
..DeviceFeatures::empty()
|
||||||
},
|
},
|
||||||
queue_create_infos: vec![
|
queue_create_infos: queue_families
|
||||||
QueueCreateInfo {
|
.iter()
|
||||||
queue_family_index: queue_family_index_gfx,
|
.map(|fam| QueueCreateInfo {
|
||||||
queues: vec![1.0],
|
queue_family_index: fam.queue_family_index,
|
||||||
|
queues: fam.priorities.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
})
|
||||||
QueueCreateInfo {
|
.collect::<Vec<_>>(),
|
||||||
queue_family_index: queue_family_index_xfer,
|
|
||||||
queues: vec![1.0],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
QueueCreateInfo {
|
|
||||||
queue_family_index: queue_family_index_xfer,
|
|
||||||
queues: vec![1.0],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
@@ -568,15 +504,7 @@ impl WlxGraphics {
|
|||||||
device.enabled_extensions().ext_image_drm_format_modifier
|
device.enabled_extensions().ext_image_drm_format_modifier
|
||||||
);
|
);
|
||||||
|
|
||||||
let graphics_queue = queues
|
let (graphics_queue, transfer_queue, capture_queue) = unwrap_queues(queues.collect());
|
||||||
.next()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("no graphics queues available"))?;
|
|
||||||
let transfer_queue = queues
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("no transfer queues available"))?;
|
|
||||||
let capture_queue = queues
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("no transfer queues available"))?;
|
|
||||||
|
|
||||||
let memory_allocator = memory_allocator(device.clone());
|
let memory_allocator = memory_allocator(device.clone());
|
||||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||||
@@ -624,7 +552,6 @@ impl WlxGraphics {
|
|||||||
)> {
|
)> {
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
descriptor_set::allocator::StandardDescriptorSetAllocatorCreateInfo,
|
descriptor_set::allocator::StandardDescriptorSetAllocatorCreateInfo,
|
||||||
device::physical::PhysicalDeviceType,
|
|
||||||
instance::InstanceCreateFlags,
|
instance::InstanceCreateFlags,
|
||||||
swapchain::{Surface, SurfaceInfo},
|
swapchain::{Surface, SurfaceInfo},
|
||||||
};
|
};
|
||||||
@@ -657,7 +584,7 @@ impl WlxGraphics {
|
|||||||
|
|
||||||
log::debug!("Device exts for app: {:?}", &device_extensions);
|
log::debug!("Device exts for app: {:?}", &device_extensions);
|
||||||
|
|
||||||
let (physical_device, my_extensions, queue_family_index) = instance
|
let (physical_device, my_extensions, queue_families) = instance
|
||||||
.enumerate_physical_devices()?
|
.enumerate_physical_devices()?
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
if p.supported_extensions().contains(&device_extensions) {
|
if p.supported_extensions().contains(&device_extensions) {
|
||||||
@@ -675,22 +602,11 @@ impl WlxGraphics {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|(p, my_extensions)| {
|
.filter_map(|(p, my_extensions)|
|
||||||
p.queue_family_properties()
|
try_all_queue_families(p.as_ref()).map(|families| (p, my_extensions, families))
|
||||||
.iter()
|
)
|
||||||
.enumerate()
|
.min_by_key(|(p, _, _)| prio_from_device_type(p)
|
||||||
.position(|(i, q)| q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
)
|
||||||
&& p.surface_support(i as u32, &surface).unwrap_or(false))
|
|
||||||
.map(|i| (p, my_extensions, i as u32))
|
|
||||||
})
|
|
||||||
.min_by_key(|(p, _, _)| match p.properties().device_type {
|
|
||||||
PhysicalDeviceType::DiscreteGpu => 0,
|
|
||||||
PhysicalDeviceType::IntegratedGpu => 1,
|
|
||||||
PhysicalDeviceType::VirtualGpu => 2,
|
|
||||||
PhysicalDeviceType::Cpu => 3,
|
|
||||||
PhysicalDeviceType::Other => 4,
|
|
||||||
_ => 5,
|
|
||||||
})
|
|
||||||
.expect("no suitable physical device found");
|
.expect("no suitable physical device found");
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
@@ -698,7 +614,7 @@ impl WlxGraphics {
|
|||||||
physical_device.properties().device_name,
|
physical_device.properties().device_name,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (device, mut queues) = Device::new(
|
let (device, queues) = Device::new(
|
||||||
physical_device,
|
physical_device,
|
||||||
DeviceCreateInfo {
|
DeviceCreateInfo {
|
||||||
enabled_extensions: my_extensions,
|
enabled_extensions: my_extensions,
|
||||||
@@ -706,14 +622,20 @@ impl WlxGraphics {
|
|||||||
dynamic_rendering: true,
|
dynamic_rendering: true,
|
||||||
..DeviceFeatures::empty()
|
..DeviceFeatures::empty()
|
||||||
},
|
},
|
||||||
queue_create_infos: vec![QueueCreateInfo {
|
queue_create_infos: queue_families
|
||||||
queue_family_index,
|
.iter()
|
||||||
..Default::default()
|
.map(|fam| QueueCreateInfo {
|
||||||
}],
|
queue_family_index: fam.queue_family_index,
|
||||||
|
queues: fam.priorities.clone(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let (graphics_queue, transfer_queue, capture_queue) = unwrap_queues(queues.collect());
|
||||||
|
|
||||||
let native_format = device
|
let native_format = device
|
||||||
.physical_device()
|
.physical_device()
|
||||||
.surface_formats(&surface, SurfaceInfo::default())
|
.surface_formats(&surface, SurfaceInfo::default())
|
||||||
@@ -721,10 +643,6 @@ impl WlxGraphics {
|
|||||||
.0;
|
.0;
|
||||||
log::info!("Using surface format: {native_format:?}");
|
log::info!("Using surface format: {native_format:?}");
|
||||||
|
|
||||||
let queue = queues
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("no GPU queues available"))?;
|
|
||||||
|
|
||||||
let memory_allocator = memory_allocator(device.clone());
|
let memory_allocator = memory_allocator(device.clone());
|
||||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||||
device.clone(),
|
device.clone(),
|
||||||
@@ -744,9 +662,9 @@ impl WlxGraphics {
|
|||||||
let me = Self {
|
let me = Self {
|
||||||
instance,
|
instance,
|
||||||
device,
|
device,
|
||||||
graphics_queue: queue.clone(),
|
graphics_queue,
|
||||||
transfer_queue: queue.clone(), // what could go wrong!
|
transfer_queue,
|
||||||
capture_queue: queue,
|
capture_queue,
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
native_format,
|
native_format,
|
||||||
texture_filtering: Filter::Linear,
|
texture_filtering: Filter::Linear,
|
||||||
@@ -1076,34 +994,17 @@ impl WlxGraphics {
|
|||||||
/// Creates a CommandBuffer to be used for texture uploads on the main thread.
|
/// Creates a CommandBuffer to be used for texture uploads on the main thread.
|
||||||
pub fn create_uploads_command_buffer(
|
pub fn create_uploads_command_buffer(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
|
queue: Arc<Queue>,
|
||||||
usage: CommandBufferUsage,
|
usage: CommandBufferUsage,
|
||||||
) -> anyhow::Result<WlxUploadsBuffer> {
|
) -> anyhow::Result<WlxUploadsBuffer> {
|
||||||
let command_buffer = AutoCommandBufferBuilder::primary(
|
let command_buffer = AutoCommandBufferBuilder::primary(
|
||||||
self.command_buffer_allocator.clone(),
|
self.command_buffer_allocator.clone(),
|
||||||
self.transfer_queue.queue_family_index(),
|
queue.queue_family_index(),
|
||||||
usage,
|
usage,
|
||||||
)?;
|
)?;
|
||||||
Ok(WlxUploadsBuffer {
|
Ok(WlxUploadsBuffer {
|
||||||
graphics: self.clone(),
|
graphics: self.clone(),
|
||||||
queue: self.transfer_queue.clone(),
|
queue,
|
||||||
command_buffer,
|
|
||||||
dummy: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a CommandBuffer to be used for texture uploads on the capture thread.
|
|
||||||
pub fn create_capture_command_buffer(
|
|
||||||
self: &Arc<Self>,
|
|
||||||
usage: CommandBufferUsage,
|
|
||||||
) -> anyhow::Result<WlxUploadsBuffer> {
|
|
||||||
let command_buffer = AutoCommandBufferBuilder::primary(
|
|
||||||
self.command_buffer_allocator.clone(),
|
|
||||||
self.capture_queue.queue_family_index(),
|
|
||||||
usage,
|
|
||||||
)?;
|
|
||||||
Ok(WlxUploadsBuffer {
|
|
||||||
graphics: self.clone(),
|
|
||||||
queue: self.capture_queue.clone(),
|
|
||||||
command_buffer,
|
command_buffer,
|
||||||
dummy: None,
|
dummy: None,
|
||||||
})
|
})
|
||||||
@@ -1577,3 +1478,103 @@ fn memory_allocator(device: Arc<Device>) -> Arc<StandardMemoryAllocator> {
|
|||||||
|
|
||||||
Arc::new(StandardMemoryAllocator::new(device, create_info))
|
Arc::new(StandardMemoryAllocator::new(device, create_info))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct QueueFamilyLayout {
|
||||||
|
queue_family_index: u32,
|
||||||
|
priorities: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prio_from_device_type(physical_device: &PhysicalDevice) -> u32 {
|
||||||
|
match physical_device.properties().device_type {
|
||||||
|
PhysicalDeviceType::DiscreteGpu => 0,
|
||||||
|
PhysicalDeviceType::IntegratedGpu => 1,
|
||||||
|
PhysicalDeviceType::VirtualGpu => 2,
|
||||||
|
PhysicalDeviceType::Cpu => 3,
|
||||||
|
_ => 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn prio_from_families(families: &[QueueFamilyLayout]) -> u32 {
|
||||||
|
match families.len() {
|
||||||
|
2 | 3 => 0,
|
||||||
|
_ => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwrap_queues(queues: Vec<Arc<Queue>>) -> (Arc<Queue>, Arc<Queue>, Option<Arc<Queue>>) {
|
||||||
|
match queues[..] {
|
||||||
|
[ref g, ref t, ref c] => (g.clone(), t.clone(), Some(c.clone())),
|
||||||
|
[ref gt, ref c] => (gt.clone(), gt.clone(), Some(c.clone())),
|
||||||
|
[ref gt] => (gt.clone(), gt.clone(), None),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_all_queue_families(physical_device: &PhysicalDevice) -> Option<Vec<QueueFamilyLayout>> {
|
||||||
|
queue_families_priorities(
|
||||||
|
physical_device,
|
||||||
|
vec![
|
||||||
|
// main-thread graphics + uploads
|
||||||
|
QueueFlags::GRAPHICS | QueueFlags::TRANSFER,
|
||||||
|
// capture-thread uploads
|
||||||
|
QueueFlags::TRANSFER,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.or_else(|| {
|
||||||
|
queue_families_priorities(
|
||||||
|
physical_device,
|
||||||
|
vec![
|
||||||
|
// main thread graphics
|
||||||
|
QueueFlags::GRAPHICS,
|
||||||
|
// main thread uploads
|
||||||
|
QueueFlags::TRANSFER,
|
||||||
|
// capture thread uploads
|
||||||
|
QueueFlags::TRANSFER,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
queue_families_priorities(
|
||||||
|
physical_device,
|
||||||
|
// main thread-only. software capture not supported.
|
||||||
|
vec![QueueFlags::GRAPHICS | QueueFlags::TRANSFER],
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn queue_families_priorities(
|
||||||
|
physical_device: &PhysicalDevice,
|
||||||
|
mut requested_queues: Vec<QueueFlags>,
|
||||||
|
) -> Option<Vec<QueueFamilyLayout>> {
|
||||||
|
let mut result = Vec::with_capacity(3);
|
||||||
|
|
||||||
|
for (idx, props) in physical_device.queue_family_properties().iter().enumerate() {
|
||||||
|
let mut remaining = props.queue_count;
|
||||||
|
let mut want = 0usize;
|
||||||
|
|
||||||
|
requested_queues.retain(|requested| {
|
||||||
|
if props.queue_flags.intersects(*requested) && remaining > 0 {
|
||||||
|
remaining -= 1;
|
||||||
|
want += 1;
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if want > 0 {
|
||||||
|
result.push(QueueFamilyLayout {
|
||||||
|
queue_family_index: idx as u32,
|
||||||
|
priorities: std::iter::repeat_n(1.0, want).collect(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if requested_queues.is_empty() {
|
||||||
|
log::debug!("Selected GPU queue families: {result:?}");
|
||||||
|
Some(result)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -240,8 +240,10 @@ impl FontCache {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if cmd_buffer.is_none() {
|
if cmd_buffer.is_none() {
|
||||||
*cmd_buffer =
|
*cmd_buffer = Some(graphics.create_uploads_command_buffer(
|
||||||
Some(graphics.create_uploads_command_buffer(CommandBufferUsage::OneTimeSubmit)?);
|
graphics.transfer_queue.clone(),
|
||||||
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let texture = cmd_buffer.as_mut().unwrap().texture2d_raw(
|
let texture = cmd_buffer.as_mut().unwrap().texture2d_raw(
|
||||||
|
|||||||
@@ -552,9 +552,10 @@ fn sprite_from_path(path: Arc<str>, app: &mut AppState) -> anyhow::Result<Arc<Im
|
|||||||
anyhow::bail!("Could not open custom sprite at: {}", path);
|
anyhow::bail!("Could not open custom sprite at: {}", path);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut command_buffer = app
|
let mut command_buffer = app.graphics.create_uploads_command_buffer(
|
||||||
.graphics
|
app.graphics.transfer_queue.clone(),
|
||||||
.create_uploads_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)?;
|
||||||
|
|
||||||
match command_buffer.texture2d_dds(f) {
|
match command_buffer.texture2d_dds(f) {
|
||||||
Ok(image) => {
|
Ok(image) => {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
command_buffer::CommandBufferUsage,
|
command_buffer::CommandBufferUsage,
|
||||||
|
device::Queue,
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{sampler::Filter, view::ImageView, Image},
|
image::{sampler::Filter, view::ImageView, Image},
|
||||||
pipeline::graphics::color_blend::AttachmentBlend,
|
pipeline::graphics::color_blend::AttachmentBlend,
|
||||||
@@ -258,6 +259,16 @@ impl ScreenPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! new_wlx_capture {
|
||||||
|
($capture_queue:expr, $capture:expr) => {
|
||||||
|
if $capture_queue.is_none() {
|
||||||
|
Box::new(MainThreadWlxCapture::new($capture)) as Box<dyn WlxCapture<_, _>>
|
||||||
|
} else {
|
||||||
|
Box::new($capture) as Box<dyn WlxCapture<_, _>>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ScreenRenderer {
|
pub struct ScreenRenderer {
|
||||||
name: Arc<str>,
|
name: Arc<str>,
|
||||||
capture: Box<dyn WlxCapture<WlxCaptureIn, WlxCaptureOut>>,
|
capture: Box<dyn WlxCapture<WlxCaptureIn, WlxCaptureOut>>,
|
||||||
@@ -282,41 +293,33 @@ impl ScreenRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub fn new_wlr_dmabuf(output: &WlxOutput) -> Option<Self> {
|
pub fn new_wlr_dmabuf(output: &WlxOutput, app: &AppState) -> Option<Self> {
|
||||||
let client = WlxClient::new()?;
|
let client = WlxClient::new()?;
|
||||||
let capture = WlrDmabufCapture::new(client, output.id);
|
let capture = new_wlx_capture!(
|
||||||
|
app.graphics.capture_queue,
|
||||||
Some(Self {
|
WlrDmabufCapture::new(client, output.id)
|
||||||
name: output.name.clone(),
|
);
|
||||||
capture: Box::new(capture),
|
Some(Self::new_raw(output.name.clone(), capture))
|
||||||
pipeline: None,
|
|
||||||
cur_frame: None,
|
|
||||||
meta: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub fn new_wlr_screencopy(output: &WlxOutput) -> Option<Self> {
|
pub fn new_wlr_screencopy(output: &WlxOutput, app: &AppState) -> Option<Self> {
|
||||||
let client = WlxClient::new()?;
|
let client = WlxClient::new()?;
|
||||||
let capture = WlrScreencopyCapture::new(client, output.id);
|
let capture = new_wlx_capture!(
|
||||||
|
app.graphics.capture_queue,
|
||||||
Some(Self {
|
WlrScreencopyCapture::new(client, output.id)
|
||||||
name: output.name.clone(),
|
);
|
||||||
capture: Box::new(capture),
|
Some(Self::new_raw(output.name.clone(), capture))
|
||||||
pipeline: None,
|
|
||||||
cur_frame: None,
|
|
||||||
meta: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub fn new_pw(
|
pub fn new_pw(
|
||||||
output: &WlxOutput,
|
output: &WlxOutput,
|
||||||
token: Option<&str>,
|
token: Option<&str>,
|
||||||
session: &AppSession,
|
app: &AppState,
|
||||||
) -> anyhow::Result<(Self, Option<String> /* pipewire restore token */)> {
|
) -> anyhow::Result<(Self, Option<String> /* pipewire restore token */)> {
|
||||||
let name = output.name.clone();
|
let name = output.name.clone();
|
||||||
let embed_mouse = !session.config.double_cursor_fix;
|
let embed_mouse = !app.session.config.double_cursor_fix;
|
||||||
|
|
||||||
let select_screen_result = select_pw_screen(
|
let select_screen_result = select_pw_screen(
|
||||||
&format!(
|
&format!(
|
||||||
@@ -336,31 +339,21 @@ impl ScreenRenderer {
|
|||||||
|
|
||||||
let node_id = select_screen_result.streams.first().unwrap().node_id; // streams guaranteed to have at least one element
|
let node_id = select_screen_result.streams.first().unwrap().node_id; // streams guaranteed to have at least one element
|
||||||
|
|
||||||
let capture = PipewireCapture::new(name, node_id);
|
let capture = new_wlx_capture!(
|
||||||
|
app.graphics.capture_queue,
|
||||||
|
PipewireCapture::new(name, node_id)
|
||||||
|
);
|
||||||
Ok((
|
Ok((
|
||||||
Self {
|
Self::new_raw(output.name.clone(), capture),
|
||||||
name: output.name.clone(),
|
|
||||||
capture: Box::new(capture),
|
|
||||||
pipeline: None,
|
|
||||||
cur_frame: None,
|
|
||||||
meta: None,
|
|
||||||
},
|
|
||||||
select_screen_result.restore_token,
|
select_screen_result.restore_token,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
pub fn new_xshm(screen: Arc<XshmScreen>) -> Self {
|
pub fn new_xshm(screen: Arc<XshmScreen>, app: &AppState) -> Self {
|
||||||
let capture = XshmCapture::new(screen.clone());
|
let capture =
|
||||||
|
new_wlx_capture!(app.graphics.capture_queue, XshmCapture::new(screen.clone()));
|
||||||
Self {
|
Self::new_raw(screen.name.clone(), capture)
|
||||||
name: screen.name.clone(),
|
|
||||||
capture: Box::new(capture),
|
|
||||||
pipeline: None,
|
|
||||||
cur_frame: None,
|
|
||||||
meta: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,6 +361,7 @@ impl ScreenRenderer {
|
|||||||
pub struct WlxCaptureIn {
|
pub struct WlxCaptureIn {
|
||||||
name: Arc<str>,
|
name: Arc<str>,
|
||||||
graphics: Arc<WlxGraphics>,
|
graphics: Arc<WlxGraphics>,
|
||||||
|
queue: Arc<Queue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -386,7 +380,7 @@ fn upload_image(
|
|||||||
) -> Option<Arc<Image>> {
|
) -> Option<Arc<Image>> {
|
||||||
let mut upload = match me
|
let mut upload = match me
|
||||||
.graphics
|
.graphics
|
||||||
.create_capture_command_buffer(CommandBufferUsage::OneTimeSubmit)
|
.create_uploads_command_buffer(me.queue.clone(), CommandBufferUsage::OneTimeSubmit)
|
||||||
{
|
{
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -518,9 +512,15 @@ impl OverlayRenderer for ScreenRenderer {
|
|||||||
|
|
||||||
let dmabuf_formats = if !supports_dmabuf {
|
let dmabuf_formats = if !supports_dmabuf {
|
||||||
log::info!("Capture method does not support DMA-buf");
|
log::info!("Capture method does not support DMA-buf");
|
||||||
|
if app.graphics.capture_queue.is_none() {
|
||||||
|
log::warn!("Current GPU does not support multiple queues. Software capture will take place on the main thread. Expect degraded performance.");
|
||||||
|
}
|
||||||
&Vec::new()
|
&Vec::new()
|
||||||
} else if !allow_dmabuf {
|
} else if !allow_dmabuf {
|
||||||
log::info!("Not using DMA-buf capture due to {capture_method}");
|
log::info!("Not using DMA-buf capture due to {capture_method}");
|
||||||
|
if app.graphics.capture_queue.is_none() {
|
||||||
|
log::warn!("Current GPU does not support multiple queues. Software capture will take place on the main thread. Expect degraded performance.");
|
||||||
|
}
|
||||||
&Vec::new()
|
&Vec::new()
|
||||||
} else {
|
} else {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
@@ -534,6 +534,12 @@ impl OverlayRenderer for ScreenRenderer {
|
|||||||
let user_data = WlxCaptureIn {
|
let user_data = WlxCaptureIn {
|
||||||
name: self.name.clone(),
|
name: self.name.clone(),
|
||||||
graphics: app.graphics.clone(),
|
graphics: app.graphics.clone(),
|
||||||
|
queue: app
|
||||||
|
.graphics
|
||||||
|
.capture_queue
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or_else(|| &app.graphics.transfer_queue)
|
||||||
|
.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.capture
|
self.capture
|
||||||
@@ -554,9 +560,10 @@ impl OverlayRenderer for ScreenRenderer {
|
|||||||
});
|
});
|
||||||
self.pipeline = Some({
|
self.pipeline = Some({
|
||||||
let mut pipeline = ScreenPipeline::new(&capture.image.extent(), app)?;
|
let mut pipeline = ScreenPipeline::new(&capture.image.extent(), app)?;
|
||||||
let mut upload = app
|
let mut upload = app.graphics.create_uploads_command_buffer(
|
||||||
.graphics
|
app.graphics.transfer_queue.clone(),
|
||||||
.create_uploads_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)?;
|
||||||
pipeline.ensure_mouse_initialized(&mut upload)?;
|
pipeline.ensure_mouse_initialized(&mut upload)?;
|
||||||
upload.build_and_execute_now()?;
|
upload.build_and_execute_now()?;
|
||||||
pipeline
|
pipeline
|
||||||
@@ -613,17 +620,17 @@ pub fn create_screen_renderer_wl(
|
|||||||
has_wlr_dmabuf: bool,
|
has_wlr_dmabuf: bool,
|
||||||
has_wlr_screencopy: bool,
|
has_wlr_screencopy: bool,
|
||||||
pw_token_store: &mut PwTokenMap,
|
pw_token_store: &mut PwTokenMap,
|
||||||
session: &AppSession,
|
app: &AppState,
|
||||||
) -> Option<ScreenRenderer> {
|
) -> Option<ScreenRenderer> {
|
||||||
let mut capture: Option<ScreenRenderer> = None;
|
let mut capture: Option<ScreenRenderer> = None;
|
||||||
if (&*session.config.capture_method == "wlr-dmabuf") && has_wlr_dmabuf {
|
if (&*app.session.config.capture_method == "wlr-dmabuf") && has_wlr_dmabuf {
|
||||||
log::info!("{}: Using Wlr DMA-Buf", &output.name);
|
log::info!("{}: Using Wlr DMA-Buf", &output.name);
|
||||||
capture = ScreenRenderer::new_wlr_dmabuf(output);
|
capture = ScreenRenderer::new_wlr_dmabuf(output, app);
|
||||||
}
|
}
|
||||||
|
|
||||||
if &*session.config.capture_method == "screencopy" && has_wlr_screencopy {
|
if &*app.session.config.capture_method == "screencopy" && has_wlr_screencopy {
|
||||||
log::info!("{}: Using Wlr Screencopy Wl-SHM", &output.name);
|
log::info!("{}: Using Wlr Screencopy Wl-SHM", &output.name);
|
||||||
capture = ScreenRenderer::new_wlr_screencopy(output);
|
capture = ScreenRenderer::new_wlr_screencopy(output, app);
|
||||||
}
|
}
|
||||||
|
|
||||||
if capture.is_none() {
|
if capture.is_none() {
|
||||||
@@ -640,7 +647,7 @@ pub fn create_screen_renderer_wl(
|
|||||||
log::info!("Found existing Pipewire token for display {display_name}: {t}");
|
log::info!("Found existing Pipewire token for display {display_name}: {t}");
|
||||||
}
|
}
|
||||||
|
|
||||||
match ScreenRenderer::new_pw(output, token, session) {
|
match ScreenRenderer::new_pw(output, token, app) {
|
||||||
Ok((renderer, restore_token)) => {
|
Ok((renderer, restore_token)) => {
|
||||||
capture = Some(renderer);
|
capture = Some(renderer);
|
||||||
|
|
||||||
@@ -793,7 +800,7 @@ pub fn create_screens_wayland(wl: &mut WlxClientAlias, app: &mut AppState) -> Sc
|
|||||||
has_wlr_dmabuf,
|
has_wlr_dmabuf,
|
||||||
has_wlr_screencopy,
|
has_wlr_screencopy,
|
||||||
&mut pw_tokens,
|
&mut pw_tokens,
|
||||||
&app.session,
|
app,
|
||||||
) {
|
) {
|
||||||
let logical_pos = vec2(output.logical_pos.0 as f32, output.logical_pos.1 as f32);
|
let logical_pos = vec2(output.logical_pos.0 as f32, output.logical_pos.1 as f32);
|
||||||
let logical_size = vec2(output.logical_size.0 as f32, output.logical_size.1 as f32);
|
let logical_size = vec2(output.logical_size.0 as f32, output.logical_size.1 as f32);
|
||||||
@@ -910,13 +917,13 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateDa
|
|||||||
native_handle: 0,
|
native_handle: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let renderer = ScreenRenderer {
|
let renderer = ScreenRenderer::new_raw(
|
||||||
name: m.name.clone(),
|
m.name.clone(),
|
||||||
capture: Box::new(PipewireCapture::new(m.name.clone(), s.node_id)),
|
new_wlx_capture!(
|
||||||
pipeline: None,
|
app.graphics.capture_queue,
|
||||||
cur_frame: None,
|
PipewireCapture::new(m.name.clone(), s.node_id)
|
||||||
meta: None,
|
),
|
||||||
};
|
);
|
||||||
|
|
||||||
let backend = Box::new(SplitOverlayBackend {
|
let backend = Box::new(SplitOverlayBackend {
|
||||||
renderer: Box::new(renderer),
|
renderer: Box::new(renderer),
|
||||||
@@ -953,7 +960,7 @@ pub fn create_screens_xshm(app: &mut AppState) -> anyhow::Result<ScreenCreateDat
|
|||||||
|
|
||||||
let size = (s.monitor.width(), s.monitor.height());
|
let size = (s.monitor.width(), s.monitor.height());
|
||||||
let pos = (s.monitor.x(), s.monitor.y());
|
let pos = (s.monitor.x(), s.monitor.y());
|
||||||
let renderer = ScreenRenderer::new_xshm(s.clone());
|
let renderer = ScreenRenderer::new_xshm(s.clone(), app);
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"{}: Init X11 screen of res {:?} at {:?}",
|
"{}: Init X11 screen of res {:?} at {:?}",
|
||||||
@@ -1139,3 +1146,62 @@ fn select_pw_screen(
|
|||||||
|
|
||||||
futures::executor::block_on(future)
|
futures::executor::block_on(future)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used when a separate GPU queue is not available
|
||||||
|
// In this case, receive_callback needs to run on the main thread
|
||||||
|
struct MainThreadWlxCapture<T>
|
||||||
|
where
|
||||||
|
T: WlxCapture<(), WlxFrame>,
|
||||||
|
{
|
||||||
|
inner: T,
|
||||||
|
data: Option<WlxCaptureIn>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MainThreadWlxCapture<T>
|
||||||
|
where
|
||||||
|
T: WlxCapture<(), WlxFrame>,
|
||||||
|
{
|
||||||
|
pub const fn new(inner: T) -> Self {
|
||||||
|
Self { inner, data: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WlxCapture<WlxCaptureIn, WlxCaptureOut> for MainThreadWlxCapture<T>
|
||||||
|
where
|
||||||
|
T: WlxCapture<(), WlxFrame>,
|
||||||
|
{
|
||||||
|
fn init(
|
||||||
|
&mut self,
|
||||||
|
dmabuf_formats: &[wlx_frame::DrmFormat],
|
||||||
|
user_data: WlxCaptureIn,
|
||||||
|
_: fn(&WlxCaptureIn, WlxFrame) -> Option<WlxCaptureOut>,
|
||||||
|
) {
|
||||||
|
self.data = Some(user_data);
|
||||||
|
self.inner.init(dmabuf_formats, (), receive_callback_dummy);
|
||||||
|
}
|
||||||
|
fn is_ready(&self) -> bool {
|
||||||
|
self.inner.is_ready()
|
||||||
|
}
|
||||||
|
fn request_new_frame(&mut self) {
|
||||||
|
self.inner.request_new_frame();
|
||||||
|
}
|
||||||
|
fn pause(&mut self) {
|
||||||
|
self.inner.pause();
|
||||||
|
}
|
||||||
|
fn resume(&mut self) {
|
||||||
|
self.inner.resume();
|
||||||
|
}
|
||||||
|
fn receive(&mut self) -> Option<WlxCaptureOut> {
|
||||||
|
self.inner
|
||||||
|
.receive()
|
||||||
|
.and_then(|frame| receive_callback(self.data.as_ref().unwrap(), frame))
|
||||||
|
}
|
||||||
|
fn supports_dmbuf(&self) -> bool {
|
||||||
|
self.inner.supports_dmbuf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::trivially_copy_pass_by_ref, clippy::unnecessary_wraps)]
|
||||||
|
const fn receive_callback_dummy(_: &(), frame: wlx_frame::WlxFrame) -> Option<wlx_frame::WlxFrame> {
|
||||||
|
Some(frame)
|
||||||
|
}
|
||||||
|
|||||||
@@ -565,9 +565,10 @@ impl WayVRRenderer {
|
|||||||
&mut self,
|
&mut self,
|
||||||
data: &wayvr::egl_data::RenderSoftwarePixelsData,
|
data: &wayvr::egl_data::RenderSoftwarePixelsData,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut upload = self
|
let mut upload = self.graphics.create_uploads_command_buffer(
|
||||||
.graphics
|
self.graphics.transfer_queue.clone(),
|
||||||
.create_uploads_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)?;
|
||||||
|
|
||||||
let tex = upload.texture2d_raw(
|
let tex = upload.texture2d_raw(
|
||||||
u32::from(data.width),
|
u32::from(data.width),
|
||||||
@@ -702,7 +703,6 @@ impl OverlayRenderer for WayVRRenderer {
|
|||||||
drop(ctx);
|
drop(ctx);
|
||||||
|
|
||||||
match data {
|
match data {
|
||||||
//TODO: render to _tgt_
|
|
||||||
wayvr::egl_data::RenderData::Dmabuf(data) => {
|
wayvr::egl_data::RenderData::Dmabuf(data) => {
|
||||||
self.ensure_dmabuf_data(&data)?;
|
self.ensure_dmabuf_data(&data)?;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user