diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 94efa197b9..17c421c6af 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -29,6 +29,8 @@ jobs: linux_stable: runs-on: ubuntu-latest steps: + - name: Install Vulkan loader + run: sudo apt-get install libvulkan-dev - uses: actions/checkout@v2 - name: Build run: cargo build --verbose diff --git a/CHANGELOG.md b/CHANGELOG.md index ea370c10d8..30bd50f9f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ - **Breaking** `UnsafeCommandBufferBuilder::pipeline_barrier` now takes a `DependencyInfo`. It will use `vkCmdPipelineBarrier2` if supported. - `UnsafeCommandPoolCreateInfo` and `UnsafeCommandPoolCreationError` interfaces exposed. - Fixed compile error in Vulkano-win on Android. +- You can now choose to link Vulkan directly at compile time by enabling the `linked` feature flag. +- **Breaking** Creating `Instance` with `Instance::new` now requires a `VulkanLibrary`, which could be created with `VulkanLibrary::linked()`, `VulkanLibrary::load()` or `VulkanLibrary::default()`. `FunctionPointers` and related types and functions are now removed. +- **Breaking** `InstanceExtensions::supported_by_core_with_loader` was removed in favor of `VulkanLibrary::instance_extensions`. `layers_list` was removed in favor of `VulkanLibrary::layers` # Version 0.29.0 (2022-03-11) diff --git a/examples/src/bin/basic-compute-shader.rs b/examples/src/bin/basic-compute-shader.rs index 8ac43711fb..ff993f620d 100644 --- a/examples/src/bin/basic-compute-shader.rs +++ b/examples/src/bin/basic-compute-shader.rs @@ -21,14 +21,15 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; fn main() { // As with other examples, the first step is to create an instance. - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); // Choose which physical device to use. let device_extensions = DeviceExtensions { diff --git a/examples/src/bin/buffer-pool.rs b/examples/src/bin/buffer-pool.rs index eca0d4f0d8..aa8682b4fd 100644 --- a/examples/src/bin/buffer-pool.rs +++ b/examples/src/bin/buffer-pool.rs @@ -33,7 +33,7 @@ use vulkano::{ }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ input_assembly::InputAssemblyState, @@ -63,11 +63,15 @@ struct Vertex { impl_vertex!(Vertex, position); fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/clear_attachments.rs b/examples/src/bin/clear_attachments.rs index d868ae6315..e952587372 100644 --- a/examples/src/bin/clear_attachments.rs +++ b/examples/src/bin/clear_attachments.rs @@ -20,7 +20,7 @@ use vulkano::{ view::ImageView, ImageUsage, SwapchainImage, }, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{graphics::viewport::ViewportState, GraphicsPipeline}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, swapchain::{ @@ -39,11 +39,15 @@ fn main() { // The start of this example is exactly the same as `triangle`. You should read the // `triangle` example if you haven't done so yet. - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/debug.rs b/examples/src/bin/debug.rs index 4f4d893ee7..f0dfa9ec26 100644 --- a/examples/src/bin/debug.rs +++ b/examples/src/bin/debug.rs @@ -16,7 +16,7 @@ use vulkano::{ image::{ImageDimensions, ImmutableImage, MipmapsCount}, instance::{ debug::{DebugCallback, MessageSeverity, MessageType}, - layers_list, Instance, InstanceCreateInfo, InstanceExtensions, + Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary, }, }; @@ -46,7 +46,8 @@ fn main() { // and you should verify that list for safety - Vulkano will return an error if you specify // any layers that are not installed on this system. That code to do could look like this: println!("List of Vulkan debugging layers available to use:"); - let mut layers = layers_list().unwrap(); + let lib = VulkanLibrary::default(); + let mut layers = lib.layers().unwrap(); while let Some(l) = layers.next() { println!("\t{}", l.name()); } @@ -59,11 +60,14 @@ fn main() { let layers = vec!["VK_LAYER_KHRONOS_validation".to_owned()]; // Important: pass the extension(s) and layer(s) when creating the vulkano instance - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: extensions, - enabled_layers: layers, - ..Default::default() - }) + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: extensions, + enabled_layers: layers, + ..Default::default() + }, + ) .expect("failed to create Vulkan instance"); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/examples/src/bin/deferred/main.rs b/examples/src/bin/deferred/main.rs index 06c240e7a2..ccd56d2f45 100644 --- a/examples/src/bin/deferred/main.rs +++ b/examples/src/bin/deferred/main.rs @@ -36,7 +36,7 @@ use vulkano::{ Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, image::{view::ImageView, ImageUsage}, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, swapchain::{ acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError, }, @@ -55,11 +55,15 @@ mod triangle_draw_system; fn main() { // Basic initialization. See the triangle example if you want more details about this. - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/dynamic-buffers.rs b/examples/src/bin/dynamic-buffers.rs index 9cb870bf92..6073b0c797 100644 --- a/examples/src/bin/dynamic-buffers.rs +++ b/examples/src/bin/dynamic-buffers.rs @@ -25,13 +25,14 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; fn main() { - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); let device_extensions = DeviceExtensions { khr_storage_buffer_storage_class: true, diff --git a/examples/src/bin/dynamic-local-size.rs b/examples/src/bin/dynamic-local-size.rs index e7d8f40792..30248e1046 100644 --- a/examples/src/bin/dynamic-local-size.rs +++ b/examples/src/bin/dynamic-local-size.rs @@ -25,22 +25,26 @@ use vulkano::{ }, format::Format, image::{view::ImageView, ImageDimensions, StorageImage}, - instance::{Instance, InstanceCreateInfo, InstanceExtensions}, + instance::{Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; fn main() { - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: InstanceExtensions { - // This extension is required to obtain physical device metadata - // about the device workgroup size limits - khr_get_physical_device_properties2: true, + let lib = VulkanLibrary::default(); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: InstanceExtensions { + // This extension is required to obtain physical device metadata + // about the device workgroup size limits + khr_get_physical_device_properties2: true, - ..InstanceExtensions::none() + ..InstanceExtensions::none() + }, + ..Default::default() }, - ..Default::default() - }) + ) .unwrap(); let device_extensions = DeviceExtensions { diff --git a/examples/src/bin/gl-interop.rs b/examples/src/bin/gl-interop.rs index f086ec8d8f..667aa3579d 100644 --- a/examples/src/bin/gl-interop.rs +++ b/examples/src/bin/gl-interop.rs @@ -26,7 +26,9 @@ mod linux { format::Format, image::{view::ImageView, ImageCreateFlags, ImageUsage, StorageImage, SwapchainImage}, impl_vertex, - instance::{debug::DebugCallback, Instance, InstanceCreateInfo, InstanceExtensions}, + instance::{ + debug::DebugCallback, Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary, + }, pipeline::{ graphics::{ color_blend::ColorBlendState, @@ -374,21 +376,25 @@ mod linux { Arc, Arc>, ) { - let required_extensions = vulkano_win::required_extensions(); - - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: InstanceExtensions { - khr_get_physical_device_properties2: true, - khr_external_memory_capabilities: true, - khr_external_semaphore_capabilities: true, - khr_external_fence_capabilities: true, - ext_debug_utils: true, - - ..InstanceExtensions::none() - } - .union(&required_extensions), - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: InstanceExtensions { + khr_get_physical_device_properties2: true, + khr_external_memory_capabilities: true, + khr_external_semaphore_capabilities: true, + khr_external_fence_capabilities: true, + ext_debug_utils: true, + + ..InstanceExtensions::none() + } + .union(&required_extensions), + ..Default::default() + }, + ) .unwrap(); let _debug_callback = DebugCallback::errors_and_warnings(&instance, |msg| { diff --git a/examples/src/bin/image-self-copy-blit/main.rs b/examples/src/bin/image-self-copy-blit/main.rs index 20d54e7beb..cd8a710d79 100644 --- a/examples/src/bin/image-self-copy-blit/main.rs +++ b/examples/src/bin/image-self-copy-blit/main.rs @@ -24,7 +24,7 @@ use vulkano::{ view::ImageView, ImageAccess, ImageDimensions, ImageUsage, StorageImage, SwapchainImage, }, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ color_blend::ColorBlendState, @@ -52,11 +52,15 @@ fn main() { // The start of this example is exactly the same as `triangle`. You should read the // `triangle` example if you haven't done so yet. - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/image/main.rs b/examples/src/bin/image/main.rs index 3c975ece01..1826827e40 100644 --- a/examples/src/bin/image/main.rs +++ b/examples/src/bin/image/main.rs @@ -23,7 +23,7 @@ use vulkano::{ SwapchainImage, }, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ color_blend::ColorBlendState, @@ -51,11 +51,15 @@ fn main() { // The start of this example is exactly the same as `triangle`. You should read the // `triangle` example if you haven't done so yet. - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/immutable-buffer-initialization.rs b/examples/src/bin/immutable-buffer-initialization.rs index 466fea2695..02d5606517 100644 --- a/examples/src/bin/immutable-buffer-initialization.rs +++ b/examples/src/bin/immutable-buffer-initialization.rs @@ -17,7 +17,7 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; @@ -25,8 +25,8 @@ use vulkano::{ fn main() { // The most part of this example is exactly the same as `basic-compute-shader`. You should read the // `basic-compute-shader` example if you haven't done so yet. - - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); let device_extensions = DeviceExtensions { khr_storage_buffer_storage_class: true, diff --git a/examples/src/bin/immutable-sampler/main.rs b/examples/src/bin/immutable-sampler/main.rs index 6b285d4d60..a2f1d6045c 100644 --- a/examples/src/bin/immutable-sampler/main.rs +++ b/examples/src/bin/immutable-sampler/main.rs @@ -32,7 +32,7 @@ use vulkano::{ SwapchainImage, }, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ color_blend::ColorBlendState, @@ -57,11 +57,15 @@ use winit::{ }; fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/indirect.rs b/examples/src/bin/indirect.rs index 32852c2ebc..1a11ef1f66 100644 --- a/examples/src/bin/indirect.rs +++ b/examples/src/bin/indirect.rs @@ -38,7 +38,7 @@ use vulkano::{ }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ input_assembly::InputAssemblyState, @@ -71,11 +71,15 @@ struct Vertex { impl_vertex!(Vertex, position); fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/instancing.rs b/examples/src/bin/instancing.rs index d3d3d6f397..0fcee6842b 100644 --- a/examples/src/bin/instancing.rs +++ b/examples/src/bin/instancing.rs @@ -23,7 +23,7 @@ use vulkano::{ }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ input_assembly::InputAssemblyState, @@ -69,11 +69,15 @@ struct InstanceData { impl_vertex!(InstanceData, position_offset, scale); fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/interactive_fractal/renderer.rs b/examples/src/bin/interactive_fractal/renderer.rs index 7f10c85eee..6e2f208b6d 100644 --- a/examples/src/bin/interactive_fractal/renderer.rs +++ b/examples/src/bin/interactive_fractal/renderer.rs @@ -19,7 +19,7 @@ use vulkano::{ view::ImageView, AttachmentImage, ImageAccess, ImageUsage, ImageViewAbstract, SampleCount, SwapchainImage, }, - instance::{Instance, InstanceCreateInfo, InstanceExtensions}, + instance::{Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary}, swapchain::{ acquire_next_image, AcquireError, PresentMode, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError, @@ -82,15 +82,19 @@ impl Renderer { /// Creates a new GPU renderer for window with given parameters pub fn new(event_loop: &EventLoop<()>, opts: RenderOptions) -> Self { println!("Creating renderer for window size {:?}", opts.window_size); + let lib = VulkanLibrary::default(); // Add instance extensions based on needs let instance_extensions = InstanceExtensions { - ..vulkano_win::required_extensions() + ..vulkano_win::required_extensions(&lib) }; // Create instance - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: instance_extensions, - ..Default::default() - }) + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: instance_extensions, + ..Default::default() + }, + ) .expect("Failed to create instance"); // Get desired device diff --git a/examples/src/bin/msaa-renderpass.rs b/examples/src/bin/msaa-renderpass.rs index 4261889552..bf06cae0c8 100644 --- a/examples/src/bin/msaa-renderpass.rs +++ b/examples/src/bin/msaa-renderpass.rs @@ -78,7 +78,7 @@ use vulkano::{ format::{ClearValue, Format}, image::{view::ImageView, AttachmentImage, ImageDimensions, SampleCount, StorageImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ vertex_input::BuffersDefinition, @@ -92,11 +92,15 @@ use vulkano::{ fn main() { // The usual Vulkan initialization. - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let device_extensions = DeviceExtensions { diff --git a/examples/src/bin/multi-window.rs b/examples/src/bin/multi-window.rs index 6eb0d82f6b..416fa76583 100644 --- a/examples/src/bin/multi-window.rs +++ b/examples/src/bin/multi-window.rs @@ -27,7 +27,7 @@ use vulkano::{ }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ input_assembly::InputAssemblyState, @@ -60,11 +60,15 @@ struct WindowSurface { } fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/multi_window_game_of_life/app.rs b/examples/src/bin/multi_window_game_of_life/app.rs index 4350285d72..5df8008923 100644 --- a/examples/src/bin/multi_window_game_of_life/app.rs +++ b/examples/src/bin/multi_window_game_of_life/app.rs @@ -94,7 +94,7 @@ impl App { impl Default for App { fn default() -> Self { App { - context: VulkanoContext::new(&VulkanoConfig::default()), + context: VulkanoContext::new(VulkanoConfig::default()), windows: HashMap::new(), pipelines: HashMap::new(), primary_window_id: unsafe { WindowId::dummy() }, diff --git a/examples/src/bin/multi_window_game_of_life/vulkano_config.rs b/examples/src/bin/multi_window_game_of_life/vulkano_config.rs index 02abeabe1d..b8f651d3de 100644 --- a/examples/src/bin/multi_window_game_of_life/vulkano_config.rs +++ b/examples/src/bin/multi_window_game_of_life/vulkano_config.rs @@ -9,7 +9,7 @@ use vulkano::{ device::{DeviceExtensions, Features}, - instance::InstanceExtensions, + instance::{InstanceExtensions, VulkanLibrary}, }; /// A utility struct to configure vulkano context @@ -20,16 +20,18 @@ pub struct VulkanoConfig { pub device_extensions: DeviceExtensions, pub features: Features, pub layers: Vec, + pub lib: VulkanLibrary, } impl Default for VulkanoConfig { fn default() -> Self { + let lib = VulkanLibrary::default(); VulkanoConfig { return_from_run: false, add_primary_window: true, instance_extensions: InstanceExtensions { ext_debug_utils: true, - ..vulkano_win::required_extensions() + ..vulkano_win::required_extensions(&lib) }, device_extensions: DeviceExtensions { khr_swapchain: true, @@ -37,6 +39,7 @@ impl Default for VulkanoConfig { }, features: Features::none(), layers: vec![], + lib, } } } diff --git a/examples/src/bin/multi_window_game_of_life/vulkano_context.rs b/examples/src/bin/multi_window_game_of_life/vulkano_context.rs index 4fabdc607a..63fe9a6a26 100644 --- a/examples/src/bin/multi_window_game_of_life/vulkano_context.rs +++ b/examples/src/bin/multi_window_game_of_life/vulkano_context.rs @@ -20,7 +20,7 @@ use vulkano::{ image::{view::ImageView, ImageUsage, StorageImage, SwapchainImage}, instance::{ debug::{DebugCallback, MessageSeverity, MessageType}, - Instance, InstanceCreateInfo, InstanceExtensions, + Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary, }, swapchain::{ ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceTransform, Swapchain, @@ -54,8 +54,12 @@ unsafe impl Sync for VulkanoContext {} unsafe impl Send for VulkanoContext {} impl VulkanoContext { - pub fn new(config: &VulkanoConfig) -> Self { - let instance = create_vk_instance(config.instance_extensions, config.layers.clone()); + pub fn new(config: VulkanoConfig) -> Self { + let instance = create_vk_instance( + config.lib, + config.instance_extensions, + config.layers.clone(), + ); let is_debug = config.layers.iter().any(|layer| { layer == "VK_LAYER_LUNARG_standard_validation" || layer == "VK_LAYER_KHRONOS_validation" }); @@ -241,36 +245,20 @@ impl VulkanoContext { // Create vk instance with given layers pub fn create_vk_instance( + lib: VulkanLibrary, instance_extensions: InstanceExtensions, layers: Vec, ) -> Arc { // Create instance. - let result = Instance::new(InstanceCreateInfo { - enabled_extensions: instance_extensions, - enabled_layers: layers, - ..Default::default() - }); - - // Handle errors. On mac os, it will ask you to install vulkan sdk if you have not done so. - #[cfg(target_os = "macos")] - let instance = { - use vulkano::instance::InstanceCreationError; + let result = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: instance_extensions, + enabled_layers: layers, + ..Default::default() + }, + ); - match result { - Err(e) => match e { - InstanceCreationError::LoadingError(le) => { - println!( - "{:?}, Did you install vulkanSDK from https://vulkan.lunarg.com/sdk/home ?", - le - ); - Err(le).expect("") - } - _ => Err(e).expect("Failed to create instance"), - }, - Ok(i) => i, - } - }; - #[cfg(not(target_os = "macos"))] let instance = result.expect("Failed to create instance"); instance diff --git a/examples/src/bin/multiview.rs b/examples/src/bin/multiview.rs index 7fee951ffe..27ea752634 100644 --- a/examples/src/bin/multiview.rs +++ b/examples/src/bin/multiview.rs @@ -28,7 +28,7 @@ use vulkano::{ SampleCount, StorageImage, }, impl_vertex, - instance::{Instance, InstanceCreateInfo, InstanceExtensions}, + instance::{Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary}, pipeline::{ graphics::{ input_assembly::InputAssemblyState, @@ -45,13 +45,17 @@ use vulkano::{ }; fn main() { - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: InstanceExtensions { - khr_get_physical_device_properties2: true, // required to get multiview limits - ..InstanceExtensions::none() + let lib = VulkanLibrary::default(); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: InstanceExtensions { + khr_get_physical_device_properties2: true, // required to get multiview limits + ..InstanceExtensions::none() + }, + ..Default::default() }, - ..Default::default() - }) + ) .unwrap(); let device_extensions = DeviceExtensions { diff --git a/examples/src/bin/occlusion-query.rs b/examples/src/bin/occlusion-query.rs index 1918ebb43a..ed14ac7882 100644 --- a/examples/src/bin/occlusion-query.rs +++ b/examples/src/bin/occlusion-query.rs @@ -23,7 +23,7 @@ use vulkano::{ format::Format, image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ depth_stencil::DepthStencilState, @@ -48,11 +48,15 @@ use winit::{ }; fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/pipeline-caching.rs b/examples/src/bin/pipeline-caching.rs index 994d735085..a932993945 100644 --- a/examples/src/bin/pipeline-caching.rs +++ b/examples/src/bin/pipeline-caching.rs @@ -36,13 +36,14 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{cache::PipelineCache, ComputePipeline}, }; fn main() { // As with other examples, the first step is to create an instance. - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); // Choose which physical device to use. let device_extensions = DeviceExtensions { diff --git a/examples/src/bin/push-constants.rs b/examples/src/bin/push-constants.rs index f0de9b8f6e..76c940cb25 100644 --- a/examples/src/bin/push-constants.rs +++ b/examples/src/bin/push-constants.rs @@ -17,13 +17,14 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; fn main() { - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); let device_extensions = DeviceExtensions { khr_storage_buffer_storage_class: true, diff --git a/examples/src/bin/push-descriptors/main.rs b/examples/src/bin/push-descriptors/main.rs index 55e9d4dc1b..ebe0fff405 100644 --- a/examples/src/bin/push-descriptors/main.rs +++ b/examples/src/bin/push-descriptors/main.rs @@ -23,7 +23,7 @@ use vulkano::{ SwapchainImage, }, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ color_blend::ColorBlendState, @@ -48,11 +48,15 @@ use winit::{ }; fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/runtime-shader/main.rs b/examples/src/bin/runtime-shader/main.rs index e5313f4809..c5ea18dfad 100644 --- a/examples/src/bin/runtime-shader/main.rs +++ b/examples/src/bin/runtime-shader/main.rs @@ -30,7 +30,7 @@ use vulkano::{ }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ input_assembly::InputAssemblyState, @@ -64,11 +64,15 @@ pub struct Vertex { impl_vertex!(Vertex, position, color); fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/runtime_array/main.rs b/examples/src/bin/runtime_array/main.rs index c8de0402fd..49d15f931d 100644 --- a/examples/src/bin/runtime_array/main.rs +++ b/examples/src/bin/runtime_array/main.rs @@ -28,7 +28,7 @@ use vulkano::{ SwapchainImage, }, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ color_blend::ColorBlendState, @@ -56,11 +56,15 @@ fn main() { // The start of this example is exactly the same as `triangle`. You should read the // `triangle` example if you haven't done so yet. - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/self-copy-buffer.rs b/examples/src/bin/self-copy-buffer.rs index 75706de456..8784ddeea0 100644 --- a/examples/src/bin/self-copy-buffer.rs +++ b/examples/src/bin/self-copy-buffer.rs @@ -18,13 +18,14 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; fn main() { - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); let device_extensions = DeviceExtensions { khr_storage_buffer_storage_class: true, diff --git a/examples/src/bin/shader-include/main.rs b/examples/src/bin/shader-include/main.rs index 88b06504e7..50f92a39dd 100644 --- a/examples/src/bin/shader-include/main.rs +++ b/examples/src/bin/shader-include/main.rs @@ -19,13 +19,14 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; fn main() { - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); let device_extensions = DeviceExtensions { khr_storage_buffer_storage_class: true, ..DeviceExtensions::none() diff --git a/examples/src/bin/shader-types-sharing.rs b/examples/src/bin/shader-types-sharing.rs index 046acf7f87..c74ea7ce4d 100644 --- a/examples/src/bin/shader-types-sharing.rs +++ b/examples/src/bin/shader-types-sharing.rs @@ -36,13 +36,14 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; fn main() { - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); let device_extensions = DeviceExtensions { khr_storage_buffer_storage_class: true, diff --git a/examples/src/bin/specialization-constants.rs b/examples/src/bin/specialization-constants.rs index c17456418b..303aa10a42 100644 --- a/examples/src/bin/specialization-constants.rs +++ b/examples/src/bin/specialization-constants.rs @@ -17,13 +17,14 @@ use vulkano::{ physical::{PhysicalDevice, PhysicalDeviceType}, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo, }, - instance::Instance, + instance::{Instance, VulkanLibrary}, pipeline::{ComputePipeline, Pipeline, PipelineBindPoint}, sync::{self, GpuFuture}, }; fn main() { - let instance = Instance::new(Default::default()).unwrap(); + let lib = VulkanLibrary::default(); + let instance = Instance::new(lib, Default::default()).unwrap(); let device_extensions = DeviceExtensions { khr_storage_buffer_storage_class: true, diff --git a/examples/src/bin/teapot/main.rs b/examples/src/bin/teapot/main.rs index 3bb3058c2a..833422bfbc 100644 --- a/examples/src/bin/teapot/main.rs +++ b/examples/src/bin/teapot/main.rs @@ -20,7 +20,7 @@ use vulkano::{ }, format::Format, image::{view::ImageView, AttachmentImage, ImageAccess, ImageUsage, SwapchainImage}, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ depth_stencil::DepthStencilState, @@ -47,12 +47,15 @@ use winit::{ fn main() { // The start of this example is exactly the same as `triangle`. You should read the // `triangle` example if you haven't done so yet. - - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/tessellation.rs b/examples/src/bin/tessellation.rs index 1dadd652c2..c9b8ae7ebc 100644 --- a/examples/src/bin/tessellation.rs +++ b/examples/src/bin/tessellation.rs @@ -29,7 +29,7 @@ use vulkano::{ }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ input_assembly::{InputAssemblyState, PrimitiveTopology}, @@ -149,11 +149,15 @@ mod fs { } fn main() { - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/texture_array/main.rs b/examples/src/bin/texture_array/main.rs index 78ac512faf..d132a0844b 100644 --- a/examples/src/bin/texture_array/main.rs +++ b/examples/src/bin/texture_array/main.rs @@ -23,7 +23,7 @@ use vulkano::{ SwapchainImage, }, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ color_blend::ColorBlendState, @@ -53,11 +53,15 @@ fn main() { // And not this: // uniform sampler2D array_of_textures[42]; - let required_extensions = vulkano_win::required_extensions(); - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); let event_loop = EventLoop::new(); diff --git a/examples/src/bin/triangle.rs b/examples/src/bin/triangle.rs index a2c6be36fd..96f0f7d592 100644 --- a/examples/src/bin/triangle.rs +++ b/examples/src/bin/triangle.rs @@ -27,7 +27,7 @@ use vulkano::{ }, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, impl_vertex, - instance::{Instance, InstanceCreateInfo}, + instance::{Instance, InstanceCreateInfo, VulkanLibrary}, pipeline::{ graphics::{ input_assembly::InputAssemblyState, @@ -57,13 +57,17 @@ fn main() { // All the window-drawing functionalities are part of non-core extensions that we need // to enable manually. To do so, we ask the `vulkano_win` crate for the list of extensions // required to draw to a window. - let required_extensions = vulkano_win::required_extensions(); + let lib = VulkanLibrary::default(); + let required_extensions = vulkano_win::required_extensions(&lib); // Now creating the instance. - let instance = Instance::new(InstanceCreateInfo { - enabled_extensions: required_extensions, - ..Default::default() - }) + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: required_extensions, + ..Default::default() + }, + ) .unwrap(); // The objective of this example is to draw a triangle on a window. To do so, we first need to diff --git a/vulkano-win/src/winit.rs b/vulkano-win/src/winit.rs index 6aa6aaad8a..b9c7c0736b 100644 --- a/vulkano-win/src/winit.rs +++ b/vulkano-win/src/winit.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use vulkano::instance::Instance; use vulkano::instance::InstanceExtensions; +use vulkano::instance::VulkanLibrary; use vulkano::swapchain::Surface; use vulkano::swapchain::SurfaceCreationError; use winit::{ @@ -14,7 +15,7 @@ use winit::{ window::{Window, WindowBuilder}, }; -pub fn required_extensions() -> InstanceExtensions { +pub fn required_extensions(lib: &VulkanLibrary) -> InstanceExtensions { let ideal = InstanceExtensions { khr_surface: true, khr_xlib_surface: true, @@ -29,7 +30,7 @@ pub fn required_extensions() -> InstanceExtensions { ..InstanceExtensions::none() }; - match InstanceExtensions::supported_by_core() { + match lib.instance_extensions() { Ok(supported) => supported.intersection(&ideal), Err(_) => InstanceExtensions::none(), } diff --git a/vulkano/Cargo.toml b/vulkano/Cargo.toml index 7c0bcea5e5..4050270af7 100644 --- a/vulkano/Cargo.toml +++ b/vulkano/Cargo.toml @@ -16,7 +16,7 @@ build = "build.rs" [dependencies] # When updating Ash, also update vk.xml to the same Vulkan patch version that Ash uses. # All versions of vk.xml can be found at https://github.com/KhronosGroup/Vulkan-Headers/commits/main/registry/vk.xml. -ash = "0.36" +ash = { version = "0.36", default_features = false, features = ["debug"] } bytemuck = { version = "1.7", features = ["derive", "extern_crate_std", "min_const_generics"] } crossbeam-queue = "0.3" half = "1.8" @@ -24,7 +24,6 @@ lazy_static = "1.4" nalgebra = { version = "0.30.0", optional = true } parking_lot = { version = "0.12", features = ["send_guard"] } rangemap = { git = "https://github.com/vulkano-rs/rangemap", branch = "range-split" } -shared_library = "0.1" smallvec = "1.8" [build-dependencies] @@ -37,3 +36,11 @@ regex = "1.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" vk-parse = "0.7" + + +[features] +default = ["loaded"] +# Link the Vulkan loader at compile time. +linked = ["ash/linked"] +# Support searching for the Vulkan loader manually at runtime. +loaded = ["ash/loaded"] diff --git a/vulkano/build.rs b/vulkano/build.rs index a2e9ce84a3..eeff42a11f 100644 --- a/vulkano/build.rs +++ b/vulkano/build.rs @@ -6,24 +6,9 @@ // at your option. All files in the project carrying such // notice may not be copied, modified, or distributed except // according to those terms. - -use std::env; - mod autogen; fn main() { - let target = env::var("TARGET").unwrap(); - if target.contains("apple-ios") { - println!("cargo:rustc-link-search=framework=/Library/Frameworks/"); - println!("cargo:rustc-link-lib=c++"); - println!("cargo:rustc-link-lib=framework=MoltenVK"); - println!("cargo:rustc-link-lib=framework=Metal"); - println!("cargo:rustc-link-lib=framework=IOSurface"); - println!("cargo:rustc-link-lib=framework=QuartzCore"); - println!("cargo:rustc-link-lib=framework=UIKit"); - println!("cargo:rustc-link-lib=framework=Foundation"); - } - // Run autogen println!("cargo:rerun-if-changed=vk.xml"); autogen::autogen(); diff --git a/vulkano/src/device/extensions.rs b/vulkano/src/device/extensions.rs index b8c21d0d61..91fcb958f4 100644 --- a/vulkano/src/device/extensions.rs +++ b/vulkano/src/device/extensions.rs @@ -8,11 +8,9 @@ // according to those terms. use crate::device::physical::PhysicalDevice; -pub use crate::extensions::{ - ExtensionRestriction, ExtensionRestrictionError, OneOfRequirements, SupportedExtensionsError, -}; +pub use crate::extensions::{ExtensionRestriction, ExtensionRestrictionError, OneOfRequirements}; use crate::instance::InstanceExtensions; -use crate::Version; +use crate::{OomError, Version}; use std::ffi::{CStr, CString}; use std::fmt::Formatter; @@ -25,9 +23,7 @@ impl DeviceExtensions { since = "0.25", note = "Use PhysicalDevice::supported_extensions instead" )] - pub fn supported_by_device_raw( - physical_device: PhysicalDevice, - ) -> Result { + pub fn supported_by_device_raw(physical_device: PhysicalDevice) -> Result { Ok(*physical_device.supported_extensions()) } diff --git a/vulkano/src/device/mod.rs b/vulkano/src/device/mod.rs index 534711afe8..c8282a66d3 100644 --- a/vulkano/src/device/mod.rs +++ b/vulkano/src/device/mod.rs @@ -17,11 +17,12 @@ //! ```no_run //! use vulkano::device::physical::PhysicalDevice; //! use vulkano::device::{Device, DeviceCreateInfo, DeviceExtensions, Features, QueueCreateInfo}; -//! use vulkano::instance::{Instance, InstanceExtensions}; +//! use vulkano::instance::{Instance, InstanceExtensions, VulkanLibrary}; //! use vulkano::Version; //! //! // Creating the instance. See the documentation of the `instance` module. -//! let instance = match Instance::new(Default::default()) { +//! let lib = VulkanLibrary::default(); +//! let instance = match Instance::new(lib, Default::default()) { //! Ok(i) => i, //! Err(err) => panic!("Couldn't build instance: {:?}", err) //! }; @@ -111,7 +112,7 @@ use crate::{ }; pub use crate::{ device::extensions::DeviceExtensions, - extensions::{ExtensionRestriction, ExtensionRestrictionError, SupportedExtensionsError}, + extensions::{ExtensionRestriction, ExtensionRestrictionError}, fns::DeviceFunctions, }; use ash::vk::Handle; diff --git a/vulkano/src/device/physical.rs b/vulkano/src/device/physical.rs index e1bc2992fb..e290addf90 100644 --- a/vulkano/src/device/physical.rs +++ b/vulkano/src/device/physical.rs @@ -282,10 +282,12 @@ fn init_info2(instance: &Instance, info: &mut PhysicalDeviceInfo) { /// ```no_run /// # use vulkano::instance::Instance; /// # use vulkano::instance::InstanceExtensions; +/// # use vulkano::instance::VulkanLibrary; /// # use vulkano::Version; /// use vulkano::device::physical::PhysicalDevice; /// -/// # let instance = Instance::new(Default::default()).unwrap(); +/// let lib = VulkanLibrary::default(); +/// let instance = Instance::new(lib, Default::default()).unwrap(); /// for physical_device in PhysicalDevice::enumerate(&instance) { /// print_infos(physical_device); /// } @@ -309,10 +311,12 @@ impl<'a> PhysicalDevice<'a> { /// ```no_run /// # use vulkano::instance::Instance; /// # use vulkano::instance::InstanceExtensions; + /// # use vulkano::instance::VulkanLibrary; /// # use vulkano::Version; /// use vulkano::device::physical::PhysicalDevice; /// - /// # let instance = Instance::new(Default::default()).unwrap(); + /// let lib = VulkanLibrary::default(); + /// let instance = Instance::new(lib, Default::default()).unwrap(); /// for physical_device in PhysicalDevice::enumerate(&instance) { /// println!("Available device: {}", physical_device.properties().device_name); /// } @@ -341,10 +345,12 @@ impl<'a> PhysicalDevice<'a> { /// ```no_run /// use vulkano::instance::Instance; /// use vulkano::instance::InstanceExtensions; + /// use vulkano::instance::VulkanLibrary; /// use vulkano::device::physical::PhysicalDevice; /// use vulkano::Version; /// - /// let instance = Instance::new(Default::default()).unwrap(); + /// let lib = VulkanLibrary::default(); + /// let instance = Instance::new(lib, Default::default()).unwrap(); /// let first_physical_device = PhysicalDevice::from_index(&instance, 0).unwrap(); /// ``` #[inline] diff --git a/vulkano/src/extensions.rs b/vulkano/src/extensions.rs index 088d61637f..81e1491953 100644 --- a/vulkano/src/extensions.rs +++ b/vulkano/src/extensions.rs @@ -7,74 +7,10 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use crate::instance::loader::LoadingError; -use crate::Error; -use crate::OomError; use crate::Version; use std::error; use std::fmt::{Display, Error as FmtError, Formatter}; -/// Error that can happen when loading the list of layers. -#[derive(Clone, Debug)] -pub enum SupportedExtensionsError { - /// Failed to load the Vulkan shared library. - LoadingError(LoadingError), - /// Not enough memory. - OomError(OomError), -} - -impl error::Error for SupportedExtensionsError { - #[inline] - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match *self { - SupportedExtensionsError::LoadingError(ref err) => Some(err), - SupportedExtensionsError::OomError(ref err) => Some(err), - } - } -} - -impl Display for SupportedExtensionsError { - #[inline] - fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { - write!( - fmt, - "{}", - match *self { - SupportedExtensionsError::LoadingError(_) => - "failed to load the Vulkan shared library", - SupportedExtensionsError::OomError(_) => "not enough memory available", - } - ) - } -} - -impl From for SupportedExtensionsError { - #[inline] - fn from(err: OomError) -> SupportedExtensionsError { - SupportedExtensionsError::OomError(err) - } -} - -impl From for SupportedExtensionsError { - #[inline] - fn from(err: LoadingError) -> SupportedExtensionsError { - SupportedExtensionsError::LoadingError(err) - } -} - -impl From for SupportedExtensionsError { - #[inline] - fn from(err: Error) -> SupportedExtensionsError { - match err { - err @ Error::OutOfHostMemory => SupportedExtensionsError::OomError(OomError::from(err)), - err @ Error::OutOfDeviceMemory => { - SupportedExtensionsError::OomError(OomError::from(err)) - } - _ => panic!("unexpected error: {:?}", err), - } - } -} - /// An error that can happen when enabling an extension on an instance or device. #[derive(Clone, Copy, Debug)] pub struct ExtensionRestrictionError { diff --git a/vulkano/src/instance/extensions.rs b/vulkano/src/instance/extensions.rs index 83fd034f89..da3626644f 100644 --- a/vulkano/src/instance/extensions.rs +++ b/vulkano/src/instance/extensions.rs @@ -7,79 +7,24 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use crate::check_errors; -pub use crate::extensions::{ - ExtensionRestriction, ExtensionRestrictionError, OneOfRequirements, SupportedExtensionsError, -}; -use crate::instance::loader; -use crate::instance::loader::LoadingError; -use crate::Version; +pub use crate::extensions::{ExtensionRestriction, ExtensionRestrictionError, OneOfRequirements}; +use crate::{OomError, Version}; use std::ffi::{CStr, CString}; use std::fmt::Formatter; -use std::ptr; + +use super::VulkanLibrary; // Generated by build.rs include!(concat!(env!("OUT_DIR"), "/instance_extensions.rs")); -impl InstanceExtensions { - /// See the docs of supported_by_core(). - pub fn supported_by_core_raw() -> Result { - InstanceExtensions::supported_by_core_raw_with_loader(loader::auto_loader()?) - } - - /// Returns an `InstanceExtensions` object with extensions supported by the core driver. - pub fn supported_by_core() -> Result { - match InstanceExtensions::supported_by_core_raw() { - Ok(l) => Ok(l), - Err(SupportedExtensionsError::LoadingError(e)) => Err(e), - Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e), - } - } - - /// Same as `supported_by_core`, but allows specifying a loader. - pub fn supported_by_core_with_loader( - ptrs: &loader::FunctionPointers, - ) -> Result - where - L: loader::Loader, - { - match InstanceExtensions::supported_by_core_raw_with_loader(ptrs) { - Ok(l) => Ok(l), - Err(SupportedExtensionsError::LoadingError(e)) => Err(e), - Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e), - } - } - - /// See the docs of supported_by_core(). - pub fn supported_by_core_raw_with_loader( - ptrs: &loader::FunctionPointers, - ) -> Result - where - L: loader::Loader, - { - let fns = ptrs.fns(); - - let properties: Vec = unsafe { - let mut num = 0; - check_errors(fns.v1_0.enumerate_instance_extension_properties( - ptr::null(), - &mut num, - ptr::null_mut(), - ))?; - - let mut properties = Vec::with_capacity(num as usize); - check_errors(fns.v1_0.enumerate_instance_extension_properties( - ptr::null(), - &mut num, - properties.as_mut_ptr(), - ))?; - properties.set_len(num as usize); - properties - }; +impl VulkanLibrary { + pub fn instance_extensions(&self) -> Result { + let properties: Vec = + self.entry().enumerate_instance_extension_properties(None)?; - Ok(Self::from(properties.iter().map(|property| unsafe { - CStr::from_ptr(property.extension_name.as_ptr()) - }))) + Ok(InstanceExtensions::from(properties.iter().map( + |property| unsafe { CStr::from_ptr(property.extension_name.as_ptr()) }, + ))) } } diff --git a/vulkano/src/instance/layers.rs b/vulkano/src/instance/layers.rs index 4c6b9f0217..2b3ce4de9e 100644 --- a/vulkano/src/instance/layers.rs +++ b/vulkano/src/instance/layers.rs @@ -7,16 +7,11 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use crate::check_errors; -use crate::instance::loader; -use crate::instance::loader::LoadingError; -use crate::Error; use crate::OomError; use crate::Version; -use std::error; use std::ffi::CStr; -use std::fmt; -use std::ptr; + +use super::VulkanLibrary; /// Queries the list of layers that are available when creating an instance. /// @@ -35,38 +30,17 @@ use std::ptr; /// # Example /// /// ```no_run -/// use vulkano::instance; +/// use vulkano::instance::VulkanLibrary; /// -/// for layer in instance::layers_list().unwrap() { +/// let lib = VulkanLibrary::default(); +/// for layer in lib.layers().unwrap() { /// println!("Available layer: {}", layer.name()); /// } /// ``` -pub fn layers_list() -> Result, LayersListError> { - layers_list_from_loader(loader::auto_loader()?) -} - -/// Same as `layers_list()`, but allows specifying a loader. -pub fn layers_list_from_loader( - ptrs: &loader::FunctionPointers, -) -> Result, LayersListError> -where - L: loader::Loader, -{ - unsafe { - let fns = ptrs.fns(); - - let mut num = 0; - check_errors( - fns.v1_0 - .enumerate_instance_layer_properties(&mut num, ptr::null_mut()), - )?; - let mut layers: Vec = Vec::with_capacity(num as usize); - check_errors({ - fns.v1_0 - .enumerate_instance_layer_properties(&mut num, layers.as_mut_ptr()) - })?; - layers.set_len(num as usize); +impl VulkanLibrary { + pub fn layers(&self) -> Result, OomError> { + let layers = self.entry().enumerate_instance_layer_properties()?; Ok(layers.into_iter().map(|p| LayerProperties { props: p })) } @@ -87,9 +61,10 @@ impl LayerProperties { /// # Example /// /// ```no_run - /// use vulkano::instance; + /// use vulkano::instance::VulkanLibrary; /// - /// for layer in instance::layers_list().unwrap() { + /// let lib = VulkanLibrary::default(); + /// for layer in lib.layers().unwrap() { /// println!("Layer name: {}", layer.name()); /// } /// ``` @@ -109,9 +84,10 @@ impl LayerProperties { /// # Example /// /// ```no_run - /// use vulkano::instance; + /// use vulkano::instance::VulkanLibrary; /// - /// for layer in instance::layers_list().unwrap() { + /// let lib = VulkanLibrary::default(); + /// for layer in lib.layers().unwrap() { /// println!("Layer description: {}", layer.description()); /// } /// ``` @@ -129,10 +105,11 @@ impl LayerProperties { /// # Example /// /// ```no_run - /// use vulkano::instance; /// use vulkano::instance::Version; + /// use vulkano::instance::VulkanLibrary; /// - /// for layer in instance::layers_list().unwrap() { + /// let lib = VulkanLibrary::default(); + /// for layer in lib.layers().unwrap() { /// if layer.vulkan_version() >= Version::major_minor(2, 0) { /// println!("Layer {} requires Vulkan 2.0", layer.name()); /// } @@ -150,9 +127,10 @@ impl LayerProperties { /// # Example /// /// ```no_run - /// use vulkano::instance; + /// use vulkano::instance::VulkanLibrary; /// - /// for layer in instance::layers_list().unwrap() { + /// let lib = VulkanLibrary::default(); + /// for layer in lib.layers().unwrap() { /// println!("Layer {} - Version: {}", layer.name(), layer.implementation_version()); /// } /// ``` @@ -161,76 +139,23 @@ impl LayerProperties { self.props.implementation_version } } - -/// Error that can happen when loading the list of layers. -#[derive(Clone, Debug)] -pub enum LayersListError { - /// Failed to load the Vulkan shared library. - LoadingError(LoadingError), - /// Not enough memory. - OomError(OomError), -} - -impl error::Error for LayersListError { - #[inline] - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match *self { - LayersListError::LoadingError(ref err) => Some(err), - LayersListError::OomError(ref err) => Some(err), - } - } -} - -impl fmt::Display for LayersListError { - #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!( - fmt, - "{}", - match *self { - LayersListError::LoadingError(_) => "failed to load the Vulkan shared library", - LayersListError::OomError(_) => "not enough memory available", - } - ) - } -} - -impl From for LayersListError { - #[inline] - fn from(err: OomError) -> LayersListError { - LayersListError::OomError(err) - } -} - -impl From for LayersListError { - #[inline] - fn from(err: LoadingError) -> LayersListError { - LayersListError::LoadingError(err) - } -} - -impl From for LayersListError { - #[inline] - fn from(err: Error) -> LayersListError { - match err { - err @ Error::OutOfHostMemory => LayersListError::OomError(OomError::from(err)), - err @ Error::OutOfDeviceMemory => LayersListError::OomError(OomError::from(err)), - _ => panic!("unexpected error: {:?}", err), - } - } -} - #[cfg(test)] mod tests { - use crate::instance; + use crate::instance::VulkanLibrary; #[test] fn layers_list() { - let mut list = match instance::layers_list() { + #[cfg(feature="linked")] + let lib = VulkanLibrary::linked(); + + #[cfg(feature="loaded")] + let lib = match unsafe { VulkanLibrary::load() } { Ok(l) => l, Err(_) => return, }; + let mut list = lib.layers().unwrap(); + while let Some(_) = list.next() {} } } diff --git a/vulkano/src/instance/library.rs b/vulkano/src/instance/library.rs new file mode 100644 index 0000000000..e290030286 --- /dev/null +++ b/vulkano/src/instance/library.rs @@ -0,0 +1,50 @@ +// Copyright (c) 2022 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +#[cfg(feature = "loaded")] +pub use ash::LoadingError; + +/// Wraps the `ash::Entry` type which contains function pointers into the Vulkan library. +pub struct VulkanLibrary { + entry: ash::Entry, +} + +impl VulkanLibrary { + /// Load entry points from a Vulkan loader linked at compile time. + #[cfg(feature = "linked")] + pub fn linked() -> VulkanLibrary { + let entry = ash::Entry::linked(); + VulkanLibrary { entry } + } + + /// Load default Vulkan library for the current platform with `libloading`. + #[cfg(feature = "loaded")] + pub unsafe fn load() -> Result { + let entry = ash::Entry::load()?; + Ok(VulkanLibrary { entry }) + } + + pub fn entry(&self) -> &ash::Entry { + &self.entry + } +} + +impl Default for VulkanLibrary { + /// Returns the default vulkan library. The way that the Vulkan library was + /// loaded depends on the feature flags. + fn default() -> Self { + #[cfg(feature = "linked")] + let entry = VulkanLibrary::linked(); + + #[cfg(feature = "loaded")] + let entry = unsafe { VulkanLibrary::load().unwrap() }; + + entry + } +} diff --git a/vulkano/src/instance/loader.rs b/vulkano/src/instance/loader.rs deleted file mode 100644 index 55b5647efa..0000000000 --- a/vulkano/src/instance/loader.rs +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -//! Vulkan implementation loading system. -//! -//! Before vulkano can do anything, it first needs to find an implementation of Vulkan. A Vulkan -//! implementation is defined as a single `vkGetInstanceProcAddr` function, which can be accessed -//! through the `Loader` trait. -//! -//! This module provides various implementations of the `Loader` trait. -//! -//! Once you have a struct that implements `Loader`, you can create a `FunctionPointers` struct -//! from it and use this `FunctionPointers` struct to build an `Instance`. -//! -//! By default vulkano will use the `auto_loader()` function, which tries to automatically load -//! a Vulkan implementation from the system. - -use crate::check_errors; -pub use crate::fns::EntryFunctions; -use crate::OomError; -use crate::SafeDeref; -use crate::Version; -use lazy_static::lazy_static; -use shared_library; -use std::error; -use std::ffi::CStr; -use std::fmt; -use std::mem; -use std::ops::Deref; -use std::os::raw::c_char; -use std::os::raw::c_void; -use std::path::Path; - -/// Implemented on objects that grant access to a Vulkan implementation. -pub unsafe trait Loader: Send + Sync { - /// Calls the `vkGetInstanceProcAddr` function. The parameters are the same. - /// - /// The returned function must stay valid for as long as `self` is alive. - fn get_instance_proc_addr( - &self, - instance: ash::vk::Instance, - name: *const c_char, - ) -> *const c_void; -} - -unsafe impl Loader for T -where - T: SafeDeref + Send + Sync, - T::Target: Loader, -{ - #[inline] - fn get_instance_proc_addr( - &self, - instance: ash::vk::Instance, - name: *const c_char, - ) -> *const c_void { - (**self).get_instance_proc_addr(instance, name) - } -} - -impl fmt::Debug for dyn Loader { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - Ok(()) - } -} - -/// Implementation of `Loader` that loads Vulkan from a dynamic library. -pub struct DynamicLibraryLoader { - vk_lib: shared_library::dynamic_library::DynamicLibrary, - get_proc_addr: - extern "system" fn(instance: ash::vk::Instance, pName: *const c_char) -> *const c_void, -} - -impl DynamicLibraryLoader { - /// Tries to load the dynamic library at the given path, and tries to - /// load `vkGetInstanceProcAddr` in it. - /// - /// # Safety - /// - /// - The dynamic library must be a valid Vulkan implementation. - /// - pub unsafe fn new

