Merge branch 'custom-derives' into incoming

This commit is contained in:
Pierre Krieger 2017-01-21 16:35:58 +01:00
commit 1216461211
30 changed files with 373 additions and 200 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
target
Cargo.lock
.cargo
.cargo

View File

@ -5,5 +5,6 @@ members = [
"vk-sys",
"vulkano",
"vulkano-shaders",
"vulkano-shader-derive",
"vulkano-win"
]

View File

@ -13,7 +13,7 @@ What does vulkano do?
- Provides a low-levelish API around Vulkan. It doesn't hide what it does, but provides some
comfort types.
- Plans to prevents all invalid API usages, even the most obscure ones. The purpose of vulkano
- Plans to prevent all invalid API usages, even the most obscure ones. The purpose of vulkano
is not to draw a teapot, but to cover all possible usages of Vulkan and detect all the
possible problems. Invalid API usage is prevented thanks to both compile-time checks and
runtime checks.

BIN
apispec.pdf Normal file

Binary file not shown.

View File

@ -7,7 +7,7 @@ build = "build.rs"
[dependencies]
vulkano = { path = "../vulkano" }
vulkano-win = { path = "../vulkano-win" }
cgmath = "0.7.0"
cgmath = "0.12.0"
image = "0.6.1"
winit = "0.5.2"
time = "0.1.35"

View File

