Path: blob/main/crates/bevy_render/src/renderer/raw_vulkan_init.rs
6596 views
use alloc::sync::Arc;1use bevy_ecs::resource::Resource;2use bevy_platform::collections::HashSet;3use core::any::{Any, TypeId};4use thiserror::Error;5use wgpu::{6hal::api::Vulkan, Adapter, Device, DeviceDescriptor, Instance, InstanceDescriptor, Queue,7};89/// When the `raw_vulkan_init` feature is enabled, these settings will be used to configure the raw vulkan instance.10#[derive(Resource, Default, Clone)]11pub struct RawVulkanInitSettings {12// SAFETY: this must remain private to ensure that registering callbacks is unsafe13create_instance_callbacks: Vec<14Arc<15dyn Fn(16&mut wgpu::hal::vulkan::CreateInstanceCallbackArgs,17&mut AdditionalVulkanFeatures,18) + Send19+ Sync,20>,21>,22// SAFETY: this must remain private to ensure that registering callbacks is unsafe23create_device_callbacks: Vec<24Arc<25dyn Fn(26&mut wgpu::hal::vulkan::CreateDeviceCallbackArgs,27&wgpu::hal::vulkan::Adapter,28&mut AdditionalVulkanFeatures,29) + Send30+ Sync,31>,32>,33}3435impl RawVulkanInitSettings {36/// Adds a new Vulkan create instance callback. See [`wgpu::hal::vulkan::Instance::init_with_callback`] for details.37///38/// # Safety39/// - Callback must not remove features.40/// - Callback must not change anything to what the instance does not support.41pub unsafe fn add_create_instance_callback(42&mut self,43callback: impl Fn(&mut wgpu::hal::vulkan::CreateInstanceCallbackArgs, &mut AdditionalVulkanFeatures)44+ Send45+ Sync46+ 'static,47) {48self.create_instance_callbacks.push(Arc::new(callback));49}5051/// Adds a new Vulkan create device callback. See [`wgpu::hal::vulkan::Adapter::open_with_callback`] for details.52///53/// # Safety54/// - Callback must not remove features.55/// - Callback must not change anything to what the device does not support.56pub unsafe fn add_create_device_callback(57&mut self,58callback: impl Fn(59&mut wgpu::hal::vulkan::CreateDeviceCallbackArgs,60&wgpu::hal::vulkan::Adapter,61&mut AdditionalVulkanFeatures,62) + Send63+ Sync64+ 'static,65) {66self.create_device_callbacks.push(Arc::new(callback));67}68}6970pub(crate) fn create_raw_vulkan_instance(71instance_descriptor: &InstanceDescriptor,72settings: &RawVulkanInitSettings,73additional_features: &mut AdditionalVulkanFeatures,74) -> Instance {75// SAFETY: Registering callbacks is unsafe. Callback authors promise not to remove features76// or change the instance to something it does not support77unsafe {78wgpu::hal::vulkan::Instance::init_with_callback(79&wgpu::hal::InstanceDescriptor {80name: "wgpu",81flags: instance_descriptor.flags,82memory_budget_thresholds: instance_descriptor.memory_budget_thresholds,83backend_options: instance_descriptor.backend_options.clone(),84},85Some(Box::new(|mut args| {86for callback in &settings.create_instance_callbacks {87(callback)(&mut args, additional_features);88}89})),90)91.map(|raw_instance| Instance::from_hal::<Vulkan>(raw_instance))92.unwrap_or_else(|_| Instance::new(instance_descriptor))93}94}9596pub(crate) async fn create_raw_device(97adapter: &Adapter,98device_descriptor: &DeviceDescriptor<'_>,99settings: &RawVulkanInitSettings,100additional_features: &mut AdditionalVulkanFeatures,101) -> Result<(Device, Queue), CreateRawVulkanDeviceError> {102// SAFETY: Registering callbacks is unsafe. Callback authors promise not to remove features103// or change the adapter to something it does not support104unsafe {105let Some(raw_adapter) = adapter.as_hal::<Vulkan>() else {106return Ok(adapter.request_device(device_descriptor).await?);107};108let open_device = raw_adapter.open_with_callback(109device_descriptor.required_features,110&device_descriptor.memory_hints,111Some(Box::new(|mut args| {112for callback in &settings.create_device_callbacks {113(callback)(&mut args, &raw_adapter, additional_features);114}115})),116)?;117118Ok(adapter.create_device_from_hal::<Vulkan>(open_device, device_descriptor)?)119}120}121122#[derive(Error, Debug)]123pub(crate) enum CreateRawVulkanDeviceError {124#[error(transparent)]125RequestDeviceError(#[from] wgpu::RequestDeviceError),126#[error(transparent)]127DeviceError(#[from] wgpu::hal::DeviceError),128}129130/// A list of additional Vulkan features that are supported by the current wgpu instance / adapter. This is populated131/// by callbacks defined in [`RawVulkanInitSettings`]132#[derive(Resource, Default, Clone)]133pub struct AdditionalVulkanFeatures(HashSet<TypeId>);134135impl AdditionalVulkanFeatures {136pub fn insert<T: Any>(&mut self) {137self.0.insert(TypeId::of::<T>());138}139140pub fn has<T: Any>(&self) -> bool {141self.0.contains(&TypeId::of::<T>())142}143144pub fn remove<T: Any>(&mut self) {145self.0.remove(&TypeId::of::<T>());146}147}148149150