feat(wayland): add vulkano infra

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2025-07-14 18:20:51 +02:00
parent 3571fa96aa
commit f855ca9820
4 changed files with 340 additions and 40 deletions

View File

@@ -1,6 +1,7 @@
pub mod core;
pub mod dmabuf;
pub mod util;
pub mod vulkano_data;
pub mod xdg;
use crate::PreFrameWait;
@@ -39,6 +40,7 @@ use std::{
use tokio::{net::UnixStream, sync::mpsc, task::AbortHandle};
use tokio_stream::StreamExt;
use tracing::{debug_span, instrument};
use vulkano_data::setup_vulkano_context;
use waynest::{
server::{
self,
@@ -294,6 +296,10 @@ impl Plugin for WaylandPlugin {
init_render_device.run_if(|| RENDER_DEVICE.get().is_none()),
);
}
fn finish(&self, app: &mut App) {
app.sub_app_mut(RenderApp)
.add_systems(Render, setup_vulkano_context);
}
}
fn init_render_device(dev: Res<RenderDevice>) {

142
src/wayland/vulkano_data.rs Normal file
View File

@@ -0,0 +1,142 @@
use std::sync::{Arc, OnceLock};
use bevy::{
ecs::system::Res,
render::renderer::{RenderAdapter, RenderDevice, RenderInstance},
};
use vulkano::{
VulkanLibrary,
command_buffer::allocator::{
CommandBufferAllocator, StandardCommandBufferAllocator,
StandardCommandBufferAllocatorCreateInfo,
},
device::{DeviceCreateInfo, QueueCreateInfo},
instance::InstanceCreateFlags,
memory::allocator::{MemoryAllocator, StandardMemoryAllocator},
};
use wgpu_hal::vulkan::Api as VulkanHal;
pub static VULKANO_CONTEXT: OnceLock<VulkanoContext> = OnceLock::new();
#[expect(dead_code)]
pub struct VulkanoContext {
pub instance: Arc<vulkano::instance::Instance>,
pub phys_dev: Arc<vulkano::device::physical::PhysicalDevice>,
pub dev: Arc<vulkano::device::Device>,
pub queue: Arc<vulkano::device::Queue>,
pub alloc: Arc<dyn MemoryAllocator>,
pub command_buffer_alloc: Arc<dyn CommandBufferAllocator>,
}
pub fn setup_vulkano_context(
dev: Res<RenderDevice>,
instance: Res<RenderInstance>,
adapter: Res<RenderAdapter>,
) {
if VULKANO_CONTEXT.get().is_some() {
return;
}
let hal_instance = unsafe { instance.as_hal::<VulkanHal>() }
.unwrap()
.shared_instance();
let ash_instance = hal_instance.raw_instance();
let vulkan_lib =
VulkanLibrary::with_loader(AshEntryVulkanoLoader(hal_instance.entry().clone())).unwrap();
let vulkano_instance = unsafe {
vulkano::instance::Instance::from_handle(
vulkan_lib,
ash_instance.handle(),
vulkano::instance::InstanceCreateInfo {
flags: InstanceCreateFlags::empty(),
max_api_version: Some(vulkano::Version::from(hal_instance.instance_api_version())),
enabled_extensions: vulkano::instance::InstanceExtensions::from_iter(
hal_instance
.extensions()
.iter()
.map(|s| s.to_str().unwrap()),
),
..Default::default()
},
)
};
let ash_phys_dev_handle = unsafe {
adapter.as_hal::<VulkanHal, _, _>(|adapter| adapter.unwrap().raw_physical_device())
};
let vulkano_phys_dev = unsafe {
vulkano::device::physical::PhysicalDevice::from_handle(
vulkano_instance.clone(),
ash_phys_dev_handle,
)
}
.unwrap();
let (ash_dev_handle, dev_create_info) = unsafe {
dev.wgpu_device().as_hal::<VulkanHal, _, _>(|dev| {
let dev = dev.unwrap();
(
dev.raw_device().handle(),
DeviceCreateInfo {
queue_create_infos: vec![QueueCreateInfo {
queue_family_index: dev.queue_family_index(),
..Default::default()
}],
enabled_extensions: dbg!(vulkano::device::DeviceExtensions::from_iter(
dev.enabled_device_extensions()
.iter()
// TODO: remove this hack by telling wgpu about the actual exts used in
// bevy_mod_openxr
.chain(bevy_dmabuf::required_device_extensions().iter())
.map(|v| v.to_str().unwrap()),
)),
// this is def wrong, lets hope it doesn't cause issues....
enabled_features: vulkano::device::DeviceFeatures::empty(),
..Default::default()
},
)
})
};
let (vulkano_dev, mut queues) = unsafe {
vulkano::device::Device::from_handle(
vulkano_phys_dev.clone(),
ash_dev_handle,
dev_create_info,
)
};
let alloc = Arc::new(StandardMemoryAllocator::new_default(vulkano_dev.clone()));
let command_buffer_alloc = Arc::new(StandardCommandBufferAllocator::new(
vulkano_dev.clone(),
StandardCommandBufferAllocatorCreateInfo::default(),
));
_ = VULKANO_CONTEXT.set(VulkanoContext {
instance: vulkano_instance,
phys_dev: vulkano_phys_dev,
dev: vulkano_dev,
queue: queues.next().unwrap(),
alloc,
command_buffer_alloc,
});
}
// ensures that we don't destroy the vulkan handles wgpu/bevy use
// TODO: remove once we don't use bevys wgpu instance/device/physical_device
impl Drop for VulkanoContext {
fn drop(&mut self) {
panic!("the vulkano context shall never be dropped");
}
}
struct AshEntryVulkanoLoader(ash::Entry);
unsafe impl vulkano::library::Loader for AshEntryVulkanoLoader {
unsafe fn get_instance_proc_addr(
&self,
instance: ash::vk::Instance,
name: *const std::os::raw::c_char,
) -> ash::vk::PFN_vkVoidFunction {
unsafe { self.0.get_instance_proc_addr(instance, name) }
}
}