Allow choosing the Vulkan max API version when creating Instance (#1585)

* Allow choosing the Vulkan max API version when creating Instance

* Rewrite feature handling, include all Vulkan 1.1 and 1.2 features

* Fixes

* Move features.rs to device module

* More small fixes

* Changelog
This commit is contained in:
Rua 2021-05-23 18:09:50 +02:00 committed by GitHub
parent d36e5a2b1d
commit 2f7e7af7ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1192 additions and 816 deletions

View File

@ -1,5 +1,7 @@
# Unreleased
- Added structs for Vulkan 1.1 and 1.2 features, with `Default` implementations.
# Version 0.6.1 (2021-04-10)
- Add `MEMORY_HEAP_MULTI_INSTANCE_BIT` for `MemoryHeap`.

View File

@ -17,13 +17,16 @@
- Now that `PipelineLayout` has no more type parameter, the trait `PipelineLayoutAbstract` is removed. The layout type parameter is also removed from `ComputePipeline` and `GraphicsPipeline`.
- `ComputeEntryPoint` and `GraphicsEntryPoint` now take a value specifying the push constants descriptor, instead of having a type parameter. The corresponding associated type on `EntryPointAbstract` has been removed.
- The `GraphicsEntryPointAbstract` trait has been removed. `GraphicsPipelineBuilder` now takes a `GraphicsEntryPoint` object directly, and has lifetime parameters for the 5 shader types instead. `EntryPointDummy` is no longer needed and has been removed.
- **Breaking** The constructors of `Instance` now take an additional argument to specify the maximum API version.
- Added `DeviceExtensions::khr_spirv_1_4`, which allows SPIR-V 1.4 shaders in Vulkan 1.1.
- Added `FunctionPointers::api_version` to query the highest supported instance version.
- Added `Instance::api_version` and `Device::api_version` to return the actual supported Vulkan version. These may differ between instance and device, and be lower than what `FunctionPointers::api_version` and `PhysicalDevice::api_version` return (currently never higher than 1.1, but this may change in the future).
- Added `Instance::api_version` and `Device::api_version` to return the actual supported Vulkan version. These may differ between instance and device, and be lower than what `FunctionPointers::api_version` and `PhysicalDevice::api_version` return.
- Added `Instance::max_api_version`, which returns the maximum version that was specified when creating the instance.
- Fixed the issue when creating a buffer with exportable fd on Linux(see to #1545).
- The `draw_indirect` and `draw_indexed_indirect` commands on `AutoCommandBufferBuilder` now check the draw count against the `max_draw_indirect_count` limit.
- Fixed a few documentation errors.
- It is now possible to construct a graphics pipeline without a fragment shader.
- Added support for all core Vulkan 1.1 and 1.2 device features.
# Version 0.23.0 (2021-04-10)

View File

@ -23,6 +23,7 @@ use vulkano::pipeline::ComputePipeline;
use vulkano::pipeline::ComputePipelineAbstract;
use vulkano::sync;
use vulkano::sync::GpuFuture;
use vulkano::Version;
const DEVICE_EXTENSIONS: DeviceExtensions = DeviceExtensions {
khr_storage_buffer_storage_class: true,
@ -36,7 +37,13 @@ const BUFFER_USAGE: BufferUsage = BufferUsage {
fn main() {
// As with other examples, the first step is to create an instance.
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
let instance = Instance::new(
None,
Version::major_minor(1, 1),
&InstanceExtensions::none(),
None,
)
.unwrap();
// Choose which physical device to use.
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();

View File

@ -36,6 +36,7 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
@ -49,7 +50,8 @@ vulkano::impl_vertex!(Vertex, position);
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
println!(

View File

@ -15,6 +15,7 @@ use vulkano::image::MipmapsCount;
use vulkano::instance;
use vulkano::instance::debug::{DebugCallback, MessageSeverity, MessageType};
use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice};
use vulkano::Version;
fn main() {
// Vulkano Debugging Example Code
@ -55,8 +56,8 @@ fn main() {
let layers = vec!["VK_LAYER_KHRONOS_validation"];
// Important: pass the extension(s) and layer(s) when creating the vulkano instance
let instance =
Instance::new(None, &extensions, layers).expect("failed to create Vulkan instance");
let instance = Instance::new(None, Version::major_minor(1, 1), &extensions, layers)
.expect("failed to create Vulkan instance");
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// After creating the instance we must register the debugging callback. //

View File

@ -25,6 +25,11 @@
// expensive otherwise. It has some drawbacks, which are the fact that transparent objects must be
// drawn after the lighting, and that the whole process consumes more memory.
use crate::frame::*;
use crate::triangle_draw_system::*;
use cgmath::Matrix4;
use cgmath::SquareMatrix;
use cgmath::Vector3;
use vulkano::device::{Device, DeviceExtensions};
use vulkano::image::view::ImageView;
use vulkano::image::ImageUsage;
@ -33,27 +38,21 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;
use cgmath::Matrix4;
use cgmath::SquareMatrix;
use cgmath::Vector3;
mod frame;
mod triangle_draw_system;
use crate::frame::*;
use crate::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(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let event_loop = EventLoop::new();

View File

@ -27,9 +27,16 @@ use vulkano::pipeline::ComputePipeline;
use vulkano::pipeline::ComputePipelineAbstract;
use vulkano::sync;
use vulkano::sync::GpuFuture;
use vulkano::Version;
fn main() {
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
let instance = Instance::new(
None,
Version::major_minor(1, 1),
&InstanceExtensions::none(),
None,
)
.unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let queue_family = physical

View File

@ -29,10 +29,12 @@ use vulkano::pipeline::ComputePipeline;
use vulkano::pipeline::ComputePipelineAbstract;
use vulkano::sync;
use vulkano::sync::GpuFuture;
use vulkano::Version;
fn main() {
let instance = Instance::new(
None,
Version::major_minor(1, 1),
&InstanceExtensions {
// This extension is required to obtain physical device metadata
// about the device workgroup size limits

View File

@ -7,6 +7,9 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use png;
use std::io::Cursor;
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
@ -27,10 +30,7 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use png;
use std::io::Cursor;
use std::sync::Arc;
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
@ -41,7 +41,8 @@ fn main() {
// `triangle` example if you haven't done so yet.
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
println!(
"Using device: {} (type: {:?})",

View File

@ -19,12 +19,19 @@ use vulkano::pipeline::ComputePipeline;
use vulkano::pipeline::ComputePipelineAbstract;
use vulkano::sync;
use vulkano::sync::GpuFuture;
use vulkano::Version;
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(None, &InstanceExtensions::none(), None).unwrap();
let instance = Instance::new(
None,
Version::major_minor(1, 1),
&InstanceExtensions::none(),
None,
)
.unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let queue_family = physical

View File

@ -49,6 +49,7 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
@ -64,7 +65,8 @@ impl_vertex!(Vertex, position);
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
println!(
"Using device: {} (type: {:?})",

View File

@ -18,6 +18,7 @@ extern crate vulkano_shaders;
extern crate vulkano_win;
extern crate winit;
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
@ -34,13 +35,12 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::{Window, WindowBuilder};
use std::sync::Arc;
// # Vertex Types
//
// Seeing as we are going to use the `OneVertexOneInstanceDefinition` vertex definition for our
@ -63,7 +63,8 @@ impl_vertex!(InstanceData, position_offset, scale);
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
println!(

View File

@ -83,11 +83,13 @@ use vulkano::pipeline::viewport::Viewport;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::{Framebuffer, Subpass};
use vulkano::sync::GpuFuture;
use vulkano::Version;
fn main() {
// The usual Vulkan initialization.
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let queue_family = physical
.queue_families()

View File

@ -34,6 +34,7 @@ use vulkano::swapchain::Surface;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::ElementState;
use winit::event::KeyboardInput;
@ -52,7 +53,8 @@ struct WindowSurface {
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let event_loop = EventLoop::new();
// A hashmap that contains all of our created windows and their resources

View File

@ -28,6 +28,7 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
@ -35,7 +36,8 @@ use winit::window::{Window, WindowBuilder};
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
println!(

View File

@ -32,15 +32,21 @@ use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::sync::Arc;
use vulkano::device::{Device, DeviceExtensions};
use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice};
use vulkano::pipeline::cache::PipelineCache;
use vulkano::pipeline::ComputePipeline;
use vulkano::Version;
fn main() {
// As with other examples, the first step is to create an instance.
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
let instance = Instance::new(
None,
Version::major_minor(1, 1),
&InstanceExtensions::none(),
None,
)
.unwrap();
// Choose which physical device to use.
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();

View File

@ -18,9 +18,16 @@ use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice};
use vulkano::pipeline::{ComputePipeline, ComputePipelineAbstract};
use vulkano::sync;
use vulkano::sync::GpuFuture;
use vulkano::Version;
fn main() {
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
let instance = Instance::new(
None,
Version::major_minor(1, 1),
&InstanceExtensions::none(),
None,
)
.unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let queue_family = physical
.queue_families()

View File

@ -49,6 +49,7 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
@ -64,7 +65,8 @@ vulkano::impl_vertex!(Vertex, position, color);
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = vk::instance::PhysicalDevice::enumerate(&instance)
.next()
.unwrap();

View File

@ -20,9 +20,16 @@ use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice};
use vulkano::pipeline::{ComputePipeline, ComputePipelineAbstract};
use vulkano::sync;
use vulkano::sync::GpuFuture;
use vulkano::Version;
fn main() {
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
let instance = Instance::new(
None,
Version::major_minor(1, 1),
&InstanceExtensions::none(),
None,
)
.unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let queue_family = physical
.queue_families()

View File

@ -18,9 +18,16 @@ use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice};
use vulkano::pipeline::{ComputePipeline, ComputePipelineAbstract};
use vulkano::sync;
use vulkano::sync::GpuFuture;
use vulkano::Version;
fn main() {
let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
let instance = Instance::new(
None,
Version::major_minor(1, 1),
&InstanceExtensions::none(),
None,
)
.unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let queue_family = physical
.queue_families()

View File

@ -33,6 +33,7 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
@ -43,7 +44,8 @@ fn main() {
// `triangle` example if you haven't done so yet.
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
println!(
"Using device: {} (type: {:?})",

View File

@ -34,6 +34,7 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
@ -136,7 +137,8 @@ mod fs {
fn main() {
let required_extensions = vulkano_win::required_extensions();
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
println!(

View File

@ -16,6 +16,7 @@
// and that you want to learn Vulkan. This means that for example it won't go into details about
// what a vertex or a shader is.
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
@ -31,14 +32,12 @@ use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::Version;
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::{Window, WindowBuilder};
use std::sync::Arc;
fn main() {
// The first step of any Vulkan program is to create an instance.
//
@ -50,7 +49,8 @@ fn main() {
let required_extensions = vulkano_win::required_extensions();
// Now creating the instance.
let instance = Instance::new(None, &required_extensions, None).unwrap();
let instance =
Instance::new(None, Version::major_minor(1, 1), &required_extensions, None).unwrap();
// We then choose which physical device to use.
//

View File

@ -19,6 +19,7 @@ use std::os::raw::c_char;
use std::os::raw::c_double;
use std::os::raw::c_ulong;
use std::os::raw::c_void;
use std::ptr;
pub type Flags = u32;
pub type Bool32 = u32;
@ -1883,6 +1884,7 @@ pub struct AllocationCallbacks {
pub pfnInternalFree: PFN_vkInternalFreeNotification,
}
#[derive(Default)]
#[repr(C)]
pub struct PhysicalDeviceFeatures {
pub robustBufferAccess: Bool32,
@ -3270,12 +3272,24 @@ pub struct MVKSwapchainPerformance {
}
#[repr(C)]
pub struct PhysicalDeviceFeatures2KHR {
pub struct PhysicalDeviceFeatures2 {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub features: PhysicalDeviceFeatures,
}
impl Default for PhysicalDeviceFeatures2 {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
pNext: ptr::null_mut(),
features: Default::default(),
}
}
}
pub type PhysicalDeviceFeatures2KHR = PhysicalDeviceFeatures2;
#[repr(C)]
pub struct PhysicalDeviceProperties2KHR {
pub sType: StructureType,
@ -3286,7 +3300,7 @@ pub struct PhysicalDeviceProperties2KHR {
#[repr(C)]
pub struct PhysicalDeviceSubgroupProperties {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub subgroupSize: u32,
pub supportedStages: ShaderStageFlags,
pub supportedOperations: SubgroupFeatureFlags,
@ -3296,14 +3310,14 @@ pub struct PhysicalDeviceSubgroupProperties {
#[repr(C)]
pub struct FormatProperties2KHR {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub formatProperties: FormatProperties,
}
#[repr(C)]
pub struct ImageFormatProperties2KHR {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub imageFormatProperties: ImageFormatProperties,
}
@ -3321,21 +3335,21 @@ pub struct PhysicalDeviceImageFormatInfo2KHR {
#[repr(C)]
pub struct QueueFamilyProperties2KHR {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub queueFamilyProperties: QueueFamilyProperties,
}
#[repr(C)]
pub struct PhysicalDeviceMemoryProperties2KHR {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub memoryProperties: PhysicalDeviceMemoryProperties,
}
#[repr(C)]
pub struct SparseImageFormatProperties2KHR {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub properties: SparseImageFormatProperties,
}
@ -3359,49 +3373,410 @@ pub struct PhysicalDeviceBufferAddressFeaturesEXT {
pub bufferDeviceAddressMultiDevice: Bool32,
}
impl Default for PhysicalDeviceBufferAddressFeaturesEXT {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
#[repr(C)]
pub struct PhysicalDeviceVariablePointersFeatures {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub variablePointersStorageBuffer: Bool32,
pub variablePointers: Bool32,
}
impl Default for PhysicalDeviceVariablePointersFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceVariablePointersFeaturesKHR = PhysicalDeviceVariablePointersFeatures;
#[repr(C)]
pub struct PhysicalDeviceShaderAtomicInt64Features {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub shaderBufferInt64Atomics: Bool32,
pub shaderSharedInt64Atomics: Bool32,
}
impl Default for PhysicalDeviceShaderAtomicInt64Features {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceShaderAtomicInt64FeaturesKHR = PhysicalDeviceShaderAtomicInt64Features;
#[repr(C)]
pub struct PhysicalDevice8BitStorageFeatures {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub storageBuffer8BitAccess: Bool32,
pub uniformAndStorageBuffer8BitAccess: Bool32,
pub storagePushConstant8: Bool32,
}
impl Default for PhysicalDevice8BitStorageFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDevice8BitStorageFeaturesKHR = PhysicalDevice8BitStorageFeatures;
#[repr(C)]
pub struct PhysicalDevice16BitStorageFeatures {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub storageBuffer16BitAccess: Bool32,
pub uniformAndStorageBuffer16BitAccess: Bool32,
pub storagePushConstant16: Bool32,
pub storageInputOutput16: Bool32,
}
impl Default for PhysicalDevice16BitStorageFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDevice16BitStorageFeaturesKHR = PhysicalDevice16BitStorageFeatures;
#[repr(C)]
pub struct PhysicalDeviceShaderFloat16Int8Features {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub shaderFloat16: Bool32,
pub shaderInt8: Bool32,
}
impl Default for PhysicalDeviceShaderFloat16Int8Features {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceShaderFloat16Int8FeaturesKHR = PhysicalDeviceShaderFloat16Int8Features;
#[repr(C)]
pub struct PhysicalDeviceMultiviewFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub multiview: Bool32,
pub multiviewGeometryShader: Bool32,
pub multiviewTessellationShader: Bool32,
}
impl Default for PhysicalDeviceMultiviewFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceMultiviewFeaturesKHR = PhysicalDeviceMultiviewFeatures;
#[repr(C)]
pub struct PhysicalDeviceSamplerYcbcrConversionFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub samplerYcbcrConversion: Bool32,
}
impl Default for PhysicalDeviceSamplerYcbcrConversionFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceSamplerYcbcrConversionFeaturesKHR =
PhysicalDeviceSamplerYcbcrConversionFeatures;
#[repr(C)]
pub struct PhysicalDeviceProtectedMemoryFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub protectedMemory: Bool32,
}
impl Default for PhysicalDeviceProtectedMemoryFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
#[repr(C)]
pub struct PhysicalDeviceDescriptorIndexingFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub shaderInputAttachmentArrayDynamicIndexing: Bool32,
pub shaderUniformTexelBufferArrayDynamicIndexing: Bool32,
pub shaderStorageTexelBufferArrayDynamicIndexing: Bool32,
pub shaderUniformBufferArrayNonUniformIndexing: Bool32,
pub shaderSampledImageArrayNonUniformIndexing: Bool32,
pub shaderStorageBufferArrayNonUniformIndexing: Bool32,
pub shaderStorageImageArrayNonUniformIndexing: Bool32,
pub shaderInputAttachmentArrayNonUniformIndexing: Bool32,
pub shaderUniformTexelBufferArrayNonUniformIndexing: Bool32,
pub shaderStorageTexelBufferArrayNonUniformIndexing: Bool32,
pub descriptorBindingUniformBufferUpdateAfterBind: Bool32,
pub descriptorBindingSampledImageUpdateAfterBind: Bool32,
pub descriptorBindingStorageImageUpdateAfterBind: Bool32,
pub descriptorBindingStorageBufferUpdateAfterBind: Bool32,
pub descriptorBindingUniformTexelBufferUpdateAfterBind: Bool32,
pub descriptorBindingStorageTexelBufferUpdateAfterBind: Bool32,
pub descriptorBindingUpdateUnusedWhilePending: Bool32,
pub descriptorBindingPartiallyBound: Bool32,
pub descriptorBindingVariableDescriptorCount: Bool32,
pub runtimeDescriptorArray: Bool32,
}
impl Default for PhysicalDeviceDescriptorIndexingFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceDescriptorIndexingFeaturesEXT = PhysicalDeviceDescriptorIndexingFeatures;
#[repr(C)]
pub struct PhysicalDeviceScalarBlockLayoutFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub scalarBlockLayout: Bool32,
}
impl Default for PhysicalDeviceScalarBlockLayoutFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceScalarBlockLayoutFeaturesEXT = PhysicalDeviceScalarBlockLayoutFeatures;
#[repr(C)]
pub struct PhysicalDeviceImagelessFramebufferFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub imagelessFramebuffer: Bool32,
}
impl Default for PhysicalDeviceImagelessFramebufferFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceImagelessFramebufferFeaturesKHR = PhysicalDeviceImagelessFramebufferFeatures;
#[repr(C)]
pub struct PhysicalDeviceUniformBufferStandardLayoutFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub uniformBufferStandardLayout: Bool32,
}
impl Default for PhysicalDeviceUniformBufferStandardLayoutFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceUniformBufferStandardLayoutFeaturesKHR =
PhysicalDeviceUniformBufferStandardLayoutFeatures;
#[repr(C)]
pub struct PhysicalDeviceShaderSubgroupExtendedTypesFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub shaderSubgroupExtendedTypes: Bool32,
}
impl Default for PhysicalDeviceShaderSubgroupExtendedTypesFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR =
PhysicalDeviceShaderSubgroupExtendedTypesFeatures;
#[repr(C)]
pub struct PhysicalDeviceSeparateDepthStencilLayoutsFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub separateDepthStencilLayouts: Bool32,
}
impl Default for PhysicalDeviceSeparateDepthStencilLayoutsFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR =
PhysicalDeviceSeparateDepthStencilLayoutsFeatures;
#[repr(C)]
pub struct PhysicalDeviceHostQueryResetFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub hostQueryReset: Bool32,
}
impl Default for PhysicalDeviceHostQueryResetFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceHostQueryResetFeaturesEXT = PhysicalDeviceHostQueryResetFeatures;
#[repr(C)]
pub struct PhysicalDeviceTimelineSemaphoreFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub timelineSemaphore: Bool32,
}
impl Default for PhysicalDeviceTimelineSemaphoreFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceTimelineSemaphoreFeaturesKHR = PhysicalDeviceTimelineSemaphoreFeatures;
#[repr(C)]
pub struct PhysicalDeviceBufferDeviceAddressFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub bufferDeviceAddress: Bool32,
pub bufferDeviceAddressCaptureReplay: Bool32,
pub bufferDeviceAddressMultiDevice: Bool32,
}
impl Default for PhysicalDeviceBufferDeviceAddressFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceBufferDeviceAddressFeaturesKHR = PhysicalDeviceBufferDeviceAddressFeatures;
#[repr(C)]
pub struct PhysicalDeviceVulkanMemoryModelFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub vulkanMemoryModel: Bool32,
pub vulkanMemoryModelDeviceScope: Bool32,
pub vulkanMemoryModelAvailabilityVisibilityChains: Bool32,
}
impl Default for PhysicalDeviceVulkanMemoryModelFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type PhysicalDeviceVulkanMemoryModelFeaturesKHR = PhysicalDeviceVulkanMemoryModelFeatures;
#[repr(C)]
pub struct PhysicalDeviceShaderDrawParametersFeatures {
pub sType: StructureType,
pub pNext: *mut c_void,
pub shaderDrawParameters: Bool32,
}
impl Default for PhysicalDeviceShaderDrawParametersFeatures {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub type ViSurfaceCreateFlagsNN = Flags;
#[repr(C)]
@ -3446,7 +3821,7 @@ pub struct DescriptorUpdateTemplateCreateInfoKHR {
#[repr(C)]
pub struct MemoryDedicatedRequirementsKHR {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub prefersDedicatedAllocation: Bool32,
pub requiresDedicatedAllocation: Bool32,
}
@ -3462,14 +3837,14 @@ pub struct MemoryDedicatedAllocateInfoKHR {
#[repr(C)]
pub struct BufferMemoryRequirementsInfo2KHR {
pub sType: StructureType,
pub pNext: *mut c_void,
pub pNext: *const c_void,
pub buffer: Buffer,
}
#[repr(C)]
pub struct ImageMemoryRequirementsInfo2KHR {
pub sType: StructureType,
pub pNext: *mut c_void,
pub pNext: *const c_void,
pub image: Image,
}
@ -3536,16 +3911,6 @@ pub struct DebugUtilsLabelEXT {
pub color: [f32; 4],
}
#[repr(C)]
pub struct PhysicalDevice16BitStorageFeaturesKHR {
pub sType: StructureType,
pub pNext: *const c_void,
pub storageBuffer16BitAccess: Bool32,
pub uniformAndStorageBuffer16BitAccess: Bool32,
pub storagePushConstant16: Bool32,
pub storageInputOutput16: Bool32,
}
#[repr(C)]
pub struct DebugUtilsObjectNameInfoEXT {
pub sType: StructureType,
@ -3558,7 +3923,7 @@ pub struct DebugUtilsObjectNameInfoEXT {
#[repr(C)]
pub struct SurfaceFullScreenExclusiveInfoEXT {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub fullScreenExclusive: FullScreenExclusiveEXT,
}
@ -3586,7 +3951,7 @@ pub struct ExternalMemoryImageCreateInfo {
#[repr(C)]
pub struct MemoryFdPropertiesKHR {
pub sType: StructureType,
pub pNext: *const c_void,
pub pNext: *mut c_void,
pub handleType: ExternalMemoryHandleTypeFlagBits,
pub memoryTypeBits: u32,
}
@ -3607,6 +3972,96 @@ pub struct ImportMemoryFdInfoKHR {
pub fd: i32,
}
#[repr(C)]
pub struct PhysicalDeviceVulkan11Features {
pub sType: StructureType,
pub pNext: *mut c_void,
pub storageBuffer16BitAccess: Bool32,
pub uniformAndStorageBuffer16BitAccess: Bool32,
pub storagePushConstant16: Bool32,
pub storageInputOutput16: Bool32,
pub multiview: Bool32,
pub multiviewGeometryShader: Bool32,
pub multiviewTessellationShader: Bool32,
pub variablePointersStorageBuffer: Bool32,
pub variablePointers: Bool32,
pub protectedMemory: Bool32,
pub samplerYcbcrConversion: Bool32,
pub shaderDrawParameters: Bool32,
}
impl Default for PhysicalDeviceVulkan11Features {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
pub struct PhysicalDeviceVulkan12Features {
pub sType: StructureType,
pub pNext: *mut c_void,
pub samplerMirrorClampToEdge: Bool32,
pub drawIndirectCount: Bool32,
pub storageBuffer8BitAccess: Bool32,
pub uniformAndStorageBuffer8BitAccess: Bool32,
pub storagePushConstant8: Bool32,
pub shaderBufferInt64Atomics: Bool32,
pub shaderSharedInt64Atomics: Bool32,
pub shaderFloat16: Bool32,
pub shaderInt8: Bool32,
pub descriptorIndexing: Bool32,
pub shaderInputAttachmentArrayDynamicIndexing: Bool32,
pub shaderUniformTexelBufferArrayDynamicIndexing: Bool32,
pub shaderStorageTexelBufferArrayDynamicIndexing: Bool32,
pub shaderUniformBufferArrayNonUniformIndexing: Bool32,
pub shaderSampledImageArrayNonUniformIndexing: Bool32,
pub shaderStorageBufferArrayNonUniformIndexing: Bool32,
pub shaderStorageImageArrayNonUniformIndexing: Bool32,
pub shaderInputAttachmentArrayNonUniformIndexing: Bool32,
pub shaderUniformTexelBufferArrayNonUniformIndexing: Bool32,
pub shaderStorageTexelBufferArrayNonUniformIndexing: Bool32,
pub descriptorBindingUniformBufferUpdateAfterBind: Bool32,
pub descriptorBindingSampledImageUpdateAfterBind: Bool32,
pub descriptorBindingStorageImageUpdateAfterBind: Bool32,
pub descriptorBindingStorageBufferUpdateAfterBind: Bool32,
pub descriptorBindingUniformTexelBufferUpdateAfterBind: Bool32,
pub descriptorBindingStorageTexelBufferUpdateAfterBind: Bool32,
pub descriptorBindingUpdateUnusedWhilePending: Bool32,
pub descriptorBindingPartiallyBound: Bool32,
pub descriptorBindingVariableDescriptorCount: Bool32,
pub runtimeDescriptorArray: Bool32,
pub samplerFilterMinmax: Bool32,
pub scalarBlockLayout: Bool32,
pub imagelessFramebuffer: Bool32,
pub uniformBufferStandardLayout: Bool32,
pub shaderSubgroupExtendedTypes: Bool32,
pub separateDepthStencilLayouts: Bool32,
pub hostQueryReset: Bool32,
pub timelineSemaphore: Bool32,
pub bufferDeviceAddress: Bool32,
pub bufferDeviceAddressCaptureReplay: Bool32,
pub bufferDeviceAddressMultiDevice: Bool32,
pub vulkanMemoryModel: Bool32,
pub vulkanMemoryModelDeviceScope: Bool32,
pub vulkanMemoryModelAvailabilityVisibilityChains: Bool32,
pub shaderOutputViewportIndex: Bool32,
pub shaderOutputLayer: Bool32,
pub subgroupBroadcastDynamicId: Bool32,
}
impl Default for PhysicalDeviceVulkan12Features {
fn default() -> Self {
Self {
sType: STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
pNext: ptr::null_mut(),
..unsafe { mem::zeroed() }
}
}
}
macro_rules! ptrs {
($struct_name:ident, { $($name:ident => ($($param_n:ident: $param_ty:ty),*) -> $ret:ty,)+ }) => (
pub struct $struct_name {

View File

@ -225,14 +225,14 @@ where
(1, 0) => {}
(1, 1) | (1, 2) | (1, 3) => {
cap_checks.push(quote! {
if device.api_version() < (Version { major: 1, minor: 1, patch: 0 }) {
if device.api_version() < Version::major_minor(1, 1) {
panic!("Device API version 1.1 required");
}
});
}
(1, 4) => {
cap_checks.push(quote! {
if device.api_version() < (Version { major: 1, minor: 2, patch: 0 })
if device.api_version() < Version::major_minor(1, 2)
&& !device.loaded_extensions().khr_spirv_1_4 {
panic!("Device API version 1.2 or extension VK_KHR_spirv_1_4 required");
}
@ -240,7 +240,7 @@ where
}
(1, 5) => {
cap_checks.push(quote! {
if device.api_version() < (Version { major: 1, minor: 2, patch: 0 }) {
if device.api_version() < Version::major_minor(1, 2) {
panic!("Device API version 1.2 required");
}
});

View File

@ -103,7 +103,10 @@ impl UnsafeBuffer {
0
};
if usage.device_address && !device.enabled_features().buffer_device_address {
if usage.device_address
&& !(device.enabled_features().buffer_device_address
|| device.enabled_features().ext_buffer_device_address)
{
usage.device_address = false;
if vk::BufferUsageFlags::from(usage) == 0 {
// return an error iff device_address was the only requested usage and the
@ -164,7 +167,7 @@ impl UnsafeBuffer {
let mut output2 = if device.loaded_extensions().khr_dedicated_allocation {
Some(vk::MemoryDedicatedRequirementsKHR {
sType: vk::STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
pNext: ptr::null(),
pNext: ptr::null_mut(),
prefersDedicatedAllocation: mem::zeroed(),
requiresDedicatedAllocation: mem::zeroed(),
})

View File

@ -0,0 +1,325 @@
// 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.
use crate::vk;
use crate::Version;
use std::marker::PhantomPinned;
use std::ptr::addr_of_mut;
macro_rules! features {
{
$({ $member:ident => $($ffi_struct:ident.$($ffi_field:ident).+)|+ },)*
} => {
/// Represents all the features that are available on a physical device or enabled on
/// a logical device.
///
/// Note that the `robust_buffer_access` is guaranteed to be supported by all Vulkan
/// implementations.
///
/// # Example
///
/// ```
/// use vulkano::device::Features;
/// # let physical_device: vulkano::instance::PhysicalDevice = return;
/// let minimal_features = Features {
/// geometry_shader: true,
/// .. Features::none()
/// };
///
/// let optimal_features = vulkano::device::Features {
/// geometry_shader: true,
/// tessellation_shader: true,
/// .. Features::none()
/// };
///
/// if !physical_device.supported_features().superset_of(&minimal_features) {
/// panic!("The physical device is not good enough for this application.");
/// }
///
/// assert!(optimal_features.superset_of(&minimal_features));
/// let features_to_request = optimal_features.intersection(physical_device.supported_features());
/// ```
///
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
#[allow(missing_docs)]
pub struct Features {
$(pub $member: bool,)*
}
impl Features {
/// Builds a `Features` object with all values to false.
pub fn none() -> Features {
Features {
$($member: false,)*
}
}
/// Builds a `Features` object with all values to true.
///
/// > **Note**: This function is used for testing purposes, and is probably useless in
/// > a real code.
pub fn all() -> Features {
Features {
$($member: true,)*
}
}
/// Returns true if `self` is a superset of the parameter.
///
/// That is, for each feature of the parameter that is true, the corresponding value
/// in self is true as well.
pub fn superset_of(&self, other: &Features) -> bool {
$((self.$member == true || other.$member == false))&&+
}
/// Builds a `Features` that is the intersection of `self` and another `Features`
/// object.
///
/// The result's field will be true if it is also true in both `self` and `other`.
pub fn intersection(&self, other: &Features) -> Features {
Features {
$($member: self.$member && other.$member,)*
}
}
/// Builds a `Features` that is the difference of another `Features` object from `self`.
///
/// The result's field will be true if it is true in `self` but not `other`.
pub fn difference(&self, other: &Features) -> Features {
Features {
$($member: self.$member && !other.$member,)*
}
}
}
impl From<&Features> for FeaturesFfi {
#[inline(always)]
fn from(features: &Features) -> Self {
let mut features_ffi = FeaturesFfi::default();
$(
$(features_ffi.$ffi_struct.$($ffi_field).+ |= features.$member as vk::Bool32;)*
)+
features_ffi
}
}
impl From<&FeaturesFfi> for Features {
#[inline(always)]
fn from(features_ffi: &FeaturesFfi) -> Self {
Features {
$($member: $(features_ffi.$ffi_struct.$($ffi_field).+ != 0)||+,)*
}
}
}
};
}
features! {
{robust_buffer_access => vulkan_1_0.features.robustBufferAccess},
{full_draw_index_uint32 => vulkan_1_0.features.fullDrawIndexUint32},
{image_cube_array => vulkan_1_0.features.imageCubeArray},
{independent_blend => vulkan_1_0.features.independentBlend},
{geometry_shader => vulkan_1_0.features.geometryShader},
{tessellation_shader => vulkan_1_0.features.tessellationShader},
{sample_rate_shading => vulkan_1_0.features.sampleRateShading},
{dual_src_blend => vulkan_1_0.features.dualSrcBlend},
{logic_op => vulkan_1_0.features.logicOp},
{multi_draw_indirect => vulkan_1_0.features.multiDrawIndirect},
{draw_indirect_first_instance => vulkan_1_0.features.drawIndirectFirstInstance},
{depth_clamp => vulkan_1_0.features.depthClamp},
{depth_bias_clamp => vulkan_1_0.features.depthBiasClamp},
{fill_mode_non_solid => vulkan_1_0.features.fillModeNonSolid},
{depth_bounds => vulkan_1_0.features.depthBounds},
{wide_lines => vulkan_1_0.features.wideLines},
{large_points => vulkan_1_0.features.largePoints},
{alpha_to_one => vulkan_1_0.features.alphaToOne},
{multi_viewport => vulkan_1_0.features.multiViewport},
{sampler_anisotropy => vulkan_1_0.features.samplerAnisotropy},
{texture_compression_etc2 => vulkan_1_0.features.textureCompressionETC2},
{texture_compression_astc_ldr => vulkan_1_0.features.textureCompressionASTC_LDR},
{texture_compression_bc => vulkan_1_0.features.textureCompressionBC},
{occlusion_query_precise => vulkan_1_0.features.occlusionQueryPrecise},
{pipeline_statistics_query => vulkan_1_0.features.pipelineStatisticsQuery},
{vertex_pipeline_stores_and_atomics => vulkan_1_0.features.vertexPipelineStoresAndAtomics},
{fragment_stores_and_atomics => vulkan_1_0.features.fragmentStoresAndAtomics},
{shader_tessellation_and_geometry_point_size => vulkan_1_0.features.shaderTessellationAndGeometryPointSize},
{shader_image_gather_extended => vulkan_1_0.features.shaderImageGatherExtended},
{shader_storage_image_extended_formats => vulkan_1_0.features.shaderStorageImageExtendedFormats},
{shader_storage_image_multisample => vulkan_1_0.features.shaderStorageImageMultisample},
{shader_storage_image_read_without_format => vulkan_1_0.features.shaderStorageImageReadWithoutFormat},
{shader_storage_image_write_without_format => vulkan_1_0.features.shaderStorageImageWriteWithoutFormat},
{shader_uniform_buffer_array_dynamic_indexing => vulkan_1_0.features.shaderUniformBufferArrayDynamicIndexing},
{shader_sampled_image_array_dynamic_indexing => vulkan_1_0.features.shaderSampledImageArrayDynamicIndexing},
{shader_storage_buffer_array_dynamic_indexing => vulkan_1_0.features.shaderStorageBufferArrayDynamicIndexing},
{shader_storage_image_array_dynamic_indexing => vulkan_1_0.features.shaderStorageImageArrayDynamicIndexing},
{shader_clip_distance => vulkan_1_0.features.shaderClipDistance},
{shader_cull_distance => vulkan_1_0.features.shaderCullDistance},
{shader_float64 => vulkan_1_0.features.shaderFloat64},
{shader_int64 => vulkan_1_0.features.shaderInt64},
{shader_int16 => vulkan_1_0.features.shaderInt16},
{shader_resource_residency => vulkan_1_0.features.shaderResourceResidency},
{shader_resource_min_lod => vulkan_1_0.features.shaderResourceMinLod},
{sparse_binding => vulkan_1_0.features.sparseBinding},
{sparse_residency_buffer => vulkan_1_0.features.sparseResidencyBuffer},
{sparse_residency_image2d => vulkan_1_0.features.sparseResidencyImage2D},
{sparse_residency_image3d => vulkan_1_0.features.sparseResidencyImage3D},
{sparse_residency2_samples => vulkan_1_0.features.sparseResidency2Samples},
{sparse_residency4_samples => vulkan_1_0.features.sparseResidency4Samples},
{sparse_residency8_samples => vulkan_1_0.features.sparseResidency8Samples},
{sparse_residency16_samples => vulkan_1_0.features.sparseResidency16Samples},
{sparse_residency_aliased => vulkan_1_0.features.sparseResidencyAliased},
{variable_multisample_rate => vulkan_1_0.features.variableMultisampleRate},
{inherited_queries => vulkan_1_0.features.inheritedQueries},
{storage_buffer_16bit => vulkan_1_1.storageBuffer16BitAccess | khr_16bit_storage.storageBuffer16BitAccess},
{storage_uniform_16bit => vulkan_1_1.uniformAndStorageBuffer16BitAccess | khr_16bit_storage.uniformAndStorageBuffer16BitAccess},
{storage_push_constant_16bit => vulkan_1_1.storagePushConstant16 | khr_16bit_storage.storagePushConstant16},
{storage_input_output_16bit => vulkan_1_1.storageInputOutput16 | khr_16bit_storage.storageInputOutput16},
{multiview => vulkan_1_1.multiview | khr_multiview.multiview},
{multiview_geometry_shader => vulkan_1_1.multiviewGeometryShader | khr_multiview.multiviewGeometryShader},
{multiview_tessellation_shader => vulkan_1_1.multiviewTessellationShader | khr_multiview.multiviewTessellationShader},
{variable_pointers_storage_buffer => vulkan_1_1.variablePointersStorageBuffer | khr_variable_pointers.variablePointersStorageBuffer},
{variable_pointers => vulkan_1_1.variablePointers | khr_variable_pointers.variablePointers},
{protected_memory => vulkan_1_1.protectedMemory | protected_memory.protectedMemory},
{sampler_ycbcr_conversion => vulkan_1_1.samplerYcbcrConversion | khr_sampler_ycbcr_conversion.samplerYcbcrConversion},
{shader_draw_parameters => vulkan_1_1.shaderDrawParameters | shader_draw_parameters.shaderDrawParameters},
{sampler_mirror_clamp_to_edge => vulkan_1_2.samplerMirrorClampToEdge},
{draw_indirect_count => vulkan_1_2.drawIndirectCount},
{storage_buffer_8bit => vulkan_1_2.storageBuffer8BitAccess | khr_8bit_storage.storageBuffer8BitAccess},
{storage_uniform_8bit => vulkan_1_2.uniformAndStorageBuffer8BitAccess | khr_8bit_storage.uniformAndStorageBuffer8BitAccess},
{storage_push_constant_8bit => vulkan_1_2.storagePushConstant8 | khr_8bit_storage.storagePushConstant8},
{shader_buffer_int64_atomics => vulkan_1_2.shaderBufferInt64Atomics | khr_shader_atomic_int64.shaderBufferInt64Atomics},
{shader_shared_int64_atomics => vulkan_1_2.shaderSharedInt64Atomics | khr_shader_atomic_int64.shaderSharedInt64Atomics},
{shader_float16 => vulkan_1_2.shaderFloat16 | khr_shader_float16_int8.shaderFloat16},
{shader_int8 => vulkan_1_2.shaderInt8 | khr_shader_float16_int8.shaderInt8},
{descriptor_indexing => vulkan_1_2.descriptorIndexing},
{shader_input_attachment_array_dynamic_indexing => vulkan_1_2.shaderInputAttachmentArrayDynamicIndexing | ext_descriptor_indexing.shaderInputAttachmentArrayDynamicIndexing},
{shader_uniform_texel_buffer_array_dynamic_indexing => vulkan_1_2.shaderUniformTexelBufferArrayDynamicIndexing | ext_descriptor_indexing.shaderUniformTexelBufferArrayDynamicIndexing},
{shader_storage_texel_buffer_array_dynamic_indexing => vulkan_1_2.shaderStorageTexelBufferArrayDynamicIndexing | ext_descriptor_indexing.shaderStorageTexelBufferArrayDynamicIndexing},
{shader_uniform_buffer_array_non_uniform_indexing => vulkan_1_2.shaderUniformBufferArrayNonUniformIndexing | ext_descriptor_indexing.shaderUniformBufferArrayNonUniformIndexing},
{shader_sampled_image_array_non_uniform_indexing => vulkan_1_2.shaderSampledImageArrayNonUniformIndexing | ext_descriptor_indexing.shaderSampledImageArrayNonUniformIndexing},
{shader_storage_buffer_array_non_uniform_indexing => vulkan_1_2.shaderStorageBufferArrayNonUniformIndexing | ext_descriptor_indexing.shaderStorageBufferArrayNonUniformIndexing},
{shader_storage_image_array_non_uniform_indexing => vulkan_1_2.shaderStorageImageArrayNonUniformIndexing | ext_descriptor_indexing.shaderStorageImageArrayNonUniformIndexing},
{shader_input_attachment_array_non_uniform_indexing => vulkan_1_2.shaderInputAttachmentArrayNonUniformIndexing | ext_descriptor_indexing.shaderInputAttachmentArrayNonUniformIndexing},
{shader_uniform_texel_buffer_array_non_uniform_indexing => vulkan_1_2.shaderUniformTexelBufferArrayNonUniformIndexing | ext_descriptor_indexing.shaderUniformTexelBufferArrayNonUniformIndexing},
{shader_storage_texel_buffer_array_non_uniform_indexing => vulkan_1_2.shaderStorageTexelBufferArrayNonUniformIndexing | ext_descriptor_indexing.shaderStorageTexelBufferArrayNonUniformIndexing},
{descriptor_binding_uniform_buffer_update_after_bind => vulkan_1_2.descriptorBindingUniformBufferUpdateAfterBind | ext_descriptor_indexing.descriptorBindingUniformBufferUpdateAfterBind},
{descriptor_binding_sampled_image_update_after_bind => vulkan_1_2.descriptorBindingSampledImageUpdateAfterBind | ext_descriptor_indexing.descriptorBindingSampledImageUpdateAfterBind},
{descriptor_binding_storage_image_update_after_bind => vulkan_1_2.descriptorBindingStorageImageUpdateAfterBind | ext_descriptor_indexing.descriptorBindingStorageImageUpdateAfterBind},
{descriptor_binding_storage_buffer_update_after_bind => vulkan_1_2.descriptorBindingStorageBufferUpdateAfterBind | ext_descriptor_indexing.descriptorBindingStorageBufferUpdateAfterBind},
{descriptor_binding_uniform_texel_buffer_update_after_bind => vulkan_1_2.descriptorBindingUniformTexelBufferUpdateAfterBind | ext_descriptor_indexing.descriptorBindingUniformTexelBufferUpdateAfterBind},
{descriptor_binding_storage_texel_buffer_update_after_bind => vulkan_1_2.descriptorBindingStorageTexelBufferUpdateAfterBind | ext_descriptor_indexing.descriptorBindingStorageTexelBufferUpdateAfterBind},
{descriptor_binding_update_unused_while_pending => vulkan_1_2.descriptorBindingUpdateUnusedWhilePending | ext_descriptor_indexing.descriptorBindingUpdateUnusedWhilePending},
{descriptor_binding_partially_bound => vulkan_1_2.descriptorBindingPartiallyBound | ext_descriptor_indexing.descriptorBindingPartiallyBound},
{descriptor_binding_variable_descriptor_count => vulkan_1_2.descriptorBindingVariableDescriptorCount | ext_descriptor_indexing.descriptorBindingVariableDescriptorCount},
{runtime_descriptor_array => vulkan_1_2.runtimeDescriptorArray | ext_descriptor_indexing.runtimeDescriptorArray},
{sampler_filter_minmax => vulkan_1_2.samplerFilterMinmax},
{scalar_block_layout => vulkan_1_2.scalarBlockLayout | ext_scalar_block_layout.scalarBlockLayout},
{imageless_framebuffer => vulkan_1_2.imagelessFramebuffer | khr_imageless_framebuffer.imagelessFramebuffer},
{uniform_buffer_standard_layout => vulkan_1_2.uniformBufferStandardLayout | khr_uniform_buffer_standard_layout.uniformBufferStandardLayout},
{shader_subgroup_extended_types => vulkan_1_2.shaderSubgroupExtendedTypes | khr_shader_subgroup_extended_types.shaderSubgroupExtendedTypes},
{separate_depth_stencil_layouts => vulkan_1_2.separateDepthStencilLayouts | khr_separate_depth_stencil_layouts.separateDepthStencilLayouts},
{host_query_reset => vulkan_1_2.hostQueryReset | ext_host_query_reset.hostQueryReset},
{timeline_semaphore => vulkan_1_2.timelineSemaphore | khr_timeline_semaphore.timelineSemaphore},
{buffer_device_address => vulkan_1_2.bufferDeviceAddress | khr_buffer_device_address.bufferDeviceAddress},
{buffer_device_address_capture_replay => vulkan_1_2.bufferDeviceAddressCaptureReplay | khr_buffer_device_address.bufferDeviceAddressCaptureReplay},
{buffer_device_address_multi_device => vulkan_1_2.bufferDeviceAddressMultiDevice | khr_buffer_device_address.bufferDeviceAddressMultiDevice},
{vulkan_memory_model => vulkan_1_2.vulkanMemoryModel | khr_vulkan_memory_model.vulkanMemoryModel},
{vulkan_memory_model_device_scope => vulkan_1_2.vulkanMemoryModelDeviceScope | khr_vulkan_memory_model.vulkanMemoryModelDeviceScope},
{vulkan_memory_model_availability_visibility_chains => vulkan_1_2.vulkanMemoryModelAvailabilityVisibilityChains | khr_vulkan_memory_model.vulkanMemoryModelAvailabilityVisibilityChains},
{shader_output_viewport_index => vulkan_1_2.shaderOutputViewportIndex},
{shader_output_layer => vulkan_1_2.shaderOutputLayer},
{subgroup_broadcast_dynamic_id => vulkan_1_2.subgroupBroadcastDynamicId},
{ext_buffer_device_address => ext_buffer_address.bufferDeviceAddress},
{ext_buffer_device_address_capture_replay => ext_buffer_address.bufferDeviceAddressCaptureReplay},
{ext_buffer_device_address_multi_device => ext_buffer_address.bufferDeviceAddressMultiDevice},
}
#[derive(Default)]
pub(crate) struct FeaturesFfi {
_pinned: PhantomPinned,
vulkan_1_0: vk::PhysicalDeviceFeatures2KHR,
vulkan_1_1: vk::PhysicalDeviceVulkan11Features,
vulkan_1_2: vk::PhysicalDeviceVulkan12Features,
protected_memory: vk::PhysicalDeviceProtectedMemoryFeatures,
shader_draw_parameters: vk::PhysicalDeviceShaderDrawParametersFeatures,
khr_16bit_storage: vk::PhysicalDevice16BitStorageFeaturesKHR,
khr_8bit_storage: vk::PhysicalDevice8BitStorageFeaturesKHR,
khr_buffer_device_address: vk::PhysicalDeviceBufferDeviceAddressFeaturesKHR,
khr_imageless_framebuffer: vk::PhysicalDeviceImagelessFramebufferFeaturesKHR,
khr_multiview: vk::PhysicalDeviceMultiviewFeaturesKHR,
khr_sampler_ycbcr_conversion: vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR,
khr_separate_depth_stencil_layouts: vk::PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR,
khr_shader_atomic_int64: vk::PhysicalDeviceShaderAtomicInt64FeaturesKHR,
khr_shader_float16_int8: vk::PhysicalDeviceShaderFloat16Int8FeaturesKHR,
khr_shader_subgroup_extended_types: vk::PhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR,
khr_timeline_semaphore: vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR,
khr_uniform_buffer_standard_layout: vk::PhysicalDeviceUniformBufferStandardLayoutFeaturesKHR,
khr_variable_pointers: vk::PhysicalDeviceVariablePointersFeaturesKHR,
khr_vulkan_memory_model: vk::PhysicalDeviceVulkanMemoryModelFeaturesKHR,
ext_buffer_address: vk::PhysicalDeviceBufferAddressFeaturesEXT,
ext_descriptor_indexing: vk::PhysicalDeviceDescriptorIndexingFeaturesEXT,
ext_host_query_reset: vk::PhysicalDeviceHostQueryResetFeaturesEXT,
ext_scalar_block_layout: vk::PhysicalDeviceScalarBlockLayoutFeaturesEXT,
}
macro_rules! push_struct {
($self:ident, $struct:ident) => {
$self.$struct.pNext = $self.vulkan_1_0.pNext;
$self.vulkan_1_0.pNext = addr_of_mut!($self.$struct) as _;
};
}
impl FeaturesFfi {
pub(crate) fn make_chain(&mut self, api_version: Version) {
if api_version >= Version::major_minor(1, 2) {
push_struct!(self, vulkan_1_1);
push_struct!(self, vulkan_1_2);
} else {
if api_version >= Version::major_minor(1, 1) {
push_struct!(self, protected_memory);
push_struct!(self, shader_draw_parameters);
}
push_struct!(self, khr_16bit_storage);
push_struct!(self, khr_8bit_storage);
push_struct!(self, khr_buffer_device_address);
push_struct!(self, khr_imageless_framebuffer);
push_struct!(self, khr_multiview);
push_struct!(self, khr_sampler_ycbcr_conversion);
push_struct!(self, khr_separate_depth_stencil_layouts);
push_struct!(self, khr_shader_atomic_int64);
push_struct!(self, khr_shader_float16_int8);
push_struct!(self, khr_shader_subgroup_extended_types);
push_struct!(self, khr_timeline_semaphore);
push_struct!(self, khr_uniform_buffer_standard_layout);
push_struct!(self, khr_variable_pointers);
push_struct!(self, khr_vulkan_memory_model);
push_struct!(self, ext_descriptor_indexing);
push_struct!(self, ext_host_query_reset);
push_struct!(self, ext_scalar_block_layout);
}
push_struct!(self, ext_buffer_address);
}
pub(crate) fn head_as_ref(&self) -> &vk::PhysicalDeviceFeatures2KHR {
&self.vulkan_1_0
}
pub(crate) fn head_as_mut(&mut self) -> &mut vk::PhysicalDeviceFeatures2KHR {
&mut self.vulkan_1_0
}
}

View File

@ -21,9 +21,10 @@
//! use vulkano::instance::Instance;
//! use vulkano::instance::InstanceExtensions;
//! use vulkano::instance::PhysicalDevice;
//! use vulkano::Version;
//!
//! // Creating the instance. See the documentation of the `instance` module.
//! let instance = match Instance::new(None, &InstanceExtensions::none(), None) {
//! let instance = match Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), None) {
//! Ok(i) => i,
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
//! };
@ -91,11 +92,17 @@
pub use self::extensions::DeviceExtensions;
pub use self::extensions::RawDeviceExtensions;
pub use self::features::Features;
pub(crate) use self::features::FeaturesFfi;
use crate::check_errors;
use crate::command_buffer::pool::StandardCommandPool;
use crate::descriptor::descriptor_set::StdDescriptorPool;
pub use crate::features::Features;
use crate::features::FeaturesFfi;
use crate::format::Format;
use crate::image::ImageCreateFlags;
use crate::image::ImageFormatProperties;
use crate::image::ImageTiling;
use crate::image::ImageType;
use crate::image::ImageUsage;
use crate::instance::Instance;
use crate::instance::PhysicalDevice;
use crate::instance::QueueFamily;
@ -104,6 +111,7 @@ use crate::vk;
use crate::Error;
use crate::OomError;
use crate::SynchronizedVulkanObject;
use crate::Version;
use crate::VulkanHandle;
use crate::VulkanObject;
use fnv::FnvHasher;
@ -123,15 +131,9 @@ use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use std::sync::Weak;
mod extensions;
use crate::format::Format;
use crate::image::ImageCreateFlags;
use crate::image::ImageFormatProperties;
use crate::image::ImageTiling;
use crate::image::ImageType;
use crate::image::ImageUsage;
use crate::Version;
use std::pin::Pin;
mod features;
/// Represents a Vulkan context.
pub struct Device {
@ -140,7 +142,7 @@ pub struct Device {
device: vk::Device,
// The highest version that is supported for this device.
// This is the minimum of Instance::desired_version and PhysicalDevice::api_version.
// This is the minimum of Instance::max_api_version and PhysicalDevice::api_version.
api_version: Version,
vk: vk::DevicePointers,
@ -193,8 +195,11 @@ impl Device {
I: IntoIterator<Item = (QueueFamily<'a>, f32)>,
Ext: Into<RawDeviceExtensions>,
{
let desired_version = phys.instance().desired_version;
let api_version = std::cmp::min(desired_version, phys.api_version());
let instance = phys.instance();
let vk_i = instance.pointers();
let max_api_version = instance.max_api_version();
let api_version = std::cmp::min(max_api_version, phys.api_version());
let queue_families = queue_families.into_iter();
@ -202,8 +207,6 @@ impl Device {
return Err(DeviceCreationError::FeatureNotPresent);
}
let vk_i = phys.instance().pointers();
// this variable will contain the queue family ID and queue ID of each requested queue
let mut output_queues: SmallVec<[(u32, u32); 8]> = SmallVec::new();
@ -216,8 +219,7 @@ impl Device {
// Because there's no way to query the list of layers enabled for an instance, we need
// to save it alongside the instance. (`vkEnumerateDeviceLayerProperties` should get
// the right list post-1.0.13, but not pre-1.0.13, so we can't use it here.)
let layers_ptr = phys
.instance()
let layers_ptr = instance
.loaded_layers()
.map(|layer| layer.as_ptr())
.collect::<SmallVec<[_; 16]>>();
@ -228,10 +230,11 @@ impl Device {
.map(|extension| extension.as_ptr())
.collect::<SmallVec<[_; 16]>>();
let mut requested_features = requested_features.clone();
// Always enabled; see below.
requested_features.robust_buffer_access = true;
let requested_features = requested_features;
let requested_features = Features {
// Always enabled; see below.
robust_buffer_access: true,
..*requested_features
};
// device creation
let device = unsafe {
@ -294,11 +297,20 @@ impl Device {
// Note that if we ever remove this, don't forget to adjust the change in
// `Device`'s construction below.
let features = Pin::<Box<FeaturesFfi>>::from(&requested_features);
let mut features_ffi = <FeaturesFfi>::from(&requested_features);
features_ffi.make_chain(api_version);
let has_khr_get_physical_device_properties2 = instance
.loaded_extensions()
.khr_get_physical_device_properties2;
let infos = vk::DeviceCreateInfo {
sType: vk::STRUCTURE_TYPE_DEVICE_CREATE_INFO,
pNext: features.base_ptr() as *const _,
pNext: if has_khr_get_physical_device_properties2 {
features_ffi.head_as_ref() as *const _ as _
} else {
ptr::null()
},
flags: 0, // reserved
queueCreateInfoCount: queues.len() as u32,
pQueueCreateInfos: queues.as_ptr(),
@ -306,7 +318,11 @@ impl Device {
ppEnabledLayerNames: layers_ptr.as_ptr(),
enabledExtensionCount: extensions_list.len() as u32,
ppEnabledExtensionNames: extensions_list.as_ptr(),
pEnabledFeatures: ptr::null(),
pEnabledFeatures: if has_khr_get_physical_device_properties2 {
ptr::null()
} else {
&features_ffi.head_as_ref().features
},
};
let mut output = MaybeUninit::uninit();
@ -367,6 +383,10 @@ impl Device {
}
/// Returns the Vulkan version supported by this `Device`.
///
/// This is the lower of the
/// [physical device's supported version](crate::instance::PhysicalDevice::api_version) and
/// the instance's [`max_api_version`](crate::instance::Instance::max_api_version).
#[inline]
pub fn api_version(&self) -> Version {
self.api_version
@ -867,7 +887,7 @@ mod tests {
use crate::device::Device;
use crate::device::DeviceCreationError;
use crate::device::DeviceExtensions;
use crate::features::Features;
use crate::device::Features;
use crate::instance;
use std::sync::Arc;

View File

@ -1,567 +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.
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::{mem, ptr};
use crate::vk;
macro_rules! features_init {
(core { $name:ident => $vk:ident }, $out:expr, $val:expr) => {
$out.$name = $val;
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)+
],
}, $out:expr, $val:expr) => {
$($out.$name = $val;)+
};
}
macro_rules! features_superset_of {
(core { $name:ident => $vk:ident }, $self:expr, $other:expr) => {
($self.$name == true || $other.$name == false)
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)+
],
}, $self:expr, $other:expr) => {
$(($self.$name == true || $other.$name == false))&&+
};
}
macro_rules! features_intersection {
(core { $name:ident => $vk:ident }, $out:expr, $self:expr, $other:expr) => {
$out.$name = $self.$name && $other.$name;
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)+
],
}, $out:expr, $self:expr, $other:expr) => {
$($out.$name = $self.$name && $other.$name;)+
};
}
macro_rules! features_difference {
(core { $name:ident => $vk:ident }, $out:expr, $self:expr, $other:expr) => {
$out.$name = $self.$name && !$other.$name;
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)+
],
}, $out:expr, $self:expr, $other:expr) => {
$($out.$name = $self.$name && !$other.$name;)+
};
}
macro_rules! from_feature_v1 {
(core { $name:ident => $vk:ident }, $out:expr, $features:expr) => {
$out.$name = $features.$vk != vk::FALSE;
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)+
],
}, $out:expr, $features:expr) => {
// nothing.
};
}
macro_rules! into_feature_v1 {
(core { $name:ident => $vk:ident }, $out:expr, $self:expr) => {
$out.$vk = if $self.$name { vk::TRUE } else { vk::FALSE };
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)+
],
}, $out:expr, $self:expr) => {
// nothing.
};
}
macro_rules! from_ext_features_match {
(core { $name:ident => $vk:ident }, $output:expr, $base_ref:expr, $base_ptr:expr) => {
// nothing.
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)+
],
}, $output:expr, $base_ref:expr, $base_ptr:expr) => {
if $base_ref.sType == $stype {
let ptr = $base_ptr as *const $ty;
let r = ptr.as_ref().unwrap();
$($output.$name = r.$vk != vk::FALSE;)+
}
};
}
macro_rules! into_ext_features_match {
(core { $name:ident => $vk:ident }, $output:expr, $base_ref:expr, $base_ptr:expr) => {
// nothing.
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)+
],
}, $this:expr, $base_ref:expr, $base_ptr:expr) => {
if $base_ref.sType == $stype {
let ptr = $base_ptr as *mut $ty;
let r = ptr.as_mut().unwrap();
$(r.$vk = if $this.$name { vk::TRUE } else { vk::FALSE };)+
}
};
}
macro_rules! features_ffi_init_pinned {
(core { $name:ident => $vk:ident }, $this:expr, $prev:expr) => {
// nothing.
};
(extension {
ty: $ty:ty,
ffi_name: $ffi_name:ident,
sType: $stype:expr,
fields: [
$($name:ident => $vk:ident,)*
],
}, $this:expr, $prev:expr) => {{
$this.$ffi_name.sType = $stype;
let next = &mut $this.$ffi_name as *mut _ as *mut Base;
(&mut *$prev).pNext = next;
$prev = next;
}};
}
#[allow(non_snake_case)]
#[repr(C)]
pub(crate) struct Base {
sType: vk::StructureType,
pNext: *mut Base,
}
// Can't define this structure with macros :(
/// Represents all the features that are available on a physical device or enabled on
/// a logical device.
///
/// Note that the `robust_buffer_access` is guaranteed to be supported by all Vulkan
/// implementations.
///
/// # Example
///
/// ```
/// use vulkano::device::Features;
/// # let physical_device: vulkano::instance::PhysicalDevice = return;
/// let minimal_features = Features {
/// geometry_shader: true,
/// .. Features::none()
/// };
///
/// let optimal_features = vulkano::device::Features {
/// geometry_shader: true,
/// tessellation_shader: true,
/// .. Features::none()
/// };
///
/// if !physical_device.supported_features().superset_of(&minimal_features) {
/// panic!("The physical device is not good enough for this application.");
/// }
///
/// assert!(optimal_features.superset_of(&minimal_features));
/// let features_to_request = optimal_features.intersection(physical_device.supported_features());
/// ```
///
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
#[allow(missing_docs)]
pub struct Features {
pub robust_buffer_access: bool,
pub full_draw_index_uint32: bool,
pub image_cube_array: bool,
pub independent_blend: bool,
pub geometry_shader: bool,
pub tessellation_shader: bool,
pub sample_rate_shading: bool,
pub dual_src_blend: bool,
pub logic_op: bool,
pub multi_draw_indirect: bool,
pub draw_indirect_first_instance: bool,
pub depth_clamp: bool,
pub depth_bias_clamp: bool,
pub fill_mode_non_solid: bool,
pub depth_bounds: bool,
pub wide_lines: bool,
pub large_points: bool,
pub alpha_to_one: bool,
pub multi_viewport: bool,
pub sampler_anisotropy: bool,
pub texture_compression_etc2: bool,
pub texture_compression_astc_ldr: bool,
pub texture_compression_bc: bool,
pub occlusion_query_precise: bool,
pub pipeline_statistics_query: bool,
pub vertex_pipeline_stores_and_atomics: bool,
pub fragment_stores_and_atomics: bool,
pub shader_tessellation_and_geometry_point_size: bool,
pub shader_image_gather_extended: bool,
pub shader_storage_image_extended_formats: bool,
pub shader_storage_image_multisample: bool,
pub shader_storage_image_read_without_format: bool,
pub shader_storage_image_write_without_format: bool,
pub shader_uniform_buffer_array_dynamic_indexing: bool,
pub shader_sampled_image_array_dynamic_indexing: bool,
pub shader_storage_buffer_array_dynamic_indexing: bool,
pub shader_storage_image_array_dynamic_indexing: bool,
pub shader_clip_distance: bool,
pub shader_cull_distance: bool,
pub shader_float64: bool,
pub shader_int64: bool,
pub shader_int16: bool,
pub shader_resource_residency: bool,
pub shader_resource_min_lod: bool,
pub sparse_binding: bool,
pub sparse_residency_buffer: bool,
pub sparse_residency_image2d: bool,
pub sparse_residency_image3d: bool,
pub sparse_residency2_samples: bool,
pub sparse_residency4_samples: bool,
pub sparse_residency8_samples: bool,
pub sparse_residency16_samples: bool,
pub sparse_residency_aliased: bool,
pub variable_multisample_rate: bool,
pub inherited_queries: bool,
pub buffer_device_address: bool,
pub buffer_device_address_capture_replay: bool,
pub buffer_device_address_multi_device: bool,
pub variable_pointers_storage_buffer: bool,
pub variable_pointers: bool,
pub shader_buffer_int64_atomics: bool,
pub shader_shared_int64_atomics: bool,
pub storage_buffer_8bit: bool,
pub storage_uniform_8bit: bool,
pub storage_push_constant_8bit: bool,
pub storage_buffer_16bit: bool,
pub storage_uniform_16bit: bool,
pub storage_push_constant_16bit: bool,
pub storage_input_output_16bit: bool,
pub shader_float16: bool,
pub shader_int8: bool,
}
pub(crate) struct FeaturesFfi {
_pinned: PhantomPinned,
pub(crate) main: vk::PhysicalDeviceFeatures2KHR,
phys_dev_buf_addr: vk::PhysicalDeviceBufferAddressFeaturesEXT,
variable_pointers: vk::PhysicalDeviceVariablePointersFeatures,
shader_atomic_i64: vk::PhysicalDeviceShaderAtomicInt64Features,
i8_storage: vk::PhysicalDevice8BitStorageFeatures,
i16_storage: vk::PhysicalDevice16BitStorageFeatures,
f16_i8: vk::PhysicalDeviceShaderFloat16Int8Features,
}
macro_rules! features {
($($kind:ident $args:tt,)+) => (
impl Features {
/// Builds a `Features` object with all values to false.
pub fn none() -> Features {
let mut out = Features::default();
$(features_init!($kind $args, out, false);)+
out
}
/// Builds a `Features` object with all values to true.
///
/// > **Note**: This function is used for testing purposes, and is probably useless in
/// > a real code.
pub fn all() -> Features {
let mut out = Features::default();
$(features_init!($kind $args, out, true);)+
out
}
/// Returns true if `self` is a superset of the parameter.
///
/// That is, for each feature of the parameter that is true, the corresponding value
/// in self is true as well.
pub fn superset_of(&self, other: &Features) -> bool {
$(features_superset_of!($kind $args, self, other))&&+
}
/// Builds a `Features` that is the intersection of `self` and another `Features`
/// object.
///
/// The result's field will be true if it is also true in both `self` and `other`.
pub fn intersection(&self, other: &Features) -> Features {
let mut out = Self::none();
$(features_intersection!($kind $args, out, self, other);)+
out
}
/// Builds a `Features` that is the difference of another `Features` object from `self`.
///
/// The result's field will be true if it is true in `self` but not `other`.
pub fn difference(&self, other: &Features) -> Features {
let mut out = Self::none();
$(features_difference!($kind $args, out, self, other);)+
out
}
}
impl From<Features> for vk::PhysicalDeviceFeatures {
#[inline]
fn from(val: Features) -> Self {
let mut out: vk::PhysicalDeviceFeatures = unsafe { mem::zeroed() };
$(into_feature_v1!($kind $args, out, val);)+
out
}
}
impl From<vk::PhysicalDeviceFeatures> for Features {
#[inline]
fn from(val: vk::PhysicalDeviceFeatures) -> Self {
let mut out = Self::none();
$(from_feature_v1!($kind $args, out, val);)+
out
}
}
impl From<&Features> for Pin<Box<FeaturesFfi>> {
#[inline(always)]
fn from(val: &Features) -> Self {
let mut features = FeaturesFfi::new();
unsafe {
let mut next = FeaturesFfi::mut_base_ptr(&mut features);
while let Some(next_mut) = next.as_mut() {
match next_mut.sType {
vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR => {
let r = (next as *mut vk::PhysicalDeviceFeatures2KHR).as_mut().unwrap();
$(into_feature_v1!($kind $args, r.features, val);)+
},
_ => {
$(into_ext_features_match!($kind $args, val, next_mut, next);)+
},
}
next = next_mut.pNext as *mut Base;
}
}
features
}
}
impl From<&vk::PhysicalDeviceFeatures2KHR> for Features {
#[inline(always)]
fn from(features: &vk::PhysicalDeviceFeatures2KHR) -> Self {
let mut output = Self::none();
unsafe {
let mut next: *const Base = features as *const vk::PhysicalDeviceFeatures2KHR as _;
while let Some(next_ref) = next.as_ref() {
match next_ref.sType {
vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR => {
let r = (next as *const vk::PhysicalDeviceFeatures2KHR).as_ref().unwrap();
$(from_feature_v1!($kind $args, output, r.features);)+
},
_ => {
$(from_ext_features_match!($kind $args, output, next_ref, next);)+
},
}
next = next_ref.pNext as *const Base;
}
}
output
}
}
impl FeaturesFfi {
#[inline(always)]
pub(crate) fn new() -> Pin<Box<Self>> {
#![allow(unused_assignments)]
let this = FeaturesFfi {
_pinned: PhantomPinned,
main: vk::PhysicalDeviceFeatures2KHR {
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR,
pNext: ptr::null(),
features: unsafe { mem::zeroed() },
},
.. unsafe { mem::zeroed() }
};
let mut this = Box::pin(this);
unsafe {
let this = this.as_mut();
let this = this.get_unchecked_mut();
let mut base = &mut this.main as *mut _ as *mut Base;
$(features_ffi_init_pinned!($kind $args, this, base);)*
}
this
}
#[inline(always)]
pub(crate) fn base_ptr(&self) -> *const Base {
&self.main as *const _ as *const Base
}
#[inline(always)]
pub(crate) fn mut_base_ptr(this: &mut Pin<Box<Self>>) -> *mut Base {
unsafe {
let this = this.as_mut();
let this = this.get_unchecked_mut();
&mut this.main as *mut _ as *mut Base
}
}
}
)
}
features! {
core { robust_buffer_access => robustBufferAccess },
core { full_draw_index_uint32 => fullDrawIndexUint32 },
core { image_cube_array => imageCubeArray },
core { independent_blend => independentBlend },
core { geometry_shader => geometryShader },
core { tessellation_shader => tessellationShader },
core { sample_rate_shading => sampleRateShading },
core { dual_src_blend => dualSrcBlend },
core { logic_op => logicOp },
core { multi_draw_indirect => multiDrawIndirect },
core { draw_indirect_first_instance => drawIndirectFirstInstance },
core { depth_clamp => depthClamp },
core { depth_bias_clamp => depthBiasClamp },
core { fill_mode_non_solid => fillModeNonSolid },
core { depth_bounds => depthBounds },
core { wide_lines => wideLines },
core { large_points => largePoints },
core { alpha_to_one => alphaToOne },
core { multi_viewport => multiViewport },
core { sampler_anisotropy => samplerAnisotropy },
core { texture_compression_etc2 => textureCompressionETC2 },
core { texture_compression_astc_ldr => textureCompressionASTC_LDR },
core { texture_compression_bc => textureCompressionBC },
core { occlusion_query_precise => occlusionQueryPrecise },
core { pipeline_statistics_query => pipelineStatisticsQuery },
core { vertex_pipeline_stores_and_atomics => vertexPipelineStoresAndAtomics },
core { fragment_stores_and_atomics => fragmentStoresAndAtomics },
core { shader_tessellation_and_geometry_point_size => shaderTessellationAndGeometryPointSize },
core { shader_image_gather_extended => shaderImageGatherExtended },
core { shader_storage_image_extended_formats => shaderStorageImageExtendedFormats },
core { shader_storage_image_multisample => shaderStorageImageMultisample },
core { shader_storage_image_read_without_format => shaderStorageImageReadWithoutFormat },
core { shader_storage_image_write_without_format => shaderStorageImageWriteWithoutFormat },
core { shader_uniform_buffer_array_dynamic_indexing => shaderUniformBufferArrayDynamicIndexing },
core { shader_sampled_image_array_dynamic_indexing => shaderSampledImageArrayDynamicIndexing },
core { shader_storage_buffer_array_dynamic_indexing => shaderStorageBufferArrayDynamicIndexing },
core { shader_storage_image_array_dynamic_indexing => shaderStorageImageArrayDynamicIndexing },
core { shader_clip_distance => shaderClipDistance },
core { shader_cull_distance => shaderCullDistance },
core { shader_float64 => shaderFloat64 },
core { shader_int64 => shaderInt64 },
core { shader_int16 => shaderInt16 },
core { shader_resource_residency => shaderResourceResidency },
core { shader_resource_min_lod => shaderResourceMinLod },
core { sparse_binding => sparseBinding },
core { sparse_residency_buffer => sparseResidencyBuffer },
core { sparse_residency_image2d => sparseResidencyImage2D },
core { sparse_residency_image3d => sparseResidencyImage3D },
core { sparse_residency2_samples => sparseResidency2Samples },
core { sparse_residency4_samples => sparseResidency4Samples },
core { sparse_residency8_samples => sparseResidency8Samples },
core { sparse_residency16_samples => sparseResidency16Samples },
core { sparse_residency_aliased => sparseResidencyAliased },
core { variable_multisample_rate => variableMultisampleRate },
core { inherited_queries => inheritedQueries },
extension {
ty: vk::PhysicalDeviceBufferAddressFeaturesEXT,
ffi_name: phys_dev_buf_addr,
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT,
fields: [
buffer_device_address => bufferDeviceAddress,
buffer_device_address_capture_replay => bufferDeviceAddressCaptureReplay,
buffer_device_address_multi_device => bufferDeviceAddressMultiDevice,
],
},
extension {
ty: vk::PhysicalDeviceVariablePointersFeatures,
ffi_name: variable_pointers,
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES,
fields: [
variable_pointers_storage_buffer => variablePointersStorageBuffer,
variable_pointers => variablePointers,
],
},
extension {
ty: vk::PhysicalDeviceShaderAtomicInt64Features,
ffi_name: shader_atomic_i64,
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES,
fields: [
shader_buffer_int64_atomics => shaderBufferInt64Atomics,
shader_shared_int64_atomics => shaderSharedInt64Atomics,
],
},
extension {
ty: vk::PhysicalDevice8BitStorageFeatures,
ffi_name: i8_storage,
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES,
fields: [
storage_buffer_8bit => storageBuffer8BitAccess,
storage_uniform_8bit => uniformAndStorageBuffer8BitAccess,
storage_push_constant_8bit => storagePushConstant8,
],
},
extension {
ty: vk::PhysicalDevice16BitStorageFeatures,
ffi_name: i16_storage,
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
fields: [
storage_buffer_16bit => storageBuffer16BitAccess,
storage_uniform_16bit => uniformAndStorageBuffer16BitAccess,
storage_push_constant_16bit => storagePushConstant16,
storage_input_output_16bit => storageInputOutput16,
],
},
extension {
ty: vk::PhysicalDeviceShaderFloat16Int8Features,
ffi_name: f16_i8,
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES,
fields: [
shader_float16 => shaderFloat16,
shader_int8 => shaderInt8,
],
},
}

View File

@ -555,7 +555,7 @@ impl UnsafeImage {
let mut output2 = if device.loaded_extensions().khr_dedicated_allocation {
Some(vk::MemoryDedicatedRequirementsKHR {
sType: vk::STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
pNext: ptr::null(),
pNext: ptr::null_mut(),
prefersDedicatedAllocation: mem::zeroed(),
requiresDedicatedAllocation: mem::zeroed(),
})

View File

@ -35,12 +35,91 @@ use std::sync::Arc;
/// An instance of a Vulkan context. This is the main object that should be created by an
/// application before everything else.
///
/// See the documentation of [the `instance` module](index.html) for an introduction about
/// Vulkan instances.
/// # Application info
///
/// # Extensions and application infos
/// When you create an instance, you have the possibility to pass an `ApplicationInfo` struct as
/// the first parameter. This struct contains various information about your application, most
/// notably its name and engine.
///
/// Please check the documentation of [the `instance` module](index.html).
/// Passing such a structure allows for example the driver to let the user configure the driver's
/// behavior for your application alone through a control panel.
///
/// ```no_run
/// # #[macro_use] extern crate vulkano;
/// # fn main() {
/// use vulkano::instance::{Instance, InstanceExtensions};
/// use vulkano::Version;
///
/// // Builds an `ApplicationInfo` by looking at the content of the `Cargo.toml` file at
/// // compile-time.
/// let app_infos = app_info_from_cargo_toml!();
///
/// let _instance = Instance::new(Some(&app_infos), Version::major_minor(1, 1), &InstanceExtensions::none(), None).unwrap();
/// # }
/// ```
///
/// # API versions
///
/// Both an `Instance` and a [`Device`](crate::device::Device) have a highest version of the Vulkan
/// API that they support. This places a limit on what Vulkan functions and features are available
/// 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),
/// while for a device it can be retrieved with
/// [`PhysicalDevice::api_version`](crate::instance::PhysicalDevice::api_version).
///
/// When creating an `Instance`, you have to specify a maximum API version that you will use.
/// This restricts the API version that is available for the instance and any devices created from
/// it. For example, if both instance and device potentially support Vulkan 1.2, but you specify
/// 1.1 as the maximum API version when creating the `Instance`, then you can only use Vulkan 1.1
/// functions, even though they could theoretically support a higher version. You can think of it
/// as a promise never to use any functionality from a higher version.
///
/// The maximum API version is not a _minimum_, so it is possible to set it to a higher version than
/// what the instance or device inherently support. The final API version that you are able to use
/// on an instance or device is the lower of the supported API version and the chosen maximum API
/// version of the `Instance`.
///
/// However, due to a quirk in how the Vulkan 1.0 specification was written, if the instance only
/// supports Vulkan 1.0, then it is not possible to specify a maximum API version higher than 1.0.
/// Trying to create an `Instance` will return an `IncompatibleDriver` error. Consequently, it is
/// not possible to use a higher device API version with an instance that only supports 1.0.
///
/// # Extensions
///
/// When creating an `Instance`, you must provide a list of extensions that must be enabled on the
/// newly-created instance. Trying to enable an extension that is not supported by the system will
/// result in an error.
///
/// Contrary to OpenGL, it is not possible to use the features of an extension if it was not
/// explicitly enabled.
///
/// Extensions are especially important to take into account if you want to render images on the
/// screen, as the only way to do so is to use the `VK_KHR_surface` extension. More information
/// about this in the `swapchain` module.
///
/// For example, here is how we create an instance with the `VK_KHR_surface` and
/// `VK_KHR_android_surface` extensions enabled, which will allow us to render images to an
/// Android screen. You can compile and run this code on any system, but it is highly unlikely to
/// succeed on anything else than an Android-running device.
///
/// ```no_run
/// use vulkano::instance::Instance;
/// use vulkano::instance::InstanceExtensions;
/// use vulkano::Version;
///
/// let extensions = InstanceExtensions {
/// khr_surface: true,
/// khr_android_surface: true,
/// .. InstanceExtensions::none()
/// };
///
/// let instance = match Instance::new(None, Version::major_minor(1, 1), &extensions, None) {
/// Ok(i) => i,
/// Err(err) => panic!("Couldn't build instance: {:?}", err)
/// };
/// ```
///
/// # Layers
///
@ -53,7 +132,7 @@ use std::sync::Arc;
/// could send information to a debugger that will debug your application.
///
/// > **Note**: From an application's point of view, layers "just exist". In practice, on Windows
/// > and Linux layers can be installed by third party installers or by package managers and can
/// > and Linux, layers can be installed by third party installers or by package managers and can
/// > also be activated by setting the value of the `VK_INSTANCE_LAYERS` environment variable
/// > before starting the program. See the documentation of the official Vulkan loader for these
/// > platforms.
@ -67,12 +146,13 @@ use std::sync::Arc;
/// ## Example
///
/// ```
/// # use std::sync::Arc;
/// # use std::error::Error;
/// # use vulkano::instance;
/// # use vulkano::instance::Instance;
/// # use vulkano::instance::InstanceExtensions;
/// # use std::sync::Arc;
/// # use std::error::Error;
/// # fn test() -> Result<Arc<Instance>, Box<Error>> {
/// # use vulkano::Version;
/// # fn test() -> Result<Arc<Instance>, Box<dyn Error>> {
/// // 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()?
@ -82,7 +162,7 @@ use std::sync::Arc;
/// let layer_names = layers.iter()
/// .map(|l| l.name());
///
/// let instance = Instance::new(None, &InstanceExtensions::none(), layer_names)?;
/// let instance = Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), layer_names)?;
/// # Ok(instance)
/// # }
/// ```
@ -91,14 +171,13 @@ pub struct Instance {
instance: vk::Instance,
//alloc: Option<Box<Alloc + Send + Sync>>,
// The desired API version for instances and devices created from it.
// TODO: allow the user to specify this on construction.
pub(crate) desired_version: Version,
// The highest version that is supported for this instance.
// This is the minimum of Instance::desired_version and FunctionPointers::api_version.
// This is the minimum of Instance::max_api_version and FunctionPointers::api_version.
api_version: Version,
// The highest allowed API version for instances and devices created from it.
max_api_version: Version,
pub(super) physical_devices: Vec<PhysicalDeviceInfos>,
vk: vk::InstancePointers,
extensions: RawInstanceExtensions,
@ -121,8 +200,9 @@ impl Instance {
/// ```no_run
/// use vulkano::instance::Instance;
/// use vulkano::instance::InstanceExtensions;
/// use vulkano::Version;
///
/// let instance = match Instance::new(None, &InstanceExtensions::none(), None) {
/// let instance = match Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), None) {
/// Ok(i) => i,
/// Err(err) => panic!("Couldn't build instance: {:?}", err)
/// };
@ -138,6 +218,7 @@ impl Instance {
// the choice to Vulkan
pub fn new<'a, L, Ext>(
app_infos: Option<&ApplicationInfo>,
max_api_version: Version,
extensions: Ext,
layers: L,
) -> Result<Arc<Instance>, InstanceCreationError>
@ -152,6 +233,7 @@ impl Instance {
Instance::new_inner(
app_infos,
max_api_version,
extensions.into(),
layers,
OwnedOrRef::Ref(loader::auto_loader()?),
@ -162,6 +244,7 @@ impl Instance {
pub fn with_loader<'a, L, Ext>(
loader: FunctionPointers<Box<dyn Loader + Send + Sync>>,
app_infos: Option<&ApplicationInfo>,
max_api_version: Version,
extensions: Ext,
layers: L,
) -> Result<Arc<Instance>, InstanceCreationError>
@ -176,6 +259,7 @@ impl Instance {
Instance::new_inner(
app_infos,
max_api_version,
extensions.into(),
layers,
OwnedOrRef::Owned(loader),
@ -184,6 +268,7 @@ impl Instance {
fn new_inner(
app_infos: Option<&ApplicationInfo>,
max_api_version: Version,
extensions: RawInstanceExtensions,
layers: SmallVec<[CString; 16]>,
function_pointers: OwnedOrRef<FunctionPointers<Box<dyn Loader + Send + Sync>>>,
@ -213,20 +298,7 @@ impl Instance {
None
};
// TODO: allow the user to specify this.
// Vulkan 1.0 will return VK_ERROR_INCOMPATIBLE_DRIVER on instance creation if this isn't
// 1.0, but higher versions never return this error, and thus will allow a desired version
// beyond what they support. The actual support on that particular instance/device is the
// minimum of desired and supported.
// In other words, it's impossible to use a Vulkan 1.1 or 1.2 device with a 1.0 instance,
// because instance creation with a higher desired_version will fail. But it is possible to
// use a 1.0 or 1.2 device with a 1.1 instance.
let desired_version = Version {
major: 1,
minor: 1,
patch: 0,
};
let api_version = std::cmp::min(desired_version, function_pointers.api_version()?);
let api_version = std::cmp::min(max_api_version, function_pointers.api_version()?);
// Building the `vk::ApplicationInfo` if required.
let app_infos = if let Some(app_infos) = app_infos {
@ -255,7 +327,7 @@ impl Instance {
.engine_version
.map(|v| v.into_vulkan_version())
.unwrap_or(0),
apiVersion: desired_version.into_vulkan_version(), // TODO:
apiVersion: max_api_version.into_vulkan_version(),
})
} else {
None
@ -302,20 +374,22 @@ impl Instance {
})
};
// Enumerating all physical devices.
let physical_devices = init_physical_devices(instance, &vk, &extensions)?;
Ok(Arc::new(Instance {
let mut instance = Instance {
instance,
api_version,
desired_version,
max_api_version,
//alloc: None,
physical_devices,
physical_devices: Vec::new(),
vk,
extensions,
layers,
function_pointers,
}))
};
// Enumerating all physical devices.
instance.physical_devices = init_physical_devices(&instance)?;
Ok(Arc::new(instance))
}
/*/// Same as `new`, but provides an allocator that will be used by the Vulkan library whenever
@ -327,11 +401,21 @@ impl Instance {
}*/
/// Returns the Vulkan version supported by this `Instance`.
///
/// This is the lower of the
/// [driver's supported version](crate::instance::loader::FunctionPointers::api_version) and
/// [`max_api_version`](Instance::max_api_version).
#[inline]
pub fn api_version(&self) -> Version {
self.api_version
}
/// Returns the maximum Vulkan version that was specified when creating this `Instance`.
#[inline]
pub fn max_api_version(&self) -> Version {
self.max_api_version
}
/// Grants access to the Vulkan functions of the instance.
#[inline]
pub fn pointers(&self) -> &vk::InstancePointers {
@ -347,9 +431,10 @@ impl Instance {
/// ```no_run
/// use vulkano::instance::Instance;
/// use vulkano::instance::InstanceExtensions;
/// use vulkano::Version;
///
/// let extensions = InstanceExtensions::supported_by_core().unwrap();
/// let instance = Instance::new(None, &extensions, None).unwrap();
/// let instance = Instance::new(None, Version::major_minor(1, 1), &extensions, None).unwrap();
/// assert_eq!(instance.loaded_extensions(), extensions);
/// ```
#[inline]

View File

@ -133,7 +133,7 @@ impl LayerProperties {
/// use vulkano::instance::Version;
///
/// for layer in instance::layers_list().unwrap() {
/// if layer.vulkan_version() >= (Version { major: 2, minor: 0, patch: 0 }) {
/// if layer.vulkan_version() >= Version::major_minor(2, 0) {
/// println!("Layer {} requires Vulkan 2.0", layer.name());
/// }
/// }

View File

@ -16,8 +16,9 @@
//! ```no_run
//! use vulkano::instance::Instance;
//! use vulkano::instance::InstanceExtensions;
//! use vulkano::Version;
//!
//! let instance = match Instance::new(None, &InstanceExtensions::none(), None) {
//! let instance = match Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), None) {
//! Ok(i) => i,
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
//! };
@ -29,70 +30,15 @@
//! ```no_run
//! # use vulkano::instance::Instance;
//! # use vulkano::instance::InstanceExtensions;
//! # use vulkano::Version;
//! use vulkano::instance::PhysicalDevice;
//!
//! # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
//! # let instance = Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), None).unwrap();
//! for physical_device in PhysicalDevice::enumerate(&instance) {
//! println!("Available device: {}", physical_device.name());
//! }
//! ```
//!
//! # Extensions
//!
//! Notice the second parameter of `Instance::new()`. It is an `InstanceExtensions` struct that
//! contains a list of extensions that must be enabled on the newly-created instance. Trying to
//! enable an extension that is not supported by the system will result in an error.
//!
//! Contrary to OpenGL, it is not possible to use the features of an extension if it was not
//! explicitly enabled.
//!
//! Extensions are especially important to take into account if you want to render images on the
//! screen, as the only way to do so is to use the `VK_KHR_surface` extension. More information
//! about this in the `swapchain` module.
//!
//! For example, here is how we create an instance with the `VK_KHR_surface` and
//! `VK_KHR_android_surface` extensions enabled, which will allow us to render images to an
//! Android screen. You can compile and run this code on any system, but it is highly unlikely to
//! succeed on anything else than an Android-running device.
//!
//! ```no_run
//! use vulkano::instance::Instance;
//! use vulkano::instance::InstanceExtensions;
//!
//! let extensions = InstanceExtensions {
//! khr_surface: true,
//! khr_android_surface: true,
//! .. InstanceExtensions::none()
//! };
//!
//! let instance = match Instance::new(None, &extensions, None) {
//! Ok(i) => i,
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
//! };
//! ```
//!
//! # Application info
//!
//! When you create an instance, you have the possibility to pass an `ApplicationInfo` struct as
//! the first parameter. This struct contains various information about your application, most
//! notably its name and engine.
//!
//! Passing such a structure allows for example the driver to let the user configure the driver's
//! behavior for your application alone through a control panel.
//!
//! ```no_run
//! # #[macro_use] extern crate vulkano;
//! # fn main() {
//! use vulkano::instance::{Instance, InstanceExtensions};
//!
//! // Builds an `ApplicationInfo` by looking at the content of the `Cargo.toml` file at
//! // compile-time.
//! let app_infos = app_info_from_cargo_toml!();
//!
//! let _instance = Instance::new(Some(&app_infos), &InstanceExtensions::none(), None).unwrap();
//! # }
//! ```
//!
//! # Enumerating physical devices and creating a device
//!
//! After you have created an instance, the next step is usually to enumerate the physical devices
@ -104,7 +50,6 @@
//!
//! Once you have chosen a physical device, you can create a `Device` object from it. See the
//! `device` module for more info.
//!
pub use self::extensions::InstanceExtensions;
pub use self::extensions::RawInstanceExtensions;

View File

@ -8,15 +8,14 @@
// according to those terms.
use crate::check_errors;
use crate::features::{Features, FeaturesFfi};
use crate::device::{Features, FeaturesFfi};
use crate::instance::limits::Limits;
use crate::instance::{Instance, InstanceCreationError, RawInstanceExtensions};
use crate::instance::{Instance, InstanceCreationError};
use crate::sync::PipelineStage;
use crate::vk;
use crate::Version;
use crate::VulkanObject;
use std::ffi::CStr;
use std::ffi::CString;
use std::hash::Hash;
use std::mem;
use std::mem::MaybeUninit;
@ -24,32 +23,35 @@ use std::ptr;
use std::sync::Arc;
pub(super) fn init_physical_devices(
instance: vk::Instance,
vk: &vk::InstancePointers,
extensions: &RawInstanceExtensions,
instance: &Instance,
) -> Result<Vec<PhysicalDeviceInfos>, InstanceCreationError> {
let vk = instance.pointers();
let extensions = instance.loaded_extensions();
let physical_devices: Vec<vk::PhysicalDevice> = unsafe {
let mut num = 0;
check_errors(vk.EnumeratePhysicalDevices(instance, &mut num, ptr::null_mut()))?;
check_errors(vk.EnumeratePhysicalDevices(
instance.internal_object(),
&mut num,
ptr::null_mut(),
))?;
let mut devices = Vec::with_capacity(num as usize);
check_errors(vk.EnumeratePhysicalDevices(instance, &mut num, devices.as_mut_ptr()))?;
check_errors(vk.EnumeratePhysicalDevices(
instance.internal_object(),
&mut num,
devices.as_mut_ptr(),
))?;
devices.set_len(num as usize);
devices
};
let vk_khr_get_physical_device_properties2 =
CString::new(b"VK_KHR_get_physical_device_properties2".to_vec()).unwrap();
// Getting the properties of all physical devices.
// If possible, we use VK_KHR_get_physical_device_properties2.
let physical_devices = if extensions
.iter()
.any(|v| *v == vk_khr_get_physical_device_properties2)
{
init_physical_devices_inner2(&vk, physical_devices, &extensions)
let physical_devices = if extensions.khr_get_physical_device_properties2 {
init_physical_devices_inner2(instance, physical_devices)
} else {
init_physical_devices_inner(&vk, physical_devices)
init_physical_devices_inner(instance, physical_devices)
};
Ok(physical_devices)
@ -57,9 +59,10 @@ pub(super) fn init_physical_devices(
/// Initialize all physical devices
fn init_physical_devices_inner(
vk: &vk::InstancePointers,
instance: &Instance,
physical_devices: Vec<vk::PhysicalDevice>,
) -> Vec<PhysicalDeviceInfos> {
let vk = instance.pointers();
let mut output = Vec::with_capacity(physical_devices.len());
for device in physical_devices.into_iter() {
@ -85,10 +88,10 @@ fn init_physical_devices_inner(
output.assume_init()
};
let available_features: vk::PhysicalDeviceFeatures = unsafe {
let mut output = MaybeUninit::uninit();
vk.GetPhysicalDeviceFeatures(device, output.as_mut_ptr());
output.assume_init()
let available_features: Features = unsafe {
let mut output = FeaturesFfi::default();
vk.GetPhysicalDeviceFeatures(device, &mut output.head_as_mut().features);
Features::from(&output)
};
output.push(PhysicalDeviceInfos {
@ -106,10 +109,10 @@ fn init_physical_devices_inner(
/// Initialize all physical devices, but use VK_KHR_get_physical_device_properties2
/// TODO: Query extension-specific physical device properties, once a new instance extension is supported.
fn init_physical_devices_inner2(
vk: &vk::InstancePointers,
instance: &Instance,
physical_devices: Vec<vk::PhysicalDevice>,
extensions: &RawInstanceExtensions,
) -> Vec<PhysicalDeviceInfos> {
let vk = instance.pointers();
let mut output = Vec::with_capacity(physical_devices.len());
for device in physical_devices.into_iter() {
@ -127,14 +130,22 @@ fn init_physical_devices_inner2(
let mut output = vk::PhysicalDeviceProperties2KHR {
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
pNext: &mut subgroup_properties,
pNext: if instance.api_version() >= Version::major_minor(1, 1) {
&mut subgroup_properties
} else {
ptr::null_mut()
},
properties: mem::zeroed(),
};
vk.GetPhysicalDeviceProperties2KHR(device, &mut output);
extended_properties = PhysicalDeviceExtendedProperties {
subgroup_size: Some(subgroup_properties.subgroupSize),
subgroup_size: if instance.api_version() >= Version::major_minor(1, 1) {
Some(subgroup_properties.subgroupSize)
} else {
None
},
..extended_properties
};
@ -172,10 +183,16 @@ fn init_physical_devices_inner2(
};
let available_features: Features = unsafe {
let mut output = FeaturesFfi::new();
let ptr = FeaturesFfi::mut_base_ptr(&mut output) as *mut _;
vk.GetPhysicalDeviceFeatures2KHR(device, ptr);
Features::from(&output.main)
let max_api_version = instance.max_api_version();
let api_version = std::cmp::min(
max_api_version,
Version::from_vulkan_version(properties.apiVersion),
);
let mut output = FeaturesFfi::default();
output.make_chain(api_version);
vk.GetPhysicalDeviceFeatures2KHR(device, output.head_as_mut());
Features::from(&output)
};
output.push(PhysicalDeviceInfos {
@ -235,9 +252,10 @@ impl PhysicalDeviceExtendedProperties {
/// ```no_run
/// # use vulkano::instance::Instance;
/// # use vulkano::instance::InstanceExtensions;
/// # use vulkano::Version;
/// use vulkano::instance::PhysicalDevice;
///
/// # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
/// # let instance = Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), None).unwrap();
/// for physical_device in PhysicalDevice::enumerate(&instance) {
/// print_infos(physical_device);
/// }
@ -260,9 +278,10 @@ impl<'a> PhysicalDevice<'a> {
/// ```no_run
/// # use vulkano::instance::Instance;
/// # use vulkano::instance::InstanceExtensions;
/// # use vulkano::Version;
/// use vulkano::instance::PhysicalDevice;
///
/// # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
/// # let instance = Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), None).unwrap();
/// for physical_device in PhysicalDevice::enumerate(&instance) {
/// println!("Available device: {}", physical_device.name());
/// }
@ -285,8 +304,9 @@ impl<'a> PhysicalDevice<'a> {
/// use vulkano::instance::Instance;
/// use vulkano::instance::InstanceExtensions;
/// use vulkano::instance::PhysicalDevice;
/// use vulkano::Version;
///
/// let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
/// let instance = Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), None).unwrap();
/// let first_physical_device = PhysicalDevice::from_index(&instance, 0).unwrap();
/// ```
#[inline]
@ -345,9 +365,10 @@ impl<'a> PhysicalDevice<'a> {
/// ```no_run
/// # use vulkano::instance::Instance;
/// # use vulkano::instance::InstanceExtensions;
/// # use vulkano::Version;
/// use vulkano::instance::PhysicalDevice;
///
/// # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap();
/// # let instance = Instance::new(None, Version::major_minor(1, 1), &InstanceExtensions::none(), None).unwrap();
/// for physical_device in PhysicalDevice::enumerate(&instance) {
/// println!("Available device: {} (type: {:?})",
/// physical_device.name(), physical_device.ty());

View File

@ -80,7 +80,6 @@ pub mod buffer;
pub mod command_buffer;
pub mod descriptor;
pub mod device;
mod features;
pub mod format;
mod version;
#[macro_use]

View File

@ -58,6 +58,7 @@
//! use vulkano::instance::Instance;
//! use vulkano::instance::InstanceExtensions;
//! use vulkano::swapchain::Surface;
//! use vulkano::Version;
//!
//! let instance = {
//! let extensions = InstanceExtensions {
@ -66,7 +67,7 @@
//! .. InstanceExtensions::none()
//! };
//!
//! match Instance::new(None, &extensions, None) {
//! match Instance::new(None, Version::major_minor(1, 1), &extensions, None) {
//! Ok(i) => i,
//! Err(err) => panic!("Couldn't build instance: {:?}", err)
//! }

View File

@ -690,7 +690,7 @@ impl<W> SwapchainBuilder<W> {
{
surface_full_screen_exclusive_info = Some(vk::SurfaceFullScreenExclusiveInfoEXT {
sType: vk::STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT,
pNext: ptr::null(),
pNext: ptr::null_mut(),
fullScreenExclusive: fullscreen_exclusive.vk_sys_enum(),
});
}

View File

@ -13,8 +13,14 @@
macro_rules! instance {
() => {{
use crate::instance;
use crate::Version;
match instance::Instance::new(None, &instance::InstanceExtensions::none(), None) {
match instance::Instance::new(
None,
Version::major_minor(1, 1),
&instance::InstanceExtensions::none(),
None,
) {
Ok(i) => i,
Err(_) => return,
}
@ -27,7 +33,7 @@ macro_rules! gfx_dev_and_queue {
use crate::instance;
use crate::device::Device;
use crate::device::DeviceExtensions;
use crate::features::Features;
use crate::device::Features;
let instance = instance!();

View File

@ -22,19 +22,17 @@ pub struct Version {
pub patch: u16,
}
impl fmt::Debug for Version {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
}
}
impl fmt::Display for Version {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, formatter)
}
}
impl Version {
/// Constructs a `Version` from the given major and minor version numbers.
#[inline]
pub const fn major_minor(major: u16, minor: u16) -> Version {
Version {
major,
minor,
patch: 0,
}
}
/// Turns a version number given by Vulkan into a `Version` struct.
#[inline]
pub fn from_vulkan_version(value: u32) -> Version {
@ -60,6 +58,18 @@ impl Version {
}
}
impl fmt::Debug for Version {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
}
}
impl fmt::Display for Version {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, formatter)
}
}
#[cfg(test)]
mod tests {
use super::Version;