fix dmabuf display

This commit is contained in:
galister
2024-02-01 03:20:27 +01:00
parent c0c74d7f2d
commit 07f21765b9
2 changed files with 49 additions and 110 deletions

View File

@@ -17,6 +17,7 @@ use vulkano::{
allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo}, allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo},
Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
}, },
command_buffer::CommandBufferInheritanceRenderingInfo,
command_buffer::{ command_buffer::{
allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo}, allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo},
sys::{CommandBufferBeginInfo, RawRecordingCommandBuffer}, sys::{CommandBufferBeginInfo, RawRecordingCommandBuffer},
@@ -43,6 +44,7 @@ use vulkano::{
Image, ImageCreateInfo, ImageLayout, ImageTiling, ImageType, ImageUsage, SampleCount, Image, ImageCreateInfo, ImageLayout, ImageTiling, ImageType, ImageUsage, SampleCount,
SubresourceLayout, SubresourceLayout,
}, },
instance::InstanceCreateFlags,
instance::InstanceExtensions, instance::InstanceExtensions,
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo},
memory::{ memory::{
@@ -73,15 +75,13 @@ use vulkano::{
SubpassDescription, SubpassDescription,
}, },
shader::ShaderModule, shader::ShaderModule,
swapchain::Surface,
sync::{ sync::{
fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, GpuFuture, fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, GpuFuture,
ImageMemoryBarrier, PipelineStages, ImageMemoryBarrier, PipelineStages,
}, },
DeviceSize, VulkanLibrary, VulkanObject, DeviceSize, VulkanLibrary, VulkanObject,
}; };
use vulkano::{
command_buffer::CommandBufferInheritanceRenderingInfo, instance::InstanceCreateFlags,
};
use wlx_capture::frame::{ use wlx_capture::frame::{
DmabufFrame, FourCC, DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_XBGR8888, DmabufFrame, FourCC, DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_XBGR8888,
@@ -124,6 +124,22 @@ impl WlxGraphics {
use ash::vk::PhysicalDeviceDynamicRenderingFeatures; use ash::vk::PhysicalDeviceDynamicRenderingFeatures;
use vulkano::Handle; use vulkano::Handle;
use winit::event_loop::EventLoop;
let event_loop = EventLoop::new().unwrap();
let instance_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance_extensions_raw = instance_extensions
.clone()
.into_iter()
.filter_map(|(name, enabled)| {
if enabled {
Some(ffi::CString::new(name).unwrap().into_raw() as *const c_char)
} else {
None
}
})
.collect::<Vec<_>>();
let vk_target_version = vk::make_api_version(0, 1, 3, 0); // Vulkan 1.1 guarantees multiview support let vk_target_version = vk::make_api_version(0, 1, 3, 0); // Vulkan 1.1 guarantees multiview support
let target_version = vulkano::Version::V1_3; let target_version = vulkano::Version::V1_3;
@@ -140,8 +156,10 @@ impl WlxGraphics {
.create_vulkan_instance( .create_vulkan_instance(
system, system,
std::mem::transmute(vk_entry.static_fn().get_instance_proc_addr), std::mem::transmute(vk_entry.static_fn().get_instance_proc_addr),
&vk::InstanceCreateInfo::builder().application_info(&vk_app_info) as *const _ &vk::InstanceCreateInfo::builder()
as *const _, .application_info(&vk_app_info)
.enabled_extension_names(&instance_extensions_raw)
as *const _ as *const _,
) )
.expect("XR error creating Vulkan instance") .expect("XR error creating Vulkan instance")
.map_err(vk::Result::from_raw) .map_err(vk::Result::from_raw)
@@ -151,6 +169,7 @@ impl WlxGraphics {
library, library,
ash::vk::Instance::from_raw(vk_instance as _), ash::vk::Instance::from_raw(vk_instance as _),
InstanceCreateInfo { InstanceCreateInfo {
enabled_extensions: instance_extensions,
..Default::default() ..Default::default()
}, },
) )
@@ -189,6 +208,7 @@ impl WlxGraphics {
.expect("Vulkan device has no graphics queue") as u32; .expect("Vulkan device has no graphics queue") as u32;
let device_extensions = DeviceExtensions { let device_extensions = DeviceExtensions {
khr_swapchain: true,
khr_external_memory: true, khr_external_memory: true,
khr_external_memory_fd: true, khr_external_memory_fd: true,
ext_external_memory_dma_buf: true, ext_external_memory_dma_buf: true,

View File

@@ -10,11 +10,7 @@ use std::{
sync::{mpsc::Receiver, Arc}, sync::{mpsc::Receiver, Arc},
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use vulkano::{ use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView};
command_buffer::CommandBufferUsage,
format::Format,
image::{sampler::Filter, view::ImageView, Image, ImageLayout},
};
use wlx_capture::{ use wlx_capture::{
frame::WlxFrame, frame::WlxFrame,
pipewire::{pipewire_select_screen, PipewireCapture}, pipewire::{pipewire_select_screen, PipewireCapture},
@@ -32,7 +28,7 @@ use crate::{
}, },
config::def_pw_tokens, config::def_pw_tokens,
config_io, config_io,
graphics::{fourcc_to_vk, WlxGraphics, WlxPipeline, WlxPipelineLegacy}, graphics::fourcc_to_vk,
hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT}, hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT},
state::{AppSession, AppState}, state::{AppSession, AppState},
}; };
@@ -107,91 +103,11 @@ impl InteractionHandler for ScreenInteractionHandler {
fn on_left(&mut self, _app: &mut AppState, _hand: usize) {} fn on_left(&mut self, _app: &mut AppState, _hand: usize) {}
} }
struct ScreenPipeline {
graphics: Arc<WlxGraphics>,
pipeline: Arc<WlxPipeline<WlxPipelineLegacy>>,
}
impl ScreenPipeline {
fn new(graphics: Arc<WlxGraphics>, extent: &[u32; 3]) -> Self {
let render_texture = graphics.render_texture(extent[0], extent[1], Format::R8G8B8A8_UNORM);
let view = ImageView::new_default(render_texture).unwrap();
let pipeline = {
let shaders = graphics.shared_shaders.read().unwrap();
graphics.create_pipeline_with_layouts(
view,
shaders.get("vert_common").unwrap().clone(),
shaders.get("frag_sprite").unwrap().clone(),
Format::R8G8B8A8_UNORM,
ImageLayout::TransferSrcOptimal,
ImageLayout::TransferSrcOptimal,
)
};
Self { graphics, pipeline }
}
fn render(&mut self, image: Arc<Image>) {
/*
self.graphics
.transition_layout(
self.pipeline.view.image().clone(),
ImageLayout::TransferSrcOptimal,
ImageLayout::ColorAttachmentOptimal,
)
.wait(None)
.unwrap();
*/
let mut command_buffer = self
.graphics
.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
command_buffer.begin_render_pass(&self.pipeline);
let set0 = self.pipeline.uniform_sampler(
0,
ImageView::new_default(image).unwrap(),
Filter::Linear,
);
let dim = self.pipeline.data.view.image().extent();
let pass = self.pipeline.create_pass(
[dim[0] as _, dim[1] as _],
self.graphics.quad_verts.clone(),
self.graphics.quad_indices.clone(),
vec![set0],
);
command_buffer.run_ref(&pass);
command_buffer.end_render_pass();
command_buffer.build_and_execute_now();
/*
self.graphics
.transition_layout(
self.pipeline.view.image().clone(),
ImageLayout::ColorAttachmentOptimal,
ImageLayout::TransferSrcOptimal,
)
.wait(None)
.unwrap();
*/
}
pub(super) fn view(&self) -> Arc<ImageView> {
self.pipeline.data.view.clone()
}
}
pub struct ScreenRenderer { pub struct ScreenRenderer {
name: Arc<str>, name: Arc<str>,
capture: Box<dyn WlxCapture>, capture: Box<dyn WlxCapture>,
receiver: Option<Receiver<WlxFrame>>, receiver: Option<Receiver<WlxFrame>>,
pipeline: Option<ScreenPipeline>, last_view: Option<Arc<ImageView>>,
last_image: Option<Arc<ImageView>>,
extent: [u32; 3], extent: [u32; 3],
} }
@@ -206,8 +122,7 @@ impl ScreenRenderer {
name: output.name.clone(), name: output.name.clone(),
capture: Box::new(capture), capture: Box::new(capture),
receiver: None, receiver: None,
pipeline: None, last_view: None,
last_image: None,
extent: extent_from_res(output.size), extent: extent_from_res(output.size),
}) })
} }
@@ -226,8 +141,7 @@ impl ScreenRenderer {
name: output.name.clone(), name: output.name.clone(),
capture: Box::new(capture), capture: Box::new(capture),
receiver: None, receiver: None,
pipeline: None, last_view: None,
last_image: None,
extent: extent_from_res(output.size), extent: extent_from_res(output.size),
}) })
} }
@@ -236,11 +150,14 @@ impl ScreenRenderer {
impl OverlayRenderer for ScreenRenderer { impl OverlayRenderer for ScreenRenderer {
fn init(&mut self, app: &mut AppState) { fn init(&mut self, app: &mut AppState) {
let images = app.graphics.shared_images.read().unwrap(); let images = app.graphics.shared_images.read().unwrap();
self.last_image = Some(images.get("fallback").unwrap().clone()); self.last_view = Some(images.get("fallback").unwrap().clone());
self.pipeline = Some(ScreenPipeline::new(app.graphics.clone(), &self.extent));
} }
fn render(&mut self, app: &mut AppState) { fn render(&mut self, app: &mut AppState) {
let receiver = self.receiver.get_or_insert_with(|| self.capture.init()); let receiver = self.receiver.get_or_insert_with(|| {
let rx = self.capture.init();
self.capture.request_new_frame();
rx
});
for frame in receiver.try_iter() { for frame in receiver.try_iter() {
match frame { match frame {
@@ -249,13 +166,14 @@ impl OverlayRenderer for ScreenRenderer {
log::error!("Invalid frame"); log::error!("Invalid frame");
continue; continue;
} }
if let (Some(new), Some(pipeline)) = if let Some(new) = app.graphics.dmabuf_texture(frame) {
(app.graphics.dmabuf_texture(frame), self.pipeline.as_mut()) log::info!("{}: New DMA-buf frame", self.name);
{
log::debug!("{}: New DMA-buf frame", self.name);
pipeline.render(new); let view = ImageView::new_default(new.clone()).unwrap();
self.last_image = Some(pipeline.view());
self.last_view = Some(view);
} else {
log::error!("{}: Failed to create DMA-buf texture", self.name);
} }
} }
WlxFrame::MemFd(frame) => { WlxFrame::MemFd(frame) => {
@@ -292,7 +210,8 @@ impl OverlayRenderer for ScreenRenderer {
unsafe { libc::munmap(map as *mut _, len) }; unsafe { libc::munmap(map as *mut _, len) };
self.last_image = Some(ImageView::new_default(image).unwrap()); self.last_view = Some(ImageView::new_default(image).unwrap());
self.capture.request_new_frame();
} }
WlxFrame::MemPtr(frame) => { WlxFrame::MemPtr(frame) => {
log::debug!("{}: New MemPtr frame", self.name); log::debug!("{}: New MemPtr frame", self.name);
@@ -308,12 +227,12 @@ impl OverlayRenderer for ScreenRenderer {
upload.texture2d(frame.format.width, frame.format.height, format, &data); upload.texture2d(frame.format.width, frame.format.height, format, &data);
upload.build_and_execute_now(); upload.build_and_execute_now();
self.last_image = Some(ImageView::new_default(image).unwrap()); self.last_view = Some(ImageView::new_default(image).unwrap());
self.capture.request_new_frame();
} }
_ => {} _ => {}
}; };
} }
self.capture.request_new_frame();
} }
fn pause(&mut self, _app: &mut AppState) { fn pause(&mut self, _app: &mut AppState) {
self.capture.pause(); self.capture.pause();
@@ -322,7 +241,7 @@ impl OverlayRenderer for ScreenRenderer {
self.capture.resume(); self.capture.resume();
} }
fn view(&mut self) -> Option<Arc<ImageView>> { fn view(&mut self) -> Option<Arc<ImageView>> {
self.last_image.take() self.last_view.take()
} }
fn extent(&self) -> [u32; 3] { fn extent(&self) -> [u32; 3] {
self.extent.clone() self.extent.clone()
@@ -514,7 +433,7 @@ fn extent_from_res(res: (i32, i32)) -> [u32; 3] {
// screens above a certain resolution will have severe aliasing // screens above a certain resolution will have severe aliasing
// TODO make dynamic. maybe don't go above HMD resolution? // TODO make dynamic. maybe don't go above HMD resolution?
let w = res.0.min(1920) as u32; let w = res.0.min(2560) as u32;
let h = (res.1 as f32 / res.0 as f32 * w as f32) as u32; let h = (res.1 as f32 / res.0 as f32 * w as f32) as u32;
[w, h, 1] [w, h, 1]
} }