Skip to content

Add no_std support #265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 39 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,56 @@ name: CI

jobs:
check_msrv:
name: Check MSRV (1.71.0)
name: Check MSRV
strategy:
matrix:
include:
target:
- os: ubuntu-latest
features: vulkan
backend: vulkan
- os: windows-latest
features: vulkan,d3d12
backend: vulkan,d3d12
- os: macos-latest
features: vulkan,metal
runs-on: ${{ matrix.os }}
backend: vulkan,metal
version:
- msrv: 1.71.0
features: std
- msrv: 1.81.0
features: hashbrown
runs-on: ${{ matrix.target.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- name: Generate lockfile with minimal dependency versions
run: cargo +nightly generate-lockfile -Zminimal-versions
- uses: dtolnay/[email protected]
# Note that examples are extempt from the MSRV check, so that they can use newer Rust features
- run: cargo check --workspace --features ${{ matrix.features }} --no-default-features
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.version.msrv }}
# Note that examples are exempt from the MSRV check, so that they can use newer Rust features
- run: cargo check --workspace --no-default-features --features ${{ matrix.target.backend }},${{ matrix.version.features }}

test:
name: Test Suite
strategy:
matrix:
include:
target:
- os: ubuntu-latest
features: vulkan,visualizer
backend: vulkan
- os: windows-latest
features: vulkan,visualizer,d3d12
backend: vulkan,d3d12
- os: macos-latest
features: vulkan,visualizer,metal
runs-on: ${{ matrix.os }}
backend: vulkan,metal
features:
- hashbrown
- std
- hashbrown,std
- visualizer,std
runs-on: ${{ matrix.target.os }}
steps:
- uses: actions/checkout@v4
- name: Cargo test all targets
run: cargo test --workspace --all-targets --features ${{ matrix.features }} --no-default-features
run: cargo test --workspace --all-targets --no-default-features --features ${{ matrix.target.backend }},${{ matrix.features }}
- name: Cargo test docs
run: cargo test --workspace --doc --features ${{ matrix.features }} --no-default-features
run: cargo test --workspace --doc --no-default-features --features ${{ matrix.target.backend }},${{ matrix.features }}

fmt:
name: Rustfmt
Expand All @@ -55,18 +67,23 @@ jobs:
name: Clippy
strategy:
matrix:
include:
target:
- os: ubuntu-latest
features: vulkan,visualizer
backend: vulkan
- os: windows-latest
features: vulkan,visualizer,d3d12
backend: vulkan,d3d12
- os: macos-latest
features: vulkan,visualizer,metal
runs-on: ${{ matrix.os }}
backend: vulkan,metal
features:
- hashbrown
- std
- hashbrown,std
- visualizer,std
runs-on: ${{ matrix.target.os }}
steps:
- uses: actions/checkout@v4
- name: Cargo clippy
run: cargo clippy --workspace --all-targets --features ${{ matrix.features }} --no-default-features -- -D warnings
run: cargo clippy --workspace --all-targets --no-default-features --features ${{ matrix.target.backend }},${{ matrix.features }} -- -D warnings

