Add VulkanLibrary as first initialization step before Instance (#1932)

* Add `VulkanLibrary` as first initialization step before `Instance`

* Fix MacOS error

* Fix Vulkano-utils
This commit is contained in:
Rua 2022-07-30 08:53:52 +02:00 committed by GitHub
parent fbe81a9c73
commit 6a755cd2f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 1136 additions and 1129 deletions

View File

@ -24,15 +24,20 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
fn main() {
// As with other examples, the first step is to create an instance.
let instance = Instance::new(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
// Choose which physical device to use.

View File

@ -49,6 +49,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -65,13 +66,17 @@ struct Vertex {
impl_vertex!(Vertex, position);
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -24,6 +24,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -36,13 +37,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -20,8 +20,9 @@ use vulkano::{
DebugUtilsMessageSeverity, DebugUtilsMessageType, DebugUtilsMessenger,
DebugUtilsMessengerCreateInfo,
},
layers_list, Instance, InstanceCreateInfo, InstanceExtensions,
Instance, InstanceCreateInfo, InstanceExtensions,
},
VulkanLibrary,
};
fn main() {
@ -39,6 +40,8 @@ fn main() {
..InstanceExtensions::none()
};
let library = VulkanLibrary::new().unwrap();
// You also need to specify (unless you've used the methods linked above) which debugging layers
// your code should use. Each layer is a bunch of checks or messages that provide information of
// some sort.
@ -50,7 +53,7 @@ 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 mut layers = library.layer_properties().unwrap();
while let Some(l) = layers.next() {
println!("\t{}", l.name());
}
@ -63,13 +66,16 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: extensions,
enabled_layers: layers,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.expect("failed to create Vulkan instance");
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -41,6 +41,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -55,13 +56,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -28,14 +28,19 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
fn main() {
let instance = Instance::new(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -28,21 +28,26 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
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 library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
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()
},
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -46,6 +46,7 @@ mod linux {
now, ExternalSemaphoreHandleTypes, FlushError, GpuFuture, PipelineStages, Semaphore,
SemaphoreCreateInfo,
},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -378,25 +379,28 @@ mod linux {
Arc<GraphicsPipeline>,
Arc<CpuAccessibleBuffer<[Vertex]>>,
) {
let required_extensions = vulkano_win::required_extensions();
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
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,
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),
..InstanceExtensions::none()
}
.union(&required_extensions),
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
..Default::default()
},
)
.unwrap();
let _debug_callback = unsafe {

View File

@ -43,6 +43,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -55,13 +56,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -41,6 +41,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -53,13 +54,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -20,17 +20,22 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
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(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -50,6 +50,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -59,13 +60,17 @@ use winit::{
};
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -54,6 +54,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -72,13 +73,17 @@ struct Vertex {
impl_vertex!(Vertex, position);
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -40,6 +40,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -71,13 +72,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -69,7 +69,10 @@ fn main() {
// Create app to hold the logic of our fractal explorer
let gfx_queue = context.graphics_queue();
// We intend to eventually render on our swapchain, thus we use that format when creating the app here.
let mut app = FractalApp::new(gfx_queue, primary_window_renderer.swapchain_format());
let mut app = FractalApp::new(
gfx_queue.clone(),
primary_window_renderer.swapchain_format(),
);
app.print_guide();
// Basic loop for our runtime

View File

@ -90,17 +90,22 @@ use vulkano::{
},
render_pass::{Framebuffer, FramebufferCreateInfo, Subpass},
sync::GpuFuture,
VulkanLibrary,
};
fn main() {
// The usual Vulkan initialization.
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -44,6 +44,7 @@ use vulkano::{
SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -62,13 +63,17 @@ struct WindowSurface {
}
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -71,8 +71,8 @@ impl App {
id1,
RenderPipeline::new(
// Use same queue.. for synchronization
self.context.graphics_queue(),
self.context.graphics_queue(),
self.context.graphics_queue().clone(),
self.context.graphics_queue().clone(),
[
(WINDOW_WIDTH / SCALING) as u32,
(WINDOW_HEIGHT / SCALING) as u32,
@ -86,8 +86,8 @@ impl App {
self.pipelines.insert(
id2,
RenderPipeline::new(
self.context.graphics_queue(),
self.context.graphics_queue(),
self.context.graphics_queue().clone(),
self.context.graphics_queue().clone(),
[
(WINDOW2_WIDTH / SCALING) as u32,
(WINDOW2_HEIGHT / SCALING) as u32,

View File

@ -45,18 +45,23 @@ use vulkano::{
RenderPass, RenderPassCreateInfo, StoreOp, Subpass, SubpassDescription,
},
sync::{self, GpuFuture},
VulkanLibrary,
};
fn main() {
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: InstanceExtensions {
khr_get_physical_device_properties2: true, // required to get multiview limits
..InstanceExtensions::none()
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: InstanceExtensions {
khr_get_physical_device_properties2: true, // required to get multiview limits
..InstanceExtensions::none()
},
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -41,6 +41,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -50,13 +51,17 @@ use winit::{
};
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -38,15 +38,20 @@ use vulkano::{
},
instance::{Instance, InstanceCreateInfo},
pipeline::{cache::PipelineCache, ComputePipeline},
VulkanLibrary,
};
fn main() {
// As with other examples, the first step is to create an instance.
let instance = Instance::new(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
// Choose which physical device to use.

View File

@ -23,14 +23,19 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
fn main() {
let instance = Instance::new(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -41,6 +41,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -50,13 +51,17 @@ use winit::{
};
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -48,6 +48,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -66,13 +67,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -46,6 +46,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -58,13 +59,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -23,14 +23,19 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
fn main() {
let instance = Instance::new(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -22,14 +22,19 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
fn main() {
let instance = Instance::new(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -39,14 +39,19 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
fn main() {
let instance = Instance::new(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -40,6 +40,7 @@ use vulkano::{
render_pass::{Framebuffer, FramebufferCreateInfo, Subpass},
swapchain::{PresentMode, Swapchain, SwapchainCreateInfo},
sync::{FenceSignalFuture, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -56,13 +57,17 @@ const PARTICLE_COUNT: usize = 100_000;
fn main() {
// The usual Vulkan initialization.
// Largely the same as example `triangle.rs` until further commentation is provided.
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -20,14 +20,19 @@ use vulkano::{
instance::{Instance, InstanceCreateInfo},
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
sync::{self, GpuFuture},
VulkanLibrary,
};
fn main() {
let instance = Instance::new(InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let device_extensions = DeviceExtensions {

View File

@ -38,6 +38,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -50,13 +51,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -47,6 +47,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -151,13 +152,17 @@ mod fs {
}
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -41,6 +41,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -55,13 +56,17 @@ 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,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
let event_loop = EventLoop::new();

View File

@ -49,7 +49,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
Version,
Version, VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -66,15 +66,19 @@ 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 library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
// Now creating the instance.
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
// The objective of this example is to draw a triangle on a window. To do so, we first need to

View File

@ -43,6 +43,7 @@ use vulkano::{
acquire_next_image, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync::{self, FlushError, GpuFuture},
VulkanLibrary,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
@ -59,15 +60,19 @@ 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 library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
// Now creating the instance.
let instance = Instance::new(InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
})
let instance = Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: required_extensions,
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true,
..Default::default()
},
)
.unwrap();
// The objective of this example is to draw a triangle on a window. To do so, we first need to

View File

@ -8,26 +8,39 @@
// according to those terms.
use std::sync::Arc;
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
use vulkano::device::{
Device, DeviceCreateInfo, DeviceExtensions, Features, Queue, QueueCreateInfo,
use vulkano::{
device::{
physical::{PhysicalDevice, PhysicalDeviceType},
Device, DeviceCreateInfo, DeviceExtensions, Features, Queue, QueueCreateInfo,
},
instance::{
debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo},
Instance, InstanceCreateInfo, InstanceExtensions,
},
};
use vulkano::instance::debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo};
use vulkano::instance::{Instance, InstanceCreateInfo};
use vulkano::Version;
use vulkano::{Version, VulkanLibrary};
/// A configuration struct to pass various creation options to create [`VulkanoContext`].
///
/// Instance extensions that are required for surface creation will be appended to the config when
/// creating [`VulkanoContext`].
pub struct VulkanoConfig {
pub instance_create_info: InstanceCreateInfo,
/// Pass the `DebugUtilsMessengerCreateInfo` to create the debug callback
/// for printing debug information at runtime.
pub debug_create_info: Option<DebugUtilsMessengerCreateInfo>,
/// Pass filter function for your physical device selection. See default for example.
pub device_filter_fn: Arc<dyn Fn(&PhysicalDevice) -> bool>,
/// Pass priority order function for your physical device selection. See default for example.
pub device_priority_fn: Arc<dyn Fn(&PhysicalDevice) -> u32>,
pub device_extensions: DeviceExtensions,
pub device_features: Features,
/// Print your selected device name at start.
pub print_device_name: bool,
}
@ -41,7 +54,7 @@ impl Default for VulkanoConfig {
VulkanoConfig {
instance_create_info: InstanceCreateInfo {
application_version: Version::V1_2,
enabled_extensions: vulkano_win::required_extensions(),
enabled_extensions: InstanceExtensions::none(),
..Default::default()
},
debug_create_info: None,
@ -65,7 +78,8 @@ impl Default for VulkanoConfig {
/// A utility struct to create, access and hold alive Vulkano device, instance and queues.
///
/// Vulkano context is used in the creation of your graphics or compute pipelines, images and
/// in the creation of [`VulkanoWindowRenderer`] through [`VulkanoWindows`].
/// in the creation of [`VulkanoWindowRenderer`](crate::renderer::VulkanoWindowRenderer) through
/// [`VulkanoWindows`](crate::window::VulkanoWindows).
///
/// ## Example
///
@ -98,8 +112,25 @@ impl VulkanoContext {
///
/// - Panics where the underlying Vulkano struct creations fail
pub fn new(mut config: VulkanoConfig) -> Self {
let library = match VulkanLibrary::new() {
Ok(x) => x,
#[cfg(target_os = "macos")]
Err(vulkano::library::LoadingError::LibraryLoadFailure(err)) => {
panic!("Failed to load Vulkan library: {}. Did you install vulkanSDK from https://vulkan.lunarg.com/sdk/home ?", err);
}
Err(err) => {
panic!("Failed to load Vulkan library: {}.", err);
}
};
// Append required extensions
config.instance_create_info.enabled_extensions = vulkano_win::required_extensions(&library)
.union(&config.instance_create_info.enabled_extensions);
// Create instance
let instance = create_instance(config.instance_create_info);
let instance = Instance::new(library.clone(), config.instance_create_info)
.expect("Failed to create instance");
// Create debug callback
let _debug_utils_messenger = if let Some(dbg_create_info) = config.debug_create_info.take()
{
@ -110,6 +141,7 @@ impl VulkanoContext {
} else {
None
};
// Get prioritized device
let physical_device = PhysicalDevice::enumerate(&instance)
.filter(|p| (config.device_filter_fn)(p))
@ -140,8 +172,8 @@ impl VulkanoContext {
}
}
/// Creates vulkano device with required queue families and required extensions. Creates a separate queue for compute
/// if possible. If not, same queue as graphics is used.
/// Creates vulkano device with required queue families and required extensions. Creates a
/// separate queue for compute if possible. If not, same queue as graphics is used.
fn create_device(
physical: PhysicalDevice,
device_extensions: DeviceExtensions,
@ -189,17 +221,17 @@ impl VulkanoContext {
(device, gfx_queue, compute_queue)
}
/// Check device name
/// Returns the name of the device.
pub fn device_name(&self) -> &str {
&self.device.physical_device().properties().device_name
}
/// Check device type
/// Returns the type of the device.
pub fn device_type(&self) -> PhysicalDeviceType {
self.device.physical_device().properties().device_type
}
/// Check device memory count
/// Returns the maximum memory allocation of the device.
pub fn max_memory(&self) -> u32 {
self.device
.physical_device()
@ -207,43 +239,25 @@ impl VulkanoContext {
.max_memory_allocation_count as u32
}
/// Access instance
pub fn instance(&self) -> Arc<Instance> {
self.instance.clone()
/// Returns the instance.
pub fn instance(&self) -> &Arc<Instance> {
&self.instance
}
/// Access device
pub fn device(&self) -> Arc<Device> {
self.device.clone()
/// Returns the device.
pub fn device(&self) -> &Arc<Device> {
&self.device
}
/// Access rendering queue
pub fn graphics_queue(&self) -> Arc<Queue> {
self.graphics_queue.clone()
/// Returns the graphics queue.
pub fn graphics_queue(&self) -> &Arc<Queue> {
&self.graphics_queue
}
/// Access compute queue. Depending on your device, this might be the same as graphics queue.
pub fn compute_queue(&self) -> Arc<Queue> {
self.compute_queue.clone()
}
}
/// Create instance, but remind user to install vulkan SDK on mac os if loading error is received on that platform.
fn create_instance(instance_create_info: InstanceCreateInfo) -> Arc<Instance> {
#[cfg(target_os = "macos")]
{
match Instance::new(instance_create_info) {
Err(e) => match e {
vulkano::instance::InstanceCreationError::LoadingError(le) => {
Err(le).expect("Failed to create instance. Did you install vulkanSDK from https://vulkan.lunarg.com/sdk/home ?")
}
_ => Err(e).expect("Failed to create instance"),
},
Ok(i) => i,
}
}
#[cfg(not(target_os = "macos"))]
{
Instance::new(instance_create_info).expect("Failed to create instance")
/// Returns the compute queue.
///
/// Depending on your device, this might be the same as graphics queue.
pub fn compute_queue(&self) -> &Arc<Queue> {
&self.compute_queue
}
}

View File

@ -66,22 +66,23 @@ impl VulkanoWindowRenderer {
swapchain_create_info_modify: fn(&mut SwapchainCreateInfo),
) -> VulkanoWindowRenderer {
// Create rendering surface from window
let surface = create_surface_from_winit(window, vulkano_context.instance()).unwrap();
let surface =
create_surface_from_winit(window, vulkano_context.instance().clone()).unwrap();
// Create swap chain & frame(s) to which we'll render
let (swap_chain, final_views) = Self::create_swap_chain(
vulkano_context.device(),
let (swap_chain, final_views) = Self::create_swapchain(
vulkano_context.device().clone(),
surface.clone(),
descriptor,
swapchain_create_info_modify,
);
let previous_frame_end = Some(sync::now(vulkano_context.device()).boxed());
let previous_frame_end = Some(sync::now(vulkano_context.device().clone()).boxed());
VulkanoWindowRenderer {
surface,
graphics_queue: vulkano_context.graphics_queue(),
compute_queue: vulkano_context.compute_queue(),
graphics_queue: vulkano_context.graphics_queue().clone(),
compute_queue: vulkano_context.compute_queue().clone(),
swap_chain,
final_views,
additional_image_views: HashMap::default(),
@ -94,7 +95,7 @@ impl VulkanoWindowRenderer {
/// Creates the swapchain and its images based on [`WindowDescriptor`]. The swapchain creation
/// can be modified with the `swapchain_create_info_modify` function passed as an input.
fn create_swap_chain(
fn create_swapchain(
device: Arc<Device>,
surface: Arc<Surface<Window>>,
window_descriptor: &WindowDescriptor,
@ -236,7 +237,7 @@ impl VulkanoWindowRenderer {
}
/// Begin your rendering by calling `acquire`.
/// Returns a [`GpuFuture`](vulkano::sync::future::GpuFuture) representing the time after which the swapchain image has been acquired
/// Returns a [`GpuFuture`](vulkano::sync::GpuFuture) representing the time after which the swapchain image has been acquired
/// and previous frame ended.
/// Execute your command buffers after calling this function and finish rendering by calling [`VulkanoWindowRenderer::present`].
pub fn acquire(&mut self) -> std::result::Result<Box<dyn GpuFuture>, AcquireError> {

View File

@ -339,7 +339,7 @@ pub struct WindowDescriptor {
pub cursor_visible: bool,
/// Sets whether the window locks the cursor inside its borders when the window has focus.
pub cursor_locked: bool,
/// Sets the [`WindowMode`](crate::WindowMode).
/// Sets the [`WindowMode`].
pub mode: WindowMode,
/// Sets whether the background of the window should be transparent.
pub transparent: bool,

View File

@ -1,20 +1,16 @@
use std::borrow::Borrow;
use std::error;
use std::fmt;
use std::rc::Rc;
use std::sync::Arc;
use vulkano::instance::Instance;
use vulkano::instance::InstanceExtensions;
use vulkano::swapchain::Surface;
use vulkano::swapchain::SurfaceCreationError;
use std::{borrow::Borrow, error, fmt, rc::Rc, sync::Arc};
use vulkano::{
instance::{Instance, InstanceExtensions},
swapchain::{Surface, SurfaceCreationError},
VulkanLibrary,
};
use winit::{
error::OsError as WindowCreationError,
event_loop::EventLoopWindowTarget,
window::{Window, WindowBuilder},
};
pub fn required_extensions() -> InstanceExtensions {
pub fn required_extensions(library: &VulkanLibrary) -> InstanceExtensions {
let ideal = InstanceExtensions {
khr_surface: true,
khr_xlib_surface: true,
@ -29,10 +25,7 @@ pub fn required_extensions() -> InstanceExtensions {
..InstanceExtensions::none()
};
match InstanceExtensions::supported_by_core() {
Ok(supported) => supported.intersection(&ideal),
Err(_) => InstanceExtensions::none(),
}
library.supported_extensions().intersection(&ideal)
}
/// Create a surface from a Winit window or a reference to it. The surface takes `W` to prevent it

View File

@ -7,10 +7,7 @@
// notice may not be copied, modified, or distributed except
// 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 std::ffi::{CStr, CString};
@ -19,28 +16,6 @@ use std::fmt::Formatter;
// Generated by build.rs
include!(concat!(env!("OUT_DIR"), "/device_extensions.rs"));
impl DeviceExtensions {
/// See the docs of supported_by_device().
#[deprecated(
since = "0.25",
note = "Use PhysicalDevice::supported_extensions instead"
)]
pub fn supported_by_device_raw(
physical_device: PhysicalDevice,
) -> Result<Self, SupportedExtensionsError> {
Ok(*physical_device.supported_extensions())
}
/// Returns a `DeviceExtensions` object with extensions supported by the `PhysicalDevice`.
#[deprecated(
since = "0.25",
note = "Use PhysicalDevice::supported_extensions instead"
)]
pub fn supported_by_device(physical_device: PhysicalDevice) -> Self {
*physical_device.supported_extensions()
}
}
#[cfg(test)]
mod tests {
use crate::device::DeviceExtensions;

View File

@ -15,16 +15,17 @@
//! Basic example:
//!
//! ```no_run
//! use vulkano::device::physical::PhysicalDevice;
//! use vulkano::device::{Device, DeviceCreateInfo, DeviceExtensions, Features, QueueCreateInfo};
//! use vulkano::instance::{Instance, InstanceExtensions};
//! use vulkano::Version;
//! use vulkano::{
//! device::{physical::PhysicalDevice, Device, DeviceCreateInfo, DeviceExtensions, Features, QueueCreateInfo},
//! instance::{Instance, InstanceExtensions},
//! Version, VulkanLibrary,
//! };
//!
//! // Creating the instance. See the documentation of the `instance` module.
//! let instance = match Instance::new(Default::default()) {
//! Ok(i) => i,
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
//! };
//! let library = VulkanLibrary::new()
//! .unwrap_or_else(|err| panic!("Couldn't load Vulkan library: {:?}", err));
//! let instance = Instance::new(library, Default::default())
//! .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err));
//!
//! // We just choose the first physical device. In a real application you would choose depending
//! // on the capabilities of the physical device and the user's preferences.
@ -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;
@ -447,7 +448,7 @@ impl Device {
self.api_version
}
/// Grants access to the Vulkan functions of the device.
/// Returns pointers to the raw Vulkan functions of the device.
#[inline]
pub fn fns(&self) -> &DeviceFunctions {
&self.fns

View File

@ -281,12 +281,14 @@ fn init_info2(instance: &Instance, info: &mut PhysicalDeviceInfo) {
/// # Example
///
/// ```no_run
/// # use vulkano::instance::Instance;
/// # use vulkano::instance::InstanceExtensions;
/// # use vulkano::Version;
/// # use vulkano::{
/// # instance::{Instance, InstanceExtensions},
/// # Version, VulkanLibrary,
/// # };
/// use vulkano::device::physical::PhysicalDevice;
///
/// # let instance = Instance::new(Default::default()).unwrap();
/// # let library = VulkanLibrary::new().unwrap();
/// # let instance = Instance::new(library, Default::default()).unwrap();
/// for physical_device in PhysicalDevice::enumerate(&instance) {
/// print_infos(physical_device);
/// }
@ -308,12 +310,14 @@ impl<'a> PhysicalDevice<'a> {
/// # Example
///
/// ```no_run
/// # use vulkano::instance::Instance;
/// # use vulkano::instance::InstanceExtensions;
/// # use vulkano::Version;
/// # use vulkano::{
/// # instance::{Instance, InstanceExtensions},
/// # Version, VulkanLibrary,
/// # };
/// use vulkano::device::physical::PhysicalDevice;
///
/// # let instance = Instance::new(Default::default()).unwrap();
/// # let library = VulkanLibrary::new().unwrap();
/// # let instance = Instance::new(library, Default::default()).unwrap();
/// for physical_device in PhysicalDevice::enumerate(&instance) {
/// println!("Available device: {}", physical_device.properties().device_name);
/// }
@ -340,12 +344,14 @@ impl<'a> PhysicalDevice<'a> {
/// # Example
///
/// ```no_run
/// use vulkano::instance::Instance;
/// use vulkano::instance::InstanceExtensions;
/// # use vulkano::{
/// # instance::{Instance, InstanceExtensions},
/// # Version, VulkanLibrary,
/// # };
/// use vulkano::device::physical::PhysicalDevice;
/// use vulkano::Version;
///
/// let instance = Instance::new(Default::default()).unwrap();
/// # let library = VulkanLibrary::new().unwrap();
/// # let instance = Instance::new(library, Default::default()).unwrap();
/// let first_physical_device = PhysicalDevice::from_index(&instance, 0).unwrap();
/// ```
#[inline]
@ -389,7 +395,7 @@ impl<'a> PhysicalDevice<'a> {
/// Returns the version of Vulkan supported by this device.
///
/// Unlike the `api_version` property, which is the version reported by the device directly,
/// this function returns the version the device can actually support, based on the instance's,
/// this function returns the version the device can actually support, based on the instance's
/// `max_api_version`.
#[inline]
pub fn api_version(&self) -> Version {

View File

@ -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<OomError> for SupportedExtensionsError {
#[inline]
fn from(err: OomError) -> SupportedExtensionsError {
SupportedExtensionsError::OomError(err)
}
}
impl From<LoadingError> for SupportedExtensionsError {
#[inline]
fn from(err: LoadingError) -> SupportedExtensionsError {
SupportedExtensionsError::LoadingError(err)
}
}
impl From<Error> 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 {

View File

@ -46,27 +46,27 @@
//! To be written.
//!
pub use self::aspect::ImageAspect;
pub use self::aspect::ImageAspects;
pub use self::attachment::AttachmentImage;
pub use self::immutable::ImmutableImage;
pub use self::layout::ImageDescriptorLayouts;
pub use self::layout::ImageLayout;
pub use self::storage::StorageImage;
pub use self::swapchain::SwapchainImage;
pub use self::sys::ImageCreationError;
pub use self::traits::ImageAccess;
pub use self::traits::ImageInner;
pub use self::usage::ImageUsage;
pub use self::view::ImageViewAbstract;
use self::view::ImageViewType;
use crate::format::Format;
use crate::memory::ExternalMemoryHandleType;
use crate::memory::ExternalMemoryProperties;
use crate::DeviceSize;
use std::cmp;
use std::ops::BitAnd;
use std::ops::Range;
pub use self::{
aspect::{ImageAspect, ImageAspects},
attachment::AttachmentImage,
immutable::ImmutableImage,
layout::{ImageDescriptorLayouts, ImageLayout},
storage::StorageImage,
swapchain::SwapchainImage,
sys::ImageCreationError,
traits::{ImageAccess, ImageInner},
usage::ImageUsage,
view::{ImageViewAbstract, ImageViewType},
};
use crate::{
format::Format,
memory::{ExternalMemoryHandleType, ExternalMemoryProperties},
DeviceSize,
};
use std::{
cmp,
ops::{BitAnd, Range},
};
mod aspect;
pub mod attachment; // TODO: make private
@ -176,9 +176,13 @@ impl SampleCounts {
/// should check the intersection of the supported sample counts because they don't have to
/// match. You could similarily apply this to the stencil counts.
/// ```no_run
/// # use vulkano::instance::Instance;
/// # use vulkano::device::physical::PhysicalDevice;
/// # let instance = Instance::new(Default::default()).unwrap();
/// # use vulkano::{
/// # instance::Instance,
/// # device::physical::PhysicalDevice,
/// # VulkanLibrary,
/// # };
/// # let library = VulkanLibrary::new().unwrap();
/// # let instance = Instance::new(library, Default::default()).unwrap();
/// # let physical_device = PhysicalDevice::from_index(&instance, 0).unwrap();
/// let properties = physical_device.properties();
/// let color_counts = properties.framebuffer_color_sample_counts;

View File

@ -7,91 +7,18 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use super::{loader, LoadingError};
use crate::{check_errors, Success};
pub use crate::{
extensions::{
ExtensionRestriction, ExtensionRestrictionError, OneOfRequirements,
SupportedExtensionsError,
},
extensions::{ExtensionRestriction, ExtensionRestrictionError, OneOfRequirements},
Version,
};
use std::{
ffi::{CStr, CString},
fmt::Formatter,
ptr,
};
// 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<Self, SupportedExtensionsError> {
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<Self, LoadingError> {
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<L>(
ptrs: &loader::FunctionPointers<L>,
) -> Result<Self, LoadingError>
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<L>(
ptrs: &loader::FunctionPointers<L>,
) -> Result<Self, SupportedExtensionsError>
where
L: loader::Loader,
{
let fns = ptrs.fns();
let extension_properties = unsafe {
loop {
let mut count = 0;
check_errors((fns.v1_0.enumerate_instance_extension_properties)(
ptr::null(),
&mut count,
ptr::null_mut(),
))?;
let mut properties = Vec::with_capacity(count as usize);
let result = check_errors((fns.v1_0.enumerate_instance_extension_properties)(
ptr::null(),
&mut count,
properties.as_mut_ptr(),
))?;
if !matches!(result, Success::Incomplete) {
properties.set_len(count as usize);
break properties;
}
}
};
Ok(Self::from(extension_properties.iter().map(
|property| unsafe { CStr::from_ptr(property.extension_name.as_ptr()) },
)))
}
}
#[cfg(test)]
mod tests {
use crate::instance::InstanceExtensions;

View File

@ -7,83 +7,13 @@
// 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::Success;
use crate::Version;
use std::error;
use std::ffi::CStr;
use std::fmt;
use std::ptr;
/// Queries the list of layers that are available when creating an instance.
///
/// On success, this function returns an iterator that produces
/// [`LayerProperties`](crate::instance::LayerProperties) objects. In order to enable a layer, you need
/// to pass its name (returned by `LayerProperties::name()`) when creating the
/// [`Instance`](crate::instance::Instance).
///
/// This function returns an error if it failed to load the Vulkan library.
///
/// > **Note**: It is possible that one of the layers enumerated here is no longer available when
/// > you create the `Instance`. This will lead to an error when calling `Instance::new`. The
/// > author isn't aware of any situation where this would happen, but it is theoretically possible
/// > according to the specifications.
///
/// # Example
///
/// ```no_run
/// use vulkano::instance;
///
/// for layer in instance::layers_list().unwrap() {
/// println!("Available layer: {}", layer.name());
/// }
/// ```
pub fn layers_list() -> Result<impl ExactSizeIterator<Item = LayerProperties>, LayersListError> {
layers_list_from_loader(loader::auto_loader()?)
}
/// Same as `layers_list()`, but allows specifying a loader.
pub fn layers_list_from_loader<L>(
ptrs: &loader::FunctionPointers<L>,
) -> Result<impl ExactSizeIterator<Item = LayerProperties>, LayersListError>
where
L: loader::Loader,
{
let fns = ptrs.fns();
let layer_properties = unsafe {
loop {
let mut count = 0;
check_errors((fns.v1_0.enumerate_instance_layer_properties)(
&mut count,
ptr::null_mut(),
))?;
let mut properties = Vec::with_capacity(count as usize);
let result = check_errors({
(fns.v1_0.enumerate_instance_layer_properties)(&mut count, properties.as_mut_ptr())
})?;
if !matches!(result, Success::Incomplete) {
properties.set_len(count as usize);
break properties;
}
}
};
Ok(layer_properties
.into_iter()
.map(|p| LayerProperties { props: p }))
}
/// Properties of a layer.
#[derive(Clone)]
pub struct LayerProperties {
props: ash::vk::LayerProperties,
pub(crate) props: ash::vk::LayerProperties,
}
impl LayerProperties {
@ -95,9 +25,11 @@ impl LayerProperties {
/// # Example
///
/// ```no_run
/// use vulkano::instance;
/// use vulkano::VulkanLibrary;
///
/// for layer in instance::layers_list().unwrap() {
/// let library = VulkanLibrary::new().unwrap();
///
/// for layer in library.layer_properties().unwrap() {
/// println!("Layer name: {}", layer.name());
/// }
/// ```
@ -117,9 +49,11 @@ impl LayerProperties {
/// # Example
///
/// ```no_run
/// use vulkano::instance;
/// use vulkano::VulkanLibrary;
///
/// for layer in instance::layers_list().unwrap() {
/// let library = VulkanLibrary::new().unwrap();
///
/// for layer in library.layer_properties().unwrap() {
/// println!("Layer description: {}", layer.description());
/// }
/// ```
@ -137,10 +71,11 @@ impl LayerProperties {
/// # Example
///
/// ```no_run
/// use vulkano::instance;
/// use vulkano::instance::Version;
/// use vulkano::{Version, VulkanLibrary};
///
/// for layer in instance::layers_list().unwrap() {
/// let library = VulkanLibrary::new().unwrap();
///
/// for layer in library.layer_properties().unwrap() {
/// if layer.vulkan_version() >= Version::major_minor(2, 0) {
/// println!("Layer {} requires Vulkan 2.0", layer.name());
/// }
@ -158,9 +93,11 @@ impl LayerProperties {
/// # Example
///
/// ```no_run
/// use vulkano::instance;
/// use vulkano::VulkanLibrary;
///
/// for layer in instance::layers_list().unwrap() {
/// let library = VulkanLibrary::new().unwrap();
///
/// for layer in library.layer_properties().unwrap() {
/// println!("Layer {} - Version: {}", layer.name(), layer.implementation_version());
/// }
/// ```
@ -170,71 +107,18 @@ impl LayerProperties {
}
}
/// 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<OomError> for LayersListError {
#[inline]
fn from(err: OomError) -> LayersListError {
LayersListError::OomError(err)
}
}
impl From<LoadingError> for LayersListError {
#[inline]
fn from(err: LoadingError) -> LayersListError {
LayersListError::LoadingError(err)
}
}
impl From<Error> 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::VulkanLibrary;
#[test]
fn layers_list() {
let mut list = match instance::layers_list() {
let library = match VulkanLibrary::new() {
Ok(x) => x,
Err(_) => return,
};
let mut list = match library.layer_properties() {
Ok(l) => l,
Err(_) => return,
};

View File

@ -1,323 +0,0 @@
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// 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<T> 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<P>(path: P) -> Result<DynamicLibraryLoader, LoadingError>
where
P: AsRef<Path>,
{
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<L> {
loader: L,
fns: EntryFunctions,
}
impl<L> FunctionPointers<L> {
/// Loads some global function pointer from the loader.
pub fn new(loader: L) -> FunctionPointers<L>
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<Version, OomError>
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<Box<dyn Loader>>, LoadingError> {
#[cfg(target_os = "ios")]
#[allow(non_snake_case)]
fn def_loader_impl() -> Result<Box<Loader>, LoadingError> {
let loader = statically_linked_vulkan_loader!();
Ok(Box::new(loader))
}
#[cfg(not(target_os = "ios"))]
fn def_loader_impl() -> Result<Box<dyn Loader>, 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<FunctionPointers<Box<dyn Loader>>, 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!(),
}
}
}
}

View File

@ -9,31 +9,34 @@
//! API entry point.
//!
//! The first thing to do before you start using Vulkan is to create an `Instance` object.
//! The first thing to do after loading the Vulkan library is to create an `Instance` object.
//!
//! For example:
//!
//! ```no_run
//! use vulkano::instance::Instance;
//! use vulkano::instance::InstanceExtensions;
//! use vulkano::Version;
//!
//! let instance = match Instance::new(Default::default()) {
//! Ok(i) => i,
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
//! use vulkano::{
//! instance::{Instance, InstanceExtensions},
//! Version, VulkanLibrary,
//! };
//!
//! let library = VulkanLibrary::new()
//! .unwrap_or_else(|err| panic!("Couldn't load Vulkan library: {:?}", err));
//! let instance = Instance::new(library, Default::default())
//! .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err));
//! ```
//!
//! Creating an instance initializes everything and allows you to enumerate physical devices,
//! ie. all the Vulkan implementations that are available on the system.
//!
//! ```no_run
//! # use vulkano::instance::Instance;
//! # use vulkano::instance::InstanceExtensions;
//! # use vulkano::Version;
//! # use vulkano::{
//! # instance::{Instance, InstanceExtensions},
//! # Version, VulkanLibrary,
//! # };
//! use vulkano::device::physical::PhysicalDevice;
//!
//! # let instance = Instance::new(Default::default()).unwrap();
//! # let library = VulkanLibrary::new().unwrap();
//! # let instance = Instance::new(library, Default::default()).unwrap();
//! for physical_device in PhysicalDevice::enumerate(&instance) {
//! println!("Available device: {}", physical_device.properties().device_name);
//! }
@ -51,23 +54,16 @@
//! Once you have chosen a physical device, you can create a `Device` object from it. See the
//! `device` module for more info.
use self::{
debug::{DebugUtilsMessengerCreateInfo, UserCallback},
loader::{FunctionPointers, Loader},
};
pub use self::{
extensions::InstanceExtensions,
layers::{layers_list, LayerProperties, LayersListError},
loader::LoadingError,
};
use self::debug::{DebugUtilsMessengerCreateInfo, UserCallback};
pub use self::{extensions::InstanceExtensions, layers::LayerProperties};
use crate::{
check_errors,
device::physical::{init_physical_devices, PhysicalDeviceInfo},
instance::debug::{trampoline, DebugUtilsMessageSeverity, DebugUtilsMessageType},
Error, OomError, VulkanObject,
Error, OomError, VulkanLibrary, VulkanObject,
};
pub use crate::{
extensions::{ExtensionRestriction, ExtensionRestrictionError, SupportedExtensionsError},
extensions::{ExtensionRestriction, ExtensionRestrictionError},
fns::InstanceFunctions,
version::Version,
};
@ -78,7 +74,6 @@ use std::{
fmt,
hash::{Hash, Hasher},
mem::MaybeUninit,
ops::Deref,
panic::{RefUnwindSafe, UnwindSafe},
ptr,
sync::Arc,
@ -87,7 +82,6 @@ use std::{
pub mod debug;
pub(crate) mod extensions;
mod layers;
pub mod loader;
/// An instance of a Vulkan context. This is the main object that should be created by an
/// application before everything else.
@ -103,10 +97,16 @@ pub mod loader;
/// ```no_run
/// # #[macro_use] extern crate vulkano;
/// # fn main() {
/// use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions};
/// use vulkano::Version;
/// use vulkano::{
/// instance::{Instance, InstanceCreateInfo, InstanceExtensions},
/// Version, VulkanLibrary,
/// };
///
/// let _instance = Instance::new(InstanceCreateInfo::application_from_cargo_toml()).unwrap();
/// let library = VulkanLibrary::new().unwrap();
/// let _instance = Instance::new(
/// library,
/// InstanceCreateInfo::application_from_cargo_toml(),
/// ).unwrap();
/// # }
/// ```
///
@ -117,7 +117,7 @@ pub mod loader;
/// to use when used on a particular instance or device. It is possible for the instance and the
/// device to support different versions. The supported version for an instance can be queried
/// before creation with
/// [`FunctionPointers::api_version`](crate::instance::loader::FunctionPointers::api_version),
/// [`VulkanLibrary::api_version`](crate::VulkanLibrary::api_version),
/// while for a device it can be retrieved with
/// [`PhysicalDevice::api_version`](crate::device::physical::PhysicalDevice::api_version).
///
@ -157,8 +157,13 @@ pub mod loader;
/// succeed on anything else than an Android-running device.
///
/// ```no_run
/// use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions};
/// use vulkano::Version;
/// use vulkano::{
/// instance::{Instance, InstanceCreateInfo, InstanceExtensions},
/// Version, VulkanLibrary,
/// };
///
/// let library = VulkanLibrary::new()
/// .unwrap_or_else(|err| panic!("Couldn't load Vulkan library: {:?}", err));
///
/// let extensions = InstanceExtensions {
/// khr_surface: true,
@ -166,20 +171,22 @@ pub mod loader;
/// .. InstanceExtensions::none()
/// };
///
/// let instance = match Instance::new(InstanceCreateInfo {
/// enabled_extensions: extensions,
/// ..Default::default()
/// }) {
/// Ok(i) => i,
/// Err(err) => panic!("Couldn't build instance: {:?}", err)
/// };
/// let instance = Instance::new(
/// library,
/// InstanceCreateInfo {
/// enabled_extensions: extensions,
/// ..Default::default()
/// },
/// )
/// .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err));
/// ```
///
/// # Layers
///
/// When creating an `Instance`, you have the possibility to pass a list of **layers** that will
/// be activated on the newly-created instance. The list of available layers can be retrieved by
/// calling [the `layers_list` function](crate::instance::layers_list).
/// calling the [`layer_properties`](crate::VulkanLibrary::layer_properties) method of
/// `VulkanLibrary`.
///
/// A layer is a component that will hook and potentially modify the Vulkan function calls.
/// For example, activating a layer could add a frames-per-second counter on the screen, or it
@ -200,24 +207,27 @@ pub mod loader;
/// ## Example
///
/// ```
/// # 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::Version;
/// # use std::{sync::Arc, error::Error};
/// # use vulkano::{
/// # instance::{Instance, InstanceCreateInfo, InstanceExtensions},
/// # Version, VulkanLibrary,
/// # };
/// # fn test() -> Result<Arc<Instance>, Box<dyn Error>> {
/// let library = VulkanLibrary::new()?;
///
/// // 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 layers: Vec<_> = library.layer_properties()?
/// .filter(|l| l.description().contains("foo"))
/// .collect();
///
/// let instance = Instance::new(InstanceCreateInfo {
/// enabled_layers: layers.iter().map(|l| l.name().to_owned()).collect(),
/// ..Default::default()
/// })?;
/// let instance = Instance::new(
/// library,
/// InstanceCreateInfo {
/// enabled_layers: layers.iter().map(|l| l.name().to_owned()).collect(),
/// ..Default::default()
/// },
/// )?;
/// # Ok(instance)
/// # }
/// ```
@ -230,7 +240,7 @@ pub struct Instance {
api_version: Version,
enabled_extensions: InstanceExtensions,
enabled_layers: Vec<String>,
function_pointers: OwnedOrRef<FunctionPointers<Box<dyn Loader>>>,
library: Arc<VulkanLibrary>,
max_api_version: Version,
user_callbacks: Vec<Box<UserCallback>>,
}
@ -247,8 +257,11 @@ 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<Arc<Instance>, InstanceCreationError> {
unsafe { Self::with_debug_utils_messengers(create_info, []) }
pub fn new(
library: Arc<VulkanLibrary>,
create_info: InstanceCreateInfo,
) -> Result<Arc<Instance>, InstanceCreationError> {
unsafe { Self::with_debug_utils_messengers(library, create_info, []) }
}
/// Creates a new `Instance` with debug messengers to use during the creation and destruction
@ -271,6 +284,7 @@ impl Instance {
/// - The `user_callback` of each element of `debug_utils_messengers` must not make any calls
/// to the Vulkan API.
pub unsafe fn with_debug_utils_messengers(
library: Arc<VulkanLibrary>,
create_info: InstanceCreateInfo,
debug_utils_messengers: impl IntoIterator<Item = DebugUtilsMessengerCreateInfo>,
) -> Result<Arc<Instance>, InstanceCreationError> {
@ -281,20 +295,13 @@ impl Instance {
enabled_layers,
engine_name,
engine_version,
function_pointers,
max_api_version,
enumerate_portability,
_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 = library.api_version();
let max_api_version = if let Some(max_api_version) = max_api_version {
max_api_version
} else if api_version < Version::V1_1 {
@ -308,8 +315,7 @@ impl Instance {
// VUID-VkApplicationInfo-apiVersion-04010
assert!(max_api_version >= Version::V1_0);
let supported_extensions =
InstanceExtensions::supported_by_core_with_loader(&function_pointers)?;
let supported_extensions = library.supported_extensions();
let mut flags = ash::vk::InstanceCreateFlags::empty();
if enumerate_portability && supported_extensions.khr_portability_enumeration {
@ -422,7 +428,7 @@ impl Instance {
// Creating the Vulkan instance.
let handle = {
let mut output = MaybeUninit::uninit();
let fns = function_pointers.fns();
let fns = library.fns();
check_errors((fns.v1_0.create_instance)(
&create_info,
ptr::null(),
@ -433,9 +439,7 @@ impl Instance {
// 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| library.get_instance_proc_addr(handle, name.as_ptr()))
};
let mut instance = Instance {
@ -446,7 +450,7 @@ impl Instance {
api_version,
enabled_extensions,
enabled_layers,
function_pointers,
library,
max_api_version,
user_callbacks,
};
@ -457,10 +461,16 @@ impl Instance {
Ok(Arc::new(instance))
}
/// Returns the Vulkan library used to create this instance.
#[inline]
pub fn library(&self) -> &Arc<VulkanLibrary> {
&self.library
}
/// Returns the Vulkan version supported by the instance.
///
/// This is the lower of the
/// [driver's supported version](crate::instance::loader::FunctionPointers::api_version) and
/// [driver's supported version](crate::VulkanLibrary::api_version) and
/// [`max_api_version`](Instance::max_api_version).
#[inline]
pub fn api_version(&self) -> Version {
@ -473,7 +483,7 @@ impl Instance {
self.max_api_version
}
/// Grants access to the Vulkan functions of the instance.
/// Returns pointers to the raw Vulkan functions of the instance.
#[inline]
pub fn fns(&self) -> &InstanceFunctions {
&self.fns
@ -537,7 +547,7 @@ impl fmt::Debug for Instance {
api_version,
enabled_extensions,
enabled_layers,
function_pointers,
library: function_pointers,
max_api_version,
user_callbacks: _,
} = self;
@ -587,12 +597,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<FunctionPointers<Box<dyn Loader>>>,
/// The highest Vulkan API version that the application will use with the instance.
///
/// Usually, you will want to leave this at the default.
@ -629,7 +633,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,
enumerate_portability: false,
_ne: crate::NonExhaustive(()),
@ -662,20 +665,24 @@ 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.
InitializationFailed,
/// One of the requested layers is missing.
LayerNotPresent,
/// One of the requested extensions is not supported by the implementation.
ExtensionNotPresent,
/// The version requested is not supported by the implementation.
IncompatibleDriver,
/// A restriction for an extension was not met.
ExtensionRestrictionNotMet(ExtensionRestrictionError),
ExtensionNotEnabled {
extension: &'static str,
reason: &'static str,
@ -686,7 +693,6 @@ impl error::Error for InstanceCreationError {
#[inline]
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
Self::LoadingError(ref err) => Some(err),
Self::OomError(ref err) => Some(err),
_ => None,
}
@ -697,9 +703,6 @@ impl fmt::Display for InstanceCreationError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Self::LoadingError(_) => {
write!(fmt, "failed to load the Vulkan shared library")
}
Self::OomError(_) => write!(fmt, "not enough memory available"),
Self::InitializationFailed => write!(fmt, "initialization failed"),
Self::LayerNotPresent => write!(fmt, "layer not present"),
@ -722,13 +725,6 @@ impl From<OomError> for InstanceCreationError {
}
}
impl From<LoadingError> for InstanceCreationError {
#[inline]
fn from(err: LoadingError) -> Self {
Self::LoadingError(err)
}
}
impl From<ExtensionRestrictionError> for InstanceCreationError {
#[inline]
fn from(err: ExtensionRestrictionError) -> Self {
@ -751,24 +747,6 @@ impl From<Error> for InstanceCreationError {
}
}
// Same as Cow but less annoying.
#[derive(Debug)]
enum OwnedOrRef<T: 'static> {
Owned(T),
Ref(&'static T),
}
impl<T> Deref for OwnedOrRef<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
match *self {
OwnedOrRef::Owned(ref v) => v,
OwnedOrRef::Ref(v) => v,
}
}
}
#[cfg(test)]
mod tests {
use crate::device::physical::PhysicalDevice;

View File

@ -12,11 +12,14 @@
//!
//! # Brief summary of Vulkan
//!
//! - The [`Instance`](crate::instance::Instance) object is the API entry point. It is the
//! first object you must create before starting to use Vulkan.
//! - The [`VulkanLibrary`](crate::VulkanLibrary) represents a Vulkan library on the system.
//! It must be loaded before you can do anything with Vulkan.
//!
//! - The [`PhysicalDevice`](crate::device::physical::PhysicalDevice) object represents an
//! implementation of Vulkan available on the system (eg. a graphics card, a software
//! - The [`Instance`](crate::instance::Instance) object is the API entry point, and represents
//! an initialised Vulkan library. This is the first Vulkan object that you create.
//!
//! - The [`PhysicalDevice`](crate::device::physical::PhysicalDevice) object represents a
//! Vulkan-capable device that is available on the system (eg. a graphics card, a software
//! implementation, etc.). Physical devices can be enumerated from an instance with
//! [`PhysicalDevice::enumerate`](crate::device::physical::PhysicalDevice::enumerate).
//!
@ -30,28 +33,28 @@
//! usually used to store information about vertices, lights, etc. or arbitrary data, while
//! images are used to store textures or multi-dimensional data.
//!
//! - In order to show something on the screen, you need a [`Swapchain`](crate::swapchain).
//! - In order to show something on the screen, you need a
//! [`Surface` and a `Swapchain`](crate::swapchain).
//! A `Swapchain` contains special `Image`s that correspond to the content of the window or the
//! monitor. When you *present* a swapchain, the content of one of these special images is shown
//! on the screen.
//!
//! - In order to ask the GPU to do something, you must create a
//! - For graphical operations, [`RenderPass`es and `Framebuffer`s](crate::render_pass)
//! describe which images the device must draw upon.
//!
//! - In order to be able to perform operations on the device, you need to have created a
//! [pipeline object](crate::pipeline) that describes the operation you want. These objects are usually
//! created during your program's initialization. `Shader`s are programs that the GPU will
//! execute as part of a pipeline. [*Descriptor sets*](crate::descriptor_set) can be used to access
//! the content of buffers or images from within shaders.
//!
//! - To tell the GPU to do something, you must create a
//! [*command buffer*](crate::command_buffer). A command buffer contains a list of commands
//! that the GPU must perform. This can include copies between buffers and images, compute
//! operations, or graphics operations. For the work to start, the command buffer must then be
//! submitted to a [`Queue`](crate::device::Queue), which is obtained when you create the
//! `Device`.
//!
//! - In order to be able to add a compute operation or a graphics operation to a command buffer,
//! you need to have created a [`ComputePipeline` or a `GraphicsPipeline`
//! object](crate::pipeline) that describes the operation you want. These objects are usually
//! created during your program's initialization. `Shader`s are programs that the GPU will
//! execute as part of a pipeline. [*Descriptor sets*](crate::descriptor_set) can be used to access
//! the content of buffers or images from within shaders.
//!
//! - For graphical operations, [`RenderPass`es and `Framebuffer`s](crate::render_pass)
//! describe on which images the implementation must draw upon.
//!
//! - Once you have built a *command buffer* that contains a list of commands, submitting it to the
//! GPU will return an object that implements [the `GpuFuture` trait](crate::sync::GpuFuture).
//! `GpuFuture`s allow you to chain multiple submissions together and are essential to performing
@ -64,6 +67,7 @@
pub use ash::vk::Handle;
pub use half;
pub use library::VulkanLibrary;
use std::{
error, fmt,
ops::Deref,
@ -86,6 +90,7 @@ pub mod render_pass;
mod fns;
pub mod image;
pub mod instance;
pub mod library;
pub mod memory;
pub mod pipeline;
pub mod query;

417
vulkano/src/library.rs Normal file
View File

@ -0,0 +1,417 @@
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
//! Vulkan library loading system.
//!
//! Before Vulkano can do anything, it first needs to find a library containing 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 type that implements `Loader`, you can create a `VulkanLibrary`
//! from it and use this `VulkanLibrary` struct to build an `Instance`.
pub use crate::fns::EntryFunctions;
use crate::{
check_errors,
instance::{InstanceExtensions, LayerProperties},
Error, OomError, SafeDeref, Success, Version,
};
use shared_library;
use std::{
error,
ffi::{c_void, CStr},
fmt,
mem::transmute,
os::raw::c_char,
path::Path,
ptr,
sync::Arc,
};
/// A loaded library containing a valid Vulkan implementation.
#[derive(Debug)]
pub struct VulkanLibrary {
loader: Box<dyn Loader>,
fns: EntryFunctions,
api_version: Version,
supported_extensions: InstanceExtensions,
}
impl VulkanLibrary {
/// Loads the default Vulkan library for this system.
pub fn new() -> Result<Arc<Self>, LoadingError> {
#[cfg(target_os = "ios")]
#[allow(non_snake_case)]
fn def_loader_impl() -> Result<Box<Loader>, LoadingError> {
let loader = statically_linked_vulkan_loader!();
Ok(Box::new(loader))
}
#[cfg(not(target_os = "ios"))]
fn def_loader_impl() -> Result<Box<dyn Loader>, 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))
}
def_loader_impl().and_then(VulkanLibrary::with_loader)
}
/// Loads a custom Vulkan library.
pub fn with_loader<L>(loader: L) -> Result<Arc<Self>, LoadingError>
where
L: Loader + 'static,
{
let fns = EntryFunctions::load(|name| unsafe {
transmute(loader.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr()))
});
// 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.
let api_version = unsafe {
let name = CStr::from_bytes_with_nul_unchecked(b"vkEnumerateInstanceVersion\0");
let func = loader.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr());
if func.is_null() {
Version {
major: 1,
minor: 0,
patch: 0,
}
} else {
type Pfn = extern "system" fn(pApiVersion: *mut u32) -> ash::vk::Result;
let func: Pfn = transmute(func);
let mut api_version = 0;
check_errors(func(&mut api_version))?;
Version::from(api_version)
}
};
let supported_extensions = unsafe {
let extension_properties = loop {
let mut count = 0;
check_errors((fns.v1_0.enumerate_instance_extension_properties)(
ptr::null(),
&mut count,
ptr::null_mut(),
))?;
let mut properties = Vec::with_capacity(count as usize);
let result = check_errors((fns.v1_0.enumerate_instance_extension_properties)(
ptr::null(),
&mut count,
properties.as_mut_ptr(),
))?;
if !matches!(result, Success::Incomplete) {
properties.set_len(count as usize);
break properties;
}
};
InstanceExtensions::from(
extension_properties
.iter()
.map(|property| CStr::from_ptr(property.extension_name.as_ptr())),
)
};
Ok(Arc::new(VulkanLibrary {
loader: Box::new(loader),
fns,
api_version,
supported_extensions,
}))
}
/// Returns pointers to the raw global Vulkan functions of the library.
#[inline]
pub fn fns(&self) -> &EntryFunctions {
&self.fns
}
/// Returns the highest Vulkan version that is supported for instances.
pub fn api_version(&self) -> Version {
self.api_version
}
/// Returns the extensions that are supported by this Vulkan library.
#[inline]
pub fn supported_extensions(&self) -> &InstanceExtensions {
&self.supported_extensions
}
/// Returns the list of layers that are available when creating an instance.
///
/// On success, this function returns an iterator that produces
/// [`LayerProperties`](crate::instance::LayerProperties) objects. In order to enable a layer,
/// you need to pass its name (returned by `LayerProperties::name()`) when creating the
/// [`Instance`](crate::instance::Instance).
///
/// > **Note**: The available layers may change between successive calls to this function, so
/// > each call may return different results. It is possible that one of the layers enumerated
/// > here is no longer available when you create the `Instance`. This will lead to an error
/// > when calling `Instance::new`.
///
/// # Example
///
/// ```no_run
/// use vulkano::VulkanLibrary;
///
/// let library = VulkanLibrary::new().unwrap();
///
/// for layer in library.layer_properties().unwrap() {
/// println!("Available layer: {}", layer.name());
/// }
/// ```
pub fn layer_properties(
&self,
) -> Result<impl ExactSizeIterator<Item = LayerProperties>, OomError> {
let fns = self.fns();
let layer_properties = unsafe {
loop {
let mut count = 0;
check_errors((fns.v1_0.enumerate_instance_layer_properties)(
&mut count,
ptr::null_mut(),
))?;
let mut properties = Vec::with_capacity(count as usize);
let result = check_errors({
(fns.v1_0.enumerate_instance_layer_properties)(
&mut count,
properties.as_mut_ptr(),
)
})?;
if !matches!(result, Success::Incomplete) {
properties.set_len(count as usize);
break properties;
}
}
};
Ok(layer_properties
.into_iter()
.map(|p| LayerProperties { props: p }))
}
/// 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 {
self.loader.get_instance_proc_addr(instance, name)
}
}
/// 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<T> 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<P>(path: P) -> Result<DynamicLibraryLoader, LoadingError>
where
P: AsRef<Path>,
{
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()))?;
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)
}
}
/// 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
}};
}
/// Error that can happen when loading a Vulkan library.
#[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),
/// Not enough memory.
OomError(OomError),
}
impl error::Error for LoadingError {
#[inline]
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
//Self::LibraryLoadFailure(ref err) => Some(err),
Self::OomError(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 {
Self::LibraryLoadFailure(_) => "failed to load the Vulkan shared library",
Self::MissingEntryPoint(_) => "one of the entry points required to be supported by the Vulkan implementation is missing",
Self::OomError(_) => "not enough memory available",
}
)
}
}
impl From<Error> for LoadingError {
#[inline]
fn from(err: Error) -> Self {
match err {
err @ Error::OutOfHostMemory => Self::OomError(OomError::from(err)),
err @ Error::OutOfDeviceMemory => Self::OomError(OomError::from(err)),
_ => panic!("unexpected error: {:?}", err),
}
}
}
#[cfg(test)]
mod tests {
use super::{DynamicLibraryLoader, LoadingError};
#[test]
fn dl_open_error() {
unsafe {
match DynamicLibraryLoader::new("_non_existing_library.void") {
Err(LoadingError::LibraryLoadFailure(_)) => (),
_ => panic!(),
}
}
}
}

View File

@ -55,24 +55,30 @@
//!
//! ```no_run
//! use std::ptr;
//! use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions};
//! use vulkano::swapchain::Surface;
//! use vulkano::Version;
//! use vulkano::{
//! instance::{Instance, InstanceCreateInfo, InstanceExtensions},
//! swapchain::Surface,
//! Version, VulkanLibrary,
//! };
//!
//! let instance = {
//! let library = VulkanLibrary::new()
//! .unwrap_or_else(|err| panic!("Couldn't load Vulkan library: {:?}", err));
//!
//! let extensions = InstanceExtensions {
//! khr_surface: true,
//! khr_win32_surface: true, // If you don't enable this, `from_hwnd` will fail.
//! .. InstanceExtensions::none()
//! };
//!
//! match Instance::new(InstanceCreateInfo {
//! enabled_extensions: extensions,
//! ..Default::default()
//! }) {
//! Ok(i) => i,
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
//! }
//! Instance::new(
//! library,
//! InstanceCreateInfo {
//! enabled_extensions: extensions,
//! ..Default::default()
//! },
//! )
//! .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err))
//! };
//!
//! # use std::sync::Arc;

View File

@ -524,11 +524,14 @@ impl From<OomError> for SemaphoreExportError {
#[cfg(test)]
mod tests {
use crate::device::physical::PhysicalDevice;
use crate::device::{Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo};
use crate::instance::{Instance, InstanceCreateInfo, InstanceExtensions};
use crate::sync::{ExternalSemaphoreHandleTypes, Semaphore, SemaphoreCreateInfo};
use crate::VulkanObject;
use crate::{
device::{
physical::PhysicalDevice, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
},
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
sync::{ExternalSemaphoreHandleTypes, Semaphore, SemaphoreCreateInfo},
VulkanLibrary, VulkanObject,
};
#[test]
fn semaphore_create() {
@ -555,14 +558,22 @@ 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()
let library = match VulkanLibrary::new() {
Ok(x) => x,
Err(_) => return,
};
let instance = match Instance::new(
library,
InstanceCreateInfo {
enabled_extensions: InstanceExtensions {
khr_get_physical_device_properties2: true,
khr_external_semaphore_capabilities: true,
..InstanceExtensions::none()
},
..Default::default()
},
..Default::default()
}) {
) {
Ok(x) => x,
Err(_) => return,
};

View File

@ -12,10 +12,15 @@
/// 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,
let library = match VulkanLibrary::new() {
Ok(x) => x,
Err(_) => return,
};
match Instance::new(library, Default::default()) {
Ok(x) => x,
Err(_) => return,
}
}};