mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 16:25:31 +00:00
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:
parent
fbe81a9c73
commit
6a755cd2f3
@ -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 {
|
||||
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.
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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");
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -28,14 +28,19 @@ use vulkano::{
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
|
||||
sync::{self, GpuFuture},
|
||||
VulkanLibrary,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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 {
|
||||
|
@ -28,10 +28,14 @@ use vulkano::{
|
||||
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
|
||||
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
|
||||
sync::{self, GpuFuture},
|
||||
VulkanLibrary,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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
|
||||
@ -42,7 +46,8 @@ fn main() {
|
||||
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
|
||||
enumerate_portability: true,
|
||||
..Default::default()
|
||||
})
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let device_extensions = DeviceExtensions {
|
||||
|
@ -46,6 +46,7 @@ mod linux {
|
||||
now, ExternalSemaphoreHandleTypes, FlushError, GpuFuture, PipelineStages, Semaphore,
|
||||
SemaphoreCreateInfo,
|
||||
},
|
||||
VulkanLibrary,
|
||||
};
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::{
|
||||
@ -378,9 +379,11 @@ mod linux {
|
||||
Arc<GraphicsPipeline>,
|
||||
Arc<CpuAccessibleBuffer<[Vertex]>>,
|
||||
) {
|
||||
let required_extensions = vulkano_win::required_extensions();
|
||||
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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,
|
||||
@ -396,7 +399,8 @@ mod linux {
|
||||
enumerate_portability: true,
|
||||
|
||||
..Default::default()
|
||||
})
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let _debug_callback = unsafe {
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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 {
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
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 {
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
||||
|
@ -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,
|
||||
|
@ -45,10 +45,14 @@ use vulkano::{
|
||||
RenderPass, RenderPassCreateInfo, StoreOp, Subpass, SubpassDescription,
|
||||
},
|
||||
sync::{self, GpuFuture},
|
||||
VulkanLibrary,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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()
|
||||
@ -56,7 +60,8 @@ fn main() {
|
||||
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
|
||||
enumerate_portability: true,
|
||||
..Default::default()
|
||||
})
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let device_extensions = DeviceExtensions {
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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.
|
||||
|
@ -23,14 +23,19 @@ use vulkano::{
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
|
||||
sync::{self, GpuFuture},
|
||||
VulkanLibrary,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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 {
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -23,14 +23,19 @@ use vulkano::{
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
|
||||
sync::{self, GpuFuture},
|
||||
VulkanLibrary,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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 {
|
||||
|
@ -22,14 +22,19 @@ use vulkano::{
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
|
||||
sync::{self, GpuFuture},
|
||||
VulkanLibrary,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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 {
|
||||
|
@ -39,14 +39,19 @@ use vulkano::{
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
|
||||
sync::{self, GpuFuture},
|
||||
VulkanLibrary,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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 {
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -20,14 +20,19 @@ use vulkano::{
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
pipeline::{ComputePipeline, Pipeline, PipelineBindPoint},
|
||||
sync::{self, GpuFuture},
|
||||
VulkanLibrary,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let instance = Instance::new(InstanceCreateInfo {
|
||||
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 {
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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
|
||||
|
@ -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 {
|
||||
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
|
||||
|
@ -8,26 +8,39 @@
|
||||
// according to those terms.
|
||||
|
||||
use std::sync::Arc;
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
/// let instance = Instance::new(
|
||||
/// library,
|
||||
/// InstanceCreateInfo {
|
||||
/// enabled_extensions: extensions,
|
||||
/// ..Default::default()
|
||||
/// }) {
|
||||
/// Ok(i) => i,
|
||||
/// Err(err) => panic!("Couldn't build instance: {:?}", err)
|
||||
/// };
|
||||
/// },
|
||||
/// )
|
||||
/// .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 {
|
||||
/// 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;
|
||||
|
@ -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
417
vulkano/src/library.rs
Normal 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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
//! Instance::new(
|
||||
//! library,
|
||||
//! InstanceCreateInfo {
|
||||
//! enabled_extensions: extensions,
|
||||
//! ..Default::default()
|
||||
//! }) {
|
||||
//! Ok(i) => i,
|
||||
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
|
||||
//! }
|
||||
//! },
|
||||
//! )
|
||||
//! .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err))
|
||||
//! };
|
||||
//!
|
||||
//! # use std::sync::Arc;
|
||||
|
@ -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 {
|
||||
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()
|
||||
}) {
|
||||
},
|
||||
) {
|
||||
Ok(x) => x,
|
||||
Err(_) => return,
|
||||
};
|
||||
|
@ -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,
|
||||
}
|
||||
}};
|
||||
|
Loading…
Reference in New Issue
Block a user