doc:
name: Build documentation
Expand Down
12 changes: 8 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ include = [
all-features = true

[dependencies]
log = "0.4"
thiserror = "1.0"
presser = { version = "0.3" }
log = { version = "0.4", default-features = false }
thiserror = { version = "2.0", default-features = false }
presser = { version = "0.3", default-features = false }
# Only needed for Vulkan. Disable all default features as good practice,
# such as the ability to link/load a Vulkan library.
ash = { version = "0.38", optional = true, default-features = false, features = ["debug"] }
# Only needed for visualizer.
egui = { version = ">=0.24, <=0.27", optional = true, default-features = false }
egui_extras = { version = ">=0.24, <=0.27", optional = true, default-features = false }
hashbrown = { version = "0.15.2", optional = true }

[target.'cfg(target_vendor = "apple")'.dependencies]
objc2 = { version = "0.6", default-features = false, optional = true }
Expand Down Expand Up @@ -87,9 +88,12 @@ name = "metal-buffer"
required-features = ["metal"]

[features]
std = ["presser/std"]
visualizer = ["dep:egui", "dep:egui_extras"]
vulkan = ["dep:ash"]
d3d12 = ["dep:windows"]
metal = ["dep:objc2", "dep:objc2-metal", "dep:objc2-foundation"]
# Enables the FreeListAllocator when `std` is not enabled by using the `hashbrown` crate
hashbrown = ["dep:hashbrown"]

default = ["d3d12", "vulkan", "metal"]
default = ["std", "d3d12", "vulkan", "metal"]
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ let mut allocator = Allocator::new(&AllocatorCreateDesc {
```

## Simple Metal allocation example

```rust
use gpu_allocator::metal::*;
use gpu_allocator::MemoryLocation;
Expand All @@ -160,9 +161,36 @@ drop(resource);
allocator.free(&allocation).unwrap();
```

## `no_std` support

`no_std` support can be enabled by compiling with `--no-default-features` to disable `std` support and `--features hashbrown` for `Hash` collections that are only defined in `std` for internal usages in crate. For example:

```toml
[dependencies]
gpu-allocator = { version = "0.27.0", default-features = false, features = ["hashbrown", "other features"] }
```

To support both `std` and `no_std` builds in your project, use the following in your `Cargo.toml`:

```toml
[features]
default = ["std", "other features"]

std = ["gpu-allocator/std"]
hashbrown = ["gpu-allocator/hashbrown"]
other_features = []

[dependencies]
gpu-allocator = { version = "0.27.0", default-features = false }
```

## Minimum Supported Rust Version

The MSRV for this crate and the `vulkan`, `d3d12` and `metal` features is Rust 1.71. Any other features such as the `visualizer` (with all the `egui` dependencies) may have a higher requirement and are not tested in our CI.
The MSRV for this crate and the `vulkan`, `d3d12` and `metal` features is Rust **1.71**.

The `no_std` support requires Rust **1.81** or higher because `no_std` support of dependency `thiserror` requires `core::error::Error` which is stabilized in **1.81**.

Any other features such as the `visualizer` (with all the `egui` dependencies) may have a higher requirement and are not tested in our CI.

## License

Expand Down
29 changes: 28 additions & 1 deletion README.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,36 @@ gpu-allocator = "0.27.0"

{{readme}}

## `no_std` support

`no_std` support can be enabled by compiling with `--no-default-features` to disable `std` support and `--features hashbrown` for `Hash` collections that are only defined in `std` for internal usages in crate. For example:

```toml
[dependencies]
gpu-allocator = { version = "0.27.0", default-features = false, features = ["hashbrown", "other features"] }
```

To support both `std` and `no_std` builds in your project, use the following in your `Cargo.toml`:

```toml
[features]
default = ["std", "other features"]

std = ["gpu-allocator/std"]
hashbrown = ["gpu-allocator/hashbrown"]
other_features = []

[dependencies]
gpu-allocator = { version = "0.27.0", default-features = false }
```

## Minimum Supported Rust Version

The MSRV for this crate and the `vulkan`, `d3d12` and `metal` features is Rust 1.71. Any other features such as the `visualizer` (with all the `egui` dependencies) may have a higher requirement and are not tested in our CI.
The MSRV for this crate and the `vulkan`, `d3d12` and `metal` features is Rust **1.71**.

The `no_std` support requires Rust **1.81** or higher because `no_std` support of dependency `thiserror` requires `core::error::Error` which is stabilized in **1.81**.

Any other features such as the `visualizer` (with all the `egui` dependencies) may have a higher requirement and are not tested in our CI.

## License

Expand Down
6 changes: 4 additions & 2 deletions release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ sign-tag = true
publish = false

pre-release-replacements = [
{ file = "README.md", search = "gpu-allocator = .*", replace = "{{crate_name}} = \"{{version}}\"" },
{ file = "README.tpl", search = "gpu-allocator = .*", replace = "{{crate_name}} = \"{{version}}\"" },
{ file = "README.md", search = "gpu-allocator = \".*\"", replace = "{{crate_name}} = \"{{version}}\"" },
{ file = "README.tpl", search = "gpu-allocator = \".*\"", replace = "{{crate_name}} = \"{{version}}\"" },
{ file = "README.md", search = "gpu-allocator = \\{ version = \".*?\"", replace = "{{crate_name}} = { version = \"{{version}}\"" },
{ file = "README.tpl", search = "gpu-allocator = \\{ version = \".*?\"", replace = "{{crate_name}} = { version = \"{{version}}\"" },
]
56 changes: 40 additions & 16 deletions src/allocator/dedicated_block_allocator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
#![deny(unsafe_code, clippy::unwrap_used)]
#[cfg(feature = "std")]
use alloc::sync::Arc;
use alloc::{
borrow::ToOwned,
string::{String, ToString},
vec::Vec,
};
#[cfg(feature = "std")]
use std::backtrace::Backtrace;

use log::{log, Level};

#[cfg(feature = "visualizer")]
pub(crate) mod visualizer;

use std::{backtrace::Backtrace, sync::Arc};

use log::{log, Level};

use super::{AllocationReport, AllocationType, SubAllocator, SubAllocatorBase};
use crate::{AllocationError, Result};

Expand All @@ -16,6 +23,7 @@ pub(crate) struct DedicatedBlockAllocator {
allocated: u64,
/// Only used if [`crate::AllocatorDebugSettings::store_stack_traces`] is [`true`]
name: Option<String>,
#[cfg(feature = "std")]
backtrace: Arc<Backtrace>,
}

Expand All @@ -25,6 +33,7 @@ impl DedicatedBlockAllocator {
size,
allocated: 0,
name: None,
#[cfg(feature = "std")]
backtrace: Arc::new(Backtrace::disabled()),
}
}
Expand All @@ -39,8 +48,8 @@ impl SubAllocator for DedicatedBlockAllocator {
_allocation_type: AllocationType,
_granularity: u64,
name: &str,
backtrace: Arc<Backtrace>,
) -> Result<(u64, std::num::NonZeroU64)> {
#[cfg(feature = "std")] backtrace: Arc<Backtrace>,
) -> Result<(u64, core::num::NonZeroU64)> {
if self.allocated != 0 {
return Err(AllocationError::OutOfMemory);
}
Expand All @@ -53,15 +62,18 @@ impl SubAllocator for DedicatedBlockAllocator {

self.allocated = size;
self.name = Some(name.to_string());
self.backtrace = backtrace;
#[cfg(feature = "std")]
{
self.backtrace = backtrace;
}

#[allow(clippy::unwrap_used)]
let dummy_id = std::num::NonZeroU64::new(1).unwrap();
let dummy_id = core::num::NonZeroU64::new(1).unwrap();
Ok((0, dummy_id))
}

fn free(&mut self, chunk_id: Option<std::num::NonZeroU64>) -> Result<()> {
if chunk_id != std::num::NonZeroU64::new(1) {
fn free(&mut self, chunk_id: Option<core::num::NonZeroU64>) -> Result<()> {
if chunk_id != core::num::NonZeroU64::new(1) {
Err(AllocationError::Internal("Chunk ID must be 1.".into()))
} else {
self.allocated = 0;
Expand All @@ -71,10 +83,10 @@ impl SubAllocator for DedicatedBlockAllocator {

fn rename_allocation(
&mut self,
chunk_id: Option<std::num::NonZeroU64>,
chunk_id: Option<core::num::NonZeroU64>,
name: &str,
) -> Result<()> {
if chunk_id != std::num::NonZeroU64::new(1) {
if chunk_id != core::num::NonZeroU64::new(1) {
Err(AllocationError::Internal("Chunk ID must be 1.".into()))
} else {
self.name = Some(name.into());
Expand All @@ -90,6 +102,20 @@ impl SubAllocator for DedicatedBlockAllocator {
) {
let empty = "".to_string();
let name = self.name.as_ref().unwrap_or(&empty);
let backtrace_info;
#[cfg(feature = "std")]
{
// TODO: Allocation could be avoided here if https://github.com/rust-lang/rust/pull/139135 is merged and stabilized.
backtrace_info = format!(
",
backtrace: {}",
self.backtrace
)
}
#[cfg(not(feature = "std"))]
{
backtrace_info = ""
}

log!(
log_level,
Expand All @@ -98,16 +124,14 @@ impl SubAllocator for DedicatedBlockAllocator {
memory block: {}
dedicated allocation: {{
size: 0x{:x},
name: {},
backtrace: {}
name: {}{backtrace_info}
}}
}}"#,
memory_type_index,
memory_block_index,
self.size,
name,
self.backtrace
)
);
}

fn report_allocations(&self) -> Vec<AllocationReport> {
Expand Down
Loading