mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-19 18:42:31 +00:00
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:
parent
d36e5a2b1d
commit
2f7e7af7ee
@ -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`.
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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!(
|
||||
|
@ -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. //
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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: {:?})",
|
||||
|
@ -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
|
||||
|
@ -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: {:?})",
|
||||
|
@ -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!(
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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!(
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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: {:?})",
|
||||
|
@ -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!(
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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 {
|
||||
|
@ -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");
|
||||
}
|
||||
});
|
||||
|
@ -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(),
|
||||
})
|
||||
|
325
vulkano/src/device/features.rs
Normal file
325
vulkano/src/device/features.rs
Normal 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
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
],
|
||||
},
|
||||
}
|
@ -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(),
|
||||
})
|
||||
|
@ -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]
|
||||
|
@ -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());
|
||||
/// }
|
||||
/// }
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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]
|
||||
|
@ -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)
|
||||
//! }
|
||||
|
@ -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(),
|
||||
});
|
||||
}
|
||||
|
@ -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!();
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user