@ -52,7 +52,7 @@ fn main() {
let present = caps.present_modes.iter().next().unwrap();
let usage = caps.supported_usage_flags;
vulkano::swapchain::Swapchain::new(&device, &window.surface(), 3,
vulkano::swapchain::Swapchain::new(&device, &window.surface(), caps.min_image_count,
vulkano::format::B8G8R8A8Srgb, dimensions, 1,
&usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
vulkano::swapchain::CompositeAlpha::Opaque,
@ -60,27 +60,18 @@ fn main() {
};
let vertex_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer::<[Vertex]>
::array(&device, 4, &vulkano::buffer::BufferUsage::all(),
Some(queue.family())).expect("failed to create buffer");
#[derive(Debug, Clone)]
struct Vertex { position: [f32; 2] }
impl_vertex!(Vertex, position);
// The buffer that we created contains uninitialized data.
// In order to fill it with data, we have to *map* it.
{
// The `write` function would return `Err` if the buffer was in use by the GPU. This
// obviously can't happen here, since we haven't ask the GPU to do anything yet.
let mut mapping = vertex_buffer.write(Duration::new(0, 0)).unwrap();
mapping[0].position = [-0.5, -0.5];
mapping[1].position = [-0.5, 0.5];
mapping[2].position = [ 0.5, -0.5];
mapping[3].position = [ 0.5, 0.5];
}
let vertex_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer::<[Vertex]>
::from_iter(&device, &vulkano::buffer::BufferUsage::all(),
Some(queue.family()), [
Vertex { position: [-0.5, -0.5 ] },
Vertex { position: [-0.5, 0.5 ] },
Vertex { position: [ 0.5, -0.5 ] },
Vertex { position: [ 0.5, 0.5 ] },
].iter().cloned()).expect("failed to create buffer");
mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/image_vs.glsl")} }
let vs = vs::Shader::load(&device).expect("failed to create shader module");
@ -116,22 +107,13 @@ fn main() {
image::ImageFormat::PNG).unwrap().to_rgba();
let image_data = image.into_raw().clone();
let image_data_chunks = image_data.chunks(4).map(|c| [c[0], c[1], c[2], c[3]]);
// TODO: staging buffer instead
let pixel_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer::<[[u8; 4]]>
::array(&device, image_data.len(), &vulkano::buffer::BufferUsage::all(),
Some(queue.family())).expect("failed to create buffer");
{
let mut mapping = pixel_buffer.write(Duration::new(0, 0)).unwrap();
for (o, i) in mapping.iter_mut().zip(image_data.chunks(4)) {
o[0] = i[0];
o[1] = i[1];
o[2] = i[2];
o[3] = i[3];
}
}
pixel_buffer
vulkano::buffer::cpu_access::CpuAccessibleBuffer::<[[u8; 4]]>
::from_iter(&device, &vulkano::buffer::BufferUsage::all(),
Some(queue.family()), image_data_chunks)
.expect("failed to create buffer")
};

View File

@ -10,7 +10,7 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_ARB_shading_language_450pack : enable
layout(location = 0) in vec2 tex_coords;
layout(location = 0) out vec4 f_color;

View File

@ -10,7 +10,7 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_ARB_shading_language_450pack : enable
layout(location = 0) in vec2 position;
layout(location = 0) out vec2 tex_coords;

View File

@ -61,7 +61,7 @@ fn main() {
let usage = caps.supported_usage_flags;
let format = caps.supported_formats[0].0;
vulkano::swapchain::Swapchain::new(&device, &window.surface(), 3, format, dimensions, 1,
vulkano::swapchain::Swapchain::new(&device, &window.surface(), caps.min_image_count, format, dimensions, 1,
&usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
vulkano::swapchain::CompositeAlpha::Opaque,
present, true, None).expect("failed to create swapchain")
@ -84,7 +84,7 @@ fn main() {
// note: this teapot was meant for OpenGL where the origin is at the lower left
// instead the origin is at the upper left in vulkan, so we reverse the Y axis
let proj = cgmath::perspective(cgmath::rad(3.141592 / 2.0), { let d = images[0].dimensions(); d[0] as f32 / d[1] as f32 }, 0.01, 100.0);
let proj = cgmath::perspective(cgmath::Rad(std::f32::consts::FRAC_PI_2), { let d = images[0].dimensions(); d[0] as f32 / d[1] as f32 }, 0.01, 100.0);
let view = cgmath::Matrix4::look_at(cgmath::Point3::new(0.3, 0.3, 1.0), cgmath::Point3::new(0.0, 0.0, 0.0), cgmath::Vector3::new(0.0, -1.0, 0.0));
let scale = cgmath::Matrix4::from_scale(0.01);
@ -186,7 +186,7 @@ fn main() {
// aquiring write lock for the uniform buffer
let mut buffer_content = uniform_buffer.write(Duration::new(1, 0)).unwrap();
let rotation = cgmath::Matrix3::from_angle_y(cgmath::rad(time::precise_time_ns() as f32 * 0.000000001));
let rotation = cgmath::Matrix3::from_angle_y(cgmath::Rad(time::precise_time_ns() as f32 * 0.000000001));
// since write lock implementd Deref and DerefMut traits,
// we can update content directly

View File

@ -10,7 +10,7 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_ARB_shading_language_450pack : enable
layout(location = 0) in vec3 v_normal;
layout(location = 0) out vec4 f_color;

View File

@ -10,7 +10,7 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_ARB_shading_language_450pack : enable
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;

View File

@ -181,7 +181,7 @@ fn main() {
let format = caps.supported_formats[0].0;
// Please take a look at the docs for the meaning of the parameters we didn't mention.
Swapchain::new(&device, &window.surface(), 2, format, dimensions, 1,
Swapchain::new(&device, &window.surface(), caps.min_image_count, format, dimensions, 1,
&caps.supported_usage_flags, &queue, SurfaceTransform::Identity, alpha,
present, true, None).expect("failed to create swapchain")
};

View File

@ -10,7 +10,7 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_ARB_shading_language_450pack : enable
layout(location = 0) out vec4 f_color;

View File

@ -10,7 +10,7 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_ARB_shading_language_450pack : enable
layout(location = 0) in vec2 position;

View File

@ -1,6 +1,6 @@
[package]
name = "glsl-to-spirv"
version = "0.1.1"
version = "0.1.2"
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
repository = "https://github.com/tomaka/vulkano"
description = "Wrapper around the official GLSL to SPIR-V compiler"
@ -8,7 +8,7 @@ license = "MIT/Apache-2.0"
build = "build/build.rs"
[dependencies]
tempdir = "0.3.4"
tempdir = "0.3.5"
[build-dependencies]
cmake = "0.1.13"
cmake = "0.1.19"

View File

@ -6,4 +6,4 @@ repository = "https://github.com/tomaka/vulkano"
description = "Bindings for the Vulkan graphics API"
license = "MIT/Apache-2.0"
documentation = "https://docs.rs/vk-sys"
keywords = ["vulkan", "bindings", "graphics", "gpu"]
keywords = ["vulkan", "bindings", "graphics", "gpu"]

Binary file not shown.

View File

@ -0,0 +1,13 @@
[package]
name = "vulkano-shader-derive"
version = "0.1.0"
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
[lib]
name = "vulkano_shader_derive"
proc-macro = true
[dependencies]
glsl-to-spirv = { version = "0.1.2", path = "../glsl-to-spirv" }
syn = { version = "0.10", features = ["aster", "visit"] }
vulkano-shaders = { version = "0.3", path = "../vulkano-shaders" }

View File

@ -0,0 +1,27 @@
# Usage
This replaces `vulkano-shaders`.
```rust
#[macro_use]
extern crate vulkano_shader_derive;
mod fs {
#[derive(VulkanoShader)]
#[ty = "fragment"]
#[src = "
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_450pack : enable
layout(location = 0) out vec4 f_color;
void main() {
f_color = vec4(1.0, 0.0, 0.0, 1.0);
}"]
struct Dummy;
}
let fs = fs::Shader::load(&device).expect("failed to create shader module");
```

View File

@ -0,0 +1,46 @@
extern crate glsl_to_spirv;
extern crate proc_macro;
extern crate syn;
extern crate vulkano_shaders;
use proc_macro::TokenStream;
#[proc_macro_derive(VulkanoShader, attributes(src, ty))]
pub fn derive(input: TokenStream) -> TokenStream {
let syn_item = syn::parse_macro_input(&input.to_string()).unwrap();
let src = syn_item.attrs.iter().filter_map(|attr| {
match attr.value {
syn::MetaItem::NameValue(ref i, syn::Lit::Str(ref val, _)) if i == "src" => {
Some(val.clone())
},
_ => None
}
}).next().expect("Can't find `src` attribute ; put #[src = \"...\"] for example.");
let ty_str = syn_item.attrs.iter().filter_map(|attr| {
match attr.value {
syn::MetaItem::NameValue(ref i, syn::Lit::Str(ref val, _)) if i == "ty" => {
Some(val.clone())
},
_ => None
}
}).next().expect("Can't find `ty` attribute ; put #[ty = \"vertex\"] for example.");
let ty = match &ty_str[..] {
"vertex" => glsl_to_spirv::ShaderType::Vertex,
"fragment" => glsl_to_spirv::ShaderType::Fragment,
"geometry" => glsl_to_spirv::ShaderType::Geometry,
"tess_ctrl" => glsl_to_spirv::ShaderType::TessellationControl,
"tess_eval" => glsl_to_spirv::ShaderType::TessellationEvaluation,
"compute" => glsl_to_spirv::ShaderType::Compute,
_ => panic!("Unexpected shader type ; valid values: vertex, fragment, geometry, tess_ctrl, tess_eval, compute")
};
let spirv_data = match glsl_to_spirv::compile(&src, ty) {
Ok(compiled) => compiled,
Err(message) => panic!("{}\nfailed to compile shader", message),
};
vulkano_shaders::reflect("Shader", spirv_data).unwrap().parse().unwrap()
}

View File

@ -8,4 +8,4 @@ license = "MIT/Apache-2.0"
documentation = "http://tomaka.github.io/vulkano/vulkano/index.html"
[dependencies]
glsl-to-spirv = { version = "0.1.0", path = "../glsl-to-spirv" }
glsl-to-spirv = { version = "0.1.2", path = "../glsl-to-spirv" }

View File

@ -29,12 +29,33 @@ pub fn write_structs(doc: &parse::Spirv) -> String {
result
}
/// Represents a rust struct member
struct Member {
name: String,
value: String,
offset: Option<usize>
}
impl Member {
fn declaration_text(&self) -> String {
let offset = match self.offset {
Some(o) => format!("/* offset: {} */", o),
_ => "".to_owned(),
};
format!(" pub {}: {} {}", self.name, self.value, offset)
}
fn copy_text(&self) -> String {
format!(" {name}: self.{name}", name = self.name)
}
}
/// Writes a single struct.
fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> String {
let name = ::name_from_id(doc, struct_id);
// Strings of each member definition.
let mut members_defs = Vec::with_capacity(members.len());
// The members of this struct.
let mut rust_members = Vec::with_capacity(members.len());
// Padding structs will be named `_paddingN` where `N` is determined by this variable.
let mut next_padding_num = 0;
@ -90,7 +111,11 @@ fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> String {
if spirv_offset != *current_rust_offset {
let diff = spirv_offset.checked_sub(*current_rust_offset).unwrap();
let padding_num = next_padding_num; next_padding_num += 1;
members_defs.push(format!("pub _dummy{}: [u8; {}]", padding_num, diff));
rust_members.push(Member {
name: format!("_dummy{}", padding_num),
value: format!("[u8; {}]", diff),
offset: None,
});
*current_rust_offset += diff;
}
}
@ -102,8 +127,11 @@ fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> String {
current_rust_offset = None;
}
members_defs.push(format!("pub {name}: {ty} /* offset: {offset} */",
name = member_name, ty = ty, offset = spirv_offset));
rust_members.push(Member {
name: member_name.to_owned(),
value: ty,
offset: Some(spirv_offset),
});
}
// Try determine the total size of the struct in order to add padding at the end of the struct.
@ -139,20 +167,27 @@ fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> String {
if let (Some(cur_size), Some(req_size)) = (current_rust_offset, spirv_req_total_size) {
let diff = req_size.checked_sub(cur_size as u32).unwrap();
if diff >= 1 {
members_defs.push(format!("pub _dummy{}: [u8; {}]", next_padding_num, diff));
rust_members.push(Member {
name: format!("_dummy{}", next_padding_num),
value: format!("[u8; {}]", diff),
offset: None,
});
}
}
// We can only derive common traits if there's no unsized member in the struct.
let derive = if current_rust_offset.is_some() {
"#[derive(Copy, Clone, Debug, Default)]\n"
// We can only implement Clone if there's no unsized member in the struct.
let impl_text = if current_rust_offset.is_some() {
format!("\nimpl Clone for {name} {{\n fn clone(&self) -> Self {{\n \
{name} {{\n{copies}\n }}\n }}\n}}\n", name = name,
copies = rust_members.iter().map(Member::copy_text).collect::<Vec<_>>().join(",\n"))
} else {
""
"".to_owned()
};
format!("#[repr(C)]\n{derive}\
pub struct {name} {{\n\t{members}\n}} /* total_size: {t:?} */\n",
derive = derive, name = name, members = members_defs.join(",\n\t"), t = spirv_req_total_size)
format!("#[repr(C)]\npub struct {name} {{\n{members}\n}} /* total_size: {t:?} */\n{impl_text}",
name = name,
members = rust_members.iter().map(Member::declaration_text).collect::<Vec<_>>().join(",\n"),
t = spirv_req_total_size, impl_text=impl_text)
}
/// Returns true if a `BuiltIn` decorator is applied on a struct member.

View File

@ -8,4 +8,4 @@ license = "MIT/Apache-2.0"
[dependencies]
vulkano = { version = "0.3.0", path = "../vulkano" }
winit = "0.5.2"
winit = "0.5.6"

View File

@ -8,9 +8,9 @@ license = "MIT/Apache-2.0"
documentation = "https://docs.rs/vulkano"
[dependencies]
crossbeam = "0.2.5"
fnv = "1.0.2"
shared_library = "0.1.4"
smallvec = "0.2.0"
lazy_static = "0.1.15"
vk-sys = { version = "0.2.0", path = "../vk-sys" }
crossbeam = "0.2.10"
fnv = "1.0.5"
shared_library = "0.1.5"
smallvec = "0.3.1"
lazy_static = "0.2.2"
vk-sys = { version = "0.2.1", path = "../vk-sys" }

View File

@ -212,7 +212,7 @@ impl Device {
if let Some(q) = queues.iter_mut().find(|q| q.0 == queue_family.id()) {
output_queues.push((queue_family.id(), q.1.len() as u32));
q.1.push(priority);
if q.1.len() >= queue_family.queues_count() {
if q.1.len() > queue_family.queues_count() {
return Err(DeviceCreationError::TooManyQueuesForFamily);
}
continue;

View File

@ -7,11 +7,12 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
//! Debug callback called by validation layers.
//! Debug callback called by intermediate layers or by the driver.
//!
//! When working on an application, it is recommended to register a debug callback. This callback
//! will be called by validation layers whenever necessary to warn you about invalid API usages
//! or performance problems.
//! When working on an application, it is recommended to register a debug callback. For example if
//! you enable the validation layers provided by the official Vulkan SDK, they will warn you about
//! invalid API usages or performance problems by calling this callback. The callback can also
//! be called by the driver or by whatever intermediate layer is activated.
//!
//! Note that the vulkano library can also emit messages to warn you about performance issues.
//! TODO: ^ that's not the case yet, need to choose whether we keep this idea
@ -29,6 +30,8 @@
//! }).ok();
//! ```
//!
//! The type of `msg` in the callback is [`Message`](struct.Message.html).
//!
//! Note that you must keep the `_callback` object alive for as long as you want your callback to
//! be callable. If you don't store the return value of `DebugCallback`'s constructor in a
//! variable, it will be immediately destroyed and your callback will not work.
@ -68,7 +71,7 @@ impl DebugCallback {
/// Panics generated by calling `user_callback` are ignored.
pub fn new<F>(instance: &Arc<Instance>, messages: MessageTypes, user_callback: F)
-> Result<DebugCallback, DebugCallbackCreationError>
where F: Fn(&Message) + 'static + panic::RefUnwindSafe
where F: Fn(&Message) + 'static + Send + panic::RefUnwindSafe
{
if !instance.loaded_extensions().ext_debug_report {
return Err(DebugCallbackCreationError::MissingExtension);
@ -156,7 +159,7 @@ impl DebugCallback {
#[inline]
pub fn errors_and_warnings<F>(instance: &Arc<Instance>, user_callback: F)
-> Result<DebugCallback, DebugCallbackCreationError>
where F: Fn(&Message) + 'static + panic::RefUnwindSafe
where F: Fn(&Message) + Send + 'static + panic::RefUnwindSafe
{
DebugCallback::new(instance, MessageTypes::errors_and_warnings(), user_callback)
}

View File

@ -9,8 +9,21 @@
//! Allows you to create surfaces that fill a whole display, outside of the windowing system.
//!
//! As far as the author knows, no existing device supports these features. Therefore the code here
//! is mostly a draft and needs rework in both the API and the implementation.
//! **As far as the author knows, no existing device supports these features. Therefore the code
//! here is mostly a draft and needs rework in both the API and the implementation.**
//!
//! The purpose of the objects in this module is to let you create a `Surface` object that
//! represents a location on the screen. This is done in four steps:
//!
//! - Choose a `Display` where the surface will be located. A `Display` represents a display
//! display, usually a monitor. The available displays can be enumerated with
//! `Display::enumerate`.
//! - Choose a `DisplayMode`, which is the combination of a display, a resolution and a refresh
//! rate. You can enumerate the modes available on a display with `Display::display_modes`, or
//! attempt to create your own mode with `TODO`.
//! - Choose a `DisplayPlane`. A display can show multiple planes in a stacking fashion.
//! - Create a `Surface` object with `Surface::from_display_mode` and pass the chosen `DisplayMode`
//! and `DisplayPlane`.
#![allow(dead_code)] // TODO: this module isn't finished
#![allow(unused_variables)] // TODO: this module isn't finished
@ -22,6 +35,7 @@ use std::vec::IntoIter;
use instance::Instance;
use instance::PhysicalDevice;
use swapchain::SupportedSurfaceTransforms;
use check_errors;
use OomError;
@ -33,6 +47,7 @@ use vk;
/// ?
// TODO: plane capabilities
// TODO: store properties in the instance?
pub struct DisplayPlane {
instance: Arc<Instance>,
physical_device: usize,
@ -111,6 +126,12 @@ impl DisplayPlane {
PhysicalDevice::from_index(&self.instance, self.physical_device).unwrap()
}
/// Returns the index of the plane.
#[inline]
pub fn index(&self) -> u32 {
self.index
}
/// Returns true if this plane supports the given display.
#[inline]
pub fn supports(&self, display: &Display) -> bool {
@ -124,6 +145,7 @@ impl DisplayPlane {
}
/// Represents a monitor connected to a physical device.
// TODO: store properties in the instance?
#[derive(Clone)]
pub struct Display {
instance: Arc<Instance>,
@ -179,8 +201,9 @@ impl Display {
#[inline]
pub fn name(&self) -> &str {
unsafe {
CStr::from_ptr(self.properties.displayName).to_str()
.expect("non UTF-8 characters in display name")
CStr::from_ptr(self.properties.displayName)
.to_str()
.expect("non UTF-8 characters in display name")
}
}
@ -190,13 +213,41 @@ impl Display {
PhysicalDevice::from_index(&self.instance, self.physical_device).unwrap()
}
/// Returns the physical resolution of the display.
/// Returns the physical dimensions of the display in millimeters.
#[inline]
pub fn physical_dimensions(&self) -> [u32; 2] {
let ref r = self.properties.physicalDimensions;
[r.width, r.height]
}
/// Returns the physical, native, or preferred resolution of the display.
///
/// > **Note**: The display is usually still capable of displaying other resolutions. This is
/// > only the "best" resolution.
#[inline]
pub fn physical_resolution(&self) -> [u32; 2] {
let ref r = self.properties.physicalResolution;
[r.width, r.height]
}
/// Returns the transforms supported by this display.
#[inline]
pub fn supported_transforms(&self) -> SupportedSurfaceTransforms {
SupportedSurfaceTransforms::from_bits(self.properties.supportedTransforms)
}
/// Returns true if TODO.
#[inline]
pub fn plane_reorder_possible(&self) -> bool {
self.properties.planeReorderPossible != 0
}
/// Returns true if TODO.
#[inline]
pub fn persistent_content(&self) -> bool {
self.properties.persistentContent != 0
}
/// See the docs of display_modes().
pub fn display_modes_raw(&self) -> Result<IntoIter<DisplayMode>, OomError> {
let vk = self.instance.pointers();

View File

@ -188,6 +188,7 @@
//!
use std::sync::atomic::AtomicBool;
use vk;
pub use self::surface::Capabilities;
pub use self::surface::Surface;
@ -204,6 +205,113 @@ pub mod display;
mod surface;
mod swapchain;
/// List of supported composite alpha modes.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SupportedSurfaceTransforms {
pub identity: bool,
pub rotate90: bool,
pub rotate180: bool,
pub rotate270: bool,
pub horizontal_mirror: bool,
pub horizontal_mirror_rotate90: bool,
pub horizontal_mirror_rotate180: bool,
pub horizontal_mirror_rotate270: bool,
pub inherit: bool,
}
impl SupportedSurfaceTransforms {
/// Builds a `SupportedSurfaceTransforms` with all fields set to false.
#[inline]
pub fn none() -> SupportedSurfaceTransforms {
SupportedSurfaceTransforms {
identity: false,
rotate90: false,
rotate180: false,
rotate270: false,
horizontal_mirror: false,
horizontal_mirror_rotate90: false,
horizontal_mirror_rotate180: false,
horizontal_mirror_rotate270: false,
inherit: false,
}
}
#[inline]
fn from_bits(val: vk::SurfaceTransformFlagsKHR) -> SupportedSurfaceTransforms {
macro_rules! v {
($val:expr, $out:ident, $e:expr, $f:ident) => (
if ($val & $e) != 0 { $out.$f = true; }
);
}
let mut result = SupportedSurfaceTransforms::none();
v!(val, result, vk::SURFACE_TRANSFORM_IDENTITY_BIT_KHR, identity);
v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, rotate90);
v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, rotate180);
v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, rotate270);
v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, horizontal_mirror);
v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR,
horizontal_mirror_rotate90);
v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR,
horizontal_mirror_rotate180);
v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR,
horizontal_mirror_rotate270);
v!(val, result, vk::SURFACE_TRANSFORM_INHERIT_BIT_KHR, inherit);
result
}
/// Returns true if the given `SurfaceTransform` is in this list.
#[inline]
pub fn supports(&self, value: SurfaceTransform) -> bool {
match value {
SurfaceTransform::Identity => self.identity,
SurfaceTransform::Rotate90 => self.rotate90,
SurfaceTransform::Rotate180 => self.rotate180,
SurfaceTransform::Rotate270 => self.rotate270,
SurfaceTransform::HorizontalMirror => self.horizontal_mirror,
SurfaceTransform::HorizontalMirrorRotate90 => self.horizontal_mirror_rotate90,
SurfaceTransform::HorizontalMirrorRotate180 => self.horizontal_mirror_rotate180,
SurfaceTransform::HorizontalMirrorRotate270 => self.horizontal_mirror_rotate270,
SurfaceTransform::Inherit => self.inherit,
}
}
/// Returns an iterator to the list of supported composite alpha.
#[inline]
pub fn iter(&self) -> SupportedSurfaceTransformsIter {
SupportedSurfaceTransformsIter(self.clone())
}
}
/// Enumeration of the `SurfaceTransform` that are supported.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SupportedSurfaceTransformsIter(SupportedSurfaceTransforms);
impl Iterator for SupportedSurfaceTransformsIter {
type Item = SurfaceTransform;
#[inline]
fn next(&mut self) -> Option<SurfaceTransform> {
if self.0.identity { self.0.identity = false; return Some(SurfaceTransform::Identity); }
if self.0.rotate90 { self.0.rotate90 = false; return Some(SurfaceTransform::Rotate90); }
if self.0.rotate180 { self.0.rotate180 = false; return Some(SurfaceTransform::Rotate180); }
if self.0.rotate270 { self.0.rotate270 = false; return Some(SurfaceTransform::Rotate270); }
if self.0.horizontal_mirror { self.0.horizontal_mirror = false; return Some(SurfaceTransform::HorizontalMirror); }
if self.0.horizontal_mirror_rotate90 { self.0.horizontal_mirror_rotate90 = false; return Some(SurfaceTransform::HorizontalMirrorRotate90); }
if self.0.horizontal_mirror_rotate180 { self.0.horizontal_mirror_rotate180 = false; return Some(SurfaceTransform::HorizontalMirrorRotate180); }
if self.0.horizontal_mirror_rotate270 { self.0.horizontal_mirror_rotate270 = false; return Some(SurfaceTransform::HorizontalMirrorRotate270); }
if self.0.inherit { self.0.inherit = false; return Some(SurfaceTransform::Inherit); }
None
}
}
impl Default for SurfaceTransform {
#[inline]
fn default() -> SurfaceTransform {
SurfaceTransform::Identity
}
}
/// Internal trait so that creating/destroying a swapchain can access the surface's "has_swapchain"
/// flag.
unsafe trait SurfaceSwapchainLock {

View File

@ -21,6 +21,7 @@ use instance::Instance;
use instance::PhysicalDevice;
use instance::QueueFamily;
use swapchain::SurfaceSwapchainLock;
use swapchain::SupportedSurfaceTransforms;
use swapchain::display::DisplayMode;
use swapchain::display::DisplayPlane;
@ -55,8 +56,7 @@ impl Surface {
pub fn from_display_mode(display_mode: &DisplayMode, plane: &DisplayPlane)
-> Result<Arc<Surface>, SurfaceCreationError>
{
unimplemented!() // TODO:
/*if !display_mode.display().physical_device().instance().loaded_extensions().khr_display {
if !display_mode.display().physical_device().instance().loaded_extensions().khr_display {
return Err(SurfaceCreationError::MissingExtension { name: "VK_KHR_display" });
}
@ -73,14 +73,14 @@ impl Surface {
pNext: ptr::null(),
flags: 0, // reserved
displayMode: display_mode.internal_object(),
planeIndex: plane.index,
planeStackIndex: plane.properties.currentStackIndex,
planeIndex: plane.index(),
planeStackIndex: 0, // FIXME: plane.properties.currentStackIndex,
transform: vk::SURFACE_TRANSFORM_IDENTITY_BIT_KHR, // TODO: let user choose
globalAlpha: 0.0, // TODO: let user choose
alphaMode: vk::DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, // TODO: let user choose
imageExtent: vk::Extent2D { // TODO: let user choose
width: display_mode.parameters.visibleRegion.width,
height: display_mode.parameters.visibleRegion.height,
width: display_mode.visible_region()[0],
height: display_mode.visible_region()[1],
},
};
@ -93,7 +93,8 @@ impl Surface {
Ok(Arc::new(Surface {
instance: instance.clone(),
surface: surface,
}))*/
has_swapchain: AtomicBool::new(false),
}))
}
/// Creates a `Surface` from a Win32 window.
@ -685,113 +686,6 @@ pub enum SurfaceTransform {
Inherit = vk::SURFACE_TRANSFORM_INHERIT_BIT_KHR,
}
/// List of supported composite alpha modes.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SupportedSurfaceTransforms {
pub identity: bool,
pub rotate90: bool,
pub rotate180: bool,
pub rotate270: bool,
pub horizontal_mirror: bool,
pub horizontal_mirror_rotate90: bool,
pub horizontal_mirror_rotate180: bool,
pub horizontal_mirror_rotate270: bool,
pub inherit: bool,
}
impl SupportedSurfaceTransforms {
/// Builds a `SupportedSurfaceTransforms` with all fields set to false.
#[inline]
pub fn none() -> SupportedSurfaceTransforms {
SupportedSurfaceTransforms {
identity: false,
rotate90: false,
rotate180: false,
rotate270: false,
horizontal_mirror: false,
horizontal_mirror_rotate90: false,
horizontal_mirror_rotate180: false,
horizontal_mirror_rotate270: false,
inherit: false,
}
}
#[inline]
fn from_bits(val: u32) -> SupportedSurfaceTransforms {
macro_rules! v {
($val:expr, $out:ident, $e:expr, $f:ident) => (
if ($val & $e) != 0 { $out.$f = true; }
);
}
let mut result = SupportedSurfaceTransforms::none();
v!(val, result, vk::SURFACE_TRANSFORM_IDENTITY_BIT_KHR, identity);
v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, rotate90);
v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, rotate180);
v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, rotate270);
v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, horizontal_mirror);
v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR,
horizontal_mirror_rotate90);
v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR,
horizontal_mirror_rotate180);
v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR,
horizontal_mirror_rotate270);
v!(val, result, vk::SURFACE_TRANSFORM_INHERIT_BIT_KHR, inherit);
result
}
/// Returns true if the given `SurfaceTransform` is in this list.
#[inline]
pub fn supports(&self, value: SurfaceTransform) -> bool {
match value {
SurfaceTransform::Identity => self.identity,
SurfaceTransform::Rotate90 => self.rotate90,
SurfaceTransform::Rotate180 => self.rotate180,
SurfaceTransform::Rotate270 => self.rotate270,
SurfaceTransform::HorizontalMirror => self.horizontal_mirror,
SurfaceTransform::HorizontalMirrorRotate90 => self.horizontal_mirror_rotate90,
SurfaceTransform::HorizontalMirrorRotate180 => self.horizontal_mirror_rotate180,
SurfaceTransform::HorizontalMirrorRotate270 => self.horizontal_mirror_rotate270,
SurfaceTransform::Inherit => self.inherit,
}
}
/// Returns an iterator to the list of supported composite alpha.
#[inline]
pub fn iter(&self) -> SupportedSurfaceTransformsIter {
SupportedSurfaceTransformsIter(self.clone())
}
}
/// Enumeration of the `SurfaceTransform` that are supported.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SupportedSurfaceTransformsIter(SupportedSurfaceTransforms);
impl Iterator for SupportedSurfaceTransformsIter {
type Item = SurfaceTransform;
#[inline]
fn next(&mut self) -> Option<SurfaceTransform> {
if self.0.identity { self.0.identity = false; return Some(SurfaceTransform::Identity); }
if self.0.rotate90 { self.0.rotate90 = false; return Some(SurfaceTransform::Rotate90); }
if self.0.rotate180 { self.0.rotate180 = false; return Some(SurfaceTransform::Rotate180); }
if self.0.rotate270 { self.0.rotate270 = false; return Some(SurfaceTransform::Rotate270); }
if self.0.horizontal_mirror { self.0.horizontal_mirror = false; return Some(SurfaceTransform::HorizontalMirror); }
if self.0.horizontal_mirror_rotate90 { self.0.horizontal_mirror_rotate90 = false; return Some(SurfaceTransform::HorizontalMirrorRotate90); }
if self.0.horizontal_mirror_rotate180 { self.0.horizontal_mirror_rotate180 = false; return Some(SurfaceTransform::HorizontalMirrorRotate180); }
if self.0.horizontal_mirror_rotate270 { self.0.horizontal_mirror_rotate270 = false; return Some(SurfaceTransform::HorizontalMirrorRotate270); }
if self.0.inherit { self.0.inherit = false; return Some(SurfaceTransform::Inherit); }
None
}
}
impl Default for SurfaceTransform {
#[inline]
fn default() -> SurfaceTransform {
SurfaceTransform::Identity
}
}
/// How the alpha values of the pixels of the window are treated.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]

View File

@ -10,9 +10,10 @@
// The `Version` object is reexported from the `instance` module.
use std::cmp::Ordering;
use std::fmt;
/// Represents an API version of Vulkan.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Version {
/// Major version number.
pub major: u16,
@ -22,6 +23,18 @@ 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 PartialOrd for Version {
#[inline]
fn partial_cmp(&self, other: &Version) -> Option<Ordering> {