Skip to content

Commit

Permalink
Add no_std support (#664)
Browse files Browse the repository at this point in the history
Co-authored-by: Marijn Suijten <marijn@traverseresearch.nl>
  • Loading branch information
i509VCB and MarijnS95 authored Mar 25, 2024
1 parent 2cd465f commit 9f712c5
Show file tree
Hide file tree
Showing 107 changed files with 7,004 additions and 7,831 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.69.0
- run: cargo check -p ash -p ash-rewrite -p ash-window --all-features
- name: Check ash, ash-window and ash-rewrite
run: cargo check -p ash -p ash-rewrite -p ash-window --all-features
- name: Check ash with no_std
run: cargo check -p ash --no-default-features

# TODO: add a similar job for the rewrite once that generates code
generated:
Expand Down
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added `std` feature. Disabling this feature makes ash `no_std` (#664)
- Added `Handle::is_null()` to allow checking if a handle is a `NULL` value (#694)
- Allow building `Entry`/`Instance`/`Device` from handle+fns (see their `from_parts_1_x()` associated functions) (#748)
- Update Vulkan-Headers to 1.3.281 (#760, #763, #783, #816, #840)
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ A very lightweight wrapper around Vulkan
- [x] No validation, everything is **unsafe**
- [x] Generated from `vk.xml`
- [x] Support for Vulkan `1.1`, `1.2`, `1.3`
- [x] `no_std` support

## ⚠️ Semver compatibility warning

Expand Down Expand Up @@ -193,6 +194,10 @@ The default `loaded` cargo feature will dynamically load the default Vulkan libr

If, on the other hand, your application cannot handle Vulkan being missing at runtime, you can instead enable the `linked` feature, which will link your binary with the Vulkan loader directly and expose the infallible `Entry::linked`.

### Use in `no_std` environments

Ash can be used in `no_std` environments (with `alloc`) by disabling the `std` feature.

## Example

You can find the examples [here](https://github.com/ash-rs/ash/tree/master/ash-examples).
Expand Down
2 changes: 1 addition & 1 deletion ash-examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ winit = { version = "0.29", features = ["rwh_06"] }
# The examples require the validation layers, which means the SDK or
# equivalent development packages should be present, so we can link
# directly and benefit from the infallible `Entry` constructor.
ash = { path = "../ash", default-features = false, features = ["linked", "debug"] }
ash = { path = "../ash", default-features = false, features = ["linked", "debug", "std"] }
ash-window = { path = "../ash-window" }
4 changes: 2 additions & 2 deletions ash-examples/src/bin/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::default::Default;
use std::error::Error;
use std::ffi::CStr;
use std::ffi;
use std::io::Cursor;
use std::mem;
use std::os::raw::c_void;
Expand Down Expand Up @@ -567,7 +567,7 @@ fn main() -> Result<(), Box<dyn Error>> {
.create_pipeline_layout(&layout_create_info, None)
.unwrap();

let shader_entry_name = CStr::from_bytes_with_nul_unchecked(b"main\0");
let shader_entry_name = ffi::CStr::from_bytes_with_nul_unchecked(b"main\0");
let shader_stage_create_infos = [
vk::PipelineShaderStageCreateInfo {
module: vertex_shader_module,
Expand Down
4 changes: 2 additions & 2 deletions ash-examples/src/bin/triangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::default::Default;
use std::error::Error;
use std::ffi::CStr;
use std::ffi;
use std::io::Cursor;
use std::mem;

Expand Down Expand Up @@ -229,7 +229,7 @@ fn main() -> Result<(), Box<dyn Error>> {
.create_pipeline_layout(&layout_create_info, None)
.unwrap();

let shader_entry_name = CStr::from_bytes_with_nul_unchecked(b"main\0");
let shader_entry_name = ffi::CStr::from_bytes_with_nul_unchecked(b"main\0");
let shader_stage_create_infos = [
vk::PipelineShaderStageCreateInfo {
module: vertex_shader_module,
Expand Down
19 changes: 8 additions & 11 deletions ash-examples/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@
)]

use std::{
borrow::Cow, cell::RefCell, default::Default, error::Error, ffi::CStr, ops::Drop,
os::raw::c_char,
borrow::Cow, cell::RefCell, default::Default, error::Error, ffi, ops::Drop, os::raw::c_char,
};

use ash::extensions::{
ext::debug_utils,
khr::{surface, swapchain},
};
#[cfg(any(target_os = "macos", target_os = "ios"))]
use ash::vk::khr;
use ash::{vk, Device, Entry, Instance};
use winit::{
event::{ElementState, Event, KeyEvent, WindowEvent},
Expand Down Expand Up @@ -106,13 +103,13 @@ unsafe extern "system" fn vulkan_debug_callback(
let message_id_name = if callback_data.p_message_id_name.is_null() {
Cow::from("")
} else {
CStr::from_ptr(callback_data.p_message_id_name).to_string_lossy()
ffi::CStr::from_ptr(callback_data.p_message_id_name).to_string_lossy()
};

let message = if callback_data.p_message.is_null() {
Cow::from("")
} else {
CStr::from_ptr(callback_data.p_message).to_string_lossy()
ffi::CStr::from_ptr(callback_data.p_message).to_string_lossy()
};

println!(
Expand Down Expand Up @@ -215,9 +212,9 @@ impl ExampleBase {
.build(&event_loop)
.unwrap();
let entry = Entry::linked();
let app_name = CStr::from_bytes_with_nul_unchecked(b"VulkanTriangle\0");
let app_name = ffi::CStr::from_bytes_with_nul_unchecked(b"VulkanTriangle\0");

let layer_names = [CStr::from_bytes_with_nul_unchecked(
let layer_names = [ffi::CStr::from_bytes_with_nul_unchecked(
b"VK_LAYER_KHRONOS_validation\0",
)];
let layers_names_raw: Vec<*const c_char> = layer_names
Expand All @@ -233,9 +230,9 @@ impl ExampleBase {

#[cfg(any(target_os = "macos", target_os = "ios"))]
{
extension_names.push(khr::portability_enumeration::NAME.as_ptr());
extension_names.push(vk::khr::portability_enumeration::NAME.as_ptr());
// Enabling this extension is a requirement when using `VK_KHR_portability_subset`
extension_names.push(khr::get_physical_device_properties2::NAME.as_ptr());
extension_names.push(vk::khr::get_physical_device_properties2::NAME.as_ptr());
}

let appinfo = vk::ApplicationInfo::default()
Expand Down Expand Up @@ -319,7 +316,7 @@ impl ExampleBase {
let device_extension_names_raw = [
swapchain::NAME.as_ptr(),
#[cfg(any(target_os = "macos", target_os = "ios"))]
khr::portability_subset::NAME.as_ptr(),
vk::khr::portability_subset::NAME.as_ptr(),
];
let features = vk::PhysicalDeviceFeatures {
shader_clip_distance: 1,
Expand Down
2 changes: 1 addition & 1 deletion ash-window/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ edition = "2021"
rust-version = "1.69.0"

[dependencies]
ash = { path = "../ash", version = "0.37", default-features = false }
ash = { path = "../ash", version = "0.37", default-features = false, features = ["std"] }
raw-window-handle = "0.6"

[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
Expand Down
6 changes: 4 additions & 2 deletions ash/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ rust-version = "1.69.0"
libloading = { version = "0.8", optional = true }

[features]
default = ["loaded", "debug"]
default = ["loaded", "debug", "std"]
# Link the Vulkan loader at compile time.
linked = []
# Support searching for the Vulkan loader manually at runtime.
loaded = ["libloading"]
loaded = ["libloading", "std"]
# Whether Vulkan structs should implement Debug.
debug = []
# Whether the standard library should be required
std = []

[package.metadata.release]
no-dev-version = true
Expand Down
9 changes: 4 additions & 5 deletions ash/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
use crate::prelude::*;
use crate::vk;
use crate::RawPtr;
use alloc::vec::Vec;
use core::ffi;
use std::mem;
use std::ptr;
use core::mem;
use core::ptr;

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDevice.html>
#[derive(Clone)]
Expand All @@ -20,9 +21,7 @@ pub struct Device {
impl Device {
pub unsafe fn load(instance_fn: &vk::InstanceFnV1_0, device: vk::Device) -> Self {
Self::load_with(
|name: &std::ffi::CStr| {
mem::transmute((instance_fn.get_device_proc_addr)(device, name.as_ptr()))
},
|name| mem::transmute((instance_fn.get_device_proc_addr)(device, name.as_ptr())),
device,
)
}
Expand Down
48 changes: 23 additions & 25 deletions ash/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,11 @@ use crate::instance::Instance;
use crate::prelude::*;
use crate::vk;
use crate::RawPtr;
use std::error::Error;
use std::ffi::CStr;
#[cfg(feature = "loaded")]
use std::ffi::OsStr;
use std::fmt;
use std::mem;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ptr;
#[cfg(feature = "loaded")]
use std::sync::Arc;
use alloc::vec::Vec;
use core::ffi;
use core::fmt;
use core::mem;
use core::ptr;

#[cfg(feature = "loaded")]
use libloading::Library;
Expand All @@ -24,7 +18,7 @@ pub struct Entry {
entry_fn_1_0: vk::EntryFnV1_0,
entry_fn_1_1: vk::EntryFnV1_1,
#[cfg(feature = "loaded")]
_lib_guard: Option<Arc<Library>>,
_lib_guard: Option<alloc::sync::Arc<Library>>,
}

/// Vulkan core 1.0
Expand Down Expand Up @@ -134,10 +128,10 @@ impl Entry {
/// may be called after it is [dropped][drop()].
#[cfg(feature = "loaded")]
#[cfg_attr(docsrs, doc(cfg(feature = "loaded")))]
pub unsafe fn load_from(path: impl AsRef<OsStr>) -> Result<Self, LoadingError> {
pub unsafe fn load_from(path: impl AsRef<std::ffi::OsStr>) -> Result<Self, LoadingError> {
let lib = Library::new(path)
.map_err(LoadingError::LibraryLoadFailure)
.map(Arc::new)?;
.map(alloc::sync::Arc::new)?;

let static_fn = vk::StaticFn::load_checked(|name| {
lib.get(name.to_bytes_with_nul())
Expand All @@ -158,7 +152,7 @@ impl Entry {
/// `static_fn` must contain valid function pointers that comply with the semantics specified
/// by Vulkan 1.0, which must remain valid for at least the lifetime of the returned [`Entry`].
pub unsafe fn from_static_fn(static_fn: vk::StaticFn) -> Self {
let load_fn = move |name: &CStr| {
let load_fn = move |name: &ffi::CStr| {
mem::transmute((static_fn.get_instance_proc_addr)(
vk::Instance::null(),
name.as_ptr(),
Expand Down Expand Up @@ -220,7 +214,7 @@ impl Entry {
#[inline]
pub unsafe fn try_enumerate_instance_version(&self) -> VkResult<Option<u32>> {
let enumerate_instance_version: Option<vk::PFN_vkEnumerateInstanceVersion> = {
let name = CStr::from_bytes_with_nul_unchecked(b"vkEnumerateInstanceVersion\0");
let name = ffi::CStr::from_bytes_with_nul_unchecked(b"vkEnumerateInstanceVersion\0");
mem::transmute((self.static_fn.get_instance_proc_addr)(
vk::Instance::null(),
name.as_ptr(),
Expand Down Expand Up @@ -275,7 +269,7 @@ impl Entry {
#[inline]
pub unsafe fn enumerate_instance_extension_properties(
&self,
layer_name: Option<&CStr>,
layer_name: Option<&ffi::CStr>,
) -> VkResult<Vec<vk::ExtensionProperties>> {
read_into_uninitialized_vector(|count, data| {
(self.entry_fn_1_0.enumerate_instance_extension_properties)(
Expand All @@ -291,7 +285,7 @@ impl Entry {
pub unsafe fn get_instance_proc_addr(
&self,
instance: vk::Instance,
p_name: *const c_char,
p_name: *const ffi::c_char,
) -> vk::PFN_vkVoidFunction {
(self.static_fn.get_instance_proc_addr)(instance, p_name)
}
Expand Down Expand Up @@ -328,11 +322,11 @@ impl Default for Entry {
impl vk::StaticFn {
pub fn load_checked<F>(mut _f: F) -> Result<Self, MissingEntryPoint>
where
F: FnMut(&CStr) -> *const c_void,
F: FnMut(&ffi::CStr) -> *const ffi::c_void,
{
Ok(Self {
get_instance_proc_addr: unsafe {
let cname = CStr::from_bytes_with_nul_unchecked(b"vkGetInstanceProcAddr\0");
let cname = ffi::CStr::from_bytes_with_nul_unchecked(b"vkGetInstanceProcAddr\0");
let val = _f(cname);
if val.is_null() {
return Err(MissingEntryPoint);
Expand All @@ -351,12 +345,15 @@ impl fmt::Display for MissingEntryPoint {
write!(f, "Cannot load `vkGetInstanceProcAddr` symbol from library")
}
}
impl Error for MissingEntryPoint {}
#[cfg(feature = "std")] // TODO: implement when error_in_core is stabilized
impl std::error::Error for MissingEntryPoint {}

#[cfg(feature = "linked")]
extern "system" {
fn vkGetInstanceProcAddr(instance: vk::Instance, name: *const c_char)
-> vk::PFN_vkVoidFunction;
fn vkGetInstanceProcAddr(
instance: vk::Instance,
name: *const ffi::c_char,
) -> vk::PFN_vkVoidFunction;
}

#[cfg(feature = "loaded")]
Expand All @@ -380,8 +377,9 @@ mod loaded {
}
}

impl Error for LoadingError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
#[cfg(feature = "std")]
impl std::error::Error for LoadingError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(match self {
Self::LibraryLoadFailure(err) => err,
Self::MissingEntryPoint(err) => err,
Expand Down
6 changes: 3 additions & 3 deletions ash/src/extensions/amd/buffer_marker.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_AMD_buffer_marker.html>

use crate::vk;
use std::ffi::CStr;
use std::mem;
use core::ffi;
use core::mem;

pub const NAME: &CStr = vk::amd::buffer_marker::NAME;
pub const NAME: &ffi::CStr = vk::amd::buffer_marker::NAME;

#[derive(Clone)]
pub struct Device {
Expand Down
7 changes: 4 additions & 3 deletions ash/src/extensions/amd/shader_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

use crate::prelude::*;
use crate::vk;
use std::ffi::CStr;
use std::mem;
use alloc::vec::Vec;
use core::ffi;
use core::mem;

pub const NAME: &CStr = vk::amd::shader_info::NAME;
pub const NAME: &ffi::CStr = vk::amd::shader_info::NAME;

#[derive(Clone)]
pub struct Device {
Expand Down
7 changes: 4 additions & 3 deletions ash/src/extensions/amdx/shader_enqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
use crate::prelude::*;
use crate::vk;
use crate::RawPtr;
use std::ffi::CStr;
use std::mem;
use alloc::vec::Vec;
use core::ffi;
use core::mem;

pub const NAME: &CStr = vk::amdx::shader_enqueue::NAME;
pub const NAME: &ffi::CStr = vk::amdx::shader_enqueue::NAME;

#[derive(Clone)]
pub struct Device {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

use crate::prelude::*;
use crate::vk;
use std::ffi::CStr;
use std::mem;
use core::ffi;
use core::mem;

pub const NAME: &CStr = vk::android::external_memory_android_hardware_buffer::NAME;
pub const NAME: &ffi::CStr = vk::android::external_memory_android_hardware_buffer::NAME;

#[derive(Clone)]
pub struct Device {
Expand Down
6 changes: 3 additions & 3 deletions ash/src/extensions/ext/acquire_drm_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

use crate::prelude::*;
use crate::vk;
use std::ffi::CStr;
use std::mem;
use core::ffi;
use core::mem;

pub const NAME: &CStr = vk::ext::acquire_drm_display::NAME;
pub const NAME: &ffi::CStr = vk::ext::acquire_drm_display::NAME;

#[derive(Clone)]
pub struct Instance {
Expand Down
Loading

0 comments on commit 9f712c5

Please sign in to comment.