refactor(waylan): WIP, use a basic bevy image for shm again
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -62,7 +62,7 @@ impl Buffer {
|
|||||||
) -> Option<Handle<Image>> {
|
) -> Option<Handle<Image>> {
|
||||||
tracing::debug!("Updating texture for buffer {:?}", self.id);
|
tracing::debug!("Updating texture for buffer {:?}", self.id);
|
||||||
match &self.backing {
|
match &self.backing {
|
||||||
BufferBacking::Shm(backing) => backing.update_tex(dmatexes, images),
|
BufferBacking::Shm(backing) => backing.update_tex(images),
|
||||||
BufferBacking::Dmabuf(backing) => backing.update_tex(dmatexes, images),
|
BufferBacking::Dmabuf(backing) => backing.update_tex(dmatexes, images),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,155 +1,20 @@
|
|||||||
use super::shm_pool::ShmPool;
|
use super::shm_pool::ShmPool;
|
||||||
use crate::wayland::{
|
|
||||||
RENDER_DEVICE,
|
|
||||||
vulkano_data::{VULKANO_CONTEXT, VulkanoContext},
|
|
||||||
};
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::{Assets, Handle},
|
asset::{Assets, Handle, RenderAssetUsages},
|
||||||
image::Image as BevyImage,
|
image::Image,
|
||||||
};
|
render::render_resource::{Extent3d, TextureDimension, TextureFormat},
|
||||||
use bevy_dmabuf::{
|
|
||||||
dmatex::{Dmatex, DmatexPlane, Resolution},
|
|
||||||
format_mapping::vk_format_to_drm_fourcc,
|
|
||||||
import::{DropCallback, ImportedDmatexs, ImportedTexture, import_texture},
|
|
||||||
};
|
};
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use parking_lot::Mutex;
|
use std::sync::Arc;
|
||||||
use std::{
|
|
||||||
os::fd::OwnedFd,
|
|
||||||
sync::{Arc, OnceLock},
|
|
||||||
};
|
|
||||||
use tracing::debug_span;
|
|
||||||
use vulkano::{
|
|
||||||
ValidationError,
|
|
||||||
buffer::{BufferCreateFlags, BufferCreateInfo, BufferUsage},
|
|
||||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, CopyBufferToImageInfo},
|
|
||||||
image::{
|
|
||||||
Image, ImageAspect, ImageCreateFlags, ImageCreateInfo, ImageLayout, ImageMemory,
|
|
||||||
ImageTiling, ImageUsage, sys::RawImage,
|
|
||||||
},
|
|
||||||
memory::{
|
|
||||||
DedicatedAllocation, DeviceMemory, ExternalMemoryHandleType, ExternalMemoryHandleTypes,
|
|
||||||
MemoryAllocateInfo, ResourceMemory, allocator::AllocationCreateInfo,
|
|
||||||
},
|
|
||||||
sync::{self, GpuFuture, Sharing},
|
|
||||||
};
|
|
||||||
use waynest::server::protocol::core::wayland::wl_shm::Format;
|
use waynest::server::protocol::core::wayland::wl_shm::Format;
|
||||||
|
|
||||||
fn create_vk_dmatex(
|
|
||||||
vulkano_context: &VulkanoContext,
|
|
||||||
size: Vector2<usize>,
|
|
||||||
) -> Result<(Arc<Image>, Dmatex), Box<ValidationError>> {
|
|
||||||
let vk_format = vulkano::format::Format::R8G8B8A8_UNORM;
|
|
||||||
|
|
||||||
let modifiers = vulkano_context
|
|
||||||
.phys_dev
|
|
||||||
.format_properties(vk_format)?
|
|
||||||
.drm_format_modifier_properties
|
|
||||||
.into_iter()
|
|
||||||
.map(|v| v.drm_format_modifier)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let raw_image = RawImage::new(
|
|
||||||
vulkano_context.dev.clone(),
|
|
||||||
ImageCreateInfo {
|
|
||||||
flags: ImageCreateFlags::empty(),
|
|
||||||
image_type: vulkano::image::ImageType::Dim2d,
|
|
||||||
format: vk_format,
|
|
||||||
view_formats: Vec::new(),
|
|
||||||
extent: [size.x as u32, size.y as u32, 1],
|
|
||||||
tiling: ImageTiling::DrmFormatModifier,
|
|
||||||
usage: ImageUsage::COLOR_ATTACHMENT | ImageUsage::SAMPLED | ImageUsage::TRANSFER_DST,
|
|
||||||
initial_layout: ImageLayout::Undefined,
|
|
||||||
drm_format_modifiers: modifiers,
|
|
||||||
external_memory_handle_types: ExternalMemoryHandleTypes::DMA_BUF,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let (modifier, num_planes) = raw_image.drm_format_modifier().unwrap();
|
|
||||||
let mem_reqs = raw_image.memory_requirements()[0];
|
|
||||||
let index = vulkano_context
|
|
||||||
.phys_dev
|
|
||||||
.memory_properties()
|
|
||||||
.memory_types
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, _v)| i as u32)
|
|
||||||
.find(|i| mem_reqs.memory_type_bits & (1 << i) != 0)
|
|
||||||
.expect("no valid memory type");
|
|
||||||
let mem = ResourceMemory::new_dedicated(
|
|
||||||
DeviceMemory::allocate(
|
|
||||||
vulkano_context.dev.clone(),
|
|
||||||
MemoryAllocateInfo {
|
|
||||||
allocation_size: mem_reqs.layout.size(),
|
|
||||||
memory_type_index: index,
|
|
||||||
dedicated_allocation: Some(DedicatedAllocation::Image(&raw_image)),
|
|
||||||
export_handle_types: ExternalMemoryHandleTypes::DMA_BUF,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let image = Arc::new(match raw_image.bind_memory([mem]) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(_) => panic!("unable to bind memory"),
|
|
||||||
});
|
|
||||||
let ImageMemory::Normal(mem) = image.memory() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let [mem] = mem.as_slice() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let fd = OwnedFd::from(
|
|
||||||
mem.device_memory()
|
|
||||||
.export_fd(ExternalMemoryHandleType::DmaBuf)
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
let planes = (0..num_planes)
|
|
||||||
.filter_map(|i| {
|
|
||||||
Some(match i {
|
|
||||||
0 => ImageAspect::MemoryPlane0,
|
|
||||||
1 => ImageAspect::MemoryPlane1,
|
|
||||||
2 => ImageAspect::MemoryPlane2,
|
|
||||||
3 => ImageAspect::MemoryPlane3,
|
|
||||||
_ => return None,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.map(|aspect| {
|
|
||||||
let plane_layout = image.subresource_layout(aspect, 0, 0).unwrap();
|
|
||||||
|
|
||||||
DmatexPlane {
|
|
||||||
dmabuf_fd: fd.try_clone().unwrap().into(),
|
|
||||||
modifier,
|
|
||||||
offset: plane_layout.offset as u32,
|
|
||||||
stride: plane_layout.row_pitch as i32,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let dmatex = Dmatex {
|
|
||||||
planes,
|
|
||||||
res: Resolution {
|
|
||||||
x: size.x as u32,
|
|
||||||
y: size.y as u32,
|
|
||||||
},
|
|
||||||
format: vk_format_to_drm_fourcc(vk_format.into()).unwrap() as u32,
|
|
||||||
flip_y: false,
|
|
||||||
srgb: true,
|
|
||||||
};
|
|
||||||
Ok((image, dmatex))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parameters for a shared memory buffer
|
/// Parameters for a shared memory buffer
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ShmBufferBacking {
|
pub struct ShmBufferBacking {
|
||||||
pool: Arc<ShmPool>,
|
pool: Arc<ShmPool>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
stride: usize,
|
stride: usize,
|
||||||
size: Vector2<usize>,
|
size: Vector2<usize>,
|
||||||
format: Format,
|
format: Format,
|
||||||
image: Arc<Image>,
|
|
||||||
image_handle: OnceLock<Handle<BevyImage>>,
|
|
||||||
pending_imported_dmatex: Mutex<Option<ImportedTexture>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShmBufferBacking {
|
impl ShmBufferBacking {
|
||||||
@@ -160,39 +25,17 @@ impl ShmBufferBacking {
|
|||||||
size: Vector2<usize>,
|
size: Vector2<usize>,
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// TODO: this might cause a freeze?
|
|
||||||
let vulkano_context = VULKANO_CONTEXT.wait();
|
|
||||||
let bevy_render_dev = RENDER_DEVICE.wait();
|
|
||||||
let (image, dmatex) = create_vk_dmatex(vulkano_context, size).unwrap();
|
|
||||||
|
|
||||||
let imported_texture = import_texture(bevy_render_dev, dmatex, DropCallback(None)).unwrap();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pool,
|
pool,
|
||||||
offset,
|
offset,
|
||||||
stride,
|
stride,
|
||||||
size,
|
size,
|
||||||
format,
|
format,
|
||||||
image,
|
|
||||||
image_handle: OnceLock::new(),
|
|
||||||
pending_imported_dmatex: Mutex::new(Some(imported_texture)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument("debug", skip_all)]
|
#[tracing::instrument("debug", skip_all)]
|
||||||
pub fn update_tex(
|
pub fn update_tex(&self, images: &mut Assets<Image>) -> Option<Handle<Image>> {
|
||||||
&self,
|
|
||||||
dmatexes: &ImportedDmatexs,
|
|
||||||
images: &mut Assets<BevyImage>,
|
|
||||||
) -> Option<Handle<BevyImage>> {
|
|
||||||
if let Some(tex) = self.pending_imported_dmatex.lock().take() {
|
|
||||||
self.image_handle
|
|
||||||
.set(dmatexes.insert_imported_dmatex(images, tex))
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
let vk = VULKANO_CONTEXT.wait();
|
|
||||||
let image_handle = self.image_handle.get().unwrap();
|
|
||||||
|
|
||||||
let src_data_lock = self.pool.data_lock();
|
let src_data_lock = self.pool.data_lock();
|
||||||
let mut src_cursor = self.offset;
|
let mut src_cursor = self.offset;
|
||||||
|
|
||||||
@@ -203,26 +46,13 @@ impl ShmBufferBacking {
|
|||||||
if max_cursor > src_data_lock.len() {
|
if max_cursor > src_data_lock.len() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let data_len = (self.size.x * self.size.y * 4) as u64;
|
let data_len = self.size.x * self.size.y * 4;
|
||||||
|
if src_data_lock.len() != data_len {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let mut dst_cursor = 0;
|
let mut dst_cursor = 0;
|
||||||
|
|
||||||
let buffer = vulkano::buffer::Buffer::new_slice::<u8>(
|
let mut dst_data = vec![0u8; data_len];
|
||||||
vk.alloc.clone(),
|
|
||||||
BufferCreateInfo {
|
|
||||||
flags: BufferCreateFlags::empty(),
|
|
||||||
sharing: Sharing::Exclusive,
|
|
||||||
usage: BufferUsage::TRANSFER_SRC,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
AllocationCreateInfo {
|
|
||||||
memory_type_filter:
|
|
||||||
vulkano::memory::allocator::MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
data_len,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let mut dst_data = buffer.write().unwrap();
|
|
||||||
for _y in 0..self.size.y {
|
for _y in 0..self.size.y {
|
||||||
for _x in 0..self.size.x {
|
for _x in 0..self.size.x {
|
||||||
match self.format {
|
match self.format {
|
||||||
@@ -239,32 +69,20 @@ impl ShmBufferBacking {
|
|||||||
}
|
}
|
||||||
src_cursor += self.stride - (self.size.x * 4);
|
src_cursor += self.stride - (self.size.x * 4);
|
||||||
}
|
}
|
||||||
drop(dst_data);
|
|
||||||
|
|
||||||
let mut command_buffer = AutoCommandBufferBuilder::primary(
|
let image = Image::new(
|
||||||
vk.command_buffer_alloc.clone(),
|
Extent3d {
|
||||||
vk.queue.queue_family_index(),
|
width: self.size().x as u32,
|
||||||
CommandBufferUsage::OneTimeSubmit,
|
height: self.size().y as u32,
|
||||||
)
|
depth_or_array_layers: 1,
|
||||||
.unwrap();
|
},
|
||||||
command_buffer
|
TextureDimension::D2,
|
||||||
.copy_buffer_to_image(CopyBufferToImageInfo::buffer_image(
|
dst_data,
|
||||||
buffer.clone(),
|
TextureFormat::Rgba8UnormSrgb,
|
||||||
self.image.clone(),
|
RenderAssetUsages::RENDER_WORLD,
|
||||||
))
|
);
|
||||||
.unwrap();
|
|
||||||
let command_buffer = command_buffer.build().unwrap();
|
|
||||||
debug_span!("waiting for buffer copy").in_scope(|| {
|
|
||||||
sync::now(vk.dev.clone())
|
|
||||||
.then_execute(vk.queue.clone(), command_buffer)
|
|
||||||
.unwrap()
|
|
||||||
.then_signal_fence_and_flush()
|
|
||||||
.unwrap()
|
|
||||||
.wait(None)
|
|
||||||
.unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
Some(image_handle.clone())
|
Some(images.add(image))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_transparent(&self) -> bool {
|
pub fn is_transparent(&self) -> bool {
|
||||||
@@ -279,17 +97,3 @@ impl ShmBufferBacking {
|
|||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for ShmBufferBacking {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("ShmBufferBacking")
|
|
||||||
.field("pool", &self.pool)
|
|
||||||
.field("offset", &self.offset)
|
|
||||||
.field("stride", &self.stride)
|
|
||||||
.field("size", &self.size)
|
|
||||||
.field("format", &self.format)
|
|
||||||
.field("image", &self.image)
|
|
||||||
.field("image_handle", &self.image_handle)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -231,10 +231,9 @@ impl WlSurface for Surface {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.state.lock().pending.buffer = buffer.and_then(|b| {
|
self.state.lock().pending.buffer = buffer.and_then(|b| {
|
||||||
let buffer = client.get::<Buffer>(b)?;
|
let buffer = client.get::<Buffer>(b)?;
|
||||||
|
let mut usage = Some(BufferUsage::new(client, &buffer));
|
||||||
Some(BufferState {
|
Some(BufferState {
|
||||||
usage: buffer
|
usage: usage.take_if(|_| buffer.uses_buffer_usage()),
|
||||||
.uses_buffer_usage()
|
|
||||||
.then(|| BufferUsage::new(client, &buffer)),
|
|
||||||
buffer,
|
buffer,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub struct DmabufBacking {
|
|||||||
format: DrmFourcc,
|
format: DrmFourcc,
|
||||||
_flags: Flags,
|
_flags: Flags,
|
||||||
tex: OnceLock<Handle<Image>>,
|
tex: OnceLock<Handle<Image>>,
|
||||||
pending_imported_dmatex: Mutex<Option<ImportedTexture>>,
|
// pending_imported_dmatex: Mutex<Option<ImportedTexture>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for DmabufBacking {
|
impl std::fmt::Debug for DmabufBacking {
|
||||||
@@ -73,7 +73,7 @@ impl DmabufBacking {
|
|||||||
format,
|
format,
|
||||||
_flags: flags,
|
_flags: flags,
|
||||||
tex: OnceLock::new(),
|
tex: OnceLock::new(),
|
||||||
pending_imported_dmatex: Mutex::new(Some(imported_tex)),
|
// pending_imported_dmatex: Mutex::new(Some(imported_tex)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,13 +84,14 @@ impl DmabufBacking {
|
|||||||
images: &mut Assets<Image>,
|
images: &mut Assets<Image>,
|
||||||
) -> Option<Handle<Image>> {
|
) -> Option<Handle<Image>> {
|
||||||
info!("updating dmabuf tex");
|
info!("updating dmabuf tex");
|
||||||
self.pending_imported_dmatex
|
// self.pending_imported_dmatex
|
||||||
.lock()
|
// .lock()
|
||||||
.take()
|
// .take()
|
||||||
.map(|tex| dmatexes.insert_imported_dmatex(images, tex))
|
// .map(|tex| dmatexes.insert_imported_dmatex(images, tex))
|
||||||
.inspect(|handle| {
|
// .inspect(|handle| {
|
||||||
_ = self.tex.set(handle.clone());
|
// _ = self.tex.set(handle.clone());
|
||||||
})
|
// })
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_transparent(&self) -> bool {
|
pub fn is_transparent(&self) -> bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user