Merge pull request #1 from MaikKlein/master

Update from master
This commit is contained in:
Graham Wihlidal 2019-02-09 21:11:37 +01:00 committed by GitHub
commit 7ffb94004d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 16824 additions and 4438 deletions

View file

@ -1,9 +1,27 @@
os:
- linux
- osx
language: rust
before_script:
- rustup component add rustfmt
rust:
- stable
script:
- cargo fmt --all -- --check
- cargo build --manifest-path ash/Cargo.toml
- cargo build --manifest-path examples/Cargo.toml
- cargo build --manifest-path generator/Cargo.toml
branches:
only:
# This is where pull requests from "bors r+" are built.
- staging
# This is where pull requests from "bors try" are built.
- trying
# Uncomment this to enable building pull requests.
- master

View file

@ -1,3 +1,19 @@
# 0.27.0/1
* Extensions are now namespaced. `ash::extensions::khr::Swapchain`
* Removed vendor tags from extension methods
* Added missing functions for VkEvent
* The examples were updated to use the new builder pattern
* A SPIR-V parsing function `ash::util::read_spv`
* Added `get_pipeline_cache_data`
# 0.26.0
* Fix loader on MacOS.
* Expose function pointers for easier interop with external libraries.
* Builder now uses bool instead of Bool32.
# 0.25.0
* Adds support for Vulkan 1.1

View file

@ -36,7 +36,7 @@ let instance = entry.create_instance(&create_info, None)
### `Vec<T>` instead of mutable slices
```Rust
pub fn get_swapchain_images_khr(&self,
pub fn get_swapchain_images(&self,
swapchain: vk::SwapchainKHR)
-> VkResult<Vec<vk::Image>>;
let present_images = swapchain_loader.get_swapchain_images_khr(swapchain).unwrap();
@ -55,6 +55,12 @@ pub fn cmd_pipeline_barrier(&self,
image_memory_barriers: &[vk::ImageMemoryBarrier]);
```
### Strongly typed handles
Each Vulkan handle type is exposed as a newtyped struct for improved type safety. Null handles can be constructed with
`T::null()`, and handles may be freely converted to and from `u64` with `Handle::from_raw` and `Handle::as_raw` for
interop with non-Ash Vulkan code.
### Default implementation for all types
```Rust
// No need to manually set the structure type
@ -71,7 +77,11 @@ let pipeline_vertex_input_state_create_info = vk::PipelineVertexInputStateCreate
.vertex_binding_descriptions(&Vertex::binding_descriptions())
.vertex_attribute_descriptions(&Vertex::attribute_descriptions()).build();
```
*Note*: No validation is done, the lifetimes only have to live as long as the builder object. It is the responsibility of the user to make sure that the pointers are valid.
Builders implement `Deref` targeting their corresponding Vulkan struct, so references to builders can be passed directly
to Vulkan functions. This is encouraged as doing so allows Rust to check the lifetimes of captured objects are valid,
whereas calling `build` discards lifetime information, making inadvertent use-after-free errors more likely.
### Flags and constants as associated constants
```Rust
@ -95,12 +105,6 @@ println!("Display: {}", flag);
// Display: COLOR_ATTACHMENT_READ | COLOR_ATTACHMENT_WRITE
```
### Interop
Vulkan objects inside Ash can be constructed from raw values with `Object::from:raw`. Useful if you need to interact with a C library.
```Rust
PipelineBindPoint::from_raw(bindpoint);
```
### Function pointer loading
Ash also takes care of loading the function pointers. Function pointers are split into 3 categories.
@ -119,9 +123,9 @@ Custom loaders can be implemented.
### Extension loading
Additionally, every Vulkan extension has to be loaded explicitly. You can find all extensions under [ash::extensions](https://github.com/MaikKlein/ash/tree/master/ash/src/extensions).
```Rust
use ash::extensions::Swapchain;
use ash::extensions::khr::Swapchain;
let swapchain_loader = Swapchain::new(&instance, &device);
let swapchain = swapchain_loader.create_swapchain_khr(&swapchain_create_info).unwrap();
let swapchain = swapchain_loader.create_swapchain(&swapchain_create_info).unwrap();
```
### Raw function pointers

View file

@ -1,15 +1,21 @@
os: Visual Studio 2015
environment:
matrix:
- TARGET: 1.28.0-x86_64-pc-windows
COMPILER: msvc
# Stable 64-bit MSVC
- channel: stable
target: x86_64-pc-windows-msvc
install:
- if %COMPILER%==gnu choco install -y mingw
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}-${env:COMPILER}.exe" -FileName "rust-install.exe"
- ps: .\rust-install.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null
- ps: $env:PATH="$env:PATH;C:\rust\bin;C:\tools\mingw64\bin"
- if %COMPILER%==gnu gcc -v
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- rustup-init -yv --default-toolchain %channel% --default-host %target%
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
- rustc -vV
- cargo -vV
build_script:
- cargo build --manifest-path ash/Cargo.toml
- cargo build --manifest-path examples/Cargo.toml
# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents
# the "directory does not contain a project or solution file" error.
build: off
test_script:
- cargo test --verbose %cargoflags%

View file

@ -1,6 +1,6 @@
[package]
name = "ash"
version = "0.25.0"
version = "0.27.1"
authors = ["maik klein <maikklein@googlemail.com>"]
description = "Vulkan bindings for Rust"
license = "MIT"
@ -11,7 +11,7 @@ documentation = "https://docs.rs/ash"
[dependencies]
shared_library = "0.1.9"
lazy_static = "0.2.1"
lazy_static = "1"
[features]
default = []

View file