(path: P) -> Result - where - P: AsRef, - { - let vk_lib = shared_library::dynamic_library::DynamicLibrary::open(Some(path.as_ref())) - .map_err(LoadingError::LibraryLoadFailure)?; - - let get_proc_addr = { - let ptr: *mut c_void = vk_lib - .symbol("vkGetInstanceProcAddr") - .map_err(|_| LoadingError::MissingEntryPoint("vkGetInstanceProcAddr".to_owned()))?; - mem::transmute(ptr) - }; - - Ok(DynamicLibraryLoader { - vk_lib, - get_proc_addr, - }) - } -} - -unsafe impl Loader for DynamicLibraryLoader { - #[inline] - fn get_instance_proc_addr( - &self, - instance: ash::vk::Instance, - name: *const c_char, - ) -> *const c_void { - (self.get_proc_addr)(instance, name) - } -} - -/// Wraps around a loader and contains function pointers. -#[derive(Debug)] -pub struct FunctionPointers { - loader: L, - fns: EntryFunctions, -} - -impl FunctionPointers { - /// Loads some global function pointer from the loader. - pub fn new(loader: L) -> FunctionPointers - where - L: Loader, - { - let fns = EntryFunctions::load(|name| unsafe { - mem::transmute(loader.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr())) - }); - - FunctionPointers { loader, fns } - } - - /// Returns the collection of Vulkan entry points from the Vulkan loader. - #[inline] - pub fn fns(&self) -> &EntryFunctions { - &self.fns - } - - /// Returns the highest Vulkan version that is supported for instances. - pub fn api_version(&self) -> Result - where - L: Loader, - { - // Per the Vulkan spec: - // If the vkGetInstanceProcAddr returns NULL for vkEnumerateInstanceVersion, it is a - // Vulkan 1.0 implementation. Otherwise, the application can call vkEnumerateInstanceVersion - // to determine the version of Vulkan. - unsafe { - let name = CStr::from_bytes_with_nul_unchecked(b"vkEnumerateInstanceVersion\0"); - let func = self.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr()); - - if func.is_null() { - Ok(Version { - major: 1, - minor: 0, - patch: 0, - }) - } else { - type Pfn = extern "system" fn(pApiVersion: *mut u32) -> ash::vk::Result; - let func: Pfn = mem::transmute(func); - let mut api_version = 0; - check_errors(func(&mut api_version))?; - Ok(Version::from(api_version)) - } - } - } - - /// Calls `get_instance_proc_addr` on the underlying loader. - #[inline] - pub fn get_instance_proc_addr( - &self, - instance: ash::vk::Instance, - name: *const c_char, - ) -> *const c_void - where - L: Loader, - { - self.loader.get_instance_proc_addr(instance, name) - } -} - -/// Expression that returns a loader that assumes that Vulkan is linked to the executable you're -/// compiling. -/// -/// If you use this macro, you must linked to a library that provides the `vkGetInstanceProcAddr` -/// symbol. -/// -/// This is provided as a macro and not as a regular function, because the macro contains an -/// `extern {}` block. -// TODO: should this be unsafe? -#[macro_export] -macro_rules! statically_linked_vulkan_loader { - () => {{ - extern "C" { - fn vkGetInstanceProcAddr( - instance: ash::vk::Instance, - pName: *const c_char, - ) -> ash::vk::PFN_vkVoidFunction; - } - - struct StaticallyLinkedVulkanLoader; - unsafe impl Loader for StaticallyLinkedVulkanLoader { - fn get_instance_proc_addr( - &self, - instance: ash::vk::Instance, - name: *const c_char, - ) -> extern "system" fn() -> () { - unsafe { vkGetInstanceProcAddr(instance, name) } - } - } - - StaticallyLinkedVulkanLoader - }}; -} - -/// Returns the default `FunctionPointers` for this system. -/// -/// This function tries to auto-guess where to find the Vulkan implementation, and loads it in a -/// `lazy_static!`. The content of the lazy_static is then returned, or an error if we failed to -/// load Vulkan. -pub fn auto_loader() -> Result<&'static FunctionPointers>, LoadingError> { - #[cfg(target_os = "ios")] - #[allow(non_snake_case)] - fn def_loader_impl() -> Result, LoadingError> { - let loader = statically_linked_vulkan_loader!(); - Ok(Box::new(loader)) - } - - #[cfg(not(target_os = "ios"))] - fn def_loader_impl() -> Result, LoadingError> { - #[cfg(windows)] - fn get_path() -> &'static Path { - Path::new("vulkan-1.dll") - } - #[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))] - fn get_path() -> &'static Path { - Path::new("libvulkan.so.1") - } - #[cfg(target_os = "macos")] - fn get_path() -> &'static Path { - Path::new("libvulkan.1.dylib") - } - #[cfg(target_os = "android")] - fn get_path() -> &'static Path { - Path::new("libvulkan.so") - } - - let loader = unsafe { DynamicLibraryLoader::new(get_path())? }; - - Ok(Box::new(loader)) - } - - lazy_static! { - static ref DEFAULT_LOADER: Result>, LoadingError> = - def_loader_impl().map(FunctionPointers::new); - } - - match DEFAULT_LOADER.deref() { - &Ok(ref ptr) => Ok(ptr), - &Err(ref err) => Err(err.clone()), - } -} - -/// Error that can happen when loading the Vulkan loader. -#[derive(Debug, Clone)] -pub enum LoadingError { - /// Failed to load the Vulkan shared library. - LibraryLoadFailure(String), // TODO: meh for error type, but this needs changes in shared_library - - /// One of the entry points required to be supported by the Vulkan implementation is missing. - MissingEntryPoint(String), -} - -impl error::Error for LoadingError { - /*#[inline] - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match *self { - LoadingError::LibraryLoadFailure(ref err) => Some(err), - _ => None - } - }*/ -} - -impl fmt::Display for LoadingError { - #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!( - fmt, - "{}", - match *self { - LoadingError::LibraryLoadFailure(_) => "failed to load the Vulkan shared library", - LoadingError::MissingEntryPoint(_) => { - "one of the entry points required to be supported by the Vulkan implementation \ - is missing" - } - } - ) - } -} - -#[cfg(test)] -mod tests { - use crate::instance::loader::DynamicLibraryLoader; - use crate::instance::loader::LoadingError; - - #[test] - fn dl_open_error() { - unsafe { - match DynamicLibraryLoader::new("_non_existing_library.void") { - Err(LoadingError::LibraryLoadFailure(_)) => (), - _ => panic!(), - } - } - } -} diff --git a/vulkano/src/instance/mod.rs b/vulkano/src/instance/mod.rs index 079a7e67c0..36a8f37d3f 100644 --- a/vulkano/src/instance/mod.rs +++ b/vulkano/src/instance/mod.rs @@ -16,9 +16,11 @@ //! ```no_run //! use vulkano::instance::Instance; //! use vulkano::instance::InstanceExtensions; +//! use vulkano::instance::VulkanLibrary; //! use vulkano::Version; //! -//! let instance = match Instance::new(Default::default()) { +//! let lib = VulkanLibrary::default(); +//! let instance = match Instance::new(lib, Default::default()) { //! Ok(i) => i, //! Err(err) => panic!("Couldn't build instance: {:?}", err) //! }; @@ -30,10 +32,12 @@ //! ```no_run //! # use vulkano::instance::Instance; //! # use vulkano::instance::InstanceExtensions; +//! # use vulkano::instance::VulkanLibrary; //! # use vulkano::Version; //! use vulkano::device::physical::PhysicalDevice; //! -//! # let instance = Instance::new(Default::default()).unwrap(); +//! let lib = VulkanLibrary::default(); +//! # let instance = Instance::new(lib, Default::default()).unwrap(); //! for physical_device in PhysicalDevice::enumerate(&instance) { //! println!("Available device: {}", physical_device.properties().device_name); //! } @@ -52,22 +56,15 @@ //! `device` module for more info. pub use self::extensions::InstanceExtensions; -pub use self::layers::layers_list; pub use self::layers::LayerProperties; -pub use self::layers::LayersListError; -pub use self::loader::LoadingError; -use crate::check_errors; use crate::device::physical::{init_physical_devices, PhysicalDeviceInfo}; -pub use crate::extensions::{ - ExtensionRestriction, ExtensionRestrictionError, SupportedExtensionsError, -}; +pub use crate::extensions::{ExtensionRestriction, ExtensionRestrictionError}; pub use crate::fns::InstanceFunctions; -use crate::instance::loader::FunctionPointers; -use crate::instance::loader::Loader; pub use crate::version::Version; use crate::Error; use crate::OomError; use crate::VulkanObject; +pub use library::VulkanLibrary; use smallvec::SmallVec; use std::error; use std::ffi::CString; @@ -82,7 +79,7 @@ use std::sync::Arc; pub mod debug; pub(crate) mod extensions; mod layers; -pub mod loader; +mod library; /// An instance of a Vulkan context. This is the main object that should be created by an /// application before everything else. @@ -98,10 +95,11 @@ pub mod loader; /// ```no_run /// # #[macro_use] extern crate vulkano; /// # fn main() { -/// use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions}; +/// use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary}; /// use vulkano::Version; /// -/// let _instance = Instance::new(InstanceCreateInfo::application_from_cargo_toml()).unwrap(); +/// let lib = VulkanLibrary::default(); +/// let _instance = Instance::new(lib, InstanceCreateInfo::application_from_cargo_toml()).unwrap(); /// # } /// ``` /// @@ -152,7 +150,7 @@ pub mod loader; /// succeed on anything else than an Android-running device. /// /// ```no_run -/// use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions}; +/// use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary}; /// use vulkano::Version; /// /// let extensions = InstanceExtensions { @@ -161,7 +159,8 @@ pub mod loader; /// .. InstanceExtensions::none() /// }; /// -/// let instance = match Instance::new(InstanceCreateInfo { +/// let lib = VulkanLibrary::default(); +/// let instance = match Instance::new(lib, InstanceCreateInfo { /// enabled_extensions: extensions, /// ..Default::default() /// }) { @@ -197,19 +196,20 @@ pub mod loader; /// ``` /// # use std::sync::Arc; /// # use std::error::Error; -/// # use vulkano::instance; /// # use vulkano::instance::Instance; /// # use vulkano::instance::InstanceCreateInfo; /// # use vulkano::instance::InstanceExtensions; +/// # use vulkano::instance::VulkanLibrary; /// # use vulkano::Version; /// # fn test() -> Result, Box> { /// // For the sake of the example, we activate all the layers that /// // contain the word "foo" in their description. -/// let layers: Vec<_> = instance::layers_list()? +/// let lib = VulkanLibrary::default(); +/// let layers: Vec<_> = lib.layers()? /// .filter(|l| l.description().contains("foo")) /// .collect(); /// -/// let instance = Instance::new(InstanceCreateInfo { +/// let instance = Instance::new(lib, InstanceCreateInfo { /// enabled_layers: layers.iter().map(|l| l.name().to_owned()).collect(), /// ..Default::default() /// })?; @@ -217,7 +217,6 @@ pub mod loader; /// # } /// ``` // TODO: mention that extensions must be supported by layers as well -#[derive(Debug)] pub struct Instance { handle: ash::vk::Instance, fns: InstanceFunctions, @@ -226,10 +225,24 @@ pub struct Instance { api_version: Version, enabled_extensions: InstanceExtensions, enabled_layers: Vec, - function_pointers: OwnedOrRef>>, + lib: VulkanLibrary, max_api_version: Version, } +impl std::fmt::Debug for Instance { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Instance") + .field("handle", &self.handle) + .field("fns", &self.fns) + .field("physical_device_infos", &self.physical_device_infos) + .field("api_version", &self.api_version) + .field("enabled_extensions", &self.enabled_extensions) + .field("enabled_layers", &self.enabled_layers) + .field("max_api_version", &self.max_api_version) + .finish() + } +} + // TODO: fix the underlying cause instead impl ::std::panic::UnwindSafe for Instance {} impl ::std::panic::RefUnwindSafe for Instance {} @@ -242,7 +255,10 @@ impl Instance { /// - Panics if any version numbers in `create_info` contain a field too large to be converted /// into a Vulkan version number. /// - Panics if `create_info.max_api_version` is not at least `V1_0`. - pub fn new(create_info: InstanceCreateInfo) -> Result, InstanceCreationError> { + pub fn new( + lib: VulkanLibrary, + create_info: InstanceCreateInfo, + ) -> Result, InstanceCreationError> { let InstanceCreateInfo { application_name, application_version, @@ -250,19 +266,16 @@ impl Instance { enabled_layers, engine_name, engine_version, - function_pointers, max_api_version, _ne: _, } = create_info; - let function_pointers = if let Some(function_pointers) = function_pointers { - OwnedOrRef::Owned(function_pointers) - } else { - OwnedOrRef::Ref(loader::auto_loader()?) - }; - let (api_version, max_api_version) = { - let api_version = function_pointers.api_version()?; + let api_version = lib + .entry() + .try_enumerate_instance_version() + .map_err(OomError::from)? + .map_or(Version::V1_0, Version::from); let max_api_version = if let Some(max_api_version) = max_api_version { max_api_version } else if api_version < Version::V1_1 { @@ -278,10 +291,7 @@ impl Instance { assert!(max_api_version >= Version::V1_0); // Check if the extensions are correct - enabled_extensions.check_requirements( - &InstanceExtensions::supported_by_core_with_loader(&function_pointers)?, - api_version, - )?; + enabled_extensions.check_requirements(&lib.instance_extensions()?, api_version)?; // FIXME: check whether each layer is supported let enabled_layers_cstr: Vec = enabled_layers @@ -331,18 +341,18 @@ impl Instance { // Creating the Vulkan instance. let handle = unsafe { let mut output = MaybeUninit::uninit(); - let fns = function_pointers.fns(); - check_errors( - fns.v1_0 - .create_instance(&create_info, ptr::null(), output.as_mut_ptr()), - )?; + lib.entry() + .fp_v1_0() + .create_instance(&create_info, ptr::null(), output.as_mut_ptr()) + .result()?; output.assume_init() }; // Loading the function pointers of the newly-created instance. let fns = { - InstanceFunctions::load(|name| { - function_pointers.get_instance_proc_addr(handle, name.as_ptr()) + InstanceFunctions::load(|name| unsafe { + let fn_ptr = lib.entry().get_instance_proc_addr(handle, name.as_ptr()); + std::mem::transmute(fn_ptr) }) }; @@ -354,7 +364,7 @@ impl Instance { api_version, enabled_extensions, enabled_layers, - function_pointers, + lib, max_api_version, }; @@ -465,12 +475,6 @@ pub struct InstanceCreateInfo { /// The default value is zero. pub engine_version: Version, - /// Function pointers loaded from a custom loader. - /// - /// You can use this if you want to load the Vulkan API explicitly, rather than using Vulkano's - /// default. - pub function_pointers: Option>>, - /// The highest Vulkan API version that the application will use with the instance. /// /// Usually, you will want to leave this at the default. @@ -492,7 +496,6 @@ impl Default for InstanceCreateInfo { enabled_layers: Vec::new(), engine_name: None, engine_version: Version::major_minor(0, 0), - function_pointers: None, max_api_version: None, _ne: crate::NonExhaustive(()), } @@ -524,8 +527,6 @@ impl InstanceCreateInfo { /// Error that can happen when creating an instance. #[derive(Clone, Debug)] pub enum InstanceCreationError { - /// Failed to load the Vulkan shared library. - LoadingError(LoadingError), /// Not enough memory. OomError(OomError), /// Failed to initialize for an implementation-specific reason. @@ -544,7 +545,6 @@ impl error::Error for InstanceCreationError { #[inline] fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { - InstanceCreationError::LoadingError(ref err) => Some(err), InstanceCreationError::OomError(ref err) => Some(err), _ => None, } @@ -555,9 +555,6 @@ impl fmt::Display for InstanceCreationError { #[inline] fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - InstanceCreationError::LoadingError(_) => { - write!(fmt, "failed to load the Vulkan shared library") - } InstanceCreationError::OomError(_) => write!(fmt, "not enough memory available"), InstanceCreationError::InitializationFailed => write!(fmt, "initialization failed"), InstanceCreationError::LayerNotPresent => write!(fmt, "layer not present"), @@ -575,13 +572,6 @@ impl From for InstanceCreationError { } } -impl From for InstanceCreationError { - #[inline] - fn from(err: LoadingError) -> InstanceCreationError { - InstanceCreationError::LoadingError(err) - } -} - impl From for InstanceCreationError { #[inline] fn from(err: ExtensionRestrictionError) -> Self { @@ -604,6 +594,29 @@ impl From for InstanceCreationError { } } +impl From for InstanceCreationError { + #[inline] + fn from(err: ash::vk::Result) -> InstanceCreationError { + match err { + ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY => { + InstanceCreationError::OomError(OomError::OutOfHostMemory) + } + ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => { + InstanceCreationError::OomError(OomError::OutOfDeviceMemory) + } + ash::vk::Result::ERROR_INITIALIZATION_FAILED => { + InstanceCreationError::InitializationFailed + } + ash::vk::Result::ERROR_LAYER_NOT_PRESENT => InstanceCreationError::LayerNotPresent, + ash::vk::Result::ERROR_EXTENSION_NOT_PRESENT => { + InstanceCreationError::ExtensionNotPresent + } + ash::vk::Result::ERROR_INCOMPATIBLE_DRIVER => InstanceCreationError::IncompatibleDriver, + _ => panic!("unexpected error: {:?}", err), + } + } +} + // Same as Cow but less annoying. #[derive(Debug)] enum OwnedOrRef { diff --git a/vulkano/src/lib.rs b/vulkano/src/lib.rs index cadf45f012..a8c77d14bc 100644 --- a/vulkano/src/lib.rs +++ b/vulkano/src/lib.rs @@ -160,6 +160,17 @@ impl From for OomError { } } +impl From for OomError { + #[inline] + fn from(err: ash::vk::Result) -> OomError { + match err { + ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY => OomError::OutOfHostMemory, + ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => OomError::OutOfDeviceMemory, + _ => panic!("unexpected error: {:?}", err), + } + } +} + /// All possible success codes returned by any Vulkan function. #[derive(Debug, Copy, Clone)] #[repr(i32)] diff --git a/vulkano/src/swapchain/mod.rs b/vulkano/src/swapchain/mod.rs index 9eab939f57..f679245664 100644 --- a/vulkano/src/swapchain/mod.rs +++ b/vulkano/src/swapchain/mod.rs @@ -55,7 +55,7 @@ //! //! ```no_run //! use std::ptr; -//! use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions}; +//! use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary}; //! use vulkano::swapchain::Surface; //! use vulkano::Version; //! @@ -66,7 +66,8 @@ //! .. InstanceExtensions::none() //! }; //! -//! match Instance::new(InstanceCreateInfo { +//! let lib = VulkanLibrary::default(); +//! match Instance::new(lib, InstanceCreateInfo { //! enabled_extensions: extensions, //! ..Default::default() //! }) { diff --git a/vulkano/src/sync/semaphore.rs b/vulkano/src/sync/semaphore.rs index 269ffebaa0..cf8b26c0e9 100644 --- a/vulkano/src/sync/semaphore.rs +++ b/vulkano/src/sync/semaphore.rs @@ -523,7 +523,7 @@ impl From for SemaphoreExportError { mod tests { use crate::device::physical::PhysicalDevice; use crate::device::{Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo}; - use crate::instance::{Instance, InstanceCreateInfo, InstanceExtensions}; + use crate::instance::{Instance, InstanceCreateInfo, InstanceExtensions, VulkanLibrary}; use crate::sync::{ExternalSemaphoreHandleTypes, Semaphore, SemaphoreCreateInfo}; use crate::VulkanObject; @@ -552,18 +552,28 @@ mod tests { #[test] fn semaphore_export() { - let instance = match Instance::new(InstanceCreateInfo { - enabled_extensions: InstanceExtensions { - khr_get_physical_device_properties2: true, - khr_external_semaphore_capabilities: true, - ..InstanceExtensions::none() - }, - ..Default::default() - }) { - Ok(x) => x, + + #[cfg(feature="linked")] + let lib = VulkanLibrary::linked(); + + #[cfg(feature="loaded")] + let lib = match unsafe { VulkanLibrary::load() } { + Ok(l) => l, Err(_) => return, }; + let instance = Instance::new( + lib, + InstanceCreateInfo { + enabled_extensions: InstanceExtensions { + khr_get_physical_device_properties2: true, + khr_external_semaphore_capabilities: true, + ..InstanceExtensions::none() + }, + ..Default::default() + }, + ).unwrap(); + let physical_device = PhysicalDevice::enumerate(&instance).next().unwrap(); let queue_family = physical_device.queue_families().next().unwrap(); diff --git a/vulkano/src/tests.rs b/vulkano/src/tests.rs index ae3ef770ec..51490d3b38 100644 --- a/vulkano/src/tests.rs +++ b/vulkano/src/tests.rs @@ -12,12 +12,18 @@ /// Creates an instance or returns if initialization fails. macro_rules! instance { () => {{ - use crate::instance::Instance; + use crate::instance::{Instance, VulkanLibrary}; - match Instance::new(Default::default()) { - Ok(i) => i, + #[cfg(feature = "linked")] + let lib = VulkanLibrary::linked(); + + #[cfg(feature = "loaded")] + let lib = match unsafe { VulkanLibrary::load() } { + Ok(lib) => lib, Err(_) => return, - } + }; + + Instance::new(lib, Default::default()).unwrap() }}; }