@ -51,11 +51,7 @@ pub trait DeviceV1_1: DeviceV1_0 {
peer_memory_features
}
unsafe fn cmd_set_device_mask(
&self,
command_buffer: vk::CommandBuffer,
device_mask: u32,
) {
unsafe fn cmd_set_device_mask(&self, command_buffer: vk::CommandBuffer, device_mask: u32) {
self.fp_v1_1()
.cmd_set_device_mask(command_buffer, device_mask);
}
@ -86,11 +82,8 @@ pub trait DeviceV1_1: DeviceV1_0 {
info: &vk::ImageMemoryRequirementsInfo2,
out: &mut vk::MemoryRequirements2,
) {
self.fp_v1_1().get_image_memory_requirements2(
self.handle(),
info,
out,
);
self.fp_v1_1()
.get_image_memory_requirements2(self.handle(), info, out);
}
unsafe fn get_buffer_memory_requirements2(
@ -98,11 +91,8 @@ pub trait DeviceV1_1: DeviceV1_0 {
info: &vk::BufferMemoryRequirementsInfo2,
out: &mut vk::MemoryRequirements2,
) {
self.fp_v1_1().get_buffer_memory_requirements2(
self.handle(),
info,
out,
);
self.fp_v1_1()
.get_buffer_memory_requirements2(self.handle(), info, out);
}
unsafe fn get_image_sparse_memory_requirements2_len(
@ -221,11 +211,8 @@ pub trait DeviceV1_1: DeviceV1_0 {
create_info: &vk::DescriptorSetLayoutCreateInfo,
out: &mut vk::DescriptorSetLayoutSupport,
) {
self.fp_v1_1().get_descriptor_set_layout_support(
self.handle(),
create_info,
out,
);
self.fp_v1_1()
.get_descriptor_set_layout_support(self.handle(), create_info, out);
}
}
@ -269,6 +256,94 @@ pub trait DeviceV1_0 {
);
}
unsafe fn create_event(
&self,
create_info: &vk::EventCreateInfo,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) -> VkResult<vk::Event> {
let mut event = mem::uninitialized();
let err_code = self.fp_v1_0().create_event(
self.handle(),
create_info,
allocation_callbacks.as_raw_ptr(),
&mut event,
);
match err_code {
vk::Result::SUCCESS => Ok(event),
_ => Err(err_code),
}
}
/// Returns true if the event was set, and false if the event was reset, otherwise it will
/// return the error code.
unsafe fn get_event_status(&self, event: vk::Event) -> VkResult<bool> {
let err_code = self.fp_v1_0().get_event_status(self.handle(), event);
match err_code {
vk::Result::EVENT_SET => Ok(true),
vk::Result::EVENT_RESET => Ok(false),
_ => Err(err_code),
}
}
unsafe fn set_event(&self, event: vk::Event) -> VkResult<()> {
let err_code = self.fp_v1_0().set_event(self.handle(), event);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
}
}
unsafe fn reset_event(&self, event: vk::Event) -> VkResult<()> {
let err_code = self.fp_v1_0().reset_event(self.handle(), event);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
}
}
unsafe fn cmd_set_event(
&self,
command_buffer: vk::CommandBuffer,
event: vk::Event,
stage_mask: vk::PipelineStageFlags,
) {
self.fp_v1_0()
.cmd_set_event(command_buffer, event, stage_mask);
}
unsafe fn cmd_reset_event(
&self,
command_buffer: vk::CommandBuffer,
event: vk::Event,
stage_mask: vk::PipelineStageFlags,
) {
self.fp_v1_0()
.cmd_reset_event(command_buffer, event, stage_mask);
}
unsafe fn cmd_wait_events(
&self,
command_buffer: vk::CommandBuffer,
events: &[vk::Event],
src_stage_mask: vk::PipelineStageFlags,
dst_stage_mask: vk::PipelineStageFlags,
memory_barriers: &[vk::MemoryBarrier],
buffer_memory_barriers: &[vk::BufferMemoryBarrier],
image_memory_barriers: &[vk::ImageMemoryBarrier],
) {
self.fp_v1_0().cmd_wait_events(
command_buffer,
events.len() as _,
events.as_ptr(),
src_stage_mask,
dst_stage_mask,
memory_barriers.len() as _,
memory_barriers.as_ptr(),
buffer_memory_barriers.len() as _,
buffer_memory_barriers.as_ptr(),
image_memory_barriers.len() as _,
image_memory_barriers.as_ptr(),
);
}
unsafe fn destroy_fence(
&self,
fence: vk::Fence,
@ -278,6 +353,15 @@ pub trait DeviceV1_0 {
.destroy_fence(self.handle(), fence, allocation_callbacks.as_raw_ptr());
}
unsafe fn destroy_event(
&self,
event: vk::Event,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) {
self.fp_v1_0()
.destroy_event(self.handle(), event, allocation_callbacks.as_raw_ptr());
}
unsafe fn destroy_image(
&self,
image: vk::Image,
@ -721,11 +805,9 @@ pub trait DeviceV1_0 {
}
unsafe fn reset_fences(&self, fences: &[vk::Fence]) -> VkResult<()> {
let err_code = self.fp_v1_0().reset_fences(
self.handle(),
fences.len() as u32,
fences.as_ptr(),
);
let err_code =
self.fp_v1_0()
.reset_fences(self.handle(), fences.len() as u32, fences.as_ptr());
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
@ -1291,6 +1373,34 @@ pub trait DeviceV1_0 {
}
}
unsafe fn get_pipeline_cache_data(
&self,
pipeline_cache: vk::PipelineCache,
) -> VkResult<Vec<u8>> {
let mut data_size: usize = 0;
let err_code = self.fp_v1_0().get_pipeline_cache_data(
self.handle(),
pipeline_cache,
&mut data_size,
ptr::null_mut(),
);
if err_code != vk::Result::SUCCESS {
return Err(err_code);
};
let mut data: Vec<u8> = Vec::with_capacity(data_size);
let err_code = self.fp_v1_0().get_pipeline_cache_data(
self.handle(),
pipeline_cache,
&mut data_size,
data.as_mut_ptr() as _,
);
data.set_len(data_size);
match err_code {
vk::Result::SUCCESS => Ok(data),
_ => Err(err_code),
}
}
unsafe fn map_memory(
&self,
memory: vk::DeviceMemory,
@ -1357,11 +1467,7 @@ pub trait DeviceV1_0 {
}
}
unsafe fn get_device_queue(
&self,
queue_family_index: u32,
queue_index: u32,
) -> vk::Queue {
unsafe fn get_device_queue(&self, queue_family_index: u32, queue_index: u32) -> vk::Queue {
let mut queue = mem::uninitialized();
self.fp_v1_0()
.get_device_queue(self.handle(), queue_family_index, queue_index, &mut queue);
@ -1413,11 +1519,11 @@ pub trait DeviceV1_0 {
unsafe fn begin_command_buffer(
&self,
command_buffer: vk::CommandBuffer,
create_info: &vk::CommandBufferBeginInfo,
begin_info: &vk::CommandBufferBeginInfo,
) -> VkResult<()> {
let err_code = self
.fp_v1_0()
.begin_command_buffer(command_buffer, create_info);
.begin_command_buffer(command_buffer, begin_info);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
@ -1473,12 +1579,9 @@ pub trait DeviceV1_0 {
submits: &[vk::SubmitInfo],
fence: vk::Fence,
) -> VkResult<()> {
let err_code = self.fp_v1_0().queue_submit(
queue,
submits.len() as u32,
submits.as_ptr(),
fence,
);
let err_code =
self.fp_v1_0()
.queue_submit(queue, submits.len() as u32, submits.as_ptr(), fence);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
@ -1725,10 +1828,7 @@ pub struct Device {
device_fn_1_1: vk::DeviceFnV1_1,
}
impl Device {
pub unsafe fn load(
instance_fn: &vk::InstanceFnV1_0,
device: vk::Device,
) -> Self {
pub unsafe fn load(instance_fn: &vk::InstanceFnV1_0, device: vk::Device) -> Self {
let device_fn_1_0 = vk::DeviceFnV1_0::load(|name| {
mem::transmute(instance_fn.get_device_proc_addr(device, name.as_ptr()))
});

View file

@ -15,25 +15,17 @@ use RawPtr;
#[cfg(windows)]
const LIB_PATH: &'static str = "vulkan-1.dll";
#[cfg(
all(
#[cfg(all(
unix,
not(
any(
target_os = "macos",
target_os = "ios",
target_os = "android"
)
)
)
)]
not(any(target_os = "macos", target_os = "ios", target_os = "android"))
))]
const LIB_PATH: &'static str = "libvulkan.so.1";
#[cfg(target_os = "android")]
const LIB_PATH: &'static str = "libvulkan.so";
#[cfg(any(target_os = "macos", target_os = "ios"))]
const LIB_PATH: &'static str = "libMoltenVK.dylib";
const LIB_PATH: &'static str = "libvulkan.dylib";
lazy_static! {
static ref VK_LIB: Result<DynamicLibrary, String> =
@ -73,7 +65,7 @@ impl Error for InstanceError {
fn cause(&self) -> Option<&Error> {
if let &InstanceError::VkError(ref err) = self {
return err.cause();
return err.source();
}
None
}

View file

@ -11,10 +11,7 @@ pub struct DebugMarker {
}
impl DebugMarker {
pub fn new<I: InstanceV1_0, D: DeviceV1_0>(
instance: &I,
device: &D,
) -> DebugMarker {
pub fn new<I: InstanceV1_0, D: DeviceV1_0>(instance: &I, device: &D) -> DebugMarker {
let debug_marker_fn = vk::ExtDebugMarkerFn::load(|name| unsafe {
mem::transmute(instance.get_device_proc_addr(device.handle(), name.as_ptr()))
});
@ -27,7 +24,7 @@ impl DebugMarker {
CStr::from_bytes_with_nul(b"VK_EXT_debug_marker\0").expect("Wrong extension string")
}
pub unsafe fn debug_marker_set_object_name_ext(
pub unsafe fn debug_marker_set_object_name(
&self,
device: vk::Device,
name_info: &vk::DebugMarkerObjectNameInfoEXT,
@ -41,7 +38,7 @@ impl DebugMarker {
}
}
pub unsafe fn cmd_debug_marker_begin_ext(
pub unsafe fn cmd_debug_marker_begin(
&self,
command_buffer: vk::CommandBuffer,
marker_info: &vk::DebugMarkerMarkerInfoEXT,
@ -50,12 +47,12 @@ impl DebugMarker {
.cmd_debug_marker_begin_ext(command_buffer, marker_info);
}
pub unsafe fn cmd_debug_marker_end_ext(&self, command_buffer: vk::CommandBuffer) {
pub unsafe fn cmd_debug_marker_end(&self, command_buffer: vk::CommandBuffer) {
self.debug_marker_fn
.cmd_debug_marker_end_ext(command_buffer);
}
pub unsafe fn cmd_debug_marker_insert_ext(
pub unsafe fn cmd_debug_marker_insert(
&self,
command_buffer: vk::CommandBuffer,
marker_info: &vk::DebugMarkerMarkerInfoEXT,

View file

@ -13,10 +13,7 @@ pub struct DebugReport {
}
impl DebugReport {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> DebugReport {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> DebugReport {
let debug_report_fn = vk::ExtDebugReportFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
@ -30,7 +27,7 @@ impl DebugReport {
CStr::from_bytes_with_nul(b"VK_EXT_debug_report\0").expect("Wrong extension string")
}
pub unsafe fn destroy_debug_report_callback_ext(
pub unsafe fn destroy_debug_report_callback(
&self,
debug: vk::DebugReportCallbackEXT,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
@ -42,7 +39,7 @@ impl DebugReport {
);
}
pub unsafe fn create_debug_report_callback_ext(
pub unsafe fn create_debug_report_callback(
&self,
create_info: &vk::DebugReportCallbackCreateInfoEXT,
allocation_callbacks: Option<&vk::AllocationCallbacks>,

View file

@ -12,10 +12,7 @@ pub struct DebugUtils {
}
impl DebugUtils {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> DebugUtils {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> DebugUtils {
let debug_utils_fn = vk::ExtDebugUtilsFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
@ -29,31 +26,35 @@ impl DebugUtils {
CStr::from_bytes_with_nul(b"VK_EXT_debug_utils\0").expect("Wrong extension string")
}
pub unsafe fn debug_utils_set_object_name_ext(
pub unsafe fn debug_utils_set_object_name(
&self,
device: vk::Device,
name_info: &vk::DebugUtilsObjectNameInfoEXT,
) -> VkResult<()> {
let err_code = self.debug_utils_fn.set_debug_utils_object_name_ext(device, name_info);
let err_code = self
.debug_utils_fn
.set_debug_utils_object_name_ext(device, name_info);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
}
}
pub unsafe fn debug_utils_set_object_tag_ext(
pub unsafe fn debug_utils_set_object_tag(
&self,
device: vk::Device,
tag_info: &vk::DebugUtilsObjectTagInfoEXT,
) -> VkResult<()> {
let err_code = self.debug_utils_fn.set_debug_utils_object_tag_ext(device, tag_info);
let err_code = self
.debug_utils_fn
.set_debug_utils_object_tag_ext(device, tag_info);
match err_code {
vk::Result::SUCCESS => Ok(()),
_ => Err(err_code),
}
}
pub unsafe fn cmd_begin_debug_utils_label_ext(
pub unsafe fn cmd_begin_debug_utils_label(
&self,
command_buffer: vk::CommandBuffer,
label: &vk::DebugUtilsLabelEXT,
@ -62,12 +63,12 @@ impl DebugUtils {
.cmd_begin_debug_utils_label_ext(command_buffer, label);
}
pub unsafe fn cmd_end_debug_utils_label_ext(&self, command_buffer: vk::CommandBuffer) {
pub unsafe fn cmd_end_debug_utils_label(&self, command_buffer: vk::CommandBuffer) {
self.debug_utils_fn
.cmd_end_debug_utils_label_ext(command_buffer);
}
pub unsafe fn cmd_insert_debug_utils_label_ext(
pub unsafe fn cmd_insert_debug_utils_label(
&self,
command_buffer: vk::CommandBuffer,
label: &vk::DebugUtilsLabelEXT,
@ -76,7 +77,7 @@ impl DebugUtils {
.cmd_insert_debug_utils_label_ext(command_buffer, label);
}
pub unsafe fn queue_begin_debug_utils_label_ext(
pub unsafe fn queue_begin_debug_utils_label(
&self,
queue: vk::Queue,
label: &vk::DebugUtilsLabelEXT,
@ -85,11 +86,11 @@ impl DebugUtils {
.queue_begin_debug_utils_label_ext(queue, label);
}
pub unsafe fn queue_end_debug_utils_label_ext(&self, queue: vk::Queue) {
pub unsafe fn queue_end_debug_utils_label(&self, queue: vk::Queue) {
self.debug_utils_fn.queue_end_debug_utils_label_ext(queue);
}
pub unsafe fn queue_insert_debug_utils_label_ext(
pub unsafe fn queue_insert_debug_utils_label(
&self,
queue: vk::Queue,
label: &vk::DebugUtilsLabelEXT,
@ -98,7 +99,7 @@ impl DebugUtils {
.queue_insert_debug_utils_label_ext(queue, label);
}
pub unsafe fn create_debug_utils_messenger_ext(
pub unsafe fn create_debug_utils_messenger(
&self,
create_info: &vk::DebugUtilsMessengerCreateInfoEXT,
allocator: Option<&vk::AllocationCallbacks>,
@ -116,7 +117,7 @@ impl DebugUtils {
}
}
pub unsafe fn destroy_debug_utils_messenger_ext(
pub unsafe fn destroy_debug_utils_messenger(
&self,
messenger: vk::DebugUtilsMessengerEXT,
allocator: Option<&vk::AllocationCallbacks>,
@ -128,7 +129,7 @@ impl DebugUtils {
);
}
pub unsafe fn submit_debug_utils_message_ext(
pub unsafe fn submit_debug_utils_message(
&self,
instance: vk::Instance,
message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,

View file

@ -0,0 +1,7 @@
pub use self::debug_marker::DebugMarker;
pub use self::debug_report::DebugReport;
pub use self::debug_utils::DebugUtils;
mod debug_marker;
mod debug_report;
mod debug_utils;

View file

@ -13,10 +13,7 @@ pub struct AndroidSurface {
}
impl AndroidSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> AndroidSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> AndroidSurface {
let surface_fn = vk::KhrAndroidSurfaceFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
@ -30,7 +27,7 @@ impl AndroidSurface {
CStr::from_bytes_with_nul(b"VK_KHR_android_surface\0").expect("Wrong extension string")
}
pub unsafe fn create_android_surface_khr(
pub unsafe fn create_android_surface(
&self,
create_info: &vk::AndroidSurfaceCreateInfoKHR,
allocation_callbacks: Option<&vk::AllocationCallbacks>,

View file

@ -13,10 +13,7 @@ pub struct DisplaySwapchain {
}
impl DisplaySwapchain {
pub fn new<I: InstanceV1_0, D: DeviceV1_0>(
instance: &I,
device: &D,
) -> DisplaySwapchain {
pub fn new<I: InstanceV1_0, D: DeviceV1_0>(instance: &I, device: &D) -> DisplaySwapchain {
let swapchain_fn = vk::KhrDisplaySwapchainFn::load(|name| unsafe {
mem::transmute(instance.get_device_proc_addr(device.handle(), name.as_ptr()))
});
@ -30,7 +27,7 @@ impl DisplaySwapchain {
CStr::from_bytes_with_nul(b"VK_KHR_display_swapchain\0").expect("Wrong extension string")
}
pub unsafe fn create_shared_swapchains_khr(
pub unsafe fn create_shared_swapchains(
&self,
create_infos: &[vk::SwapchainCreateInfoKHR],
allocation_callbacks: Option<&vk::AllocationCallbacks>,

View file

@ -0,0 +1,17 @@
pub use self::android_surface::AndroidSurface;
pub use self::display_swapchain::DisplaySwapchain;
pub use self::surface::Surface;
pub use self::swapchain::Swapchain;
pub use self::wayland_surface::WaylandSurface;
pub use self::win32_surface::Win32Surface;
pub use self::xcb_surface::XcbSurface;
pub use self::xlib_surface::XlibSurface;
mod android_surface;
mod display_swapchain;
mod surface;
mod swapchain;
mod wayland_surface;
mod win32_surface;
mod xcb_surface;
mod xlib_surface;

View file

@ -14,10 +14,7 @@ pub struct Surface {
}
impl Surface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> Surface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> Surface {
let surface_fn = vk::KhrSurfaceFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
@ -31,7 +28,7 @@ impl Surface {
CStr::from_bytes_with_nul(b"VK_KHR_surface\0").expect("Wrong extension string")
}
pub unsafe fn get_physical_device_surface_support_khr(
pub unsafe fn get_physical_device_surface_support(
&self,
physical_device: vk::PhysicalDevice,
queue_index: u32,
@ -47,7 +44,7 @@ impl Surface {
b > 0
}
pub unsafe fn get_physical_device_surface_present_modes_khr(
pub unsafe fn get_physical_device_surface_present_modes(
&self,
physical_device: vk::PhysicalDevice,
surface: vk::SurfaceKHR,
@ -76,7 +73,7 @@ impl Surface {
}
}
pub unsafe fn get_physical_device_surface_capabilities_khr(
pub unsafe fn get_physical_device_surface_capabilities(
&self,
physical_device: vk::PhysicalDevice,
surface: vk::SurfaceKHR,
@ -95,7 +92,7 @@ impl Surface {
}
}
pub unsafe fn get_physical_device_surface_formats_khr(
pub unsafe fn get_physical_device_surface_formats(
&self,
physical_device: vk::PhysicalDevice,
surface: vk::SurfaceKHR,
@ -121,7 +118,7 @@ impl Surface {
}
}
pub unsafe fn destroy_surface_khr(
pub unsafe fn destroy_surface(
&self,
surface: vk::SurfaceKHR,
allocation_callbacks: Option<&vk::AllocationCallbacks>,

View file

@ -14,10 +14,7 @@ pub struct Swapchain {
}
impl Swapchain {
pub fn new<I: InstanceV1_0, D: DeviceV1_0>(
instance: &I,
device: &D,
) -> Swapchain {
pub fn new<I: InstanceV1_0, D: DeviceV1_0>(instance: &I, device: &D) -> Swapchain {
let swapchain_fn = vk::KhrSwapchainFn::load(|name| unsafe {
mem::transmute(instance.get_device_proc_addr(device.handle(), name.as_ptr()))
});
@ -31,7 +28,7 @@ impl Swapchain {
CStr::from_bytes_with_nul(b"VK_KHR_swapchain\0").expect("Wrong extension string")
}
pub unsafe fn destroy_swapchain_khr(
pub unsafe fn destroy_swapchain(
&self,
swapchain: vk::SwapchainKHR,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
@ -44,7 +41,7 @@ impl Swapchain {
}
/// On success, returns the next image's index and whether the swapchain is suboptimal for the surface.
pub unsafe fn acquire_next_image_khr(
pub unsafe fn acquire_next_image(
&self,
swapchain: vk::SwapchainKHR,
timeout: u64,
@ -67,7 +64,7 @@ impl Swapchain {
}
}
pub unsafe fn create_swapchain_khr(
pub unsafe fn create_swapchain(
&self,
create_info: &vk::SwapchainCreateInfoKHR,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
@ -86,7 +83,7 @@ impl Swapchain {
}
/// On success, returns whether the swapchain is suboptimal for the surface.
pub unsafe fn queue_present_khr(
pub unsafe fn queue_present(
&self,
queue: vk::Queue,
create_info: &vk::PresentInfoKHR,
@ -99,7 +96,7 @@ impl Swapchain {
}
}
pub unsafe fn get_swapchain_images_khr(
pub unsafe fn get_swapchain_images(
&self,
swapchain: vk::SwapchainKHR,
) -> VkResult<Vec<vk::Image>> {

View file

@ -13,10 +13,7 @@ pub struct WaylandSurface {
}
impl WaylandSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> WaylandSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> WaylandSurface {
let surface_fn = vk::KhrWaylandSurfaceFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
@ -30,7 +27,7 @@ impl WaylandSurface {
CStr::from_bytes_with_nul(b"VK_KHR_wayland_surface\0").expect("Wrong extension string")
}
pub unsafe fn create_wayland_surface_khr(
pub unsafe fn create_wayland_surface(
&self,
create_info: &vk::WaylandSurfaceCreateInfoKHR,
allocation_callbacks: Option<&vk::AllocationCallbacks>,

View file

@ -13,10 +13,7 @@ pub struct Win32Surface {
}
impl Win32Surface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> Win32Surface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> Win32Surface {
let surface_fn = vk::KhrWin32SurfaceFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
@ -30,7 +27,7 @@ impl Win32Surface {
CStr::from_bytes_with_nul(b"VK_KHR_win32_surface\0").expect("Wrong extension string")
}
pub unsafe fn create_win32_surface_khr(
pub unsafe fn create_win32_surface(
&self,
create_info: &vk::Win32SurfaceCreateInfoKHR,
allocation_callbacks: Option<&vk::AllocationCallbacks>,

View file

@ -13,10 +13,7 @@ pub struct XcbSurface {
}
impl XcbSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> XcbSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> XcbSurface {
let surface_fn = vk::KhrXcbSurfaceFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
@ -30,7 +27,7 @@ impl XcbSurface {
CStr::from_bytes_with_nul(b"VK_KHR_xcb_surface\0").expect("Wrong extension string")
}
pub unsafe fn create_xcb_surface_khr(
pub unsafe fn create_xcb_surface(
&self,
create_info: &vk::XcbSurfaceCreateInfoKHR,
allocation_callbacks: Option<&vk::AllocationCallbacks>,

View file

@ -13,10 +13,7 @@ pub struct XlibSurface {
}
impl XlibSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> XlibSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> XlibSurface {
let surface_fn = vk::KhrXlibSurfaceFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
@ -30,7 +27,7 @@ impl XlibSurface {
CStr::from_bytes_with_nul(b"VK_KHR_xlib_surface\0").expect("Wrong extension string")
}
pub unsafe fn create_xlib_surface_khr(
pub unsafe fn create_xlib_surface(
&self,
create_info: &vk::XlibSurfaceCreateInfoKHR,
allocation_callbacks: Option<&vk::AllocationCallbacks>,

View file

@ -1,27 +1,4 @@
pub use self::android_surface::AndroidSurface;
pub use self::debug_marker::DebugMarker;
pub use self::debug_report::DebugReport;
pub use self::debug_utils::DebugUtils;
pub use self::display_swapchain::DisplaySwapchain;
pub use self::ios_surface::IOSSurface;
pub use self::macos_surface::MacOSSurface;
pub use self::surface::Surface;
pub use self::swapchain::Swapchain;
pub use self::wayland_surface::WaylandSurface;
pub use self::win32_surface::Win32Surface;
pub use self::xcb_surface::XcbSurface;
pub use self::xlib_surface::XlibSurface;
mod android_surface;
mod debug_marker;
mod debug_report;
mod debug_utils;
mod display_swapchain;
mod ios_surface;
mod macos_surface;
mod surface;
mod swapchain;
mod wayland_surface;
mod win32_surface;
mod xcb_surface;
mod xlib_surface;
pub mod ext;
pub mod khr;
pub mod mvk;
pub mod nv;

View file

@ -13,10 +13,7 @@ pub struct IOSSurface {
}
impl IOSSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> IOSSurface{
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> IOSSurface {
let surface_fn = vk::MvkIosSurfaceFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});

View file

@ -13,10 +13,7 @@ pub struct MacOSSurface {
}
impl MacOSSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(
entry: &E,
instance: &I,
) -> MacOSSurface {
pub fn new<E: EntryV1_0, I: InstanceV1_0>(entry: &E, instance: &I) -> MacOSSurface {
let surface_fn = vk::MvkMacosSurfaceFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});

View file

@ -0,0 +1,5 @@
pub use self::ios_surface::IOSSurface;
pub use self::macos_surface::MacOSSurface;
mod ios_surface;
mod macos_surface;

View file

@ -0,0 +1,67 @@
#![allow(dead_code)]
use std::ffi::CStr;
use std::mem;
use version::{DeviceV1_0, InstanceV1_0};
use vk;
#[derive(Clone)]
pub struct MeshShader {
mesh_shader_fn: vk::NvMeshShaderFn,
}
impl MeshShader {
pub fn new<I: InstanceV1_0, D: DeviceV1_0>(instance: &I, device: &D) -> MeshShader {
let mesh_shader_fn = vk::NvMeshShaderFn::load(|name| unsafe {
mem::transmute(instance.get_device_proc_addr(device.handle(), name.as_ptr()))
});
MeshShader { mesh_shader_fn }
}
pub unsafe fn cmd_draw_mesh_tasks(
&self,
command_buffer: vk::CommandBuffer,
task_count: u32,
first_task: u32,
) {
self.mesh_shader_fn
.cmd_draw_mesh_tasks_nv(command_buffer, task_count, first_task);
}
pub unsafe fn cmd_draw_mesh_tasks_indirect(
&self,
command_buffer: vk::CommandBuffer,
buffer: vk::Buffer,
offset: vk::DeviceSize,
draw_count: u32,
stride: u32,
) {
self.mesh_shader_fn.cmd_draw_mesh_tasks_indirect_nv(
command_buffer,
buffer,
offset,
draw_count,
stride,
);
}
pub unsafe fn cmd_draw_mesh_tasks_indirect_count(
&self,
command_buffer: vk::CommandBuffer,
buffer: vk::Buffer,
offset: vk::DeviceSize,
count_buffer: vk::Buffer,
count_buffer_offset: vk::DeviceSize,
max_draw_count: u32,
stride: u32,
) {
self.mesh_shader_fn.cmd_draw_mesh_tasks_indirect_count_nv(
command_buffer,
buffer,
offset,
count_buffer,
count_buffer_offset,
max_draw_count,
stride,
);
}
pub fn name() -> &'static CStr {
CStr::from_bytes_with_nul(b"VK_NV_mesh_shader\0").expect("Wrong extension string")
}
}

View file

@ -0,0 +1,3 @@
pub use self::mesh_shader::MeshShader;
mod mesh_shader;

View file

@ -1,6 +1,7 @@
#[macro_use]
extern crate lazy_static;
extern crate shared_library;
pub use device::Device;
pub use entry::{Entry, InstanceError, LoadingError};
pub use instance::Instance;

View file

@ -2,6 +2,7 @@ use std::iter::Iterator;
use std::marker::PhantomData;
use std::mem::size_of;
use std::os::raw::c_void;
use std::{io, slice};
use vk;
/// `Align` handles dynamic alignment. The is useful for dynamic uniform buffers where
@ -46,11 +47,7 @@ fn calc_padding(adr: vk::DeviceSize, align: vk::DeviceSize) -> vk::DeviceSize {
}
impl<T> Align<T> {
pub unsafe fn new(
ptr: *mut c_void,
alignment: vk::DeviceSize,
size: vk::DeviceSize,
) -> Self {
pub unsafe fn new(ptr: *mut c_void, alignment: vk::DeviceSize, size: vk::DeviceSize) -> Self {
let padding = calc_padding(size_of::<T>() as vk::DeviceSize, alignment);
let elem_size = size_of::<T>() as vk::DeviceSize + padding;
assert!(calc_padding(size, alignment) == 0, "size must be aligned");
@ -84,3 +81,58 @@ impl<'a, T: Copy + 'a> Iterator for AlignIter<'a, T> {
}
}
}
/// Decode SPIR-V from bytes.
///
/// This function handles SPIR-V of arbitrary endianness gracefully, and returns correctly aligned
/// storage.
///
/// # Examples
/// ```no_run
/// // Decode SPIR-V from a file
/// let mut file = std::fs::File::open("/path/to/shader.spv").unwrap();
/// let words = ash::util::read_spv(&mut file).unwrap();
/// ```
/// ```
/// // Decode SPIR-V from memory
/// const SPIRV: &[u8] = &[
/// // ...
/// # 0x03, 0x02, 0x23, 0x07,
/// ];
/// let words = ash::util::read_spv(&mut std::io::Cursor::new(&SPIRV[..])).unwrap();
/// ```
pub fn read_spv<R: io::Read + io::Seek>(x: &mut R) -> io::Result<Vec<u32>> {
let size = x.seek(io::SeekFrom::End(0))?;
if size % 4 != 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"input length not divisible by 4",
));
}
if size > usize::max_value() as u64 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "input too long"));
}
let words = (size / 4) as usize;
let mut result = Vec::<u32>::with_capacity(words);
x.seek(io::SeekFrom::Start(0))?;
unsafe {
x.read_exact(slice::from_raw_parts_mut(
result.as_mut_ptr() as *mut u8,
words * 4,
))?;
result.set_len(words);
}
const MAGIC_NUMBER: u32 = 0x07230203;
if result.len() > 0 && result[0] == MAGIC_NUMBER.swap_bytes() {
for word in &mut result {
*word = word.swap_bytes();
}
}
if result.len() == 0 || result[0] != MAGIC_NUMBER {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"input missing SPIR-V magic number",
));
}
Ok(result)
}

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,11 @@ use ash::vk;
#[test]
fn display_flags() {
assert_eq!((vk::AccessFlags::INDIRECT_COMMAND_READ | vk::AccessFlags::VERTEX_ATTRIBUTE_READ).to_string(), "INDIRECT_COMMAND_READ | VERTEX_ATTRIBUTE_READ");
assert_eq!(
(vk::AccessFlags::INDIRECT_COMMAND_READ | vk::AccessFlags::VERTEX_ATTRIBUTE_READ)
.to_string(),
"INDIRECT_COMMAND_READ | VERTEX_ATTRIBUTE_READ"
);
}
#[test]

6
bors.toml Normal file
View file

@ -0,0 +1,6 @@
status = [
"continuous-integration/travis-ci/push",
"continuous-integration/appveyor/branch"
]
timeout_sec = 18000 # 5 hours

View file

@ -5,11 +5,9 @@ extern crate image;
use std::default::Default;
use std::ffi::CString;
use std::fs::File;
use std::io::Read;
use std::mem::{self, align_of};
use std::os::raw::c_void;
use std::path::Path;
use std::ptr;
use ash::util::*;
use ash::vk;
@ -33,91 +31,70 @@ pub struct Vector3 {
fn main() {
unsafe {
let base = ExampleBase::new(1920, 1080);
let renderpass_attachments = [
vk::AttachmentDescription {
format: base.surface_format.format,
flags: vk::AttachmentDescriptionFlags::empty(),
samples: vk::SampleCountFlags::TYPE_1,
load_op: vk::AttachmentLoadOp::CLEAR,
store_op: vk::AttachmentStoreOp::STORE,
stencil_load_op: vk::AttachmentLoadOp::DONT_CARE,
stencil_store_op: vk::AttachmentStoreOp::DONT_CARE,
initial_layout: vk::ImageLayout::UNDEFINED,
final_layout: vk::ImageLayout::PRESENT_SRC_KHR,
..Default::default()
},
vk::AttachmentDescription {
format: vk::Format::D16_UNORM,
flags: vk::AttachmentDescriptionFlags::empty(),
samples: vk::SampleCountFlags::TYPE_1,
load_op: vk::AttachmentLoadOp::CLEAR,
store_op: vk::AttachmentStoreOp::DONT_CARE,
stencil_load_op: vk::AttachmentLoadOp::DONT_CARE,
stencil_store_op: vk::AttachmentStoreOp::DONT_CARE,
initial_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
final_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
..Default::default()
},
];
let color_attachment_ref = vk::AttachmentReference {
let color_attachment_refs = [vk::AttachmentReference {
attachment: 0,
layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
};
}];
let depth_attachment_ref = vk::AttachmentReference {
attachment: 1,
layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
};
let dependency = vk::SubpassDependency {
dependency_flags: Default::default(),
let dependencies = [vk::SubpassDependency {
src_subpass: vk::SUBPASS_EXTERNAL,
dst_subpass: Default::default(),
src_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
src_access_mask: Default::default(),
dst_access_mask: vk::AccessFlags::COLOR_ATTACHMENT_READ
| vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
dst_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
};
let subpass = vk::SubpassDescription {
color_attachment_count: 1,
p_color_attachments: &color_attachment_ref,
p_depth_stencil_attachment: &depth_attachment_ref,
flags: Default::default(),
pipeline_bind_point: vk::PipelineBindPoint::GRAPHICS,
input_attachment_count: 0,
p_input_attachments: ptr::null(),
p_resolve_attachments: ptr::null(),
preserve_attachment_count: 0,
p_preserve_attachments: ptr::null(),
};
let renderpass_create_info = vk::RenderPassCreateInfo {
s_type: vk::StructureType::RENDER_PASS_CREATE_INFO,
flags: Default::default(),
p_next: ptr::null(),
attachment_count: renderpass_attachments.len() as u32,
p_attachments: renderpass_attachments.as_ptr(),
subpass_count: 1,
p_subpasses: &subpass,
dependency_count: 1,
p_dependencies: &dependency,
};
..Default::default()
}];
let subpasses = [vk::SubpassDescription::builder()
.color_attachments(&color_attachment_refs)
.depth_stencil_attachment(&depth_attachment_ref)
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.build()];
let renderpass_create_info = vk::RenderPassCreateInfo::builder()
.attachments(&renderpass_attachments)
.subpasses(&subpasses)
.dependencies(&dependencies);
let renderpass = base
.device
.create_render_pass(&renderpass_create_info, None)
.unwrap();
let framebuffers: Vec<vk::Framebuffer> = base
.present_image_views
.iter()
.map(|&present_image_view| {
let framebuffer_attachments = [present_image_view, base.depth_image_view];
let frame_buffer_create_info = vk::FramebufferCreateInfo {
s_type: vk::StructureType::FRAMEBUFFER_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
render_pass: renderpass,
attachment_count: framebuffer_attachments.len() as u32,
p_attachments: framebuffer_attachments.as_ptr(),
width: base.surface_resolution.width,
height: base.surface_resolution.height,
layers: 1,
};
let frame_buffer_create_info = vk::FramebufferCreateInfo::builder()
.render_pass(renderpass)
.attachments(&framebuffer_attachments)
.width(base.surface_resolution.width)
.height(base.surface_resolution.height)
.layers(1);
base.device
.create_framebuffer(&frame_buffer_create_info, None)
.unwrap()
@ -125,28 +102,23 @@ fn main() {
.collect();
let index_buffer_data = [0u32, 1, 2, 2, 3, 0];
let index_buffer_info = vk::BufferCreateInfo {
s_type: vk::StructureType::BUFFER_CREATE_INFO,
p_next: ptr::null(),
flags: vk::BufferCreateFlags::empty(),
size: std::mem::size_of_val(&index_buffer_data) as u64,
usage: vk::BufferUsageFlags::INDEX_BUFFER,
sharing_mode: vk::SharingMode::EXCLUSIVE,
queue_family_index_count: 0,
p_queue_family_indices: ptr::null(),
..Default::default()
};
let index_buffer = base.device.create_buffer(&index_buffer_info, None).unwrap();
let index_buffer_memory_req = base.device.get_buffer_memory_requirements(index_buffer);
let index_buffer_memory_index =
find_memorytype_index(
let index_buffer_memory_index = find_memorytype_index(
&index_buffer_memory_req,
&base.device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE,
).expect("Unable to find suitable memorytype for the index buffer.");
)
.expect("Unable to find suitable memorytype for the index buffer.");
let index_allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
p_next: ptr::null(),
allocation_size: index_buffer_memory_req.size,
memory_type_index: index_buffer_memory_index,
..Default::default()
};
let index_buffer_memory = base
.device
@ -191,14 +163,10 @@ fn main() {
},
];
let vertex_input_buffer_info = vk::BufferCreateInfo {
s_type: vk::StructureType::BUFFER_CREATE_INFO,
p_next: ptr::null(),
flags: vk::BufferCreateFlags::empty(),
size: std::mem::size_of_val(&vertices) as u64,
usage: vk::BufferUsageFlags::VERTEX_BUFFER,
sharing_mode: vk::SharingMode::EXCLUSIVE,
queue_family_index_count: 0,
p_queue_family_indices: ptr::null(),
..Default::default()
};
let vertex_input_buffer = base
.device
@ -207,23 +175,23 @@ fn main() {
let vertex_input_buffer_memory_req = base
.device
.get_buffer_memory_requirements(vertex_input_buffer);
let vertex_input_buffer_memory_index =
find_memorytype_index(
let vertex_input_buffer_memory_index = find_memorytype_index(
&vertex_input_buffer_memory_req,
&base.device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE,
).expect("Unable to find suitable memorytype for the vertex buffer.");
)
.expect("Unable to find suitable memorytype for the vertex buffer.");
let vertex_buffer_allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
p_next: ptr::null(),
allocation_size: vertex_input_buffer_memory_req.size,
memory_type_index: vertex_input_buffer_memory_index,
..Default::default()
};
let vertex_input_buffer_memory = base
.device
.allocate_memory(&vertex_buffer_allocate_info, None)
.unwrap();
let vert_ptr = base
.device
.map_memory(
@ -251,14 +219,10 @@ fn main() {
_pad: 0.0,
};
let uniform_color_buffer_info = vk::BufferCreateInfo {
s_type: vk::StructureType::BUFFER_CREATE_INFO,
p_next: ptr::null(),
flags: vk::BufferCreateFlags::empty(),
size: std::mem::size_of_val(&uniform_color_buffer_data) as u64,
usage: vk::BufferUsageFlags::UNIFORM_BUFFER,
sharing_mode: vk::SharingMode::EXCLUSIVE,
queue_family_index_count: 0,
p_queue_family_indices: ptr::null(),
..Default::default()
};
let uniform_color_buffer = base
.device
@ -267,18 +231,17 @@ fn main() {
let uniform_color_buffer_memory_req = base
.device
.get_buffer_memory_requirements(uniform_color_buffer);
let uniform_color_buffer_memory_index =
find_memorytype_index(
let uniform_color_buffer_memory_index = find_memorytype_index(
&uniform_color_buffer_memory_req,
&base.device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE,
).expect("Unable to find suitable memorytype for the vertex buffer.");
)
.expect("Unable to find suitable memorytype for the vertex buffer.");
let uniform_color_buffer_allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
p_next: ptr::null(),
allocation_size: uniform_color_buffer_memory_req.size,
memory_type_index: uniform_color_buffer_memory_index,
..Default::default()
};
let uniform_color_buffer_memory = base
.device
@ -308,29 +271,24 @@ fn main() {
let image_dimensions = image.dimensions();
let image_data = image.into_raw();
let image_buffer_info = vk::BufferCreateInfo {
s_type: vk::StructureType::BUFFER_CREATE_INFO,
p_next: ptr::null(),
flags: vk::BufferCreateFlags::empty(),
size: (std::mem::size_of::<u8>() * image_data.len()) as u64,
usage: vk::BufferUsageFlags::TRANSFER_SRC,
sharing_mode: vk::SharingMode::EXCLUSIVE,
queue_family_index_count: 0,
p_queue_family_indices: ptr::null(),
..Default::default()
};
let image_buffer = base.device.create_buffer(&image_buffer_info, None).unwrap();
let image_buffer_memory_req = base.device.get_buffer_memory_requirements(image_buffer);
let image_buffer_memory_index =
find_memorytype_index(
let image_buffer_memory_index = find_memorytype_index(
&image_buffer_memory_req,
&base.device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE,
).expect("Unable to find suitable memorytype for the vertex buffer.");
)
.expect("Unable to find suitable memorytype for the vertex buffer.");
let image_buffer_allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
p_next: ptr::null(),
allocation_size: image_buffer_memory_req.size,
memory_type_index: image_buffer_memory_index,
..Default::default()
};
let image_buffer_memory = base
.device
@ -357,9 +315,6 @@ fn main() {
.unwrap();
let texture_create_info = vk::ImageCreateInfo {
s_type: vk::StructureType::IMAGE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
image_type: vk::ImageType::TYPE_2D,
format: vk::Format::R8G8B8A8_UNORM,
extent: vk::Extent3D {
@ -373,27 +328,24 @@ fn main() {
tiling: vk::ImageTiling::OPTIMAL,
usage: vk::ImageUsageFlags::TRANSFER_DST | vk::ImageUsageFlags::SAMPLED,
sharing_mode: vk::SharingMode::EXCLUSIVE,
queue_family_index_count: 0,
p_queue_family_indices: ptr::null(),
initial_layout: vk::ImageLayout::UNDEFINED,
..Default::default()
};
let texture_image = base
.device
.create_image(&texture_create_info, None)
.unwrap();
let texture_memory_req = base.device.get_image_memory_requirements(texture_image);
let texture_memory_index =
find_memorytype_index(
let texture_memory_index = find_memorytype_index(
&texture_memory_req,
&base.device_memory_properties,
vk::MemoryPropertyFlags::DEVICE_LOCAL,
).expect("Unable to find suitable memory index for depth image.");
)
.expect("Unable to find suitable memory index for depth image.");
let texture_allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
p_next: ptr::null(),
allocation_size: texture_memory_req.size,
memory_type_index: texture_memory_index,
..Default::default()
};
let texture_memory = base
.device
@ -407,27 +359,21 @@ fn main() {
&base.device,
base.setup_command_buffer,
base.present_queue,
&[vk::PipelineStageFlags::TOP_OF_PIPE],
&[],
&[],
&[],
|device, texture_command_buffer| {
let texture_barrier = vk::ImageMemoryBarrier {
s_type: vk::StructureType::IMAGE_MEMORY_BARRIER,
p_next: ptr::null(),
src_access_mask: Default::default(),
dst_access_mask: vk::AccessFlags::TRANSFER_WRITE,
old_layout: vk::ImageLayout::UNDEFINED,
new_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
image: texture_image,
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
..Default::default()
},
..Default::default()
};
device.cmd_pipeline_barrier(
texture_command_buffer,
@ -438,48 +384,39 @@ fn main() {
&[],
&[texture_barrier],
);
let buffer_copy_regions = [vk::BufferImageCopy {
image_subresource: vk::ImageSubresourceLayers {
aspect_mask: vk::ImageAspectFlags::COLOR,
mip_level: 0,
base_array_layer: 0,
layer_count: 1,
},
image_extent: vk::Extent3D {
let buffer_copy_regions = vk::BufferImageCopy::builder()
.image_subresource(
vk::ImageSubresourceLayers::builder()
.aspect_mask(vk::ImageAspectFlags::COLOR)
.layer_count(1)
.build(),
)
.image_extent(vk::Extent3D {
width: image_dimensions.0,
height: image_dimensions.1,
depth: 1,
},
buffer_offset: 0,
// FIX ME
buffer_image_height: 0,
buffer_row_length: 0,
image_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
}];
});
device.cmd_copy_buffer_to_image(
texture_command_buffer,
image_buffer,
texture_image,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&buffer_copy_regions,
&[buffer_copy_regions.build()],
);
let texture_barrier_end = vk::ImageMemoryBarrier {
s_type: vk::StructureType::IMAGE_MEMORY_BARRIER,
p_next: ptr::null(),
src_access_mask: vk::AccessFlags::TRANSFER_WRITE,
dst_access_mask: vk::AccessFlags::SHADER_READ,
old_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
new_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
image: texture_image,
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
..Default::default()
},
..Default::default()
};
device.cmd_pipeline_barrier(
texture_command_buffer,
@ -494,32 +431,21 @@ fn main() {
);
let sampler_info = vk::SamplerCreateInfo {
s_type: vk::StructureType::SAMPLER_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
mag_filter: vk::Filter::LINEAR,
min_filter: vk::Filter::LINEAR,
mipmap_mode: vk::SamplerMipmapMode::LINEAR,
address_mode_u: vk::SamplerAddressMode::MIRRORED_REPEAT,
address_mode_v: vk::SamplerAddressMode::MIRRORED_REPEAT,
address_mode_w: vk::SamplerAddressMode::MIRRORED_REPEAT,
mip_lod_bias: 0.0,
min_lod: 0.0,
max_lod: 0.0,
anisotropy_enable: 0,
max_anisotropy: 1.0,
border_color: vk::BorderColor::FLOAT_OPAQUE_WHITE,
compare_enable: 0,
compare_op: vk::CompareOp::NEVER,
unnormalized_coordinates: 0,
..Default::default()
};
let sampler = base.device.create_sampler(&sampler_info, None).unwrap();
let tex_image_view_info = vk::ImageViewCreateInfo {
s_type: vk::StructureType::IMAGE_VIEW_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
view_type: vk::ImageViewType::TYPE_2D,
format: texture_create_info.format,
components: vk::ComponentMapping {
@ -530,12 +456,12 @@ fn main() {
},
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
..Default::default()
},
image: texture_image,
..Default::default()
};
let tex_image_view = base
.device
@ -551,53 +477,40 @@ fn main() {
descriptor_count: 1,
},
];
let descriptor_pool_info = vk::DescriptorPoolCreateInfo {
s_type: vk::StructureType::DESCRIPTOR_POOL_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
pool_size_count: descriptor_sizes.len() as u32,
p_pool_sizes: descriptor_sizes.as_ptr(),
max_sets: 1,
};
let descriptor_pool_info = vk::DescriptorPoolCreateInfo::builder()
.pool_sizes(&descriptor_sizes)
.max_sets(1);
let descriptor_pool = base
.device
.create_descriptor_pool(&descriptor_pool_info, None)
.unwrap();
let desc_layout_bindings = [
vk::DescriptorSetLayoutBinding {
binding: 0,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::FRAGMENT,
p_immutable_samplers: ptr::null(),
..Default::default()
},
vk::DescriptorSetLayoutBinding {
binding: 1,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::FRAGMENT,
p_immutable_samplers: ptr::null(),
..Default::default()
},
];
let descriptor_info = vk::DescriptorSetLayoutCreateInfo {
s_type: vk::StructureType::DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
binding_count: desc_layout_bindings.len() as u32,
p_bindings: desc_layout_bindings.as_ptr(),
};
let descriptor_info =
vk::DescriptorSetLayoutCreateInfo::builder().bindings(&desc_layout_bindings);
let desc_set_layouts = [base
.device
.create_descriptor_set_layout(&descriptor_info, None)
.unwrap()];
let desc_alloc_info = vk::DescriptorSetAllocateInfo {
s_type: vk::StructureType::DESCRIPTOR_SET_ALLOCATE_INFO,
p_next: ptr::null(),
descriptor_pool: descriptor_pool,
descriptor_set_count: desc_set_layouts.len() as u32,
p_set_layouts: desc_set_layouts.as_ptr(),
};
let desc_alloc_info = vk::DescriptorSetAllocateInfo::builder()
.descriptor_pool(descriptor_pool)
.set_layouts(&desc_set_layouts);
let descriptor_sets = base
.device
.allocate_descriptor_sets(&desc_alloc_info)
@ -610,63 +523,43 @@ fn main() {
};
let tex_descriptor = vk::DescriptorImageInfo {
image_layout: vk::ImageLayout::GENERAL,
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
image_view: tex_image_view,
sampler: sampler,
};
let write_desc_sets = [
vk::WriteDescriptorSet {
s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
p_next: ptr::null(),
dst_set: descriptor_sets[0],
dst_binding: 0,
dst_array_element: 0,
descriptor_count: 1,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
p_image_info: ptr::null(),
p_buffer_info: &uniform_color_buffer_descriptor,
p_texel_buffer_view: ptr::null(),
..Default::default()
},
vk::WriteDescriptorSet {
s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
p_next: ptr::null(),
dst_set: descriptor_sets[0],
dst_binding: 1,
dst_array_element: 0,
descriptor_count: 1,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
p_image_info: &tex_descriptor,
p_buffer_info: ptr::null(),
p_texel_buffer_view: ptr::null(),
..Default::default()
},
];
base.device.update_descriptor_sets(&write_desc_sets, &[]);
let vertex_spv_file =
let mut vertex_spv_file =
File::open(Path::new("shader/texture/vert.spv")).expect("Could not find vert.spv.");
let frag_spv_file =
let mut frag_spv_file =
File::open(Path::new("shader/texture/frag.spv")).expect("Could not find frag.spv.");
let vertex_bytes: Vec<u8> = vertex_spv_file
.bytes()
.filter_map(|byte| byte.ok())
.collect();
let vertex_shader_info = vk::ShaderModuleCreateInfo {
s_type: vk::StructureType::SHADER_MODULE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
code_size: vertex_bytes.len(),
p_code: vertex_bytes.as_ptr() as *const u32,
};
let frag_bytes: Vec<u8> = frag_spv_file.bytes().filter_map(|byte| byte.ok()).collect();
let frag_shader_info = vk::ShaderModuleCreateInfo {
s_type: vk::StructureType::SHADER_MODULE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
code_size: frag_bytes.len(),
p_code: frag_bytes.as_ptr() as *const u32,
};
let vertex_code =
read_spv(&mut vertex_spv_file).expect("Failed to read vertex shader spv file");
let vertex_shader_info = vk::ShaderModuleCreateInfo::builder().code(&vertex_code);
let frag_code =
read_spv(&mut frag_spv_file).expect("Failed to read fragment shader spv file");
let frag_shader_info = vk::ShaderModuleCreateInfo::builder().code(&frag_code);
let vertex_shader_module = base
.device
.create_shader_module(&vertex_shader_info, None)
@ -677,15 +570,8 @@ fn main() {
.create_shader_module(&frag_shader_info, None)
.expect("Fragment shader module error");
let layout_create_info = vk::PipelineLayoutCreateInfo {
s_type: vk::StructureType::PIPELINE_LAYOUT_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
set_layout_count: desc_set_layouts.len() as u32,
p_set_layouts: desc_set_layouts.as_ptr(),
push_constant_range_count: 0,
p_push_constant_ranges: ptr::null(),
};
let layout_create_info =
vk::PipelineLayoutCreateInfo::builder().set_layouts(&desc_set_layouts);
let pipeline_layout = base
.device
@ -695,22 +581,16 @@ fn main() {
let shader_entry_name = CString::new("main").unwrap();
let shader_stage_create_infos = [
vk::PipelineShaderStageCreateInfo {
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
module: vertex_shader_module,
p_name: shader_entry_name.as_ptr(),
p_specialization_info: ptr::null(),
stage: vk::ShaderStageFlags::VERTEX,
..Default::default()
},
vk::PipelineShaderStageCreateInfo {
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
module: fragment_shader_module,
p_name: shader_entry_name.as_ptr(),
p_specialization_info: ptr::null(),
stage: vk::ShaderStageFlags::FRAGMENT,
..Default::default()
},
];
let vertex_input_binding_descriptions = [vk::VertexInputBindingDescription {
@ -732,21 +612,13 @@ fn main() {
offset: offset_of!(Vertex, uv) as u32,
},
];
let vertex_input_state_info = vk::PipelineVertexInputStateCreateInfo {
s_type: vk::StructureType::PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
vertex_attribute_description_count: vertex_input_attribute_descriptions.len() as u32,
p_vertex_attribute_descriptions: vertex_input_attribute_descriptions.as_ptr(),
vertex_binding_description_count: vertex_input_binding_descriptions.len() as u32,
p_vertex_binding_descriptions: vertex_input_binding_descriptions.as_ptr(),
};
let vertex_input_state_info = vk::PipelineVertexInputStateCreateInfo::builder()
.vertex_attribute_descriptions(&vertex_input_attribute_descriptions)
.vertex_binding_descriptions(&vertex_input_binding_descriptions);
let vertex_input_assembly_state_info = vk::PipelineInputAssemblyStateCreateInfo {
s_type: vk::StructureType::PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
flags: Default::default(),
p_next: ptr::null(),
primitive_restart_enable: 0,
topology: vk::PrimitiveTopology::TRIANGLE_LIST,
..Default::default()
};
let viewports = [vk::Viewport {
x: 0.0,
@ -757,67 +629,40 @@ fn main() {
max_depth: 1.0,
}];
let scissors = [vk::Rect2D {
offset: vk::Offset2D { x: 0, y: 0 },
extent: base.surface_resolution.clone(),
..Default::default()
}];
let viewport_state_info = vk::PipelineViewportStateCreateInfo {
s_type: vk::StructureType::PIPELINE_VIEWPORT_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
scissor_count: scissors.len() as u32,
p_scissors: scissors.as_ptr(),
viewport_count: viewports.len() as u32,
p_viewports: viewports.as_ptr(),
};
let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
.scissors(&scissors)
.viewports(&viewports);
let rasterization_info = vk::PipelineRasterizationStateCreateInfo {
s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
cull_mode: vk::CullModeFlags::NONE,
depth_bias_clamp: 0.0,
depth_bias_constant_factor: 0.0,
depth_bias_enable: 0,
depth_bias_slope_factor: 0.0,
depth_clamp_enable: 0,
front_face: vk::FrontFace::COUNTER_CLOCKWISE,
line_width: 1.0,
polygon_mode: vk::PolygonMode::FILL,
rasterizer_discard_enable: 0,
};
let multisample_state_info = vk::PipelineMultisampleStateCreateInfo {
s_type: vk::StructureType::PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
flags: Default::default(),
p_next: ptr::null(),
rasterization_samples: vk::SampleCountFlags::TYPE_1,
sample_shading_enable: 0,
min_sample_shading: 0.0,
p_sample_mask: ptr::null(),
alpha_to_one_enable: 0,
alpha_to_coverage_enable: 0,
..Default::default()
};
let multisample_state_info = vk::PipelineMultisampleStateCreateInfo::builder()
.rasterization_samples(vk::SampleCountFlags::TYPE_1);
let noop_stencil_state = vk::StencilOpState {
fail_op: vk::StencilOp::KEEP,
pass_op: vk::StencilOp::KEEP,
depth_fail_op: vk::StencilOp::KEEP,
compare_op: vk::CompareOp::ALWAYS,
compare_mask: 0,
write_mask: 0,
reference: 0,
..Default::default()
};
let depth_state_info = vk::PipelineDepthStencilStateCreateInfo {
s_type: vk::StructureType::PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
depth_test_enable: 1,
depth_write_enable: 1,
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
depth_bounds_test_enable: 0,
stencil_test_enable: 0,
front: noop_stencil_state.clone(),
back: noop_stencil_state.clone(),
max_depth_bounds: 1.0,
min_depth_bounds: 0.0,
..Default::default()
};
let color_blend_attachment_states = [vk::PipelineColorBlendAttachmentState {
blend_enable: 0,
src_color_blend_factor: vk::BlendFactor::SRC_COLOR,
@ -828,48 +673,34 @@ fn main() {
alpha_blend_op: vk::BlendOp::ADD,
color_write_mask: vk::ColorComponentFlags::all(),
}];
let color_blend_state = vk::PipelineColorBlendStateCreateInfo {
s_type: vk::StructureType::PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
logic_op_enable: 0,
logic_op: vk::LogicOp::CLEAR,
attachment_count: color_blend_attachment_states.len() as u32,
p_attachments: color_blend_attachment_states.as_ptr(),
blend_constants: [0.0, 0.0, 0.0, 0.0],
};
let color_blend_state = vk::PipelineColorBlendStateCreateInfo::builder()
.logic_op(vk::LogicOp::CLEAR)
.attachments(&color_blend_attachment_states);
let dynamic_state = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
let dynamic_state_info = vk::PipelineDynamicStateCreateInfo {
s_type: vk::StructureType::PIPELINE_DYNAMIC_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
dynamic_state_count: dynamic_state.len() as u32,
p_dynamic_states: dynamic_state.as_ptr(),
};
let graphic_pipeline_info = vk::GraphicsPipelineCreateInfo {
s_type: vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO,
p_next: ptr::null(),
flags: vk::PipelineCreateFlags::empty(),
stage_count: shader_stage_create_infos.len() as u32,
p_stages: shader_stage_create_infos.as_ptr(),
p_vertex_input_state: &vertex_input_state_info,
p_input_assembly_state: &vertex_input_assembly_state_info,
p_tessellation_state: ptr::null(),
p_viewport_state: &viewport_state_info,
p_rasterization_state: &rasterization_info,
p_multisample_state: &multisample_state_info,
p_depth_stencil_state: &depth_state_info,
p_color_blend_state: &color_blend_state,
p_dynamic_state: &dynamic_state_info,
layout: pipeline_layout,
render_pass: renderpass,
subpass: 0,
base_pipeline_handle: vk::Pipeline::null(),
base_pipeline_index: 0,
};
let dynamic_state_info =
vk::PipelineDynamicStateCreateInfo::builder().dynamic_states(&dynamic_state);
let graphic_pipeline_infos = vk::GraphicsPipelineCreateInfo::builder()
.stages(&shader_stage_create_infos)
.vertex_input_state(&vertex_input_state_info)
.input_assembly_state(&vertex_input_assembly_state_info)
.viewport_state(&viewport_state_info)
.rasterization_state(&rasterization_info)
.multisample_state(&multisample_state_info)
.depth_stencil_state(&depth_state_info)
.color_blend_state(&color_blend_state)
.dynamic_state(&dynamic_state_info)
.layout(pipeline_layout)
.render_pass(renderpass);
let graphics_pipelines = base
.device
.create_graphics_pipelines(vk::PipelineCache::null(), &[graphic_pipeline_info], None)
.create_graphics_pipelines(
vk::PipelineCache::null(),
&[graphic_pipeline_infos.build()],
None,
)
.unwrap();
let graphic_pipeline = graphics_pipelines[0];
@ -877,7 +708,7 @@ fn main() {
base.render_loop(|| {
let (present_index, _) = base
.swapchain_loader
.acquire_next_image_khr(
.acquire_next_image(
base.swapchain,
std::u64::MAX,
base.present_complete_semaphore,
@ -898,18 +729,15 @@ fn main() {
},
];
let render_pass_begin_info = vk::RenderPassBeginInfo {
s_type: vk::StructureType::RENDER_PASS_BEGIN_INFO,
p_next: ptr::null(),
render_pass: renderpass,
framebuffer: framebuffers[present_index as usize],
render_area: vk::Rect2D {
let render_pass_begin_info = vk::RenderPassBeginInfo::builder()
.render_pass(renderpass)
.framebuffer(framebuffers[present_index as usize])
.render_area(vk::Rect2D {
offset: vk::Offset2D { x: 0, y: 0 },
extent: base.surface_resolution.clone(),
},
clear_value_count: clear_values.len() as u32,
p_clear_values: clear_values.as_ptr(),
};
})
.clear_values(&clear_values);
record_submit_commandbuffer(
&base.device,
base.draw_command_buffer,
@ -965,17 +793,15 @@ fn main() {
);
//let mut present_info_err = mem::uninitialized();
let present_info = vk::PresentInfoKHR {
s_type: vk::StructureType::PRESENT_INFO_KHR,
p_next: ptr::null(),
wait_semaphore_count: 1,
p_wait_semaphores: &base.rendering_complete_semaphore,
swapchain_count: 1,
p_swapchains: &base.swapchain,
p_image_indices: &present_index,
p_results: ptr::null_mut(),
..Default::default()
};
base.swapchain_loader
.queue_present_khr(base.present_queue, &present_info)
.queue_present(base.present_queue, &present_info)
.unwrap();
});
base.device.device_wait_idle().unwrap();

View file

@ -7,11 +7,9 @@ use examples::*;
use std::default::Default;
use std::ffi::CString;
use std::fs::File;
use std::io::Read;
use std::mem;
use std::mem::align_of;
use std::path::Path;
use std::ptr;
#[derive(Clone, Debug, Copy)]
struct Vertex {
@ -25,117 +23,91 @@ fn main() {
let renderpass_attachments = [
vk::AttachmentDescription {
format: base.surface_format.format,
flags: vk::AttachmentDescriptionFlags::empty(),
samples: vk::SampleCountFlags::TYPE_1,
load_op: vk::AttachmentLoadOp::CLEAR,
store_op: vk::AttachmentStoreOp::STORE,
stencil_load_op: vk::AttachmentLoadOp::DONT_CARE,
stencil_store_op: vk::AttachmentStoreOp::DONT_CARE,
initial_layout: vk::ImageLayout::UNDEFINED,
final_layout: vk::ImageLayout::PRESENT_SRC_KHR,
..Default::default()
},
vk::AttachmentDescription {
format: vk::Format::D16_UNORM,
flags: vk::AttachmentDescriptionFlags::empty(),
samples: vk::SampleCountFlags::TYPE_1,
load_op: vk::AttachmentLoadOp::CLEAR,
store_op: vk::AttachmentStoreOp::DONT_CARE,
stencil_load_op: vk::AttachmentLoadOp::DONT_CARE,
stencil_store_op: vk::AttachmentStoreOp::DONT_CARE,
initial_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
final_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
..Default::default()
},
];
let color_attachment_ref = vk::AttachmentReference {
let color_attachment_refs = [vk::AttachmentReference {
attachment: 0,
layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
};
}];
let depth_attachment_ref = vk::AttachmentReference {
attachment: 1,
layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
};
let dependency = vk::SubpassDependency {
dependency_flags: Default::default(),
let dependencies = [vk::SubpassDependency {
src_subpass: vk::SUBPASS_EXTERNAL,
dst_subpass: Default::default(),
src_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
src_access_mask: Default::default(),
dst_access_mask: vk::AccessFlags::COLOR_ATTACHMENT_READ
| vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
dst_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
};
let subpass = vk::SubpassDescription {
color_attachment_count: 1,
p_color_attachments: &color_attachment_ref,
p_depth_stencil_attachment: &depth_attachment_ref,
flags: Default::default(),
pipeline_bind_point: vk::PipelineBindPoint::GRAPHICS,
input_attachment_count: 0,
p_input_attachments: ptr::null(),
p_resolve_attachments: ptr::null(),
preserve_attachment_count: 0,
p_preserve_attachments: ptr::null(),
};
let renderpass_create_info = vk::RenderPassCreateInfo {
s_type: vk::StructureType::RENDER_PASS_CREATE_INFO,
flags: Default::default(),
p_next: ptr::null(),
attachment_count: renderpass_attachments.len() as u32,
p_attachments: renderpass_attachments.as_ptr(),
subpass_count: 1,
p_subpasses: &subpass,
dependency_count: 1,
p_dependencies: &dependency,
};
..Default::default()
}];
let subpasses = [vk::SubpassDescription::builder()
.color_attachments(&color_attachment_refs)
.depth_stencil_attachment(&depth_attachment_ref)
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.build()];
let renderpass_create_info = vk::RenderPassCreateInfo::builder()
.attachments(&renderpass_attachments)
.subpasses(&subpasses)
.dependencies(&dependencies);
let renderpass = base
.device
.create_render_pass(&renderpass_create_info, None)
.unwrap();
let framebuffers: Vec<vk::Framebuffer> = base
.present_image_views
.iter()
.map(|&present_image_view| {
let framebuffer_attachments = [present_image_view, base.depth_image_view];
let frame_buffer_create_info = vk::FramebufferCreateInfo {
s_type: vk::StructureType::FRAMEBUFFER_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
render_pass: renderpass,
attachment_count: framebuffer_attachments.len() as u32,
p_attachments: framebuffer_attachments.as_ptr(),
width: base.surface_resolution.width,
height: base.surface_resolution.height,
layers: 1,
};
let frame_buffer_create_info = vk::FramebufferCreateInfo::builder()
.render_pass(renderpass)
.attachments(&framebuffer_attachments)
.width(base.surface_resolution.width)
.height(base.surface_resolution.height)
.layers(1);
base.device
.create_framebuffer(&frame_buffer_create_info, None)
.unwrap()
})
.collect();
let index_buffer_data = [0u32, 1, 2];
let index_buffer_info = vk::BufferCreateInfo {
s_type: vk::StructureType::BUFFER_CREATE_INFO,
p_next: ptr::null(),
flags: vk::BufferCreateFlags::empty(),
size: std::mem::size_of_val(&index_buffer_data) as u64,
usage: vk::BufferUsageFlags::INDEX_BUFFER,
sharing_mode: vk::SharingMode::EXCLUSIVE,
queue_family_index_count: 0,
p_queue_family_indices: ptr::null(),
};
let index_buffer_info = vk::BufferCreateInfo::builder()
.size(std::mem::size_of_val(&index_buffer_data) as u64)
.usage(vk::BufferUsageFlags::INDEX_BUFFER)
.sharing_mode(vk::SharingMode::EXCLUSIVE);
let index_buffer = base.device.create_buffer(&index_buffer_info, None).unwrap();
let index_buffer_memory_req = base.device.get_buffer_memory_requirements(index_buffer);
let index_buffer_memory_index =
find_memorytype_index(
let index_buffer_memory_index = find_memorytype_index(
&index_buffer_memory_req,
&base.device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE,
).expect("Unable to find suitable memorytype for the index buffer.");
)
.expect("Unable to find suitable memorytype for the index buffer.");
let index_allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
p_next: ptr::null(),
allocation_size: index_buffer_memory_req.size,
memory_type_index: index_buffer_memory_index,
..Default::default()
};
let index_buffer_memory = base
.device
@ -162,39 +134,39 @@ fn main() {
.unwrap();
let vertex_input_buffer_info = vk::BufferCreateInfo {
s_type: vk::StructureType::BUFFER_CREATE_INFO,
p_next: ptr::null(),
flags: vk::BufferCreateFlags::empty(),
size: 3 * std::mem::size_of::<Vertex>() as u64,
usage: vk::BufferUsageFlags::VERTEX_BUFFER,
sharing_mode: vk::SharingMode::EXCLUSIVE,
queue_family_index_count: 0,
p_queue_family_indices: ptr::null(),
..Default::default()
};
let vertex_input_buffer = base
.device
.create_buffer(&vertex_input_buffer_info, None)
.unwrap();
let vertex_input_buffer_memory_req = base
.device
.get_buffer_memory_requirements(vertex_input_buffer);
let vertex_input_buffer_memory_index =
find_memorytype_index(
let vertex_input_buffer_memory_index = find_memorytype_index(
&vertex_input_buffer_memory_req,
&base.device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE,
).expect("Unable to find suitable memorytype for the vertex buffer.");
)
.expect("Unable to find suitable memorytype for the vertex buffer.");
let vertex_buffer_allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
p_next: ptr::null(),
allocation_size: vertex_input_buffer_memory_req.size,
memory_type_index: vertex_input_buffer_memory_index,
..Default::default()
};
let vertex_input_buffer_memory = base
.device
.allocate_memory(&vertex_buffer_allocate_info, None)
.unwrap();
let vertices = [
Vertex {
pos: [-1.0, 1.0, 0.0, 1.0],
@ -209,6 +181,7 @@ fn main() {
color: [1.0, 0.0, 0.0, 1.0],
},
];
let vert_ptr = base
.device
.map_memory(
@ -218,6 +191,7 @@ fn main() {
vk::MemoryMapFlags::empty(),
)
.unwrap();
let mut vert_align = Align::new(
vert_ptr,
align_of::<Vertex>() as u64,
@ -228,30 +202,19 @@ fn main() {
base.device
.bind_buffer_memory(vertex_input_buffer, vertex_input_buffer_memory, 0)
.unwrap();
let vertex_spv_file =
let mut vertex_spv_file =
File::open(Path::new("shader/triangle/vert.spv")).expect("Could not find vert.spv.");
let frag_spv_file =
let mut frag_spv_file =
File::open(Path::new("shader/triangle/frag.spv")).expect("Could not find frag.spv.");
let vertex_bytes: Vec<u8> = vertex_spv_file
.bytes()
.filter_map(|byte| byte.ok())
.collect();
let vertex_shader_info = vk::ShaderModuleCreateInfo {
s_type: vk::StructureType::SHADER_MODULE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
code_size: vertex_bytes.len(),
p_code: vertex_bytes.as_ptr() as *const u32,
};
let frag_bytes: Vec<u8> = frag_spv_file.bytes().filter_map(|byte| byte.ok()).collect();
let frag_shader_info = vk::ShaderModuleCreateInfo {
s_type: vk::StructureType::SHADER_MODULE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
code_size: frag_bytes.len(),
p_code: frag_bytes.as_ptr() as *const u32,
};
let vertex_code =
read_spv(&mut vertex_spv_file).expect("Failed to read vertex shader spv file");
let vertex_shader_info = vk::ShaderModuleCreateInfo::builder().code(&vertex_code);
let frag_code =
read_spv(&mut frag_spv_file).expect("Failed to read fragment shader spv file");
let frag_shader_info = vk::ShaderModuleCreateInfo::builder().code(&frag_code);
let vertex_shader_module = base
.device
.create_shader_module(&vertex_shader_info, None)
@ -262,15 +225,7 @@ fn main() {
.create_shader_module(&frag_shader_info, None)
.expect("Fragment shader module error");
let layout_create_info = vk::PipelineLayoutCreateInfo {
s_type: vk::StructureType::PIPELINE_LAYOUT_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
set_layout_count: 0,
p_set_layouts: ptr::null(),
push_constant_range_count: 0,
p_push_constant_ranges: ptr::null(),
};
let layout_create_info = vk::PipelineLayoutCreateInfo::default();
let pipeline_layout = base
.device
@ -280,22 +235,17 @@ fn main() {
let shader_entry_name = CString::new("main").unwrap();
let shader_stage_create_infos = [
vk::PipelineShaderStageCreateInfo {
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
module: vertex_shader_module,
p_name: shader_entry_name.as_ptr(),
p_specialization_info: ptr::null(),
stage: vk::ShaderStageFlags::VERTEX,
..Default::default()
},
vk::PipelineShaderStageCreateInfo {
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
module: fragment_shader_module,
p_name: shader_entry_name.as_ptr(),
p_specialization_info: ptr::null(),
stage: vk::ShaderStageFlags::FRAGMENT,
..Default::default()
},
];
let vertex_input_binding_descriptions = [vk::VertexInputBindingDescription {
@ -317,21 +267,17 @@ fn main() {
offset: offset_of!(Vertex, color) as u32,
},
];
let vertex_input_state_info = vk::PipelineVertexInputStateCreateInfo {
s_type: vk::StructureType::PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
vertex_attribute_description_count: vertex_input_attribute_descriptions.len() as u32,
p_vertex_attribute_descriptions: vertex_input_attribute_descriptions.as_ptr(),
vertex_binding_description_count: vertex_input_binding_descriptions.len() as u32,
p_vertex_binding_descriptions: vertex_input_binding_descriptions.as_ptr(),
..Default::default()
};
let vertex_input_assembly_state_info = vk::PipelineInputAssemblyStateCreateInfo {
s_type: vk::StructureType::PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
flags: Default::default(),
p_next: ptr::null(),
primitive_restart_enable: 0,
topology: vk::PrimitiveTopology::TRIANGLE_LIST,
..Default::default()
};
let viewports = [vk::Viewport {
x: 0.0,
@ -345,63 +291,35 @@ fn main() {
offset: vk::Offset2D { x: 0, y: 0 },
extent: base.surface_resolution.clone(),
}];
let viewport_state_info = vk::PipelineViewportStateCreateInfo {
s_type: vk::StructureType::PIPELINE_VIEWPORT_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
scissor_count: scissors.len() as u32,
p_scissors: scissors.as_ptr(),
viewport_count: viewports.len() as u32,
p_viewports: viewports.as_ptr(),
};
let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
.scissors(&scissors)
.viewports(&viewports);
let rasterization_info = vk::PipelineRasterizationStateCreateInfo {
s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
cull_mode: vk::CullModeFlags::NONE,
depth_bias_clamp: 0.0,
depth_bias_constant_factor: 0.0,
depth_bias_enable: 0,
depth_bias_slope_factor: 0.0,
depth_clamp_enable: 0,
front_face: vk::FrontFace::COUNTER_CLOCKWISE,
line_width: 1.0,
polygon_mode: vk::PolygonMode::FILL,
rasterizer_discard_enable: 0,
..Default::default()
};
let multisample_state_info = vk::PipelineMultisampleStateCreateInfo {
s_type: vk::StructureType::PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
flags: Default::default(),
p_next: ptr::null(),
rasterization_samples: vk::SampleCountFlags::TYPE_1,
sample_shading_enable: 0,
min_sample_shading: 0.0,
p_sample_mask: ptr::null(),
alpha_to_one_enable: 0,
alpha_to_coverage_enable: 0,
..Default::default()
};
let noop_stencil_state = vk::StencilOpState {
fail_op: vk::StencilOp::KEEP,
pass_op: vk::StencilOp::KEEP,
depth_fail_op: vk::StencilOp::KEEP,
compare_op: vk::CompareOp::ALWAYS,
compare_mask: 0,
write_mask: 0,
reference: 0,
..Default::default()
};
let depth_state_info = vk::PipelineDepthStencilStateCreateInfo {
s_type: vk::StructureType::PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
depth_test_enable: 1,
depth_write_enable: 1,
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
depth_bounds_test_enable: 0,
stencil_test_enable: 0,
front: noop_stencil_state.clone(),
back: noop_stencil_state.clone(),
max_depth_bounds: 1.0,
min_depth_bounds: 0.0,
..Default::default()
};
let color_blend_attachment_states = [vk::PipelineColorBlendAttachmentState {
blend_enable: 0,
@ -413,48 +331,34 @@ fn main() {
alpha_blend_op: vk::BlendOp::ADD,
color_write_mask: vk::ColorComponentFlags::all(),
}];
let color_blend_state = vk::PipelineColorBlendStateCreateInfo {
s_type: vk::StructureType::PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
logic_op_enable: 0,
logic_op: vk::LogicOp::CLEAR,
attachment_count: color_blend_attachment_states.len() as u32,
p_attachments: color_blend_attachment_states.as_ptr(),
blend_constants: [0.0, 0.0, 0.0, 0.0],
};
let color_blend_state = vk::PipelineColorBlendStateCreateInfo::builder()
.logic_op(vk::LogicOp::CLEAR)
.attachments(&color_blend_attachment_states);
let dynamic_state = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
let dynamic_state_info = vk::PipelineDynamicStateCreateInfo {
s_type: vk::StructureType::PIPELINE_DYNAMIC_STATE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
dynamic_state_count: dynamic_state.len() as u32,
p_dynamic_states: dynamic_state.as_ptr(),
};
let graphic_pipeline_info = vk::GraphicsPipelineCreateInfo {
s_type: vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO,
p_next: ptr::null(),
flags: vk::PipelineCreateFlags::empty(),
stage_count: shader_stage_create_infos.len() as u32,
p_stages: shader_stage_create_infos.as_ptr(),
p_vertex_input_state: &vertex_input_state_info,
p_input_assembly_state: &vertex_input_assembly_state_info,
p_tessellation_state: ptr::null(),
p_viewport_state: &viewport_state_info,
p_rasterization_state: &rasterization_info,
p_multisample_state: &multisample_state_info,
p_depth_stencil_state: &depth_state_info,
p_color_blend_state: &color_blend_state,
p_dynamic_state: &dynamic_state_info,
layout: pipeline_layout,
render_pass: renderpass,
subpass: 0,
base_pipeline_handle: vk::Pipeline::null(),
base_pipeline_index: 0,
};
let dynamic_state_info =
vk::PipelineDynamicStateCreateInfo::builder().dynamic_states(&dynamic_state);
let graphic_pipeline_info = vk::GraphicsPipelineCreateInfo::builder()
.stages(&shader_stage_create_infos)
.vertex_input_state(&vertex_input_state_info)
.input_assembly_state(&vertex_input_assembly_state_info)
.viewport_state(&viewport_state_info)
.rasterization_state(&rasterization_info)
.multisample_state(&multisample_state_info)
.depth_stencil_state(&depth_state_info)
.color_blend_state(&color_blend_state)
.dynamic_state(&dynamic_state_info)
.layout(pipeline_layout)
.render_pass(renderpass);
let graphics_pipelines = base
.device
.create_graphics_pipelines(vk::PipelineCache::null(), &[graphic_pipeline_info], None)
.create_graphics_pipelines(
vk::PipelineCache::null(),
&[graphic_pipeline_info.build()],
None,
)
.expect("Unable to create graphics pipeline");
let graphic_pipeline = graphics_pipelines[0];
@ -462,7 +366,7 @@ fn main() {
base.render_loop(|| {
let (present_index, _) = base
.swapchain_loader
.acquire_next_image_khr(
.acquire_next_image(
base.swapchain,
std::u64::MAX,
base.present_complete_semaphore,
@ -483,18 +387,15 @@ fn main() {
},
];
let render_pass_begin_info = vk::RenderPassBeginInfo {
s_type: vk::StructureType::RENDER_PASS_BEGIN_INFO,
p_next: ptr::null(),
render_pass: renderpass,
framebuffer: framebuffers[present_index as usize],
render_area: vk::Rect2D {
let render_pass_begin_info = vk::RenderPassBeginInfo::builder()
.render_pass(renderpass)
.framebuffer(framebuffers[present_index as usize])
.render_area(vk::Rect2D {
offset: vk::Offset2D { x: 0, y: 0 },
extent: base.surface_resolution.clone(),
},
clear_value_count: clear_values.len() as u32,
p_clear_values: clear_values.as_ptr(),
};
})
.clear_values(&clear_values);
record_submit_commandbuffer(
&base.device,
base.draw_command_buffer,
@ -541,18 +442,16 @@ fn main() {
},
);
//let mut present_info_err = mem::uninitialized();
let present_info = vk::PresentInfoKHR {
s_type: vk::StructureType::PRESENT_INFO_KHR,
p_next: ptr::null(),
wait_semaphore_count: 1,
p_wait_semaphores: &base.rendering_complete_semaphore,
swapchain_count: 1,
p_swapchains: &base.swapchain,
p_image_indices: &present_index,
p_results: ptr::null_mut(),
};
let wait_semaphors = [base.rendering_complete_semaphore];
let swapchains = [base.swapchain];
let image_indices = [present_index];
let present_info = vk::PresentInfoKHR::builder()
.wait_semaphores(&wait_semaphors) // &base.rendering_complete_semaphore)
.swapchains(&swapchains)
.image_indices(&image_indices);
base.swapchain_loader
.queue_present_khr(base.present_queue, &present_info)
.queue_present(base.present_queue, &present_info)
.unwrap();
});

View file

@ -2,15 +2,16 @@
extern crate ash;
#[cfg(target_os = "windows")]
extern crate winapi;
extern crate winit;
#[cfg(target_os = "macos")]
extern crate objc;
#[cfg(target_os = "macos")]
extern crate cocoa;
#[cfg(target_os = "macos")]
extern crate metal_rs as metal;
#[cfg(target_os = "macos")]
extern crate objc;
#[cfg(target_os = "macos")]
use cocoa::appkit::{NSView, NSWindow};
#[cfg(target_os = "macos")]
use cocoa::base::id as cocoa_id;
@ -21,24 +22,24 @@ use objc::runtime::YES;
#[cfg(target_os = "macos")]
use std::mem;
use ash::vk;
use ash::Device;
use ash::Entry;
use ash::Instance;
pub use ash::version::{DeviceV1_0, EntryV1_0, InstanceV1_0};
use ash::extensions::{DebugReport, Surface, Swapchain};
#[cfg(target_os = "windows")]
use ash::extensions::Win32Surface;
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
use ash::extensions::XlibSurface;
use ash::extensions::khr::XlibSurface;
use ash::extensions::{
ext::DebugReport,
khr::{Surface, Swapchain},
};
#[cfg(target_os = "windows")]
use ash::extensions::khr::Win32Surface;
#[cfg(target_os = "macos")]
use ash::extensions::MacOSSurface;
use ash::extensions::mvk::MacOSSurface;
pub use ash::version::{DeviceV1_0, EntryV1_0, InstanceV1_0};
use ash::{vk, Device, Entry, Instance};
use std::cell::RefCell;
use std::default::Default;
use std::ffi::{CStr, CString};
use std::ops::Drop;
use std::os::raw::{c_char, c_void};
use std::ptr;
// Simple offset_of macro akin to C++ offsetof
#[macro_export]
@ -66,13 +67,12 @@ pub fn record_submit_commandbuffer<D: DeviceV1_0, F: FnOnce(&D, vk::CommandBuffe
.reset_command_buffer(
command_buffer,
vk::CommandBufferResetFlags::RELEASE_RESOURCES,
).expect("Reset command buffer failed.");
let command_buffer_begin_info = vk::CommandBufferBeginInfo {
s_type: vk::StructureType::COMMAND_BUFFER_BEGIN_INFO,
p_next: ptr::null(),
p_inheritance_info: ptr::null(),
flags: vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT,
};
)
.expect("Reset command buffer failed.");
let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder()
.flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT);
device
.begin_command_buffer(command_buffer, &command_buffer_begin_info)
.expect("Begin commandbuffer");
@ -80,27 +80,21 @@ pub fn record_submit_commandbuffer<D: DeviceV1_0, F: FnOnce(&D, vk::CommandBuffe
device
.end_command_buffer(command_buffer)
.expect("End commandbuffer");
let fence_create_info = vk::FenceCreateInfo {
s_type: vk::StructureType::FENCE_CREATE_INFO,
p_next: ptr::null(),
flags: vk::FenceCreateFlags::empty(),
};
let submit_fence = device
.create_fence(&fence_create_info, None)
.create_fence(&vk::FenceCreateInfo::default(), None)
.expect("Create fence failed.");
let submit_info = vk::SubmitInfo {
s_type: vk::StructureType::SUBMIT_INFO,
p_next: ptr::null(),
wait_semaphore_count: wait_semaphores.len() as u32,
p_wait_semaphores: wait_semaphores.as_ptr(),
p_wait_dst_stage_mask: wait_mask.as_ptr(),
command_buffer_count: 1,
p_command_buffers: &command_buffer,
signal_semaphore_count: signal_semaphores.len() as u32,
p_signal_semaphores: signal_semaphores.as_ptr(),
};
let command_buffers = vec![command_buffer];
let submit_info = vk::SubmitInfo::builder()
.wait_semaphores(wait_semaphores)
.wait_dst_stage_mask(wait_mask)
.command_buffers(&command_buffers)
.signal_semaphores(signal_semaphores);
device
.queue_submit(submit_queue, &[submit_info], submit_fence)
.queue_submit(submit_queue, &[submit_info.build()], submit_fence)
.expect("queue submit failed.");
device
.wait_for_fences(&[submit_fence], true, std::u64::MAX)
@ -118,16 +112,12 @@ unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
use winit::os::unix::WindowExt;
let x11_display = window.get_xlib_display().unwrap();
let x11_window = window.get_xlib_window().unwrap();
let x11_create_info = vk::XlibSurfaceCreateInfoKHR {
s_type: vk::StructureType::XLIB_SURFACE_CREATE_INFO_KHR,
p_next: ptr::null(),
flags: Default::default(),
window: x11_window as vk::Window,
dpy: x11_display as *mut vk::Display,
};
let xlib_surface_loader =
XlibSurface::new(entry, instance);
xlib_surface_loader.create_xlib_surface_khr(&x11_create_info, None)
let x11_create_info = vk::XlibSurfaceCreateInfoKHR::builder()
.window(x11_window)
.dpy(x11_display as *mut vk::Display);
let xlib_surface_loader = XlibSurface::new(entry, instance);
xlib_surface_loader.create_xlib_surface(&x11_create_info, None)
}
#[cfg(target_os = "macos")]
@ -136,6 +126,7 @@ unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
instance: &I,
window: &winit::Window,
) -> Result<vk::SurfaceKHR, vk::Result> {
use std::ptr;
use winit::os::macos::WindowExt;
let wnd: cocoa_id = mem::transmute(window.get_nswindow());
@ -153,15 +144,14 @@ unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
view.setWantsLayer(YES);
let create_info = vk::MacOSSurfaceCreateInfoMVK {
s_type: vk::StructureType::MacOSSurfaceCreateInfoMvk,
s_type: vk::StructureType::MACOS_SURFACE_CREATE_INFO_M,
p_next: ptr::null(),
flags: Default::default(),
p_view: window.get_nsview() as *const vk::types::c_void
p_view: window.get_nsview() as *const c_void,
};
let macos_surface_loader =
MacOSSurface::new(entry, instance).expect("Unable to load macOS surface");
macos_surface_loader.create_macos_surface_mvk(&create_info, None)
let macos_surface_loader = MacOSSurface::new(entry, instance);
macos_surface_loader.create_mac_os_surface_mvk(&create_info, None)
}
#[cfg(target_os = "windows")]
@ -170,6 +160,7 @@ unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
instance: &I,
window: &winit::Window,
) -> Result<vk::SurfaceKHR, vk::Result> {
use std::ptr;
use winapi::shared::windef::HWND;
use winapi::um::libloaderapi::GetModuleHandleW;
use winit::os::windows::WindowExt;
@ -183,9 +174,8 @@ unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
hinstance: hinstance,
hwnd: hwnd as *const c_void,
};
let win32_surface_loader =
Win32Surface::new(entry, instance);
win32_surface_loader.create_win32_surface_khr(&win32_create_info, None)
let win32_surface_loader = Win32Surface::new(entry, instance);
win32_surface_loader.create_win32_surface(&win32_create_info, None)
}
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
@ -332,11 +322,11 @@ impl ExampleBase {
.with_dimensions(winit::dpi::LogicalSize::new(
window_width as f64,
window_height as f64,
)).build(&events_loop)
))
.build(&events_loop)
.unwrap();
let entry = Entry::new().unwrap();
let app_name = CString::new("VulkanTriangle").unwrap();
let raw_name = app_name.as_ptr();
let layer_names = [CString::new("VK_LAYER_LUNARG_standard_validation").unwrap()];
let layers_names_raw: Vec<*const i8> = layer_names
@ -345,48 +335,40 @@ impl ExampleBase {
.collect();
let extension_names_raw = extension_names();
let appinfo = vk::ApplicationInfo {
p_application_name: raw_name,
s_type: vk::StructureType::APPLICATION_INFO,
p_next: ptr::null(),
application_version: 0,
p_engine_name: raw_name,
engine_version: 0,
api_version: vk_make_version!(1, 0, 36),
};
let create_info = vk::InstanceCreateInfo {
s_type: vk::StructureType::INSTANCE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
p_application_info: &appinfo,
pp_enabled_layer_names: layers_names_raw.as_ptr(),
enabled_layer_count: layers_names_raw.len() as u32,
pp_enabled_extension_names: extension_names_raw.as_ptr(),
enabled_extension_count: extension_names_raw.len() as u32,
};
let appinfo = vk::ApplicationInfo::builder()
.application_name(&app_name)
.application_version(0)
.engine_name(&app_name)
.engine_version(0)
.api_version(vk_make_version!(1, 0, 36));
let create_info = vk::InstanceCreateInfo::builder()
.application_info(&appinfo)
.enabled_layer_names(&layers_names_raw)
.enabled_extension_names(&extension_names_raw);
let instance: Instance = entry
.create_instance(&create_info, None)
.expect("Instance creation error");
let debug_info = vk::DebugReportCallbackCreateInfoEXT {
s_type: vk::StructureType::DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
p_next: ptr::null(),
flags: vk::DebugReportFlagsEXT::ERROR
let debug_info = vk::DebugReportCallbackCreateInfoEXT::builder()
.flags(
vk::DebugReportFlagsEXT::ERROR
| vk::DebugReportFlagsEXT::WARNING
| vk::DebugReportFlagsEXT::PERFORMANCE_WARNING,
pfn_callback: Some(vulkan_debug_callback),
p_user_data: ptr::null_mut(),
};
let debug_report_loader =
DebugReport::new(&entry, &instance);
)
.pfn_callback(Some(vulkan_debug_callback));
let debug_report_loader = DebugReport::new(&entry, &instance);
let debug_call_back = debug_report_loader
.create_debug_report_callback_ext(&debug_info, None)
.create_debug_report_callback(&debug_info, None)
.unwrap();
let surface = create_surface(&entry, &instance, &window).unwrap();
let pdevices = instance
.enumerate_physical_devices()
.expect("Physical device error");
let surface_loader =
Surface::new(&entry, &instance);
let surface_loader = Surface::new(&entry, &instance);
let (pdevice, queue_family_index) = pdevices
.iter()
.map(|pdevice| {
@ -396,8 +378,8 @@ impl ExampleBase {
.enumerate()
.filter_map(|(index, ref info)| {
let supports_graphic_and_surface =
info.queue_flags.contains(vk::QueueFlags::GRAPHICS) && surface_loader
.get_physical_device_surface_support_khr(
info.queue_flags.contains(vk::QueueFlags::GRAPHICS)
&& surface_loader.get_physical_device_surface_support(
*pdevice,
index as u32,
surface,
@ -406,8 +388,10 @@ impl ExampleBase {
true => Some((*pdevice, index)),
_ => None,
}
}).nth(0)
}).filter_map(|v| v)
})
.nth(0)
})
.filter_map(|v| v)
.nth(0)
.expect("Couldn't find suitable device.");
let queue_family_index = queue_family_index as u32;
@ -417,33 +401,24 @@ impl ExampleBase {
..Default::default()
};
let priorities = [1.0];
let queue_info = vk::DeviceQueueCreateInfo {
s_type: vk::StructureType::DEVICE_QUEUE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
queue_family_index: queue_family_index as u32,
p_queue_priorities: priorities.as_ptr(),
queue_count: priorities.len() as u32,
};
let device_create_info = vk::DeviceCreateInfo {
s_type: vk::StructureType::DEVICE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
queue_create_info_count: 1,
p_queue_create_infos: &queue_info,
enabled_layer_count: 0,
pp_enabled_layer_names: ptr::null(),
enabled_extension_count: device_extension_names_raw.len() as u32,
pp_enabled_extension_names: device_extension_names_raw.as_ptr(),
p_enabled_features: &features,
};
let queue_info = [vk::DeviceQueueCreateInfo::builder()
.queue_family_index(queue_family_index)
.queue_priorities(&priorities)
.build()];
let device_create_info = vk::DeviceCreateInfo::builder()
.queue_create_infos(&queue_info)
.enabled_extension_names(&device_extension_names_raw)
.enabled_features(&features);
let device: Device = instance
.create_device(pdevice, &device_create_info, None)
.unwrap();
let present_queue = device.get_device_queue(queue_family_index as u32, 0);
let surface_formats = surface_loader
.get_physical_device_surface_formats_khr(pdevice, surface)
.get_physical_device_surface_formats(pdevice, surface)
.unwrap();
let surface_format = surface_formats
.iter()
@ -453,10 +428,11 @@ impl ExampleBase {
color_space: sfmt.color_space,
},
_ => sfmt.clone(),
}).nth(0)
})
.nth(0)
.expect("Unable to find suitable surface format.");
let surface_capabilities = surface_loader
.get_physical_device_surface_capabilities_khr(pdevice, surface)
.get_physical_device_surface_capabilities(pdevice, surface)
.unwrap();
let mut desired_image_count = surface_capabilities.min_image_count + 1;
if surface_capabilities.max_image_count > 0
@ -480,156 +456,135 @@ impl ExampleBase {
surface_capabilities.current_transform
};
let present_modes = surface_loader
.get_physical_device_surface_present_modes_khr(pdevice, surface)
.get_physical_device_surface_present_modes(pdevice, surface)
.unwrap();
let present_mode = present_modes
.iter()
.cloned()
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
.unwrap_or(vk::PresentModeKHR::FIFO);
let swapchain_loader =
Swapchain::new(&instance, &device);
let swapchain_create_info = vk::SwapchainCreateInfoKHR {
s_type: vk::StructureType::SWAPCHAIN_CREATE_INFO_KHR,
p_next: ptr::null(),
flags: Default::default(),
surface: surface,
min_image_count: desired_image_count,
image_color_space: surface_format.color_space,
image_format: surface_format.format,
image_extent: surface_resolution.clone(),
image_usage: vk::ImageUsageFlags::COLOR_ATTACHMENT,
image_sharing_mode: vk::SharingMode::EXCLUSIVE,
pre_transform: pre_transform,
composite_alpha: vk::CompositeAlphaFlagsKHR::OPAQUE,
present_mode: present_mode,
clipped: 1,
old_swapchain: vk::SwapchainKHR::null(),
image_array_layers: 1,
p_queue_family_indices: ptr::null(),
queue_family_index_count: 0,
};
let swapchain_loader = Swapchain::new(&instance, &device);
let swapchain_create_info = vk::SwapchainCreateInfoKHR::builder()
.surface(surface)
.min_image_count(desired_image_count)
.image_color_space(surface_format.color_space)
.image_format(surface_format.format)
.image_extent(surface_resolution.clone())
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
.pre_transform(pre_transform)
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
.present_mode(present_mode)
.clipped(true)
.image_array_layers(1);
let swapchain = swapchain_loader
.create_swapchain_khr(&swapchain_create_info, None)
.create_swapchain(&swapchain_create_info, None)
.unwrap();
let pool_create_info = vk::CommandPoolCreateInfo {
s_type: vk::StructureType::COMMAND_POOL_CREATE_INFO,
p_next: ptr::null(),
flags: vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER,
queue_family_index: queue_family_index,
};
let pool_create_info = vk::CommandPoolCreateInfo::builder()
.flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER)
.queue_family_index(queue_family_index);
let pool = device.create_command_pool(&pool_create_info, None).unwrap();
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo {
s_type: vk::StructureType::COMMAND_BUFFER_ALLOCATE_INFO,
p_next: ptr::null(),
command_buffer_count: 2,
command_pool: pool,
level: vk::CommandBufferLevel::PRIMARY,
};
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::builder()
.command_buffer_count(2)
.command_pool(pool)
.level(vk::CommandBufferLevel::PRIMARY);
let command_buffers = device
.allocate_command_buffers(&command_buffer_allocate_info)
.unwrap();
let setup_command_buffer = command_buffers[0];
let draw_command_buffer = command_buffers[1];
let present_images = swapchain_loader
.get_swapchain_images_khr(swapchain)
.unwrap();
let present_images = swapchain_loader.get_swapchain_images(swapchain).unwrap();
let present_image_views: Vec<vk::ImageView> = present_images
.iter()
.map(|&image| {
let create_view_info = vk::ImageViewCreateInfo {
s_type: vk::StructureType::IMAGE_VIEW_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
view_type: vk::ImageViewType::TYPE_2D,
format: surface_format.format,
components: vk::ComponentMapping {
let create_view_info = vk::ImageViewCreateInfo::builder()
.view_type(vk::ImageViewType::TYPE_2D)
.format(surface_format.format)
.components(vk::ComponentMapping {
r: vk::ComponentSwizzle::R,
g: vk::ComponentSwizzle::G,
b: vk::ComponentSwizzle::B,
a: vk::ComponentSwizzle::A,
},
subresource_range: vk::ImageSubresourceRange {
})
.subresource_range(vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
},
image: image,
};
})
.image(image);
device.create_image_view(&create_view_info, None).unwrap()
}).collect();
})
.collect();
let device_memory_properties = instance.get_physical_device_memory_properties(pdevice);
let depth_image_create_info = vk::ImageCreateInfo {
s_type: vk::StructureType::IMAGE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
image_type: vk::ImageType::TYPE_2D,
format: vk::Format::D16_UNORM,
extent: vk::Extent3D {
let depth_image_create_info = vk::ImageCreateInfo::builder()
.image_type(vk::ImageType::TYPE_2D)
.format(vk::Format::D16_UNORM)
.extent(vk::Extent3D {
width: surface_resolution.width,
height: surface_resolution.height,
depth: 1,
},
mip_levels: 1,
array_layers: 1,
samples: vk::SampleCountFlags::TYPE_1,
tiling: vk::ImageTiling::OPTIMAL,
usage: vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT,
sharing_mode: vk::SharingMode::EXCLUSIVE,
queue_family_index_count: 0,
p_queue_family_indices: ptr::null(),
initial_layout: vk::ImageLayout::UNDEFINED,
};
})
.mip_levels(1)
.array_layers(1)
.samples(vk::SampleCountFlags::TYPE_1)
.tiling(vk::ImageTiling::OPTIMAL)
.usage(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT)
.sharing_mode(vk::SharingMode::EXCLUSIVE);
let depth_image = device.create_image(&depth_image_create_info, None).unwrap();
let depth_image_memory_req = device.get_image_memory_requirements(depth_image);
let depth_image_memory_index = find_memorytype_index(
&depth_image_memory_req,
&device_memory_properties,
vk::MemoryPropertyFlags::DEVICE_LOCAL,
).expect("Unable to find suitable memory index for depth image.");
)
.expect("Unable to find suitable memory index for depth image.");
let depth_image_allocate_info = vk::MemoryAllocateInfo::builder()
.allocation_size(depth_image_memory_req.size)
.memory_type_index(depth_image_memory_index);
let depth_image_allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
p_next: ptr::null(),
allocation_size: depth_image_memory_req.size,
memory_type_index: depth_image_memory_index,
};
let depth_image_memory = device
.allocate_memory(&depth_image_allocate_info, None)
.unwrap();
device
.bind_image_memory(depth_image, depth_image_memory, 0)
.expect("Unable to bind depth image memory");
record_submit_commandbuffer(
&device,
setup_command_buffer,
present_queue,
&[vk::PipelineStageFlags::BOTTOM_OF_PIPE],
&[],
&[],
&[],
|device, setup_command_buffer| {
let layout_transition_barrier = vk::ImageMemoryBarrier {
s_type: vk::StructureType::IMAGE_MEMORY_BARRIER,
p_next: ptr::null(),
src_access_mask: Default::default(),
dst_access_mask: vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
let layout_transition_barriers = vk::ImageMemoryBarrier::builder()
.image(depth_image)
.dst_access_mask(
vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
| vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
old_layout: vk::ImageLayout::UNDEFINED,
new_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
image: depth_image,
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::DEPTH,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
},
};
)
.new_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
.old_layout(vk::ImageLayout::UNDEFINED)
.subresource_range(
vk::ImageSubresourceRange::builder()
.aspect_mask(vk::ImageAspectFlags::DEPTH)
.layer_count(1)
.level_count(1)
.build(),
);
device.cmd_pipeline_barrier(
setup_command_buffer,
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
@ -637,39 +592,29 @@ impl ExampleBase {
vk::DependencyFlags::empty(),
&[],
&[],
&[layout_transition_barrier],
&[layout_transition_barriers.build()],
);
},
);
let depth_image_view_info = vk::ImageViewCreateInfo {
s_type: vk::StructureType::IMAGE_VIEW_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
view_type: vk::ImageViewType::TYPE_2D,
format: depth_image_create_info.format,
components: vk::ComponentMapping {
r: vk::ComponentSwizzle::IDENTITY,
g: vk::ComponentSwizzle::IDENTITY,
b: vk::ComponentSwizzle::IDENTITY,
a: vk::ComponentSwizzle::IDENTITY,
},
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::DEPTH,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
},
image: depth_image,
};
let depth_image_view_info = vk::ImageViewCreateInfo::builder()
.subresource_range(
vk::ImageSubresourceRange::builder()
.aspect_mask(vk::ImageAspectFlags::DEPTH)
.level_count(1)
.layer_count(1)
.build(),
)
.image(depth_image)
.format(depth_image_create_info.format)
.view_type(vk::ImageViewType::TYPE_2D);
let depth_image_view = device
.create_image_view(&depth_image_view_info, None)
.unwrap();
let semaphore_create_info = vk::SemaphoreCreateInfo {
s_type: vk::StructureType::SEMAPHORE_CREATE_INFO,
p_next: ptr::null(),
flags: Default::default(),
};
let semaphore_create_info = vk::SemaphoreCreateInfo::default();
let present_complete_semaphore = device
.create_semaphore(&semaphore_create_info, None)
.unwrap();
@ -725,11 +670,11 @@ impl Drop for ExampleBase {
}
self.device.destroy_command_pool(self.pool, None);
self.swapchain_loader
.destroy_swapchain_khr(self.swapchain, None);
.destroy_swapchain(self.swapchain, None);
self.device.destroy_device(None);
self.surface_loader.destroy_surface_khr(self.surface, None);
self.surface_loader.destroy_surface(self.surface, None);
self.debug_report_loader
.destroy_debug_report_callback_ext(self.debug_call_back, None);
.destroy_debug_report_callback(self.debug_call_back, None);
self.instance.destroy_instance(None);
}
}

View file

@ -4,7 +4,7 @@ version = "0.1.0"
authors = ["Maik Klein <maikklein@googlemail.com>"]
[dependencies]
vk-parse = "0.1"
vk-parse = "0.2"
vkxml = "0.3"
nom = "4.0"
heck = "0.3"

@ -1 +1 @@
Subproject commit 718a04e51b967fbe6de9d09ecfc15397f0eae5bd
Subproject commit 114c3546e195819bd53a34b39f5194b2989a5b12

View file

@ -1,11 +1,11 @@
#![recursion_limit = "256"]
extern crate heck;
extern crate itertools;
#[macro_use]
extern crate nom;
extern crate heck;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
extern crate itertools;
extern crate syn;
pub extern crate vk_parse;
pub extern crate vkxml;
@ -87,6 +87,7 @@ named!(cfloat<&str, f32>,
pub fn define_handle_macro() -> Tokens {
quote! {
#[macro_export]
macro_rules! define_handle{
($name: ident, $ty: ident) => {
#[repr(transparent)]
@ -131,6 +132,7 @@ pub fn define_handle_macro() -> Tokens {
pub fn handle_nondispatchable_macro() -> Tokens {
quote! {
#[macro_export]
macro_rules! handle_nondispatchable {
($name: ident, $ty: ident) => {
#[repr(transparent)]
@ -197,6 +199,7 @@ pub fn vk_version_macros() -> Tokens {
}
pub fn vk_bitflags_wrapped_macro() -> Tokens {
quote! {
#[macro_export]
macro_rules! vk_bitflags_wrapped {
($name: ident, $all: expr, $flag_type: ty) => {
@ -350,8 +353,10 @@ pub fn platform_specific_types() -> Tokens {
pub type HANDLE = *mut c_void;
pub type DWORD = c_ulong;
pub type LPCWSTR = *const u16;
#[allow(non_camel_case_types)]
pub type zx_handle_t = u32;
// FIXME: Platform specific types that should come from a library
// FIXME: Platform specific types that should come from a library id:0
// typedefs are only here so that the code compiles for now
#[allow(non_camel_case_types)]
pub type SECURITY_ATTRIBUTES = ();
@ -534,7 +539,8 @@ impl CommandExt for vkxml::Command {
.map(|field| match field.basetype.as_str() {
"VkDevice" | "VkCommandBuffer" | "VkQueue" => true,
_ => false,
}).unwrap_or(false);
})
.unwrap_or(false);
match self.name.as_str() {
"vkGetInstanceProcAddr" => FunctionType::Static,
"vkCreateInstance"
@ -671,7 +677,11 @@ impl FieldExt for vkxml::Field {
pub type CommandMap<'a> = HashMap<vkxml::Identifier, &'a vkxml::Command>;
fn generate_function_pointers(ident: Ident, commands: &[&vkxml::Command]) -> quote::Tokens {
fn generate_function_pointers<'a>(
ident: Ident,
commands: &[&'a vkxml::Command],
fn_cache: &mut HashSet<&'a str>,
) -> quote::Tokens {
let names: Vec<_> = commands.iter().map(|cmd| cmd.command_ident()).collect();
let names_ref = &names;
let names_ref1 = &names;
@ -685,6 +695,19 @@ fn generate_function_pointers(ident: Ident, commands: &[&vkxml::Command]) -> quo
let names_left = &names;
let names_right = &names;
let pfn_commands: Vec<_> = commands
.iter()
.filter(|cmd| {
let ident = cmd.name.as_str();
if !fn_cache.contains(ident) {
fn_cache.insert(ident);
return true;
} else {
return false;
}
})
.collect();
let params: Vec<Vec<(Ident, Tokens)>> = commands
.iter()
.map(|cmd| {
@ -695,9 +718,11 @@ fn generate_function_pointers(ident: Ident, commands: &[&vkxml::Command]) -> quo
let name = field.param_ident();
let ty = field.type_tokens();
(name, ty)
}).collect();
})
.collect();
params
}).collect();
})
.collect();
let params_names: Vec<Vec<_>> = params
.iter()
@ -706,7 +731,8 @@ fn generate_function_pointers(ident: Ident, commands: &[&vkxml::Command]) -> quo
.iter()
.map(|&(param_name, _)| param_name)
.collect()
}).collect();
})
.collect();
let param_names_ref = &params_names;
let expanded_params: Vec<_> = params
.iter()
@ -717,7 +743,8 @@ fn generate_function_pointers(ident: Ident, commands: &[&vkxml::Command]) -> quo
quote! {
#(#inner_params_iter,)*
}
}).collect();
})
.collect();
let expanded_params_unused: Vec<_> = params
.iter()
.map(|inner_params| {
@ -728,7 +755,8 @@ fn generate_function_pointers(ident: Ident, commands: &[&vkxml::Command]) -> quo
quote! {
#(#inner_params_iter,)*
}
}).collect();
})
.collect();
let expanded_params_ref = &expanded_params;
let return_types: Vec<_> = commands
@ -736,10 +764,45 @@ fn generate_function_pointers(ident: Ident, commands: &[&vkxml::Command]) -> quo
.map(|cmd| cmd.return_type.type_tokens())
.collect();
let return_types_ref = &return_types;
let pfn_names: Vec<_> = pfn_commands
.iter()
.map(|cmd| Ident::from(format!("PFN_{}", cmd.name.as_str())))
.collect();
let pfn_names_ref = &pfn_names;
let signature_params: Vec<Vec<_>> = pfn_commands
.iter()
.map(|cmd| {
let params: Vec<_> = cmd
.param
.iter()
.map(|field| {
let name = field.param_ident();
let ty = field.type_tokens();
quote! { #name: #ty }
})
.collect();
params
})
.collect();
let signature_params_ref = &signature_params;
let pfn_return_types: Vec<_> = pfn_commands
.iter()
.map(|cmd| cmd.return_type.type_tokens())
.collect();
let pfn_return_types_ref = &pfn_return_types;
quote! {
#(
#[allow(non_camel_case_types)]
pub type #pfn_names_ref = extern "system" fn(#(#signature_params_ref),*) -> #pfn_return_types_ref;
)*
pub struct #ident {
#(
#names_ref: extern "system" fn(#expanded_params_ref) -> #return_types_ref,
pub #names_ref: extern "system" fn(#expanded_params_ref) -> #return_types_ref,
)*
}
@ -804,16 +867,17 @@ impl<'a> ConstantExt for ExtensionConstant<'a> {
pub fn generate_extension_constants<'a>(
extension_name: &str,
extension_number: i64,
extension_items: &'a [vk_parse::ExtensionItem],
extension_items: &'a [vk_parse::ExtensionChild],
const_cache: &mut HashSet<&'a str>,
const_values: &mut HashMap<Ident, Vec<Ident>>,
) -> quote::Tokens {
let items = extension_items
.iter()
.filter_map(|item| match item {
vk_parse::ExtensionItem::Require { items, .. } => Some(items.iter()),
vk_parse::ExtensionChild::Require { items, .. } => Some(items.iter()),
_ => None,
}).flat_map(|iter| iter);
})
.flat_map(|iter| iter);
let enum_tokens = items.filter_map(|item| match item {
vk_parse::InterfaceItem::Enum(_enum) => {
use vk_parse::EnumSpec;
@ -821,8 +885,6 @@ pub fn generate_extension_constants<'a>(
return None;
}
let (constant, extends) = match &_enum.spec {
EnumSpec::Alias { .. } => None,
EnumSpec::Value { .. } => None,
EnumSpec::Bitpos { bitpos, extends } => {
Some((Constant::BitPos(*bitpos as u32), extends.clone()))
}
@ -847,7 +909,9 @@ pub fn generate_extension_constants<'a>(
constant,
};
let ident = name_to_tokens(&extends);
const_values.entry(ident.clone()).or_insert_with(Vec::new)
const_values
.entry(ident.clone())
.or_insert_with(Vec::new)
.push(ext_constant.variant_ident(&extends));
let impl_block = bitflags_impl_block(ident, &extends, &[&ext_constant]);
let doc_string = format!("Generated from '{}'", extension_name);
@ -865,32 +929,37 @@ pub fn generate_extension_constants<'a>(
#(#enum_tokens)*
}
}
pub fn generate_extension_commands(
pub fn generate_extension_commands<'a>(
extension_name: &str,
items: &[vk_parse::ExtensionItem],
cmd_map: &CommandMap,
items: &[vk_parse::ExtensionChild],
cmd_map: &CommandMap<'a>,
fn_cache: &mut HashSet<&'a str>,
) -> Tokens {
let commands = items
.iter()
.filter_map(|ext_item| match ext_item {
vk_parse::ExtensionItem::Require { items, .. } => {
vk_parse::ExtensionChild::Require { items, .. } => {
Some(items.iter().filter_map(|item| match item {
vk_parse::InterfaceItem::Command { name, .. } => cmd_map.get(name).map(|c| *c),
vk_parse::InterfaceItem::Command { ref name, .. } => {
cmd_map.get(name).map(|c| *c)
}
_ => None,
}))
}
_ => None,
}).flat_map(|iter| iter)
})
.flat_map(|iter| iter)
.collect_vec();
let name = format!("{}Fn", extension_name.to_camel_case());
let ident = Ident::from(&name[2..]);
generate_function_pointers(ident, &commands)
generate_function_pointers(ident, &commands, fn_cache)
}
pub fn generate_extension<'a>(
extension: &'a vk_parse::Extension,
cmd_map: &CommandMap,
cmd_map: &CommandMap<'a>,
const_cache: &mut HashSet<&'a str>,
const_values: &mut HashMap<Ident, Vec<Ident>>
const_values: &mut HashMap<Ident, Vec<Ident>>,
fn_cache: &mut HashSet<&'a str>,
) -> Option<quote::Tokens> {
// Okay this is a little bit odd. We need to generate all extensions, even disabled ones,
// because otherwise some StructureTypes won't get generated. But we don't generate extensions
@ -901,11 +970,11 @@ pub fn generate_extension<'a>(
let extension_tokens = generate_extension_constants(
&extension.name,
extension.number.unwrap_or(0),
&extension.items,
&extension.children,
const_cache,
const_values,
);
let fp = generate_extension_commands(&extension.name, &extension.items, cmd_map);
let fp = generate_extension_commands(&extension.name, &extension.children, cmd_map, fn_cache);
let q = quote! {
#fp
#extension_tokens
@ -919,7 +988,10 @@ pub fn generate_typedef(typedef: &vkxml::Typedef) -> Tokens {
pub type #typedef_name = #typedef_ty;
}
}
pub fn generate_bitmask(bitmask: &vkxml::Bitmask) -> Option<Tokens> {
pub fn generate_bitmask(
bitmask: &vkxml::Bitmask,
bitflags_cache: &mut HashSet<Ident>,
) -> Option<Tokens> {
// Workaround for empty bitmask
if bitmask.name.is_empty() {
return None;
@ -931,6 +1003,10 @@ pub fn generate_bitmask(bitmask: &vkxml::Bitmask) -> Option<Tokens> {
let name = &bitmask.name[2..];
let ident = Ident::from(name);
if bitflags_cache.contains(&ident) {
return None;
};
bitflags_cache.insert(ident.clone());
Some(quote! {
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -946,8 +1022,8 @@ pub enum EnumType {
pub fn variant_ident(enum_name: &str, variant_name: &str) -> Ident {
let _name = enum_name.replace("FlagBits", "");
// TODO: Should be read from vk.xml
// TODO: Also needs to be more robust, vendor names can be substrings from itself,
// TODO: Should be read from vk.xml id:2
// TODO: Also needs to be more robust, vendor names can be substrings from itself, id:4
// like NVX and NV
let vendors = ["_NVX", "_KHR", "_EXT", "_NV", "_AMD", "_ANDROID", "_GOOGLE"];
let mut struct_name = _name.to_shouty_snake_case();
@ -986,7 +1062,8 @@ pub fn bitflags_impl_block(
let variant_ident = constant.variant_ident(enum_name);
let tokens = constant.to_tokens();
(variant_ident, tokens)
}).collect_vec();
})
.collect_vec();
let notations = constants.iter().map(|constant| {
constant.notation().map(|n| {
@ -1016,7 +1093,8 @@ pub fn bitflags_impl_block(
pub fn generate_enum<'a>(
_enum: &'a vkxml::Enumeration,
const_cache: &mut HashSet<&'a str>,
const_values: &mut HashMap<Ident, Vec<Ident>>
const_values: &mut HashMap<Ident, Vec<Ident>>,
bitflags_cache: &mut HashSet<Ident>,
) -> EnumType {
let name = &_enum.name[2..];
let _name = name.replace("FlagBits", "Flags");
@ -1027,7 +1105,8 @@ pub fn generate_enum<'a>(
.filter_map(|elem| match *elem {
vkxml::EnumerationElement::Enum(ref constant) => Some(constant),
_ => None,
}).collect_vec();
})
.collect_vec();
let values = const_values.entry(ident.clone()).or_insert_with(Vec::new);
for constant in &constants {
const_cache.insert(constant.name.as_str());
@ -1043,6 +1122,10 @@ pub fn generate_enum<'a>(
let all_bits_term = Term::intern(&format!("0b{:b}", all_bits));
let impl_bitflags = bitflags_impl_block(ident, &_enum.name, &constants);
if bitflags_cache.contains(&ident) {
EnumType::Bitflags(quote! {})
} else {
bitflags_cache.insert(ident.clone());
let q = quote! {
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -1051,6 +1134,7 @@ pub fn generate_enum<'a>(
#impl_bitflags
};
EnumType::Bitflags(q)
}
} else {
let impl_block = bitflags_impl_block(ident, &_enum.name, &constants);
let enum_quote = quote! {
@ -1131,7 +1215,8 @@ fn is_static_array(field: &vkxml::Field) -> bool {
.map(|ty| match ty {
vkxml::ArrayType::Static => true,
_ => false,
}).unwrap_or(false)
})
.unwrap_or(false)
}
pub fn derive_default(_struct: &vkxml::Struct) -> Option<Tokens> {
let name = name_to_tokens(&_struct.name);
@ -1198,9 +1283,7 @@ pub fn derive_default(_struct: &vkxml::Struct) -> Option<Tokens> {
}
}
}
} else if is_static_array(field)
|| handles.contains(&field.basetype.as_str())
{
} else if is_static_array(field) || handles.contains(&field.basetype.as_str()) {
quote! {
#param_ident: unsafe { ::std::mem::zeroed() }
}
@ -1237,7 +1320,9 @@ pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Opt
.map(|n| n.contains("pfn"))
.unwrap_or(false)
});
let contains_static_array = members.clone().any(|x| is_static_array(x) && x.basetype == "char");
let contains_static_array = members
.clone()
.any(|x| is_static_array(x) && x.basetype == "char");
let contains_union = members
.clone()
.any(|field| union_types.contains(field.basetype.as_str()));
@ -1250,7 +1335,7 @@ pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Opt
let debug_value = if is_static_array(field) && field.basetype == "char" {
quote! {
&unsafe {
::std::ffi::CStr::from_ptr(self.#param_ident.as_ptr() as *const i8)
::std::ffi::CStr::from_ptr(self.#param_ident.as_ptr() as *const c_char)
}
}
} else if param_ident.as_ref().contains("pfn") {
@ -1282,35 +1367,68 @@ pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Opt
}
pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
if &_struct.name == "VkBaseInStructure" || &_struct.name == "VkBaseOutStructure" {
return None;
}
let name = name_to_tokens(&_struct.name);
let name_builder = name_to_tokens(&(_struct.name.to_string() + "Builder"));
let name_builder = name_to_tokens(&(_struct.name.clone() + "Builder"));
let members = _struct.elements.iter().filter_map(|elem| match *elem {
vkxml::StructElement::Member(ref field) => Some(field),
_ => None,
});
let filter_members: Vec<String> = members.clone().filter_map(|field| {
let (has_next, is_next_const) = match members
.clone()
.find(|field| field.param_ident().to_string() == "p_next")
{
Some(p_next) => {
if p_next.type_tokens().to_string().starts_with("*const") {
(true, true)
} else {
(true, false)
}
}
None => (false, false),
};
let nofilter_count_members = [
"VkPipelineViewportStateCreateInfo.pViewports",
"VkPipelineViewportStateCreateInfo.pScissors",
"VkDescriptorSetLayoutBinding.pImmutableSamplers",
];
let filter_members: Vec<String> = members
.clone()
.filter_map(|field| {
let field_name = field.name.as_ref().unwrap();
// Associated _count members
if field.array.is_some() {
if let Some(ref array_size) = field.size {
if !array_size.starts_with("latexmath") {
if !array_size.starts_with("latexmath")
&& !nofilter_count_members
.iter()
.any(|n| *n == &(_struct.name.clone() + "." + field_name))
{
return Some((*array_size).clone());
}
}
}
// VkShaderModuleCreateInfo requiers a custom setter
if field.name.as_ref().unwrap() == "codeSize" {
return Some(field.name.clone().unwrap());
if field_name == "codeSize" {
return Some(field_name.clone());
}
None
}).collect();
})
.collect();
let setters = members.clone().filter_map(|field| {
let param_ident = field.param_ident();
let param_ty_tokens = field.type_tokens();
let param_ty_string = param_ty_tokens.to_string();
let param_ident_string = param_ident.to_string();
if param_ident_string == "s_type" || param_ident_string == "p_next" {
@ -1342,12 +1460,19 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
}
});
}
if name == "pSampleMask" {
return Some(quote!{
pub fn sample_mask(mut self, sample_mask: &'a [SampleMask]) -> #name_builder<'a> {
self.inner.p_sample_mask = sample_mask.as_ptr() as *const SampleMask;
self
}
});
}
}
// TODO: Improve in future when https://github.com/rust-lang/rust/issues/53667 is merged
// TODO: Improve in future when https://github.com/rust-lang/rust/issues/53667 is merged id:6
if param_ident_string.starts_with("p_") || param_ident_string.starts_with("pp_") {
let param_ty_string = param_ty_tokens.to_string();
if param_ty_string == "*const c_char" {
return Some(quote!{
pub fn #param_ident_short(mut self, #param_ident_short: &'a ::std::ffi::CStr) -> #name_builder<'a> {
@ -1360,45 +1485,48 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
if let Some(ref array_type) = field.array {
if let Some(ref array_size) = field.size {
if !array_size.starts_with("latexmath") {
let length_type;
let array_size_ident = Ident::from(array_size.to_snake_case().as_str());
if array_size_ident.to_string().contains("_count") {
length_type = Term::intern("u32");
} else {
length_type = Term::intern("usize");
}
if param_ty_string == "*const *const c_char" {
return Some(quote!{
pub fn #param_ident_short(mut self, #param_ident_short: &'a [*const c_char]) -> #name_builder<'a> {
self.inner.#param_ident = #param_ident_short.as_ptr();
self.inner.#array_size_ident = #param_ident_short.len() as #length_type;
self.inner.#array_size_ident = #param_ident_short.len() as _;
self
}
});
}
let slice_param_ty_tokens;
let ptr_mutability;
let ptr;
if param_ty_string.starts_with("*const ") {
slice_param_ty_tokens = "&'a [".to_string() + &param_ty_string[7..] + "]";
ptr_mutability = ".as_ptr()";
let slice_type = &param_ty_string[7..];
if slice_type == "c_void" {
slice_param_ty_tokens = "&'a [u8]".to_string();
ptr = ".as_ptr() as *const c_void";
} else {
slice_param_ty_tokens = "&'a [".to_string() + slice_type + "]";
ptr = ".as_ptr()";
}
} else {
// *mut
slice_param_ty_tokens =
"&'a mut [".to_string() + &param_ty_string[5..] + "]";
ptr_mutability = ".as_mut_ptr()";
let slice_type = &param_ty_string[5..];
if slice_type == "c_void" {
slice_param_ty_tokens = "&mut 'a [u8]".to_string();
ptr = ".as_mut_ptr() as *mut c_void";
} else {
slice_param_ty_tokens = "&'a mut [".to_string() + slice_type + "]";
ptr = ".as_mut_ptr()";
}
}
let slice_param_ty_tokens = Term::intern(&slice_param_ty_tokens);
let ptr_mutability = Term::intern(ptr_mutability);
let ptr = Term::intern(ptr);
match array_type {
vkxml::ArrayType::Dynamic => {
return Some(quote!{
pub fn #param_ident_short(mut self, #param_ident_short: #slice_param_ty_tokens) -> #name_builder<'a> {
self.inner.#array_size_ident = #param_ident_short.len() as #length_type;
self.inner.#param_ident = #param_ident_short#ptr_mutability;
self.inner.#array_size_ident = #param_ident_short.len() as _;
self.inner.#param_ident = #param_ident_short#ptr;
self
}
});
@ -1421,6 +1549,15 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
}
}
if param_ty_string == "Bool32" {
return Some(quote!{
pub fn #param_ident_short(mut self, #param_ident_short: bool) -> #name_builder<'a> {
self.inner.#param_ident = #param_ident_short.into();
self
}
});
}
Some(quote!{
pub fn #param_ident_short(mut self, #param_ident_short: #param_ty_tokens) -> #name_builder<'a> {
self.inner.#param_ident = #param_ident_short;
@ -1429,6 +1566,50 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
})
});
let mut nexts = Vec::new();
let extends_name = name_to_tokens(&format!("Extends{}", name));
if let Some(extends) = &_struct.extends {
for target in extends.split(',') {
let target = match target {
// https://github.com/KhronosGroup/Vulkan-Docs/pull/870
"VkPhysicalDeviceProperties" => "VkPhysicalDeviceProperties2",
x => x,
};
let target_ident = name_to_tokens(&format!("Extends{}", name_to_tokens(target)));
nexts.push(quote! {
unsafe impl #target_ident for #name {}
});
}
}
let next_function = if has_next {
if is_next_const {
quote! {
pub fn next<T>(mut self, next: &'a T) -> #name_builder<'a> where T: #extends_name {
self.inner.p_next = next as *const T as *const c_void;
self
}
}
} else {
quote! {
pub fn next<T>(mut self, next: &'a mut T) -> #name_builder<'a> where T: #extends_name {
self.inner.p_next = next as *mut T as *mut c_void;
self
}
}
}
} else {
quote! {}
};
let next_trait = if has_next {
quote! {
pub unsafe trait #extends_name {}
}
} else {
quote! {}
};
let q = quote! {
impl #name {
pub fn builder<'a>() -> #name_builder<'a> {
@ -1444,6 +1625,10 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
marker: ::std::marker::PhantomData<&'a ()>,
}
#next_trait
#(#nexts)*
impl<'a> ::std::ops::Deref for #name_builder<'a> {
type Target = #name;
@ -1455,6 +1640,8 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
impl<'a> #name_builder<'a> {
#(#setters)*
#next_function
pub fn build(self) -> #name {
self.inner
}
@ -1578,20 +1765,25 @@ fn generate_union(union: &vkxml::Union) -> Tokens {
pub fn generate_definition(
definition: &vkxml::DefinitionsElement,
union_types: &HashSet<&str>,
bitflags_cache: &mut HashSet<Ident>,
) -> Option<Tokens> {
match *definition {
vkxml::DefinitionsElement::Typedef(ref typedef) => Some(generate_typedef(typedef)),
vkxml::DefinitionsElement::Struct(ref _struct) => {
Some(generate_struct(_struct, union_types))
}
vkxml::DefinitionsElement::Bitmask(ref mask) => generate_bitmask(mask),
vkxml::DefinitionsElement::Bitmask(ref mask) => generate_bitmask(mask, bitflags_cache),
vkxml::DefinitionsElement::Handle(ref handle) => generate_handle(handle),
vkxml::DefinitionsElement::FuncPtr(ref fp) => Some(generate_funcptr(fp)),
vkxml::DefinitionsElement::Union(ref union) => Some(generate_union(union)),
_ => None,
}
}
pub fn generate_feature(feature: &vkxml::Feature, commands: &CommandMap) -> quote::Tokens {
pub fn generate_feature<'a>(
feature: &vkxml::Feature,
commands: &CommandMap<'a>,
fn_cache: &mut HashSet<&'a str>,
) -> quote::Tokens {
let (static_commands, entry_commands, device_commands, instance_commands) = feature
.elements
.iter()
@ -1606,11 +1798,13 @@ pub fn generate_feature(feature: &vkxml::Feature, commands: &CommandMap) -> quot
} else {
None
}
}).collect()
})
.collect()
} else {
vec![]
}
}).filter_map(|cmd_ref| commands.get(&cmd_ref.name))
})
.filter_map(|cmd_ref| commands.get(&cmd_ref.name))
.fold(
(Vec::new(), Vec::new(), Vec::new(), Vec::new()),
|mut acc, &cmd_ref| {
@ -1633,21 +1827,24 @@ pub fn generate_feature(feature: &vkxml::Feature, commands: &CommandMap) -> quot
);
let version = feature.version_string();
let static_fn = if feature.version == 1.0 {
generate_function_pointers(Ident::from("StaticFn"), &static_commands)
generate_function_pointers(Ident::from("StaticFn"), &static_commands, fn_cache)
} else {
quote! {}
};
let entry = generate_function_pointers(
Ident::from(format!("EntryFnV{}", version).as_str()),
&entry_commands,
fn_cache,
);
let instance = generate_function_pointers(
Ident::from(format!("InstanceFnV{}", version).as_str()),
&instance_commands,
fn_cache,
);
let device = generate_function_pointers(
Ident::from(format!("DeviceFnV{}", version).as_str()),
&device_commands,
fn_cache,
);
quote! {
#static_fn
@ -1683,12 +1880,16 @@ pub fn generate_constant<'a>(
pub fn generate_feature_extension<'a>(
registry: &'a vk_parse::Registry,
const_cache: &mut HashSet<&'a str>,
const_values: &mut HashMap<Ident, Vec<Ident>>
const_values: &mut HashMap<Ident, Vec<Ident>>,
) -> Tokens {
let constants = registry.0.iter().filter_map(|item| match item {
vk_parse::RegistryItem::Feature { name, items, .. } => {
Some(generate_extension_constants(name, 0, items, const_cache, const_values))
}
vk_parse::RegistryChild::Feature(feature) => Some(generate_extension_constants(
&feature.name,
0,
&feature.children,
const_cache,
const_values,
)),
_ => None,
});
quote! {
@ -1697,7 +1898,8 @@ pub fn generate_feature_extension<'a>(
}
pub fn generate_const_displays<'a>(const_values: &HashMap<Ident, Vec<Ident>>) -> Tokens {
let impls = const_values.iter()
let impls = const_values
.iter()
.filter(|(ty, _)| *ty != "Result")
.map(|(ty, values)| {
if ty.to_string().contains("Flags") {
@ -1757,7 +1959,33 @@ pub fn generate_const_displays<'a>(const_values: &HashMap<Ident, Vec<Ident>>) ->
#(#impls)*
}
}
pub fn generate_aliases_of_types<'a>(
types: &'a vk_parse::Types,
ty_cache: &mut HashSet<Ident>,
) -> Tokens {
let aliases = types
.children
.iter()
.filter_map(|child| match child {
vk_parse::TypesChild::Type(ty) => Some((ty.name.as_ref()?, ty.alias.as_ref()?)),
_ => None,
})
.filter_map(|(name, alias)| {
let name_ident = name_to_tokens(name);
if ty_cache.contains(&name_ident) {
return None;
};
ty_cache.insert(name_ident.clone());
let alias_ident = name_to_tokens(alias);
let tokens = quote! {
pub type #name_ident = #alias_ident;
};
Some(tokens)
});
quote! {
#(#aliases)*
}
}
pub fn write_source_code(path: &Path) {
use std::fs::File;
use std::io::Write;
@ -1766,10 +1994,22 @@ pub fn write_source_code(path: &Path) {
.0
.iter()
.filter_map(|item| match item {
vk_parse::RegistryItem::Extensions { items: ext, .. } => Some(ext),
vk_parse::RegistryChild::Extensions(ref ext) => Some(&ext.children),
_ => None,
}).nth(0)
})
.nth(0)
.expect("extension");
let mut ty_cache = HashSet::new();
let aliases: Vec<_> = spec2
.0
.iter()
.filter_map(|item| match item {
vk_parse::RegistryChild::Types(ref ty) => {
Some(generate_aliases_of_types(ty, &mut ty_cache))
}
_ => None,
})
.collect();
let spec = vk_parse::parse_file_as_vkxml(path);
let commands: HashMap<vkxml::Identifier, &vkxml::Command> = spec
@ -1778,7 +2018,8 @@ pub fn write_source_code(path: &Path) {
.filter_map(|elem| match elem {
vkxml::RegistryElement::Commands(ref cmds) => Some(cmds),
_ => None,
}).flat_map(|cmds| cmds.elements.iter().map(|cmd| (cmd.name.clone(), cmd)))
})
.flat_map(|cmds| cmds.elements.iter().map(|cmd| (cmd.name.clone(), cmd)))
.collect();
let features: Vec<&vkxml::Feature> = spec
@ -1787,7 +2028,8 @@ pub fn write_source_code(path: &Path) {
.filter_map(|elem| match elem {
vkxml::RegistryElement::Features(ref features) => Some(features),
_ => None,
}).flat_map(|features| features.elements.iter())
})
.flat_map(|features| features.elements.iter())
.collect();
let definitions: Vec<&vkxml::DefinitionsElement> = spec
@ -1796,7 +2038,8 @@ pub fn write_source_code(path: &Path) {
.filter_map(|elem| match elem {
vkxml::RegistryElement::Definitions(ref definitions) => Some(definitions),
_ => None,
}).flat_map(|definitions| definitions.elements.iter())
})
.flat_map(|definitions| definitions.elements.iter())
.collect();
let enums: Vec<&vkxml::Enumeration> = spec
@ -1805,12 +2048,14 @@ pub fn write_source_code(path: &Path) {
.filter_map(|elem| match elem {
vkxml::RegistryElement::Enums(ref enums) => Some(enums),
_ => None,
}).flat_map(|enums| {
})
.flat_map(|enums| {
enums.elements.iter().filter_map(|_enum| match *_enum {
vkxml::EnumsElement::Enumeration(ref e) => Some(e),
_ => None,
})
}).collect();
})
.collect();
let constants: Vec<&vkxml::Constant> = spec
.elements
@ -1818,16 +2063,19 @@ pub fn write_source_code(path: &Path) {
.filter_map(|elem| match elem {
vkxml::RegistryElement::Constants(ref constants) => Some(constants),
_ => None,
}).flat_map(|constants| constants.elements.iter())
})
.flat_map(|constants| constants.elements.iter())
.collect();
let mut fn_cache = HashSet::new();
let mut bitflags_cache = HashSet::new();
let mut const_cache = HashSet::new();
let mut const_values: HashMap<Ident, Vec<Ident>> = HashMap::new();
let (enum_code, bitflags_code) = enums
.into_iter()
.map(|e| generate_enum(e, &mut const_cache, &mut const_values))
.map(|e| generate_enum(e, &mut const_cache, &mut const_values, &mut bitflags_cache))
.fold((Vec::new(), Vec::new()), |mut acc, elem| {
match elem {
EnumType::Enum(token) => acc.0.push(token),
@ -1842,7 +2090,15 @@ pub fn write_source_code(path: &Path) {
.collect();
let extension_code = extensions
.iter()
.filter_map(|ext| generate_extension(ext, &commands, &mut const_cache, &mut const_values))
.filter_map(|ext| {
generate_extension(
ext,
&commands,
&mut const_cache,
&mut const_values,
&mut fn_cache,
)
})
.collect_vec();
let union_types = definitions
@ -1850,18 +2106,20 @@ pub fn write_source_code(path: &Path) {
.filter_map(|def| match def {
vkxml::DefinitionsElement::Union(ref union) => Some(union.name.as_str()),
_ => None,
}).collect::<HashSet<&str>>();
})
.collect::<HashSet<&str>>();
let definition_code: Vec<_> = definitions
.into_iter()
.filter_map(|def| generate_definition(def, &union_types))
.filter_map(|def| generate_definition(def, &union_types, &mut bitflags_cache))
.collect();
let feature_code: Vec<_> = features
.iter()
.map(|feature| generate_feature(feature, &commands))
.map(|feature| generate_feature(feature, &commands, &mut fn_cache))
.collect();
let feature_extensions_code = generate_feature_extension(&spec2, &mut const_cache, &mut const_values);
let feature_extensions_code =
generate_feature_extension(&spec2, &mut const_cache, &mut const_values);
let const_displays = generate_const_displays(&const_values);
@ -1894,6 +2152,7 @@ pub fn write_source_code(path: &Path) {
#(#extension_code)*
#feature_extensions_code
#const_displays
#(#aliases)*
};
write!(&mut file, "{}", source_code).expect("Unable to write to file");
}

17
imdone-help.md Normal file
View file

@ -0,0 +1,17 @@
imdone-help
====
#HELP: Try dragging this card to your new list id:8 +imdone-help
#HELP: Ignore files by adding `.imdoneignore` to the root of your project. id:1 +imdone-help
- [imdone.io](https://imdone.io) implements this with the [ignore package](https://www.npmjs.com/package/ignore)
#HELP: Use markdown in todo comments or in the description id:3 +imdone-help
- **This is a description...**
#HELP: Add tags to your comments like this `+mvp` id:5 +imdone-help
#HELP: Add metadata like this... points:5 id:7 +imdone-help
- [imdone.io](https://imdone.io) adds `id:n` to all your todo comments, so take care to leave that one alone
#HELP: Include subtasks using GFM task lists id:9 +imdone-help
- [ ] A task yet to be done
- [x] This is done

View file

@ -1,2 +1 @@
max_width = 100
error_on_line_overflow = false