Bug 1838493 - Update wgpu to revision dcad7dfba92dd85c3ca21bb553a61834e01b04f5. r=webgpu-reviewers,gfx-reviewers,supply-chain-reviewers,glandium,ErichDonGubler

Bug 1838493 - Update `foreign-types`, `core-graphics` and `core-text`. r=#gfx-reviewers

Bug 1838493 - Vet `wgpu` and `naga` commits. r=#supply-chain-reviewers

Bug 1838493 - Vendor `wgpu` changes. r=#webgpu-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D182578
This commit is contained in:
Teodor Tanasoaia 2023-07-05 17:30:46 +00:00
parent 4306f9129c
commit b739a20ea0
261 changed files with 25176 additions and 12941 deletions

View File

@ -30,14 +30,14 @@ git = "https://github.com/gfx-rs/d3d12-rs"
rev = "b940b1d71"
replace-with = "vendored-sources"
[source."git+https://github.com/gfx-rs/naga?rev=b99d58ea435090e561377949f428bce2c18451bb"]
[source."git+https://github.com/gfx-rs/naga?rev=76003dc0035d53a474d366dcdf49d2e4d12e921f"]
git = "https://github.com/gfx-rs/naga"
rev = "b99d58ea435090e561377949f428bce2c18451bb"
rev = "76003dc0035d53a474d366dcdf49d2e4d12e921f"
replace-with = "vendored-sources"
[source."git+https://github.com/gfx-rs/wgpu?rev=f71a1bc736fde37509262ca03e91d8f56a13aeb5"]
[source."git+https://github.com/gfx-rs/wgpu?rev=dcad7dfba92dd85c3ca21bb553a61834e01b04f5"]
git = "https://github.com/gfx-rs/wgpu"
rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5"
rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
replace-with = "vendored-sources"
[source."git+https://github.com/glandium/warp?rev=4af45fae95bc98b0eba1ef0db17e1dac471bb23d"]

67
Cargo.lock generated
View File

@ -140,9 +140,9 @@ dependencies = [
[[package]]
name = "ash"
version = "0.37.2+1.3.238"
version = "0.37.3+1.3.251"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28bf19c1f0a470be5fbf7522a308a05df06610252c5bcf5143e1b23f629a9a03"
checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a"
dependencies = [
"libloading",
]
@ -831,9 +831,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "core-graphics"
version = "0.22.3"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
checksum = "506752f2b58723339d41d013009be97e549860785a366e2a5e75dfbd9725b48e"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
@ -844,21 +844,20 @@ dependencies = [
[[package]]
name = "core-graphics-types"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"foreign-types",
"libc",
]
[[package]]
name = "core-text"
version = "19.2.0"
version = "20.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"
checksum = "02083d15989d6247553e1a63753561555a72b2038bba1e4239db70602a798742"
dependencies = [
"core-foundation",
"core-graphics",
@ -1784,18 +1783,30 @@ dependencies = [
[[package]]
name = "foreign-types"
version = "0.3.2"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [
"foreign-types-macros",
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
name = "foreign-types-macros"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.18",
]
[[package]]
name = "foreign-types-shared"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
[[package]]
name = "form_urlencoded"
@ -2312,21 +2323,21 @@ dependencies = [
[[package]]
name = "gpu-alloc"
version = "0.5.3"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d"
checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
dependencies = [
"bitflags 1.3.2",
"bitflags 2.999.999",
"gpu-alloc-types",
]
[[package]]
name = "gpu-alloc-types"
version = "0.2.0"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5"
checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
dependencies = [
"bitflags 1.3.2",
"bitflags 2.999.999",
]
[[package]]
@ -3170,9 +3181,9 @@ dependencies = [
[[package]]
name = "metal"
version = "0.24.0"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060"
checksum = "550b24b0cd4cf923f36bae78eca457b3a10d8a6a14a9c84cb2687b527e6a84af"
dependencies = [
"bitflags 1.3.2",
"block",
@ -3180,6 +3191,7 @@ dependencies = [
"foreign-types",
"log",
"objc",
"paste",
]
[[package]]
@ -3549,10 +3561,10 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
[[package]]
name = "naga"
version = "0.12.0"
source = "git+https://github.com/gfx-rs/naga?rev=b99d58ea435090e561377949f428bce2c18451bb#b99d58ea435090e561377949f428bce2c18451bb"
source = "git+https://github.com/gfx-rs/naga?rev=76003dc0035d53a474d366dcdf49d2e4d12e921f#76003dc0035d53a474d366dcdf49d2e4d12e921f"
dependencies = [
"bit-set",
"bitflags 1.3.2",
"bitflags 2.999.999",
"codespan-reporting",
"hexf-parse",
"indexmap",
@ -6084,7 +6096,7 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "0.16.0"
source = "git+https://github.com/gfx-rs/wgpu?rev=f71a1bc736fde37509262ca03e91d8f56a13aeb5#f71a1bc736fde37509262ca03e91d8f56a13aeb5"
source = "git+https://github.com/gfx-rs/wgpu?rev=dcad7dfba92dd85c3ca21bb553a61834e01b04f5#dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
dependencies = [
"arrayvec",
"bit-vec",
@ -6107,7 +6119,7 @@ dependencies = [
[[package]]
name = "wgpu-hal"
version = "0.16.0"
source = "git+https://github.com/gfx-rs/wgpu?rev=f71a1bc736fde37509262ca03e91d8f56a13aeb5#f71a1bc736fde37509262ca03e91d8f56a13aeb5"
source = "git+https://github.com/gfx-rs/wgpu?rev=dcad7dfba92dd85c3ca21bb553a61834e01b04f5#dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
dependencies = [
"android_system_properties",
"arrayvec",
@ -6117,7 +6129,6 @@ dependencies = [
"block",
"core-graphics-types",
"d3d12",
"foreign-types",
"gpu-alloc",
"gpu-descriptor",
"js-sys",
@ -6144,7 +6155,7 @@ dependencies = [
[[package]]
name = "wgpu-types"
version = "0.16.0"
source = "git+https://github.com/gfx-rs/wgpu?rev=f71a1bc736fde37509262ca03e91d8f56a13aeb5#f71a1bc736fde37509262ca03e91d8f56a13aeb5"
source = "git+https://github.com/gfx-rs/wgpu?rev=dcad7dfba92dd85c3ca21bb553a61834e01b04f5#dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
dependencies = [
"bitflags 2.999.999",
"js-sys",

View File

@ -7,5 +7,8 @@ license = "MIT/Apache-2.0"
[lib]
path = "lib.rs"
[features]
serde = []
[dependencies.bitflags]
version = "1.0"

View File

@ -35,6 +35,6 @@ winapi = "0.3"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9"
core-graphics = "0.22"
foreign-types = "0.3.0"
core-graphics = "0.23"
foreign-types = "0.5.0"
objc = "0.2"

View File

@ -17,7 +17,7 @@ default = []
[dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5"
rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
#Note: "replay" shouldn't ideally be needed,
# but it allows us to serialize everything across IPC.
features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"]
@ -27,32 +27,32 @@ features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"]
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5"
rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
features = ["metal"]
# We want the wgpu-core Direct3D backends on Windows.
[target.'cfg(windows)'.dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5"
rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
features = ["dx11", "dx12"]
# We want the wgpu-core Vulkan backend on Linux and Windows.
[target.'cfg(any(windows, all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5"
rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
features = ["vulkan"]
[dependencies.wgt]
package = "wgpu-types"
git = "https://github.com/gfx-rs/wgpu"
rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5"
rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
[dependencies.wgh]
package = "wgpu-hal"
git = "https://github.com/gfx-rs/wgpu"
rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5"
rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
[dependencies]
bincode = "1"

View File

@ -20,11 +20,11 @@ origin:
# Human-readable identifier for this version/release
# Generally "version NNN", "tag SSS", "bookmark SSS"
release: commit f71a1bc736fde37509262ca03e91d8f56a13aeb5
release: commit dcad7dfba92dd85c3ca21bb553a61834e01b04f5
# Revision to pull in
# Must be a long or short commit SHA (long preferred)
revision: f71a1bc736fde37509262ca03e91d8f56a13aeb5
revision: dcad7dfba92dd85c3ca21bb553a61834e01b04f5
license: ['MIT', 'Apache-2.0']

View File

@ -7,7 +7,7 @@ use crate::{
DropAction, ImageDataLayout, ImplicitLayout, QueueWriteAction, RawString, TextureAction,
};
use wgc::{hub::IdentityManager, id};
use wgc::{identity::IdentityManager, id};
use wgt::{Backend, TextureFormat};
pub use wgc::command::{compute_ffi::*, render_ffi::*};

View File

@ -13,7 +13,7 @@ pub struct IdentityRecycler<I> {
kind: &'static str,
}
impl<I: id::TypedId + Clone + std::fmt::Debug> wgc::hub::IdentityHandler<I>
impl<I: id::TypedId + Clone + std::fmt::Debug> wgc::identity::IdentityHandler<I>
for IdentityRecycler<I>
{
type Input = I;
@ -51,7 +51,7 @@ pub struct IdentityRecyclerFactory {
free_surface: extern "C" fn(id::SurfaceId, FactoryParam),
}
impl wgc::hub::IdentityHandlerFactory<id::AdapterId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::AdapterId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::AdapterId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -61,7 +61,7 @@ impl wgc::hub::IdentityHandlerFactory<id::AdapterId> for IdentityRecyclerFactory
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::DeviceId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::DeviceId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::DeviceId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -71,7 +71,7 @@ impl wgc::hub::IdentityHandlerFactory<id::DeviceId> for IdentityRecyclerFactory
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::PipelineLayoutId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::PipelineLayoutId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::PipelineLayoutId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -81,7 +81,7 @@ impl wgc::hub::IdentityHandlerFactory<id::PipelineLayoutId> for IdentityRecycler
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::ShaderModuleId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::ShaderModuleId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::ShaderModuleId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -91,7 +91,7 @@ impl wgc::hub::IdentityHandlerFactory<id::ShaderModuleId> for IdentityRecyclerFa
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::BindGroupLayoutId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::BindGroupLayoutId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::BindGroupLayoutId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -101,7 +101,7 @@ impl wgc::hub::IdentityHandlerFactory<id::BindGroupLayoutId> for IdentityRecycle
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::BindGroupId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::BindGroupId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::BindGroupId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -111,7 +111,7 @@ impl wgc::hub::IdentityHandlerFactory<id::BindGroupId> for IdentityRecyclerFacto
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::CommandBufferId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::CommandBufferId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::CommandBufferId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -121,7 +121,7 @@ impl wgc::hub::IdentityHandlerFactory<id::CommandBufferId> for IdentityRecyclerF
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::RenderBundleId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::RenderBundleId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::RenderBundleId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -131,7 +131,7 @@ impl wgc::hub::IdentityHandlerFactory<id::RenderBundleId> for IdentityRecyclerFa
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::RenderPipelineId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::RenderPipelineId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::RenderPipelineId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -141,7 +141,7 @@ impl wgc::hub::IdentityHandlerFactory<id::RenderPipelineId> for IdentityRecycler
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::ComputePipelineId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::ComputePipelineId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::ComputePipelineId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -151,7 +151,7 @@ impl wgc::hub::IdentityHandlerFactory<id::ComputePipelineId> for IdentityRecycle
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::QuerySetId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::QuerySetId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::QuerySetId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -161,7 +161,7 @@ impl wgc::hub::IdentityHandlerFactory<id::QuerySetId> for IdentityRecyclerFactor
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::BufferId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::BufferId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::BufferId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -171,7 +171,7 @@ impl wgc::hub::IdentityHandlerFactory<id::BufferId> for IdentityRecyclerFactory
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::StagingBufferId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::StagingBufferId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::StagingBufferId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -181,7 +181,7 @@ impl wgc::hub::IdentityHandlerFactory<id::StagingBufferId> for IdentityRecyclerF
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::TextureId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::TextureId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::TextureId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -191,7 +191,7 @@ impl wgc::hub::IdentityHandlerFactory<id::TextureId> for IdentityRecyclerFactory
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::TextureViewId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::TextureViewId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::TextureViewId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -201,7 +201,7 @@ impl wgc::hub::IdentityHandlerFactory<id::TextureViewId> for IdentityRecyclerFac
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::SamplerId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::SamplerId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::SamplerId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -211,7 +211,7 @@ impl wgc::hub::IdentityHandlerFactory<id::SamplerId> for IdentityRecyclerFactory
}
}
}
impl wgc::hub::IdentityHandlerFactory<id::SurfaceId> for IdentityRecyclerFactory {
impl wgc::identity::IdentityHandlerFactory<id::SurfaceId> for IdentityRecyclerFactory {
type Filter = IdentityRecycler<id::SurfaceId>;
fn spawn(&self) -> Self::Filter {
IdentityRecycler {
@ -222,4 +222,4 @@ impl wgc::hub::IdentityHandlerFactory<id::SurfaceId> for IdentityRecyclerFactory
}
}
impl wgc::hub::GlobalIdentityHandlerFactory for IdentityRecyclerFactory {}
impl wgc::identity::GlobalIdentityHandlerFactory for IdentityRecyclerFactory {}

View File

@ -88,10 +88,10 @@ impl ErrorBuffer {
}
// hide wgc's global in private
pub struct Global(wgc::hub::Global<IdentityRecyclerFactory>);
pub struct Global(wgc::global::Global<IdentityRecyclerFactory>);
impl std::ops::Deref for Global {
type Target = wgc::hub::Global<IdentityRecyclerFactory>;
type Target = wgc::global::Global<IdentityRecyclerFactory>;
fn deref(&self) -> &Self::Target {
&self.0
}
@ -110,7 +110,7 @@ pub extern "C" fn wgpu_server_new(factory: IdentityRecyclerFactory) -> *mut Glob
);
wgc::instance::parse_backends_from_comma_list(&backends_pref)
};
let global = Global(wgc::hub::Global::new(
let global = Global(wgc::global::Global::new(
"wgpu",
factory,
wgt::InstanceDescriptor {
@ -448,7 +448,7 @@ pub extern "C" fn wgpu_server_buffer_drop(global: &Global, self_id: id::BufferId
}
impl Global {
fn device_action<A: wgc::hub::HalApi>(
fn device_action<A: wgc::hal_api::HalApi>(
&self,
self_id: id::DeviceId,
action: DeviceAction,
@ -548,7 +548,7 @@ impl Global {
}
}
fn texture_action<A: wgc::hub::HalApi>(
fn texture_action<A: wgc::hal_api::HalApi>(
&self,
self_id: id::TextureId,
action: TextureAction,
@ -564,7 +564,7 @@ impl Global {
}
}
fn command_encoder_action<A: wgc::hub::HalApi>(
fn command_encoder_action<A: wgc::hal_api::HalApi>(
&self,
self_id: id::CommandEncoderId,
action: CommandEncoderAction,

View File

@ -46,6 +46,6 @@ dwrote = "0.11"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9.2"
core-graphics = "0.22.3"
core-text = { version = "19.2", default-features = false }
core-graphics = "0.23"
core-text = { version = "20", default-features = false }
objc = "0.2"

View File

@ -40,7 +40,7 @@ default-features = false
features = ["png"]
[target.'cfg(target_os = "macos")'.dependencies]
core-graphics = "0.22"
core-graphics = "0.23"
core-foundation = "0.9"
[features]

View File

@ -471,6 +471,11 @@ who = "Nicolas Silva <nical@fastmail.com>"
criteria = "safe-to-deploy"
delta = "0.37.1+1.3.235 -> 0.37.2+1.3.238"
[[audits.ash]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.37.2+1.3.238 -> 0.37.3+1.3.251"
[[audits.ashmem]]
who = "Matthew Gregan <kinetik@flim.org>"
criteria = "safe-to-deploy"
@ -601,6 +606,11 @@ who = "Nicolas Silva <nical@fastmail.com>"
criteria = "safe-to-deploy"
delta = "2.0.2 -> 2.1.0"
[[audits.bitflags]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "2.2.1 -> 2.3.2"
[[audits.block-buffer]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -720,6 +730,21 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-run"
delta = "0.16.0 -> 0.16.2"
[[audits.core-graphics]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.22.3 -> 0.23.0"
[[audits.core-graphics-types]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.1.1 -> 0.1.2"
[[audits.core-text]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "19.2.0 -> 20.0.0"
[[audits.coreaudio-sys]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -1277,6 +1302,21 @@ criteria = "safe-to-deploy"
version = "1.0.7"
notes = "Simple hasher implementation with no unsafe code."
[[audits.foreign-types]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.3.2 -> 0.5.0"
[[audits.foreign-types-macros]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
version = "0.2.3"
[[audits.foreign-types-shared]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.1.1 -> 0.3.1"
[[audits.fs-err]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -1546,6 +1586,16 @@ criteria = "safe-to-deploy"
delta = "0.5.4 -> 0.6.0"
notes = "Mostly bug fixes and some added functionality"
[[audits.gpu-alloc]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.5.3 -> 0.6.0"
[[audits.gpu-alloc-types]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.2.0 -> 0.3.0"
[[audits.gpu-descriptor]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -1840,6 +1890,11 @@ criteria = "safe-to-deploy"
delta = "0.23.1 -> 0.24.0"
notes = "This audit treats Dzmitry Malyshau (kvark) as a trusted reviewer."
[[audits.metal]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.24.0 -> 0.25.0"
[[audits.midir]]
who = "Bobby Holley <bobbyholley@gmail.com>"
criteria = "safe-to-deploy"
@ -1946,6 +2001,11 @@ who = "Nicolas Silva <nical@fastmail.com>"
criteria = "safe-to-deploy"
delta = "0.11.0@git:f59668ccfaf7bdb3a7e43d84363a21c77357b2fe -> 0.12.0@git:b99d58ea435090e561377949f428bce2c18451bb"
[[audits.naga]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.12.0@git:b99d58ea435090e561377949f428bce2c18451bb -> 0.12.0@git:76003dc0035d53a474d366dcdf49d2e4d12e921f"
[[audits.net2]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-run"
@ -3533,6 +3593,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
criteria = "safe-to-deploy"
delta = "0.16.0@git:25cb9f61e9a6be572ee42536bbe57aa5f759a700 -> 0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5"
[[audits.wgpu-core]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
[[audits.wgpu-hal]]
who = "Dzmitry Malyshau <kvark@fastmail.com>"
criteria = "safe-to-deploy"
@ -3611,6 +3676,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
criteria = "safe-to-deploy"
delta = "0.16.0@git:25cb9f61e9a6be572ee42536bbe57aa5f759a700 -> 0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5"
[[audits.wgpu-hal]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
[[audits.wgpu-types]]
who = "Dzmitry Malyshau <kvark@fastmail.com>"
criteria = "safe-to-deploy"
@ -3689,6 +3759,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
criteria = "safe-to-deploy"
delta = "0.16.0@git:25cb9f61e9a6be572ee42536bbe57aa5f759a700 -> 0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5"
[[audits.wgpu-types]]
who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5"
[[audits.whatsys]]
who = "Bobby Holley <bobbyholley@gmail.com>"
criteria = "safe-to-deploy"

File diff suppressed because one or more lines are too long

View File

@ -10,10 +10,10 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
edition = "2021"
rust-version = "1.59.0"
name = "ash"
version = "0.37.2+1.3.238"
version = "0.37.3+1.3.251"
authors = [
"Maik Klein <maikklein@googlemail.com>",
"Benjamin Saunders <ben.e.saunders@gmail.com>",
@ -28,9 +28,7 @@ keywords = [
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/MaikKlein/ash"
[package.metadata.release]
no-dev-version = true
resolver = "1"
[package.metadata.docs.rs]
all-features = true
@ -39,6 +37,9 @@ rustdoc-args = [
"docsrs",
]
[package.metadata.release]
no-dev-version = true
[dependencies.libloading]
version = "0.7"
optional = true

View File

@ -8,6 +8,7 @@ A very lightweight wrapper around Vulkan
[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT)
[![LICENSE](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE-APACHE)
[![Join the chat at https://gitter.im/MaikKlein/ash](https://badges.gitter.im/MaikKlein/ash.svg)](https://gitter.im/MaikKlein/ash?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![MSRV](https://img.shields.io/badge/rustc-1.60.0+-ab6000.svg)](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html)
## Overview
- [x] A true Vulkan API without compromises

View File

@ -13,12 +13,12 @@ fn main() {
("windows", "64") => "Lib",
_ => "lib",
};
println!("cargo:rustc-link-search={}/{}", var, suffix);
println!("cargo:rustc-link-search={var}/{suffix}");
}
let lib = match &*target_family {
"windows" => "vulkan-1",
_ => "vulkan",
};
println!("cargo:rustc-link-lib={}", lib);
println!("cargo:rustc-link-lib={lib}");
}
}

View File

@ -465,34 +465,42 @@ impl Device {
#[inline]
pub unsafe fn get_device_buffer_memory_requirements(
&self,
create_info: &vk::DeviceBufferMemoryRequirements,
memory_requirements: &vk::DeviceBufferMemoryRequirements,
out: &mut vk::MemoryRequirements2,
) {
(self.device_fn_1_3.get_device_buffer_memory_requirements)(self.handle, create_info, out)
(self.device_fn_1_3.get_device_buffer_memory_requirements)(
self.handle,
memory_requirements,
out,
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceImageMemoryRequirements.html>
#[inline]
pub unsafe fn get_device_image_memory_requirements(
&self,
create_info: &vk::DeviceImageMemoryRequirements,
memory_requirements: &vk::DeviceImageMemoryRequirements,
out: &mut vk::MemoryRequirements2,
) {
(self.device_fn_1_3.get_device_image_memory_requirements)(self.handle, create_info, out)
(self.device_fn_1_3.get_device_image_memory_requirements)(
self.handle,
memory_requirements,
out,
)
}
/// Retrieve the number of elements to pass to [`get_device_image_sparse_memory_requirements()`][Self::get_device_image_sparse_memory_requirements()]
#[inline]
pub unsafe fn get_device_image_sparse_memory_requirements_len(
&self,
create_info: &vk::DeviceImageMemoryRequirements,
memory_requirements: &vk::DeviceImageMemoryRequirements,
) -> usize {
let mut count = 0;
(self
.device_fn_1_3
.get_device_image_sparse_memory_requirements)(
self.handle,
create_info,
memory_requirements,
&mut count,
std::ptr::null_mut(),
);
@ -506,7 +514,7 @@ impl Device {
#[inline]
pub unsafe fn get_device_image_sparse_memory_requirements(
&self,
create_info: &vk::DeviceImageMemoryRequirements,
memory_requirements: &vk::DeviceImageMemoryRequirements,
out: &mut [vk::SparseImageMemoryRequirements2],
) {
let mut count = out.len() as u32;
@ -514,7 +522,7 @@ impl Device {
.device_fn_1_3
.get_device_image_sparse_memory_requirements)(
self.handle,
create_info,
memory_requirements,
&mut count,
out.as_mut_ptr(),
);
@ -846,6 +854,14 @@ impl Device {
(self.device_fn_1_1.trim_command_pool)(self.handle(), command_pool, flags);
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceQueue2.html>
#[inline]
pub unsafe fn get_device_queue2(&self, queue_info: &vk::DeviceQueueInfo2) -> vk::Queue {
let mut queue = mem::zeroed();
(self.device_fn_1_1.get_device_queue2)(self.handle(), queue_info, &mut queue);
queue
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateSamplerYcbcrConversion.html>
#[inline]
pub unsafe fn create_sampler_ycbcr_conversion(
@ -1499,17 +1515,17 @@ impl Device {
#[inline]
pub unsafe fn allocate_descriptor_sets(
&self,
create_info: &vk::DescriptorSetAllocateInfo,
allocate_info: &vk::DescriptorSetAllocateInfo,
) -> VkResult<Vec<vk::DescriptorSet>> {
let mut desc_set = Vec::with_capacity(create_info.descriptor_set_count as usize);
let mut desc_set = Vec::with_capacity(allocate_info.descriptor_set_count as usize);
(self.device_fn_1_0.allocate_descriptor_sets)(
self.handle(),
create_info,
allocate_info,
desc_set.as_mut_ptr(),
)
.result()?;
desc_set.set_len(create_info.descriptor_set_count as usize);
desc_set.set_len(allocate_info.descriptor_set_count as usize);
Ok(desc_set)
}
@ -1786,10 +1802,10 @@ impl Device {
pub unsafe fn cmd_begin_render_pass(
&self,
command_buffer: vk::CommandBuffer,
create_info: &vk::RenderPassBeginInfo,
render_pass_begin: &vk::RenderPassBeginInfo,
contents: vk::SubpassContents,
) {
(self.device_fn_1_0.cmd_begin_render_pass)(command_buffer, create_info, contents);
(self.device_fn_1_0.cmd_begin_render_pass)(command_buffer, render_pass_begin, contents);
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdNextSubpass.html>
@ -2488,16 +2504,16 @@ impl Device {
#[inline]
pub unsafe fn allocate_command_buffers(
&self,
create_info: &vk::CommandBufferAllocateInfo,
allocate_info: &vk::CommandBufferAllocateInfo,
) -> VkResult<Vec<vk::CommandBuffer>> {
let mut buffers = Vec::with_capacity(create_info.command_buffer_count as usize);
let mut buffers = Vec::with_capacity(allocate_info.command_buffer_count as usize);
(self.device_fn_1_0.allocate_command_buffers)(
self.handle(),
create_info,
allocate_info,
buffers.as_mut_ptr(),
)
.result()?;
buffers.set_len(create_info.command_buffer_count as usize);
buffers.set_len(allocate_info.command_buffer_count as usize);
Ok(buffers)
}
@ -2592,13 +2608,13 @@ impl Device {
#[inline]
pub unsafe fn allocate_memory(
&self,
create_info: &vk::MemoryAllocateInfo,
allocate_info: &vk::MemoryAllocateInfo,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) -> VkResult<vk::DeviceMemory> {
let mut memory = mem::zeroed();
(self.device_fn_1_0.allocate_memory)(
self.handle(),
create_info,
allocate_info,
allocation_callbacks.as_raw_ptr(),
&mut memory,
)

View File

@ -37,9 +37,15 @@ impl Entry {
/// development packages installed (e.g. the Vulkan SDK, or Ubuntu's `libvulkan-dev`).
///
/// # Safety
///
/// `dlopen`ing native libraries is inherently unsafe. The safety guidelines
/// for [`Library::new()`] and [`Library::get()`] apply here.
///
/// No Vulkan functions loaded directly or indirectly from this [`Entry`]
/// may be called after it is [dropped][drop()].
///
/// # Example
///
/// ```no_run
/// use ash::{vk, Entry};
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
@ -86,6 +92,11 @@ impl Entry {
/// Note that instance/device functions are still fetched via `vkGetInstanceProcAddr` and
/// `vkGetDeviceProcAddr` for maximum performance.
///
/// Any Vulkan function acquired directly or indirectly from this [`Entry`] may be called after it
/// is [dropped][drop()].
///
/// # Example
///
/// ```no_run
/// use ash::{vk, Entry};
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
@ -116,8 +127,12 @@ impl Entry {
/// Load Vulkan library at `path`
///
/// # Safety
///
/// `dlopen`ing native libraries is inherently unsafe. The safety guidelines
/// for [`Library::new()`] and [`Library::get()`] apply here.
///
/// No Vulkan functions loaded directly or indirectly from this [`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> {
@ -140,8 +155,9 @@ impl Entry {
/// Load entry points based on an already-loaded [`vk::StaticFn`]
///
/// # Safety
/// `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`].
///
/// `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 = |name: &std::ffi::CStr| {
mem::transmute((static_fn.get_instance_proc_addr)(
@ -176,6 +192,9 @@ impl Entry {
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceVersion.html>
///
/// # Example
///
/// ```no_run
/// # use ash::{Entry, vk};
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
@ -217,9 +236,13 @@ impl Entry {
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateInstance.html>
///
/// # Safety
/// In order for the created [`Instance`] to be valid for the duration of its
/// usage, the [`Entry`](Self) this was called on must be dropped later than the
/// resulting [`Instance`].
///
/// The resulting [`Instance`] and any function-pointer objects (e.g. [`Device`][crate::Device]
/// and [extensions][crate::extensions]) loaded from it may not be used after this [`Entry`]
/// object is dropped, unless it was crated using [`Entry::linked()`].
///
/// [`Instance`] does _not_ implement [drop][drop()] semantics and can only be destroyed via
/// [`destroy_instance()`][Instance::destroy_instance()].
#[inline]
pub unsafe fn create_instance(
&self,

View File

@ -1,9 +1,10 @@
use crate::prelude::*;
use crate::vk;
use crate::{Device, Instance};
use crate::{Device, Entry, Instance};
use std::ffi::CStr;
use std::mem;
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_EXT_full_screen_exclusive.html>
#[derive(Clone)]
pub struct FullScreenExclusive {
handle: vk::Device,
@ -11,6 +12,13 @@ pub struct FullScreenExclusive {
}
impl FullScreenExclusive {
/// # Warning
/// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called:
/// - [`Self::get_physical_device_surface_present_modes2()`]
///
/// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the
/// above [`Instance`] function is called. This will be solved in the next breaking `ash`
/// release: <https://github.com/ash-rs/ash/issues/727>.
pub fn new(instance: &Instance, device: &Device) -> Self {
let handle = device.handle();
let fp = vk::ExtFullScreenExclusiveFn::load(|name| unsafe {
@ -19,6 +27,19 @@ impl FullScreenExclusive {
Self { handle, fp }
}
/// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra
/// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be
/// loaded instead of always panicking. See also [`Self::new()`] for more details.
///
/// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the
/// [`Instance`] function.
pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self {
let fp = vk::ExtFullScreenExclusiveFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
Self { handle: device, fp }
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkAcquireFullScreenExclusiveModeEXT.html>
#[inline]
pub unsafe fn acquire_full_screen_exclusive_mode(
@ -29,6 +50,10 @@ impl FullScreenExclusive {
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetPhysicalDeviceSurfacePresentModes2EXT.html>
///
/// # Warning
///
/// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`].
#[inline]
pub unsafe fn get_physical_device_surface_present_modes2(
&self,

View File

@ -17,8 +17,10 @@ pub use self::image_drm_format_modifier::ImageDrmFormatModifier;
pub use self::mesh_shader::MeshShader;
pub use self::metal_surface::MetalSurface;
pub use self::physical_device_drm::PhysicalDeviceDrm;
pub use self::pipeline_properties::PipelineProperties;
pub use self::private_data::PrivateData;
pub use self::sample_locations::SampleLocations;
pub use self::shader_object::ShaderObject;
pub use self::tooling_info::ToolingInfo;
mod acquire_drm_display;
@ -40,6 +42,8 @@ mod image_drm_format_modifier;
mod mesh_shader;
mod metal_surface;
mod physical_device_drm;
mod pipeline_properties;
mod private_data;
mod sample_locations;
mod shader_object;
mod tooling_info;

View File

@ -0,0 +1,52 @@
use crate::prelude::*;
use crate::vk;
use crate::{Device, Instance};
use std::ffi::CStr;
use std::mem;
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_EXT_pipeline_properties.html>
#[derive(Clone)]
pub struct PipelineProperties {
handle: vk::Device,
fp: vk::ExtPipelinePropertiesFn,
}
impl PipelineProperties {
pub fn new(instance: &Instance, device: &Device) -> Self {
let handle = device.handle();
let fp = vk::ExtPipelinePropertiesFn::load(|name| unsafe {
mem::transmute(instance.get_device_proc_addr(handle, name.as_ptr()))
});
Self { handle, fp }
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetPipelinePropertiesEXT.html>
#[inline]
pub unsafe fn get_pipeline_properties(
&self,
pipeline_info: &vk::PipelineInfoEXT,
pipeline_properties: &mut impl vk::GetPipelinePropertiesEXTParamPipelineProperties,
) -> VkResult<()> {
(self.fp.get_pipeline_properties_ext)(
self.handle,
pipeline_info,
<*mut _>::cast(pipeline_properties),
)
.result()
}
#[inline]
pub const fn name() -> &'static CStr {
vk::ExtPipelinePropertiesFn::name()
}
#[inline]
pub fn fp(&self) -> &vk::ExtPipelinePropertiesFn {
&self.fp
}
#[inline]
pub fn device(&self) -> vk::Device {
self.handle
}
}

View File

@ -0,0 +1,719 @@
use crate::prelude::*;
use crate::vk;
use crate::RawPtr;
use crate::{Device, Instance};
use std::ffi::CStr;
use std::mem;
use std::ptr;
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_shader_object.html>
#[derive(Clone)]
pub struct ShaderObject {
handle: vk::Device,
fp: vk::ExtShaderObjectFn,
}
impl ShaderObject {
pub fn new(instance: &Instance, device: &Device) -> Self {
let handle = device.handle();
let fp = vk::ExtShaderObjectFn::load(|name| unsafe {
mem::transmute(instance.get_device_proc_addr(handle, name.as_ptr()))
});
Self { handle, fp }
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateShadersEXT.html>
#[inline]
pub unsafe fn create_shaders(
&self,
create_infos: &[vk::ShaderCreateInfoEXT],
allocator: Option<&vk::AllocationCallbacks>,
) -> VkResult<Vec<vk::ShaderEXT>> {
let mut shaders = Vec::with_capacity(create_infos.len());
(self.fp.create_shaders_ext)(
self.handle,
create_infos.len() as u32,
create_infos.as_ptr(),
allocator.as_raw_ptr(),
shaders.as_mut_ptr(),
)
.result()?;
shaders.set_len(create_infos.len());
Ok(shaders)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkDestroyShaderEXT.html>
#[inline]
pub unsafe fn destroy_shader(
&self,
shader: vk::ShaderEXT,
allocator: Option<&vk::AllocationCallbacks>,
) {
(self.fp.destroy_shader_ext)(self.handle, shader, allocator.as_raw_ptr())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetShaderBinaryDataEXT.html>
#[inline]
pub unsafe fn get_shader_binary_data(&self, shader: vk::ShaderEXT) -> VkResult<Vec<u8>> {
read_into_uninitialized_vector(|count, data: *mut u8| {
(self.fp.get_shader_binary_data_ext)(self.handle, shader, count, data.cast())
})
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdBindShadersEXT.html>
#[inline]
pub unsafe fn cmd_bind_shaders(
&self,
command_buffer: vk::CommandBuffer,
stages: &[vk::ShaderStageFlags],
shaders: &[vk::ShaderEXT],
) {
assert_eq!(stages.len(), shaders.len());
(self.fp.cmd_bind_shaders_ext)(
command_buffer,
stages.len() as u32,
stages.as_ptr(),
shaders.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetVertexInputEXT.html>
#[inline]
pub unsafe fn cmd_set_vertex_input(
&self,
command_buffer: vk::CommandBuffer,
vertex_binding_descriptions: &[vk::VertexInputBindingDescription2EXT],
vertex_attribute_descriptions: &[vk::VertexInputAttributeDescription2EXT],
) {
(self.fp.cmd_set_vertex_input_ext)(
command_buffer,
vertex_binding_descriptions.len() as u32,
vertex_binding_descriptions.as_ptr(),
vertex_attribute_descriptions.len() as u32,
vertex_attribute_descriptions.as_ptr(),
)
}
// --- extended_dynamic_state functions ---
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetCullModeEXT.html>
#[inline]
pub unsafe fn cmd_set_cull_mode(
&self,
command_buffer: vk::CommandBuffer,
cull_mode: vk::CullModeFlags,
) {
(self.fp.cmd_set_cull_mode_ext)(command_buffer, cull_mode)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetFrontFaceEXT.html>
#[inline]
pub unsafe fn cmd_set_front_face(
&self,
command_buffer: vk::CommandBuffer,
front_face: vk::FrontFace,
) {
(self.fp.cmd_set_front_face_ext)(command_buffer, front_face)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetPrimitiveTopologyEXT.html>
#[inline]
pub unsafe fn cmd_set_primitive_topology(
&self,
command_buffer: vk::CommandBuffer,
primitive_topology: vk::PrimitiveTopology,
) {
(self.fp.cmd_set_primitive_topology_ext)(command_buffer, primitive_topology)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetViewportWithCountEXT.html>
#[inline]
pub unsafe fn cmd_set_viewport_with_count(
&self,
command_buffer: vk::CommandBuffer,
viewports: &[vk::Viewport],
) {
(self.fp.cmd_set_viewport_with_count_ext)(
command_buffer,
viewports.len() as u32,
viewports.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetScissorWithCountEXT.html>
#[inline]
pub unsafe fn cmd_set_scissor_with_count(
&self,
command_buffer: vk::CommandBuffer,
scissors: &[vk::Rect2D],
) {
(self.fp.cmd_set_scissor_with_count_ext)(
command_buffer,
scissors.len() as u32,
scissors.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdBindVertexBuffers2EXT.html>
#[inline]
pub unsafe fn cmd_bind_vertex_buffers2(
&self,
command_buffer: vk::CommandBuffer,
first_binding: u32,
buffers: &[vk::Buffer],
offsets: &[vk::DeviceSize],
sizes: Option<&[vk::DeviceSize]>,
strides: Option<&[vk::DeviceSize]>,
) {
assert_eq!(offsets.len(), buffers.len());
let p_sizes = if let Some(sizes) = sizes {
assert_eq!(sizes.len(), buffers.len());
sizes.as_ptr()
} else {
ptr::null()
};
let p_strides = if let Some(strides) = strides {
assert_eq!(strides.len(), buffers.len());
strides.as_ptr()
} else {
ptr::null()
};
(self.fp.cmd_bind_vertex_buffers2_ext)(
command_buffer,
first_binding,
buffers.len() as u32,
buffers.as_ptr(),
offsets.as_ptr(),
p_sizes,
p_strides,
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDepthTestEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_depth_test_enable(
&self,
command_buffer: vk::CommandBuffer,
depth_test_enable: bool,
) {
(self.fp.cmd_set_depth_test_enable_ext)(command_buffer, depth_test_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDepthWriteEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_depth_write_enable(
&self,
command_buffer: vk::CommandBuffer,
depth_write_enable: bool,
) {
(self.fp.cmd_set_depth_write_enable_ext)(command_buffer, depth_write_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDepthCompareOpEXT.html>
#[inline]
pub unsafe fn cmd_set_depth_compare_op(
&self,
command_buffer: vk::CommandBuffer,
depth_compare_op: vk::CompareOp,
) {
(self.fp.cmd_set_depth_compare_op_ext)(command_buffer, depth_compare_op)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDepthBoundsTestEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_depth_bounds_test_enable(
&self,
command_buffer: vk::CommandBuffer,
depth_bounds_test_enable: bool,
) {
(self.fp.cmd_set_depth_bounds_test_enable_ext)(
command_buffer,
depth_bounds_test_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetStencilTestEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_stencil_test_enable(
&self,
command_buffer: vk::CommandBuffer,
stencil_test_enable: bool,
) {
(self.fp.cmd_set_stencil_test_enable_ext)(command_buffer, stencil_test_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetStencilOpEXT.html>
#[inline]
pub unsafe fn cmd_set_stencil_op(
&self,
command_buffer: vk::CommandBuffer,
face_mask: vk::StencilFaceFlags,
fail_op: vk::StencilOp,
pass_op: vk::StencilOp,
depth_fail_op: vk::StencilOp,
compare_op: vk::CompareOp,
) {
(self.fp.cmd_set_stencil_op_ext)(
command_buffer,
face_mask,
fail_op,
pass_op,
depth_fail_op,
compare_op,
)
}
// --- extended_dynamic_state2 functions ---
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetPatchControlPointsEXT.html>
#[inline]
pub unsafe fn cmd_set_patch_control_points(
&self,
command_buffer: vk::CommandBuffer,
patch_control_points: u32,
) {
(self.fp.cmd_set_patch_control_points_ext)(command_buffer, patch_control_points)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetRasterizerDiscardEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_rasterizer_discard_enable(
&self,
command_buffer: vk::CommandBuffer,
rasterizer_discard_enable: bool,
) {
(self.fp.cmd_set_rasterizer_discard_enable_ext)(
command_buffer,
rasterizer_discard_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDepthBiasEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_depth_bias_enable(
&self,
command_buffer: vk::CommandBuffer,
depth_bias_enable: bool,
) {
(self.fp.cmd_set_depth_bias_enable_ext)(command_buffer, depth_bias_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetLogicOpEXT.html>
#[inline]
pub unsafe fn cmd_set_logic_op(
&self,
command_buffer: vk::CommandBuffer,
logic_op: vk::LogicOp,
) {
(self.fp.cmd_set_logic_op_ext)(command_buffer, logic_op)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetPrimitiveRestartEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_primitive_restart_enable(
&self,
command_buffer: vk::CommandBuffer,
primitive_restart_enable: bool,
) {
(self.fp.cmd_set_primitive_restart_enable_ext)(
command_buffer,
primitive_restart_enable.into(),
)
}
// --- extended_dynamic_state3 functions ---
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetTessellationDomainOriginEXT.html>
#[inline]
pub unsafe fn cmd_set_tessellation_domain_origin(
&self,
command_buffer: vk::CommandBuffer,
domain_origin: vk::TessellationDomainOrigin,
) {
(self.fp.cmd_set_tessellation_domain_origin_ext)(command_buffer, domain_origin)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDepthClampEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_depth_clamp_enable(
&self,
command_buffer: vk::CommandBuffer,
depth_clamp_enable: bool,
) {
(self.fp.cmd_set_depth_clamp_enable_ext)(command_buffer, depth_clamp_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetPolygonModeEXT.html>
#[inline]
pub unsafe fn cmd_set_polygon_mode(
&self,
command_buffer: vk::CommandBuffer,
polygon_mode: vk::PolygonMode,
) {
(self.fp.cmd_set_polygon_mode_ext)(command_buffer, polygon_mode)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetRasterizationSamplesEXT.html>
#[inline]
pub unsafe fn cmd_set_rasterization_samples(
&self,
command_buffer: vk::CommandBuffer,
rasterization_samples: vk::SampleCountFlags,
) {
(self.fp.cmd_set_rasterization_samples_ext)(command_buffer, rasterization_samples)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetSampleMaskEXT.html>
#[inline]
pub unsafe fn cmd_set_sample_mask(
&self,
command_buffer: vk::CommandBuffer,
samples: vk::SampleCountFlags,
sample_mask: &[vk::SampleMask],
) {
assert!(
samples.as_raw().is_power_of_two(),
"Only one SampleCount bit must be set"
);
assert_eq!(samples.as_raw() as usize / 32, sample_mask.len());
(self.fp.cmd_set_sample_mask_ext)(command_buffer, samples, sample_mask.as_ptr())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetAlphaToCoverageEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_alpha_to_coverage_enable(
&self,
command_buffer: vk::CommandBuffer,
alpha_to_coverage_enable: bool,
) {
(self.fp.cmd_set_alpha_to_coverage_enable_ext)(
command_buffer,
alpha_to_coverage_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetAlphaToOneEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_alpha_to_one_enable(
&self,
command_buffer: vk::CommandBuffer,
alpha_to_one_enable: bool,
) {
(self.fp.cmd_set_alpha_to_one_enable_ext)(command_buffer, alpha_to_one_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetLogicOpEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_logic_op_enable(
&self,
command_buffer: vk::CommandBuffer,
logic_op_enable: bool,
) {
(self.fp.cmd_set_logic_op_enable_ext)(command_buffer, logic_op_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetColorBlendEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_color_blend_enable(
&self,
command_buffer: vk::CommandBuffer,
first_attachment: u32,
color_blend_enables: &[vk::Bool32],
) {
(self.fp.cmd_set_color_blend_enable_ext)(
command_buffer,
first_attachment,
color_blend_enables.len() as u32,
color_blend_enables.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetColorBlendEquationEXT.html>
#[inline]
pub unsafe fn cmd_set_color_blend_equation(
&self,
command_buffer: vk::CommandBuffer,
first_attachment: u32,
color_blend_equations: &[vk::ColorBlendEquationEXT],
) {
(self.fp.cmd_set_color_blend_equation_ext)(
command_buffer,
first_attachment,
color_blend_equations.len() as u32,
color_blend_equations.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetColorWriteMaskEXT.html>
#[inline]
pub unsafe fn cmd_set_color_write_mask(
&self,
command_buffer: vk::CommandBuffer,
first_attachment: u32,
color_write_masks: &[vk::ColorComponentFlags],
) {
(self.fp.cmd_set_color_write_mask_ext)(
command_buffer,
first_attachment,
color_write_masks.len() as u32,
color_write_masks.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetRasterizationStreamEXT.html>
#[inline]
pub unsafe fn cmd_set_rasterization_stream(
&self,
command_buffer: vk::CommandBuffer,
rasterization_stream: u32,
) {
(self.fp.cmd_set_rasterization_stream_ext)(command_buffer, rasterization_stream)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetConservativeRasterizationModeEXT.html>
#[inline]
pub unsafe fn cmd_set_conservative_rasterization_mode(
&self,
command_buffer: vk::CommandBuffer,
conservative_rasterization_mode: vk::ConservativeRasterizationModeEXT,
) {
(self.fp.cmd_set_conservative_rasterization_mode_ext)(
command_buffer,
conservative_rasterization_mode,
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetExtraPrimitiveOverestimationSizeEXT.html>
#[inline]
pub unsafe fn cmd_set_extra_primitive_overestimation_size(
&self,
command_buffer: vk::CommandBuffer,
extra_primitive_overestimation_size: f32,
) {
(self.fp.cmd_set_extra_primitive_overestimation_size_ext)(
command_buffer,
extra_primitive_overestimation_size,
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDepthClipEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_depth_clip_enable(
&self,
command_buffer: vk::CommandBuffer,
depth_clip_enable: bool,
) {
(self.fp.cmd_set_depth_clip_enable_ext)(command_buffer, depth_clip_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetSampleLocationsEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_sample_locations_enable(
&self,
command_buffer: vk::CommandBuffer,
sample_locations_enable: bool,
) {
(self.fp.cmd_set_sample_locations_enable_ext)(
command_buffer,
sample_locations_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetColorBlendAdvancedEXT.html>
#[inline]
pub unsafe fn cmd_set_color_blend_advanced(
&self,
command_buffer: vk::CommandBuffer,
first_attachment: u32,
color_blend_advanced: &[vk::ColorBlendAdvancedEXT],
) {
(self.fp.cmd_set_color_blend_advanced_ext)(
command_buffer,
first_attachment,
color_blend_advanced.len() as u32,
color_blend_advanced.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetProvokingVertexModeEXT.html>
#[inline]
pub unsafe fn cmd_set_provoking_vertex_mode(
&self,
command_buffer: vk::CommandBuffer,
provoking_vertex_mode: vk::ProvokingVertexModeEXT,
) {
(self.fp.cmd_set_provoking_vertex_mode_ext)(command_buffer, provoking_vertex_mode)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetLineRasterizationModeEXT.html>
#[inline]
pub unsafe fn cmd_set_line_rasterization_mode(
&self,
command_buffer: vk::CommandBuffer,
line_rasterization_mode: vk::LineRasterizationModeEXT,
) {
(self.fp.cmd_set_line_rasterization_mode_ext)(command_buffer, line_rasterization_mode)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetLineStippleEnableEXT.html>
#[inline]
pub unsafe fn cmd_set_line_stipple_enable(
&self,
command_buffer: vk::CommandBuffer,
stippled_line_enable: bool,
) {
(self.fp.cmd_set_line_stipple_enable_ext)(command_buffer, stippled_line_enable.into())
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDepthClipNegativeOneToOneEXT.html>
#[inline]
pub unsafe fn cmd_set_depth_clip_negative_one_to_one(
&self,
command_buffer: vk::CommandBuffer,
negative_one_to_one: bool,
) {
(self.fp.cmd_set_depth_clip_negative_one_to_one_ext)(
command_buffer,
negative_one_to_one.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetViewportWScalingEnableNV.html>
#[inline]
pub unsafe fn cmd_set_viewport_w_scaling_enable_nv(
&self,
command_buffer: vk::CommandBuffer,
viewport_w_scaling_enable: bool,
) {
(self.fp.cmd_set_viewport_w_scaling_enable_nv)(
command_buffer,
viewport_w_scaling_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetViewportSwizzleNV.html>
#[inline]
pub unsafe fn cmd_set_viewport_swizzle_nv(
&self,
command_buffer: vk::CommandBuffer,
first_attachment: u32,
viewport_swizzles: &[vk::ViewportSwizzleNV],
) {
(self.fp.cmd_set_viewport_swizzle_nv)(
command_buffer,
first_attachment,
viewport_swizzles.len() as u32,
viewport_swizzles.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetCoverageToColorEnableNV.html>
#[inline]
pub unsafe fn cmd_set_coverage_to_color_enable_nv(
&self,
command_buffer: vk::CommandBuffer,
coverage_to_color_enable: bool,
) {
(self.fp.cmd_set_coverage_to_color_enable_nv)(
command_buffer,
coverage_to_color_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetCoverageToColorLocationNV.html>
#[inline]
pub unsafe fn cmd_set_coverage_to_color_location_nv(
&self,
command_buffer: vk::CommandBuffer,
coverage_to_color_location: u32,
) {
(self.fp.cmd_set_coverage_to_color_location_nv)(command_buffer, coverage_to_color_location)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetCoverageModulationModeNV.html>
#[inline]
pub unsafe fn cmd_set_coverage_modulation_mode_nv(
&self,
command_buffer: vk::CommandBuffer,
coverage_modulation_mode: vk::CoverageModulationModeNV,
) {
(self.fp.cmd_set_coverage_modulation_mode_nv)(command_buffer, coverage_modulation_mode)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetCoverageModulationTableEnableNV.html>
#[inline]
pub unsafe fn cmd_set_coverage_modulation_table_enable_nv(
&self,
command_buffer: vk::CommandBuffer,
coverage_modulation_table_enable: bool,
) {
(self.fp.cmd_set_coverage_modulation_table_enable_nv)(
command_buffer,
coverage_modulation_table_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetCoverageModulationTableNV.html>
#[inline]
pub unsafe fn cmd_set_coverage_modulation_table_nv(
&self,
command_buffer: vk::CommandBuffer,
coverage_modulation_table: &[f32],
) {
(self.fp.cmd_set_coverage_modulation_table_nv)(
command_buffer,
coverage_modulation_table.len() as u32,
coverage_modulation_table.as_ptr(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetShadingRateImageEnableNV.html>
#[inline]
pub unsafe fn cmd_set_shading_rate_image_enable_nv(
&self,
command_buffer: vk::CommandBuffer,
shading_rate_image_enable: bool,
) {
(self.fp.cmd_set_shading_rate_image_enable_nv)(
command_buffer,
shading_rate_image_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetRepresentativeFragmentTestEnableNV.html>
#[inline]
pub unsafe fn cmd_set_representative_fragment_test_enable_nv(
&self,
command_buffer: vk::CommandBuffer,
representative_fragment_test_enable: bool,
) {
(self.fp.cmd_set_representative_fragment_test_enable_nv)(
command_buffer,
representative_fragment_test_enable.into(),
)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetCoverageReductionModeNV.html>
#[inline]
pub unsafe fn cmd_set_coverage_reduction_mode_nv(
&self,
command_buffer: vk::CommandBuffer,
coverage_reduction_mode: vk::CoverageReductionModeNV,
) {
(self.fp.cmd_set_coverage_reduction_mode_nv)(command_buffer, coverage_reduction_mode)
}
pub const fn name() -> &'static CStr {
vk::ExtShaderObjectFn::name()
}
#[inline]
pub fn fp(&self) -> &vk::ExtShaderObjectFn {
&self.fp
}
#[inline]
pub fn device(&self) -> vk::Device {
self.handle
}
}

View File

@ -2,7 +2,7 @@
use super::Swapchain;
use crate::prelude::*;
use crate::vk;
use crate::{Device, Instance};
use crate::{Device, Entry, Instance};
use std::ffi::CStr;
use std::mem;
@ -14,6 +14,13 @@ pub struct DeviceGroup {
}
impl DeviceGroup {
/// # Warning
/// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called:
/// - [`Self::get_physical_device_present_rectangles()`]
///
/// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the
/// above [`Instance`] function is called. This will be solved in the next breaking `ash`
/// release: <https://github.com/ash-rs/ash/issues/727>.
pub fn new(instance: &Instance, device: &Device) -> Self {
let handle = device.handle();
let fp = vk::KhrDeviceGroupFn::load(|name| unsafe {
@ -22,6 +29,19 @@ impl DeviceGroup {
Self { handle, fp }
}
/// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra
/// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be
/// loaded instead of always panicking. See also [`Self::new()`] for more details.
///
/// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the
/// [`Instance`] function.
pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self {
let fp = vk::KhrDeviceGroupFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
Self { handle: device, fp }
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceGroupPeerMemoryFeaturesKHR.html>
#[inline]
pub unsafe fn get_device_group_peer_memory_features(
@ -112,6 +132,10 @@ impl DeviceGroup {
///
/// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html
/// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html
///
/// # Warning
///
/// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`].
#[inline]
pub unsafe fn get_physical_device_present_rectangles(
&self,

View File

@ -59,8 +59,14 @@ impl DeviceGroupCreation {
&self.fp
}
#[deprecated = "typo: this function is called `device()`, but returns an `Instance`."]
#[inline]
pub fn device(&self) -> vk::Instance {
self.handle
}
#[inline]
pub fn instance(&self) -> vk::Instance {
self.handle
}
}

View File

@ -21,9 +21,9 @@ impl ExternalMemoryFd {
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetMemoryFdKHR.html>
#[inline]
pub unsafe fn get_memory_fd(&self, create_info: &vk::MemoryGetFdInfoKHR) -> VkResult<i32> {
pub unsafe fn get_memory_fd(&self, get_fd_info: &vk::MemoryGetFdInfoKHR) -> VkResult<i32> {
let mut fd = -1;
(self.fp.get_memory_fd_khr)(self.handle, create_info, &mut fd).result_with_success(fd)
(self.fp.get_memory_fd_khr)(self.handle, get_fd_info, &mut fd).result_with_success(fd)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetMemoryFdPropertiesKHR.html>

View File

@ -22,32 +22,32 @@ impl Maintenance4 {
#[inline]
pub unsafe fn get_device_buffer_memory_requirements(
&self,
create_info: &vk::DeviceBufferMemoryRequirementsKHR,
memory_requirements: &vk::DeviceBufferMemoryRequirementsKHR,
out: &mut vk::MemoryRequirements2,
) {
(self.fp.get_device_buffer_memory_requirements_khr)(self.handle, create_info, out)
(self.fp.get_device_buffer_memory_requirements_khr)(self.handle, memory_requirements, out)
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceImageMemoryRequirementsKHR.html>
#[inline]
pub unsafe fn get_device_image_memory_requirements(
&self,
create_info: &vk::DeviceImageMemoryRequirementsKHR,
memory_requirements: &vk::DeviceImageMemoryRequirementsKHR,
out: &mut vk::MemoryRequirements2,
) {
(self.fp.get_device_image_memory_requirements_khr)(self.handle, create_info, out)
(self.fp.get_device_image_memory_requirements_khr)(self.handle, memory_requirements, out)
}
/// Retrieve the number of elements to pass to [`get_device_image_sparse_memory_requirements()`][Self::get_device_image_sparse_memory_requirements()]
#[inline]
pub unsafe fn get_device_image_sparse_memory_requirements_len(
&self,
create_info: &vk::DeviceImageMemoryRequirementsKHR,
memory_requirements: &vk::DeviceImageMemoryRequirementsKHR,
) -> usize {
let mut count = 0;
(self.fp.get_device_image_sparse_memory_requirements_khr)(
self.handle,
create_info,
memory_requirements,
&mut count,
std::ptr::null_mut(),
);
@ -61,13 +61,13 @@ impl Maintenance4 {
#[inline]
pub unsafe fn get_device_image_sparse_memory_requirements(
&self,
create_info: &vk::DeviceImageMemoryRequirementsKHR,
memory_requirements: &vk::DeviceImageMemoryRequirementsKHR,
out: &mut [vk::SparseImageMemoryRequirements2],
) {
let mut count = out.len() as u32;
(self.fp.get_device_image_sparse_memory_requirements_khr)(
self.handle,
create_info,
memory_requirements,
&mut count,
out.as_mut_ptr(),
);

View File

@ -22,6 +22,7 @@ pub use self::get_surface_capabilities2::GetSurfaceCapabilities2;
pub use self::maintenance1::Maintenance1;
pub use self::maintenance3::Maintenance3;
pub use self::maintenance4::Maintenance4;
pub use self::performance_query::PerformanceQuery;
pub use self::pipeline_executable_properties::PipelineExecutableProperties;
pub use self::present_wait::PresentWait;
pub use self::push_descriptor::PushDescriptor;
@ -60,6 +61,7 @@ mod get_surface_capabilities2;
mod maintenance1;
mod maintenance3;
mod maintenance4;
mod performance_query;
mod pipeline_executable_properties;
mod present_wait;
mod push_descriptor;

View File

@ -0,0 +1,121 @@
use crate::prelude::*;
use crate::vk;
use crate::{Entry, Instance};
use std::ffi::CStr;
use std::mem;
use std::ptr;
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_performance_query.html>
#[derive(Clone)]
pub struct PerformanceQuery {
handle: vk::Instance,
fp: vk::KhrPerformanceQueryFn,
}
impl PerformanceQuery {
pub fn new(entry: &Entry, instance: &Instance) -> Self {
let handle = instance.handle();
let fp = vk::KhrPerformanceQueryFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(handle, name.as_ptr()))
});
Self { handle, fp }
}
/// Retrieve the number of elements to pass to [`enumerate_physical_device_queue_family_performance_query_counters()`][Self::enumerate_physical_device_queue_family_performance_query_counters()]
#[inline]
pub unsafe fn enumerate_physical_device_queue_family_performance_query_counters_len(
&self,
physical_device: vk::PhysicalDevice,
queue_family_index: u32,
) -> VkResult<usize> {
let mut count = 0;
(self
.fp
.enumerate_physical_device_queue_family_performance_query_counters_khr)(
physical_device,
queue_family_index,
&mut count,
ptr::null_mut(),
ptr::null_mut(),
)
.result_with_success(count as usize)
}
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR.html>
///
/// Call [`enumerate_physical_device_queue_family_performance_query_counters_len()`][Self::enumerate_physical_device_queue_family_performance_query_counters_len()] to query the number of elements to pass to `out_counters` and `out_counter_descriptions`.
/// Be sure to [`Default::default()`]-initialize these elements and optionally set their `p_next` pointer.
#[inline]
pub unsafe fn enumerate_physical_device_queue_family_performance_query_counters(
&self,
physical_device: vk::PhysicalDevice,
queue_family_index: u32,
out_counters: &mut [vk::PerformanceCounterKHR],
out_counter_descriptions: &mut [vk::PerformanceCounterDescriptionKHR],
) -> VkResult<()> {
assert_eq!(out_counters.len(), out_counter_descriptions.len());
let mut count = out_counters.len() as u32;
(self
.fp
.enumerate_physical_device_queue_family_performance_query_counters_khr)(
physical_device,
queue_family_index,
&mut count,
out_counters.as_mut_ptr(),
out_counter_descriptions.as_mut_ptr(),
)
.result()?;
assert_eq!(count as usize, out_counters.len());
assert_eq!(count as usize, out_counter_descriptions.len());
Ok(())
}
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR.html>
#[inline]
pub unsafe fn get_physical_device_queue_family_performance_query_passes(
&self,
physical_device: vk::PhysicalDevice,
performance_query_create_info: &vk::QueryPoolPerformanceCreateInfoKHR,
) -> u32 {
let mut num_passes = 0;
(self
.fp
.get_physical_device_queue_family_performance_query_passes_khr)(
physical_device,
performance_query_create_info,
&mut num_passes,
);
num_passes
}
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkAcquireProfilingLockKHR.html>
#[inline]
pub unsafe fn acquire_profiling_lock(
&self,
device: vk::Device,
info: &vk::AcquireProfilingLockInfoKHR,
) -> VkResult<()> {
(self.fp.acquire_profiling_lock_khr)(device, info).result()
}
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkReleaseProfilingLockKHR.html>
#[inline]
pub unsafe fn release_profiling_lock(&self, device: vk::Device) {
(self.fp.release_profiling_lock_khr)(device)
}
#[inline]
pub const fn name() -> &'static CStr {
vk::KhrPerformanceQueryFn::name()
}
#[inline]
pub fn fp(&self) -> &vk::KhrPerformanceQueryFn {
&self.fp
}
#[inline]
pub fn instance(&self) -> vk::Instance {
self.handle
}
}

View File

@ -3,10 +3,11 @@ use super::DeviceGroup;
use crate::prelude::*;
use crate::vk;
use crate::RawPtr;
use crate::{Device, Instance};
use crate::{Device, Entry, Instance};
use std::ffi::CStr;
use std::mem;
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_swapchain.html>
#[derive(Clone)]
pub struct Swapchain {
handle: vk::Device,
@ -14,6 +15,13 @@ pub struct Swapchain {
}
impl Swapchain {
/// # Warning
/// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called:
/// - [`Self::get_physical_device_present_rectangles()`]
///
/// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the
/// above [`Instance`] function is called. This will be solved in the next breaking `ash`
/// release: <https://github.com/ash-rs/ash/issues/727>.
pub fn new(instance: &Instance, device: &Device) -> Self {
let handle = device.handle();
let fp = vk::KhrSwapchainFn::load(|name| unsafe {
@ -22,6 +30,19 @@ impl Swapchain {
Self { handle, fp }
}
/// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra
/// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be
/// loaded instead of always panicking. See also [`Self::new()`] for more details.
///
/// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the
/// [`Instance`] function.
pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self {
let fp = vk::KhrSwapchainFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
Self { handle: device, fp }
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateSwapchainKHR.html>
#[inline]
pub unsafe fn create_swapchain(
@ -153,6 +174,10 @@ impl Swapchain {
///
/// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html
/// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html
///
/// # Warning
///
/// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`].
#[inline]
pub unsafe fn get_physical_device_present_rectangles(
&self,

View File

@ -1,3 +1,5 @@
#[cfg(doc)]
use super::Entry;
use crate::device::Device;
use crate::prelude::*;
use crate::vk;
@ -335,9 +337,17 @@ impl Instance {
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateDevice.html>
///
/// # Safety
/// In order for the created [`Device`] to be valid for the duration of its
/// usage, the [`Instance`] this was called on must be dropped later than the
/// resulting [`Device`].
///
/// There is a [parent/child relation] between [`Instance`] and the resulting [`Device`]. The
/// application must not [destroy][Instance::destroy_instance()] the parent [`Instance`] object
/// before first [destroying][Device::destroy_device()] the returned [`Device`] child object.
/// [`Device`] does _not_ implement [drop][drop()] semantics and can only be destroyed via
/// [`destroy_device()`][Device::destroy_device()].
///
/// See the [`Entry::create_instance()`] documentation for more destruction ordering rules on
/// [`Instance`].
///
/// [parent/child relation]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#fundamentals-objectmodel-lifetime
#[inline]
pub unsafe fn create_device(
&self,

View File

@ -26,13 +26,12 @@ impl vk::Result {
}
}
/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore,
/// ensuring all available data has been read into the vector.
/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, ensuring all
/// available data has been read into the vector.
///
/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available
/// items may change between calls; [`vk::Result::INCOMPLETE`] is returned when the count
/// increased (and the vector is not large enough after querying the initial size),
/// requiring Ash to try again.
/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available items may
/// change between calls; [`vk::Result::INCOMPLETE`] is returned when the count increased (and the
/// vector is not large enough after querying the initial size), requiring Ash to try again.
///
/// [`vkEnumerateInstanceExtensionProperties`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceExtensionProperties.html
pub(crate) unsafe fn read_into_uninitialized_vector<N: Copy + Default + TryInto<usize>, T>(
@ -56,18 +55,17 @@ where
}
}
/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore,
/// ensuring all available data has been read into the vector.
/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, ensuring all
/// available data has been read into the vector.
///
/// Items in the target vector are [`default()`][`Default::default()`]-initialized which
/// is required for [`vk::BaseOutStructure`]-like structs where [`vk::BaseOutStructure::s_type`]
/// needs to be a valid type and [`vk::BaseOutStructure::p_next`] a valid or
/// [`null`][`std::ptr::null_mut()`] pointer.
/// Items in the target vector are [`default()`][Default::default()]-initialized which is required
/// for [`vk::BaseOutStructure`]-like structs where [`vk::BaseOutStructure::s_type`] needs to be a
/// valid type and [`vk::BaseOutStructure::p_next`] a valid or [`null`][std::ptr::null_mut()]
/// pointer.
///
/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available
/// items may change between calls; [`vk::Result::INCOMPLETE`] is returned when the count
/// increased (and the vector is not large enough after querying the initial size),
/// requiring Ash to try again.
/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available items may
/// change between calls; [`vk::Result::INCOMPLETE`] is returned when the count increased (and the
/// vector is not large enough after querying the initial size), requiring Ash to try again.
///
/// [`vkEnumerateInstanceExtensionProperties`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceExtensionProperties.html
pub(crate) unsafe fn read_into_defaulted_vector<
@ -116,7 +114,7 @@ pub(crate) fn debug_flags<Value: Into<u64> + Copy>(
if !first {
f.write_str(" | ")?;
}
write!(f, "{:b}", accum)?;
write!(f, "{accum:b}")?;
}
Ok(())
}

View File

@ -104,7 +104,9 @@ impl<'a, T: Copy + 'a> Iterator for AlignIter<'a, T> {
/// 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>> {
// TODO use stream_len() once it is stabilized and remove the subsequent rewind() call
let size = x.seek(io::SeekFrom::End(0))?;
x.rewind()?;
if size % 4 != 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
@ -119,7 +121,6 @@ pub fn read_spv<R: io::Read + io::Seek>(x: &mut R) -> io::Result<Vec<u32>> {
// Zero-initialize the result to prevent read_exact from possibly
// reading uninitialized memory.
let mut result = vec![0u32; words];
x.seek(io::SeekFrom::Start(0))?;
x.read_exact(unsafe {
slice::from_raw_parts_mut(result.as_mut_ptr().cast::<u8>(), words * 4)
})?;

View File

@ -200,6 +200,8 @@ pub type PhysicalDeviceSubgroupSizeControlPropertiesEXT =
PhysicalDeviceSubgroupSizeControlProperties;
pub type PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT =
PipelineShaderStageRequiredSubgroupSizeCreateInfo;
pub type ShaderRequiredSubgroupSizeCreateInfoEXT =
PipelineShaderStageRequiredSubgroupSizeCreateInfo;
pub type MemoryOpaqueCaptureAddressAllocateInfoKHR = MemoryOpaqueCaptureAddressAllocateInfo;
pub type DeviceMemoryOpaqueCaptureAddressInfoKHR = DeviceMemoryOpaqueCaptureAddressInfo;
pub type PhysicalDevicePipelineCreationCacheControlFeaturesEXT =

View File

@ -1280,13 +1280,23 @@ impl VideoEncodeCapabilityFlagsKHR {
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkVideoEncodeFeedbackFlagBitsKHR.html>"]
pub struct VideoEncodeFeedbackFlagsKHR(pub(crate) Flags);
vk_bitflags_wrapped!(VideoEncodeFeedbackFlagsKHR, Flags);
impl VideoEncodeFeedbackFlagsKHR {
pub const BITSTREAM_BUFFER_OFFSET: Self = Self(0b1);
pub const BITSTREAM_BYTES_WRITTEN: Self = Self(0b10);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkVideoEncodeRateControlModeFlagBitsKHR.html>"]
pub struct VideoEncodeRateControlModeFlagsKHR(pub(crate) Flags);
vk_bitflags_wrapped!(VideoEncodeRateControlModeFlagsKHR, Flags);
impl VideoEncodeRateControlModeFlagsKHR {
pub const NONE: Self = Self(0);
pub const CBR: Self = Self(1);
pub const VBR: Self = Self(2);
pub const DEFAULT: Self = Self(0);
pub const DISABLED: Self = Self(0b1);
pub const CBR: Self = Self(0b10);
pub const VBR: Self = Self(0b100);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -1319,26 +1329,7 @@ impl VideoEncodeH264CapabilityFlagsEXT {
pub const ROW_UNALIGNED_SLICE: Self = Self(0b100_0000_0000_0000_0000_0000);
pub const DIFFERENT_SLICE_TYPE: Self = Self(0b1000_0000_0000_0000_0000_0000);
pub const B_FRAME_IN_L1_LIST: Self = Self(0b1_0000_0000_0000_0000_0000_0000);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkVideoEncodeH264InputModeFlagBitsEXT.html>"]
pub struct VideoEncodeH264InputModeFlagsEXT(pub(crate) Flags);
vk_bitflags_wrapped!(VideoEncodeH264InputModeFlagsEXT, Flags);
impl VideoEncodeH264InputModeFlagsEXT {
pub const FRAME: Self = Self(0b1);
pub const SLICE: Self = Self(0b10);
pub const NON_VCL: Self = Self(0b100);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkVideoEncodeH264OutputModeFlagBitsEXT.html>"]
pub struct VideoEncodeH264OutputModeFlagsEXT(pub(crate) Flags);
vk_bitflags_wrapped!(VideoEncodeH264OutputModeFlagsEXT, Flags);
impl VideoEncodeH264OutputModeFlagsEXT {
pub const FRAME: Self = Self(0b1);
pub const SLICE: Self = Self(0b10);
pub const NON_VCL: Self = Self(0b100);
pub const DIFFERENT_REFERENCE_FINAL_LISTS: Self = Self(0b10_0000_0000_0000_0000_0000_0000);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -1474,26 +1465,7 @@ impl VideoEncodeH265CapabilityFlagsEXT {
pub const DEPENDENT_SLICE_SEGMENT: Self = Self(0b1000_0000_0000_0000_0000_0000);
pub const DIFFERENT_SLICE_TYPE: Self = Self(0b1_0000_0000_0000_0000_0000_0000);
pub const B_FRAME_IN_L1_LIST: Self = Self(0b10_0000_0000_0000_0000_0000_0000);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkVideoEncodeH265InputModeFlagBitsEXT.html>"]
pub struct VideoEncodeH265InputModeFlagsEXT(pub(crate) Flags);
vk_bitflags_wrapped!(VideoEncodeH265InputModeFlagsEXT, Flags);
impl VideoEncodeH265InputModeFlagsEXT {
pub const FRAME: Self = Self(0b1);
pub const SLICE_SEGMENT: Self = Self(0b10);
pub const NON_VCL: Self = Self(0b100);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkVideoEncodeH265OutputModeFlagBitsEXT.html>"]
pub struct VideoEncodeH265OutputModeFlagsEXT(pub(crate) Flags);
vk_bitflags_wrapped!(VideoEncodeH265OutputModeFlagsEXT, Flags);
impl VideoEncodeH265OutputModeFlagsEXT {
pub const FRAME: Self = Self(0b1);
pub const SLICE_SEGMENT: Self = Self(0b10);
pub const NON_VCL: Self = Self(0b100);
pub const DIFFERENT_REFERENCE_FINAL_LISTS: Self = Self(0b100_0000_0000_0000_0000_0000_0000);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -1641,3 +1613,11 @@ vk_bitflags_wrapped!(MicromapCreateFlagsEXT, Flags);
impl MicromapCreateFlagsEXT {
pub const DEVICE_ADDRESS_CAPTURE_REPLAY: Self = Self(0b1);
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkShaderCreateFlagBitsEXT.html>"]
pub struct ShaderCreateFlagsEXT(pub(crate) Flags);
vk_bitflags_wrapped!(ShaderCreateFlagsEXT, Flags);
impl ShaderCreateFlagsEXT {
pub const LINK_STAGE: Self = Self(0b1);
}

View File

@ -318,11 +318,15 @@ impl fmt::Debug for AccessFlags2 {
),
(AccessFlags2::MICROMAP_READ_EXT.0, "MICROMAP_READ_EXT"),
(AccessFlags2::MICROMAP_WRITE_EXT.0, "MICROMAP_WRITE_EXT"),
(AccessFlags2::RESERVED_49_ARM.0, "RESERVED_49_ARM"),
(AccessFlags2::RESERVED_50_ARM.0, "RESERVED_50_ARM"),
(AccessFlags2::OPTICAL_FLOW_READ_NV.0, "OPTICAL_FLOW_READ_NV"),
(
AccessFlags2::OPTICAL_FLOW_WRITE_NV.0,
"OPTICAL_FLOW_WRITE_NV",
),
(AccessFlags2::RESERVED_47_EXT.0, "RESERVED_47_EXT"),
(AccessFlags2::RESERVED_48_EXT.0, "RESERVED_48_EXT"),
];
debug_flags(f, KNOWN, self.0)
}
@ -515,6 +519,7 @@ impl fmt::Debug for BufferCreateFlags {
BufferCreateFlags::DESCRIPTOR_BUFFER_CAPTURE_REPLAY_EXT.0,
"DESCRIPTOR_BUFFER_CAPTURE_REPLAY_EXT",
),
(BufferCreateFlags::RESERVED_6_KHR.0, "RESERVED_6_KHR"),
(BufferCreateFlags::PROTECTED.0, "PROTECTED"),
(
BufferCreateFlags::DEVICE_ADDRESS_CAPTURE_REPLAY.0,
@ -655,12 +660,12 @@ impl fmt::Debug for BuildAccelerationStructureFlagsKHR {
"ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT",
),
(
BuildAccelerationStructureFlagsKHR::RESERVED_9_NV.0,
"RESERVED_9_NV",
BuildAccelerationStructureFlagsKHR::ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV.0,
"ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV",
),
(
BuildAccelerationStructureFlagsKHR::RESERVED_10_NV.0,
"RESERVED_10_NV",
BuildAccelerationStructureFlagsKHR::ALLOW_DATA_ACCESS.0,
"ALLOW_DATA_ACCESS",
),
];
debug_flags(f, KNOWN, self.0)
@ -1204,6 +1209,10 @@ impl fmt::Debug for DescriptorSetLayoutCreateFlags {
DescriptorSetLayoutCreateFlags::HOST_ONLY_POOL_EXT.0,
"HOST_ONLY_POOL_EXT",
),
(
DescriptorSetLayoutCreateFlags::RESERVED_6_EXT.0,
"RESERVED_6_EXT",
),
(
DescriptorSetLayoutCreateFlags::UPDATE_AFTER_BIND_POOL.0,
"UPDATE_AFTER_BIND_POOL",
@ -1444,6 +1453,21 @@ impl fmt::Debug for DiscardRectangleModeEXT {
}
}
}
impl fmt::Debug for DisplacementMicromapFormatNV {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match *self {
Self::TYPE_64_TRIANGLES_64_BYTES => Some("TYPE_64_TRIANGLES_64_BYTES"),
Self::TYPE_256_TRIANGLES_128_BYTES => Some("TYPE_256_TRIANGLES_128_BYTES"),
Self::TYPE_1024_TRIANGLES_128_BYTES => Some("TYPE_1024_TRIANGLES_128_BYTES"),
_ => None,
};
if let Some(x) = name {
f.write_str(x)
} else {
self.0.fmt(f)
}
}
}
impl fmt::Debug for DisplayEventTypeEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match *self {
@ -1525,6 +1549,7 @@ impl fmt::Debug for DriverId {
Self::MESA_VENUS => Some("MESA_VENUS"),
Self::MESA_DOZEN => Some("MESA_DOZEN"),
Self::MESA_NVK => Some("MESA_NVK"),
Self::IMAGINATION_OPEN_SOURCE_MESA => Some("IMAGINATION_OPEN_SOURCE_MESA"),
_ => None,
};
if let Some(x) = name {
@ -1548,12 +1573,15 @@ impl fmt::Debug for DynamicState {
Self::STENCIL_REFERENCE => Some("STENCIL_REFERENCE"),
Self::VIEWPORT_W_SCALING_NV => Some("VIEWPORT_W_SCALING_NV"),
Self::DISCARD_RECTANGLE_EXT => Some("DISCARD_RECTANGLE_EXT"),
Self::DISCARD_RECTANGLE_ENABLE_EXT => Some("DISCARD_RECTANGLE_ENABLE_EXT"),
Self::DISCARD_RECTANGLE_MODE_EXT => Some("DISCARD_RECTANGLE_MODE_EXT"),
Self::SAMPLE_LOCATIONS_EXT => Some("SAMPLE_LOCATIONS_EXT"),
Self::RAY_TRACING_PIPELINE_STACK_SIZE_KHR => {
Some("RAY_TRACING_PIPELINE_STACK_SIZE_KHR")
}
Self::VIEWPORT_SHADING_RATE_PALETTE_NV => Some("VIEWPORT_SHADING_RATE_PALETTE_NV"),
Self::VIEWPORT_COARSE_SAMPLE_ORDER_NV => Some("VIEWPORT_COARSE_SAMPLE_ORDER_NV"),
Self::EXCLUSIVE_SCISSOR_ENABLE_NV => Some("EXCLUSIVE_SCISSOR_ENABLE_NV"),
Self::EXCLUSIVE_SCISSOR_NV => Some("EXCLUSIVE_SCISSOR_NV"),
Self::FRAGMENT_SHADING_RATE_KHR => Some("FRAGMENT_SHADING_RATE_KHR"),
Self::LINE_STIPPLE_EXT => Some("LINE_STIPPLE_EXT"),
@ -1600,6 +1628,9 @@ impl fmt::Debug for DynamicState {
Some("REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV")
}
Self::COVERAGE_REDUCTION_MODE_NV => Some("COVERAGE_REDUCTION_MODE_NV"),
Self::ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT => {
Some("ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT")
}
Self::CULL_MODE => Some("CULL_MODE"),
Self::FRONT_FACE => Some("FRONT_FACE"),
Self::PRIMITIVE_TOPOLOGY => Some("PRIMITIVE_TOPOLOGY"),
@ -1680,14 +1711,6 @@ impl fmt::Debug for ExternalFenceHandleTypeFlags {
"OPAQUE_WIN32_KMT",
),
(ExternalFenceHandleTypeFlags::SYNC_FD.0, "SYNC_FD"),
(
ExternalFenceHandleTypeFlags::RESERVED_4_NV.0,
"RESERVED_4_NV",
),
(
ExternalFenceHandleTypeFlags::RESERVED_5_NV.0,
"RESERVED_5_NV",
),
];
debug_flags(f, KNOWN, self.0)
}
@ -1765,8 +1788,8 @@ impl fmt::Debug for ExternalMemoryHandleTypeFlags {
"RDMA_ADDRESS_NV",
),
(
ExternalMemoryHandleTypeFlags::RESERVED_13_NV.0,
"RESERVED_13_NV",
ExternalMemoryHandleTypeFlags::TYPE_530_QNX.0,
"TYPE_530_QNX",
),
];
debug_flags(f, KNOWN, self.0)
@ -1825,10 +1848,6 @@ impl fmt::Debug for ExternalSemaphoreHandleTypeFlags {
ExternalSemaphoreHandleTypeFlags::ZIRCON_EVENT_FUCHSIA.0,
"ZIRCON_EVENT_FUCHSIA",
),
(
ExternalSemaphoreHandleTypeFlags::RESERVED_5_NV.0,
"RESERVED_5_NV",
),
];
debug_flags(f, KNOWN, self.0)
}
@ -2190,7 +2209,7 @@ impl fmt::Debug for FormatFeatureFlags {
}
impl fmt::Debug for FormatFeatureFlags2 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN : & [(Flags64 , & str)] = & [(FormatFeatureFlags2 :: SAMPLED_IMAGE . 0 , "SAMPLED_IMAGE") , (FormatFeatureFlags2 :: STORAGE_IMAGE . 0 , "STORAGE_IMAGE") , (FormatFeatureFlags2 :: STORAGE_IMAGE_ATOMIC . 0 , "STORAGE_IMAGE_ATOMIC") , (FormatFeatureFlags2 :: UNIFORM_TEXEL_BUFFER . 0 , "UNIFORM_TEXEL_BUFFER") , (FormatFeatureFlags2 :: STORAGE_TEXEL_BUFFER . 0 , "STORAGE_TEXEL_BUFFER") , (FormatFeatureFlags2 :: STORAGE_TEXEL_BUFFER_ATOMIC . 0 , "STORAGE_TEXEL_BUFFER_ATOMIC") , (FormatFeatureFlags2 :: VERTEX_BUFFER . 0 , "VERTEX_BUFFER") , (FormatFeatureFlags2 :: COLOR_ATTACHMENT . 0 , "COLOR_ATTACHMENT") , (FormatFeatureFlags2 :: COLOR_ATTACHMENT_BLEND . 0 , "COLOR_ATTACHMENT_BLEND") , (FormatFeatureFlags2 :: DEPTH_STENCIL_ATTACHMENT . 0 , "DEPTH_STENCIL_ATTACHMENT") , (FormatFeatureFlags2 :: BLIT_SRC . 0 , "BLIT_SRC") , (FormatFeatureFlags2 :: BLIT_DST . 0 , "BLIT_DST") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_LINEAR . 0 , "SAMPLED_IMAGE_FILTER_LINEAR") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_CUBIC . 0 , "SAMPLED_IMAGE_FILTER_CUBIC") , (FormatFeatureFlags2 :: TRANSFER_SRC . 0 , "TRANSFER_SRC") , (FormatFeatureFlags2 :: TRANSFER_DST . 0 , "TRANSFER_DST") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_MINMAX . 0 , "SAMPLED_IMAGE_FILTER_MINMAX") , (FormatFeatureFlags2 :: MIDPOINT_CHROMA_SAMPLES . 0 , "MIDPOINT_CHROMA_SAMPLES") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE") , (FormatFeatureFlags2 :: DISJOINT . 0 , "DISJOINT") , (FormatFeatureFlags2 :: COSITED_CHROMA_SAMPLES . 0 , "COSITED_CHROMA_SAMPLES") , (FormatFeatureFlags2 :: STORAGE_READ_WITHOUT_FORMAT . 0 , "STORAGE_READ_WITHOUT_FORMAT") , (FormatFeatureFlags2 :: STORAGE_WRITE_WITHOUT_FORMAT . 0 , "STORAGE_WRITE_WITHOUT_FORMAT") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_DEPTH_COMPARISON . 0 , "SAMPLED_IMAGE_DEPTH_COMPARISON") , (FormatFeatureFlags2 :: VIDEO_DECODE_OUTPUT_KHR . 0 , "VIDEO_DECODE_OUTPUT_KHR") , (FormatFeatureFlags2 :: VIDEO_DECODE_DPB_KHR . 0 , "VIDEO_DECODE_DPB_KHR") , (FormatFeatureFlags2 :: ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR . 0 , "ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR") , (FormatFeatureFlags2 :: FRAGMENT_DENSITY_MAP_EXT . 0 , "FRAGMENT_DENSITY_MAP_EXT") , (FormatFeatureFlags2 :: FRAGMENT_SHADING_RATE_ATTACHMENT_KHR . 0 , "FRAGMENT_SHADING_RATE_ATTACHMENT_KHR") , (FormatFeatureFlags2 :: RESERVED_44_EXT . 0 , "RESERVED_44_EXT") , (FormatFeatureFlags2 :: RESERVED_45_EXT . 0 , "RESERVED_45_EXT") , (FormatFeatureFlags2 :: VIDEO_ENCODE_INPUT_KHR . 0 , "VIDEO_ENCODE_INPUT_KHR") , (FormatFeatureFlags2 :: VIDEO_ENCODE_DPB_KHR . 0 , "VIDEO_ENCODE_DPB_KHR") , (FormatFeatureFlags2 :: LINEAR_COLOR_ATTACHMENT_NV . 0 , "LINEAR_COLOR_ATTACHMENT_NV") , (FormatFeatureFlags2 :: WEIGHT_IMAGE_QCOM . 0 , "WEIGHT_IMAGE_QCOM") , (FormatFeatureFlags2 :: WEIGHT_SAMPLED_IMAGE_QCOM . 0 , "WEIGHT_SAMPLED_IMAGE_QCOM") , (FormatFeatureFlags2 :: BLOCK_MATCHING_QCOM . 0 , "BLOCK_MATCHING_QCOM") , (FormatFeatureFlags2 :: BOX_FILTER_SAMPLED_QCOM . 0 , "BOX_FILTER_SAMPLED_QCOM") , (FormatFeatureFlags2 :: RESERVED_39_EXT . 0 , "RESERVED_39_EXT") , (FormatFeatureFlags2 :: OPTICAL_FLOW_IMAGE_NV . 0 , "OPTICAL_FLOW_IMAGE_NV") , (FormatFeatureFlags2 :: OPTICAL_FLOW_VECTOR_NV . 0 , "OPTICAL_FLOW_VECTOR_NV") , (FormatFeatureFlags2 :: OPTICAL_FLOW_COST_NV . 0 , "OPTICAL_FLOW_COST_NV")] ;
const KNOWN : & [(Flags64 , & str)] = & [(FormatFeatureFlags2 :: SAMPLED_IMAGE . 0 , "SAMPLED_IMAGE") , (FormatFeatureFlags2 :: STORAGE_IMAGE . 0 , "STORAGE_IMAGE") , (FormatFeatureFlags2 :: STORAGE_IMAGE_ATOMIC . 0 , "STORAGE_IMAGE_ATOMIC") , (FormatFeatureFlags2 :: UNIFORM_TEXEL_BUFFER . 0 , "UNIFORM_TEXEL_BUFFER") , (FormatFeatureFlags2 :: STORAGE_TEXEL_BUFFER . 0 , "STORAGE_TEXEL_BUFFER") , (FormatFeatureFlags2 :: STORAGE_TEXEL_BUFFER_ATOMIC . 0 , "STORAGE_TEXEL_BUFFER_ATOMIC") , (FormatFeatureFlags2 :: VERTEX_BUFFER . 0 , "VERTEX_BUFFER") , (FormatFeatureFlags2 :: COLOR_ATTACHMENT . 0 , "COLOR_ATTACHMENT") , (FormatFeatureFlags2 :: COLOR_ATTACHMENT_BLEND . 0 , "COLOR_ATTACHMENT_BLEND") , (FormatFeatureFlags2 :: DEPTH_STENCIL_ATTACHMENT . 0 , "DEPTH_STENCIL_ATTACHMENT") , (FormatFeatureFlags2 :: BLIT_SRC . 0 , "BLIT_SRC") , (FormatFeatureFlags2 :: BLIT_DST . 0 , "BLIT_DST") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_LINEAR . 0 , "SAMPLED_IMAGE_FILTER_LINEAR") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_CUBIC . 0 , "SAMPLED_IMAGE_FILTER_CUBIC") , (FormatFeatureFlags2 :: TRANSFER_SRC . 0 , "TRANSFER_SRC") , (FormatFeatureFlags2 :: TRANSFER_DST . 0 , "TRANSFER_DST") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_MINMAX . 0 , "SAMPLED_IMAGE_FILTER_MINMAX") , (FormatFeatureFlags2 :: MIDPOINT_CHROMA_SAMPLES . 0 , "MIDPOINT_CHROMA_SAMPLES") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE") , (FormatFeatureFlags2 :: DISJOINT . 0 , "DISJOINT") , (FormatFeatureFlags2 :: COSITED_CHROMA_SAMPLES . 0 , "COSITED_CHROMA_SAMPLES") , (FormatFeatureFlags2 :: STORAGE_READ_WITHOUT_FORMAT . 0 , "STORAGE_READ_WITHOUT_FORMAT") , (FormatFeatureFlags2 :: STORAGE_WRITE_WITHOUT_FORMAT . 0 , "STORAGE_WRITE_WITHOUT_FORMAT") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_DEPTH_COMPARISON . 0 , "SAMPLED_IMAGE_DEPTH_COMPARISON") , (FormatFeatureFlags2 :: VIDEO_DECODE_OUTPUT_KHR . 0 , "VIDEO_DECODE_OUTPUT_KHR") , (FormatFeatureFlags2 :: VIDEO_DECODE_DPB_KHR . 0 , "VIDEO_DECODE_DPB_KHR") , (FormatFeatureFlags2 :: ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR . 0 , "ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR") , (FormatFeatureFlags2 :: FRAGMENT_DENSITY_MAP_EXT . 0 , "FRAGMENT_DENSITY_MAP_EXT") , (FormatFeatureFlags2 :: FRAGMENT_SHADING_RATE_ATTACHMENT_KHR . 0 , "FRAGMENT_SHADING_RATE_ATTACHMENT_KHR") , (FormatFeatureFlags2 :: RESERVED_44_EXT . 0 , "RESERVED_44_EXT") , (FormatFeatureFlags2 :: RESERVED_45_EXT . 0 , "RESERVED_45_EXT") , (FormatFeatureFlags2 :: RESERVED_46_EXT . 0 , "RESERVED_46_EXT") , (FormatFeatureFlags2 :: VIDEO_ENCODE_INPUT_KHR . 0 , "VIDEO_ENCODE_INPUT_KHR") , (FormatFeatureFlags2 :: VIDEO_ENCODE_DPB_KHR . 0 , "VIDEO_ENCODE_DPB_KHR") , (FormatFeatureFlags2 :: LINEAR_COLOR_ATTACHMENT_NV . 0 , "LINEAR_COLOR_ATTACHMENT_NV") , (FormatFeatureFlags2 :: WEIGHT_IMAGE_QCOM . 0 , "WEIGHT_IMAGE_QCOM") , (FormatFeatureFlags2 :: WEIGHT_SAMPLED_IMAGE_QCOM . 0 , "WEIGHT_SAMPLED_IMAGE_QCOM") , (FormatFeatureFlags2 :: BLOCK_MATCHING_QCOM . 0 , "BLOCK_MATCHING_QCOM") , (FormatFeatureFlags2 :: BOX_FILTER_SAMPLED_QCOM . 0 , "BOX_FILTER_SAMPLED_QCOM") , (FormatFeatureFlags2 :: RESERVED_39_EXT . 0 , "RESERVED_39_EXT") , (FormatFeatureFlags2 :: OPTICAL_FLOW_IMAGE_NV . 0 , "OPTICAL_FLOW_IMAGE_NV") , (FormatFeatureFlags2 :: OPTICAL_FLOW_VECTOR_NV . 0 , "OPTICAL_FLOW_VECTOR_NV") , (FormatFeatureFlags2 :: OPTICAL_FLOW_COST_NV . 0 , "OPTICAL_FLOW_COST_NV")] ;
debug_flags(f, KNOWN, self.0)
}
}
@ -2546,6 +2565,7 @@ impl fmt::Debug for ImageCreateFlags {
ImageCreateFlags::FRAGMENT_DENSITY_MAP_OFFSET_QCOM.0,
"FRAGMENT_DENSITY_MAP_OFFSET_QCOM",
),
(ImageCreateFlags::RESERVED_20_KHR.0, "RESERVED_20_KHR"),
(ImageCreateFlags::ALIAS.0, "ALIAS"),
(
ImageCreateFlags::SPLIT_INSTANCE_BIND_REGIONS.0,
@ -2721,6 +2741,7 @@ impl fmt::Debug for ImageUsageFlags {
ImageUsageFlags::SAMPLE_BLOCK_MATCH_QCOM.0,
"SAMPLE_BLOCK_MATCH_QCOM",
),
(ImageUsageFlags::RESERVED_23_EXT.0, "RESERVED_23_EXT"),
];
debug_flags(f, KNOWN, self.0)
}
@ -2740,7 +2761,6 @@ impl fmt::Debug for ImageViewCreateFlags {
ImageViewCreateFlags::FRAGMENT_DENSITY_MAP_DEFERRED_EXT.0,
"FRAGMENT_DENSITY_MAP_DEFERRED_EXT",
),
(ImageViewCreateFlags::RESERVED_3_EXT.0, "RESERVED_3_EXT"),
];
debug_flags(f, KNOWN, self.0)
}
@ -2925,7 +2945,6 @@ impl fmt::Debug for MemoryHeapFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(MemoryHeapFlags::DEVICE_LOCAL.0, "DEVICE_LOCAL"),
(MemoryHeapFlags::RESERVED_2_KHR.0, "RESERVED_2_KHR"),
(MemoryHeapFlags::MULTI_INSTANCE.0, "MULTI_INSTANCE"),
];
debug_flags(f, KNOWN, self.0)
@ -2974,6 +2993,12 @@ impl fmt::Debug for MemoryPropertyFlags {
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for MemoryUnmapFlagsKHR {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[];
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for MetalSurfaceCreateFlagsEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[];
@ -2993,6 +3018,7 @@ impl fmt::Debug for MicromapTypeEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match *self {
Self::OPACITY_MICROMAP => Some("OPACITY_MICROMAP"),
Self::DISPLACEMENT_MICROMAP_NV => Some("DISPLACEMENT_MICROMAP_NV"),
_ => None,
};
if let Some(x) = name {
@ -3307,14 +3333,10 @@ impl fmt::Debug for PipelineBindPoint {
}
impl fmt::Debug for PipelineCacheCreateFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(PipelineCacheCreateFlags::RESERVED_1_EXT.0, "RESERVED_1_EXT"),
(PipelineCacheCreateFlags::RESERVED_2_KHR.0, "RESERVED_2_KHR"),
(
PipelineCacheCreateFlags::EXTERNALLY_SYNCHRONIZED.0,
"EXTERNALLY_SYNCHRONIZED",
),
];
const KNOWN: &[(Flags, &str)] = &[(
PipelineCacheCreateFlags::EXTERNALLY_SYNCHRONIZED.0,
"EXTERNALLY_SYNCHRONIZED",
)];
debug_flags(f, KNOWN, self.0)
}
}
@ -3454,7 +3476,10 @@ impl fmt::Debug for PipelineCreateFlags {
PipelineCreateFlags::RAY_TRACING_OPACITY_MICROMAP_EXT.0,
"RAY_TRACING_OPACITY_MICROMAP_EXT",
),
(PipelineCreateFlags::RESERVED_28_NV.0, "RESERVED_28_NV"),
(
PipelineCreateFlags::RAY_TRACING_DISPLACEMENT_MICROMAP_NV.0,
"RAY_TRACING_DISPLACEMENT_MICROMAP_NV",
),
(
PipelineCreateFlags::NO_PROTECTED_ACCESS_EXT.0,
"NO_PROTECTED_ACCESS_EXT",
@ -3800,10 +3825,12 @@ impl fmt::Debug for PipelineStageFlags2 {
"MICROMAP_BUILD_EXT",
),
(
PipelineStageFlags2::RESEVED_41_HUAWEI.0,
"RESEVED_41_HUAWEI",
PipelineStageFlags2::CLUSTER_CULLING_SHADER_HUAWEI.0,
"CLUSTER_CULLING_SHADER_HUAWEI",
),
(PipelineStageFlags2::RESERVED_43_ARM.0, "RESERVED_43_ARM"),
(PipelineStageFlags2::OPTICAL_FLOW_NV.0, "OPTICAL_FLOW_NV"),
(PipelineStageFlags2::RESERVED_42_EXT.0, "RESERVED_42_EXT"),
];
debug_flags(f, KNOWN, self.0)
}
@ -3928,7 +3955,8 @@ impl fmt::Debug for PrimitiveTopology {
}
impl fmt::Debug for PrivateDataSlotCreateFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[];
const KNOWN: &[(Flags, &str)] =
&[(PrivateDataSlotCreateFlags::RESERVED_0_NV.0, "RESERVED_0_NV")];
debug_flags(f, KNOWN, self.0)
}
}
@ -4007,6 +4035,10 @@ impl fmt::Debug for QueryPipelineStatisticFlags {
QueryPipelineStatisticFlags::MESH_SHADER_INVOCATIONS_EXT.0,
"MESH_SHADER_INVOCATIONS_EXT",
),
(
QueryPipelineStatisticFlags::CLUSTER_CULLING_SHADER_INVOCATIONS_HUAWEI.0,
"CLUSTER_CULLING_SHADER_INVOCATIONS_HUAWEI",
),
];
debug_flags(f, KNOWN, self.0)
}
@ -4076,9 +4108,7 @@ impl fmt::Debug for QueryType {
Some("ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV")
}
Self::PERFORMANCE_QUERY_INTEL => Some("PERFORMANCE_QUERY_INTEL"),
Self::VIDEO_ENCODESTREAM_BUFFER_RANGE_KHR => {
Some("VIDEO_ENCODESTREAM_BUFFER_RANGE_KHR")
}
Self::VIDEO_ENCODE_FEEDBACK_KHR => Some("VIDEO_ENCODE_FEEDBACK_KHR"),
Self::MESH_PRIMITIVES_GENERATED_EXT => Some("MESH_PRIMITIVES_GENERATED_EXT"),
Self::PRIMITIVES_GENERATED_EXT => Some("PRIMITIVES_GENERATED_EXT"),
Self::ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR => {
@ -4107,7 +4137,9 @@ impl fmt::Debug for QueueFlags {
(QueueFlags::RESERVED_9_EXT.0, "RESERVED_9_EXT"),
(QueueFlags::VIDEO_ENCODE_KHR.0, "VIDEO_ENCODE_KHR"),
(QueueFlags::RESERVED_7_QCOM.0, "RESERVED_7_QCOM"),
(QueueFlags::RESERVED_11_ARM.0, "RESERVED_11_ARM"),
(QueueFlags::OPTICAL_FLOW_NV.0, "OPTICAL_FLOW_NV"),
(QueueFlags::RESERVED_10_EXT.0, "RESERVED_10_EXT"),
(QueueFlags::PROTECTED.0, "PROTECTED"),
];
debug_flags(f, KNOWN, self.0)
@ -4206,6 +4238,10 @@ impl fmt::Debug for ResolveModeFlags {
(ResolveModeFlags::AVERAGE.0, "AVERAGE"),
(ResolveModeFlags::MIN.0, "MIN"),
(ResolveModeFlags::MAX.0, "MAX"),
(
ResolveModeFlags::EXTENSION_469_FLAG_0.0,
"EXTENSION_469_FLAG_0",
),
];
debug_flags(f, KNOWN, self.0)
}
@ -4379,12 +4415,52 @@ impl fmt::Debug for SemaphoreWaitFlags {
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for ShaderCodeTypeEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match *self {
Self::BINARY => Some("BINARY"),
Self::SPIRV => Some("SPIRV"),
_ => None,
};
if let Some(x) = name {
f.write_str(x)
} else {
self.0.fmt(f)
}
}
}
impl fmt::Debug for ShaderCorePropertiesFlagsAMD {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[];
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for ShaderCreateFlagsEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(ShaderCreateFlagsEXT::LINK_STAGE.0, "LINK_STAGE"),
(
ShaderCreateFlagsEXT::ALLOW_VARYING_SUBGROUP_SIZE.0,
"ALLOW_VARYING_SUBGROUP_SIZE",
),
(
ShaderCreateFlagsEXT::REQUIRE_FULL_SUBGROUPS.0,
"REQUIRE_FULL_SUBGROUPS",
),
(ShaderCreateFlagsEXT::NO_TASK_SHADER.0, "NO_TASK_SHADER"),
(ShaderCreateFlagsEXT::DISPATCH_BASE.0, "DISPATCH_BASE"),
(
ShaderCreateFlagsEXT::FRAGMENT_SHADING_RATE_ATTACHMENT.0,
"FRAGMENT_SHADING_RATE_ATTACHMENT",
),
(
ShaderCreateFlagsEXT::FRAGMENT_DENSITY_MAP_ATTACHMENT.0,
"FRAGMENT_DENSITY_MAP_ATTACHMENT",
),
];
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for ShaderFloatControlsIndependence {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match *self {
@ -4466,10 +4542,10 @@ impl fmt::Debug for ShaderStageFlags {
ShaderStageFlags::SUBPASS_SHADING_HUAWEI.0,
"SUBPASS_SHADING_HUAWEI",
),
(ShaderStageFlags::RESERVED_19_HUAWEI.0, "RESERVED_19_HUAWEI"),
(ShaderStageFlags::EXT_483_RESERVE_15.0, "EXT_483_RESERVE_15"),
(ShaderStageFlags::EXT_483_RESERVE_16.0, "EXT_483_RESERVE_16"),
(ShaderStageFlags::EXT_483_RESERVE_17.0, "EXT_483_RESERVE_17"),
(
ShaderStageFlags::CLUSTER_CULLING_HUAWEI.0,
"CLUSTER_CULLING_HUAWEI",
),
];
debug_flags(f, KNOWN, self.0)
}
@ -4745,9 +4821,6 @@ impl fmt::Debug for StructureType {
Self::VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT => {
Some("VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT")
}
Self::VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT => {
Some("VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT")
}
Self::VIDEO_ENCODE_H264_PROFILE_INFO_EXT => Some("VIDEO_ENCODE_H264_PROFILE_INFO_EXT"),
Self::VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT => {
Some("VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT")
@ -4755,9 +4828,6 @@ impl fmt::Debug for StructureType {
Self::VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT => {
Some("VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT")
}
Self::VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT => {
Some("VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT")
}
Self::VIDEO_ENCODE_H265_CAPABILITIES_EXT => Some("VIDEO_ENCODE_H265_CAPABILITIES_EXT"),
Self::VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT => {
Some("VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT")
@ -4774,13 +4844,7 @@ impl fmt::Debug for StructureType {
Self::VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT => {
Some("VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT")
}
Self::VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT => {
Some("VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT")
}
Self::VIDEO_ENCODE_H265_PROFILE_INFO_EXT => Some("VIDEO_ENCODE_H265_PROFILE_INFO_EXT"),
Self::VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT => {
Some("VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT")
}
Self::VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT => {
Some("VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT")
}
@ -5374,6 +5438,8 @@ impl fmt::Debug for StructureType {
Self::PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR => {
Some("PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR")
}
Self::MEMORY_MAP_INFO_KHR => Some("MEMORY_MAP_INFO_KHR"),
Self::MEMORY_UNMAP_INFO_KHR => Some("MEMORY_UNMAP_INFO_KHR"),
Self::PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT")
}
@ -5476,6 +5542,9 @@ impl fmt::Debug for StructureType {
}
Self::VIDEO_ENCODE_CAPABILITIES_KHR => Some("VIDEO_ENCODE_CAPABILITIES_KHR"),
Self::VIDEO_ENCODE_USAGE_INFO_KHR => Some("VIDEO_ENCODE_USAGE_INFO_KHR"),
Self::QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR => {
Some("QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR")
}
Self::PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV => {
Some("PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV")
}
@ -5483,6 +5552,7 @@ impl fmt::Debug for StructureType {
Some("DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV")
}
Self::RESERVED_QCOM => Some("RESERVED_QCOM"),
Self::QUERY_LOW_LATENCY_SUPPORT_NV => Some("QUERY_LOW_LATENCY_SUPPORT_NV"),
Self::EXPORT_METAL_OBJECT_CREATE_INFO_EXT => {
Some("EXPORT_METAL_OBJECT_CREATE_INFO_EXT")
}
@ -5736,6 +5806,12 @@ impl fmt::Debug for StructureType {
Self::PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT")
}
Self::PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT")
}
Self::PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT => {
Some("PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT")
}
Self::MICROMAP_BUILD_INFO_EXT => Some("MICROMAP_BUILD_INFO_EXT"),
Self::MICROMAP_VERSION_INFO_EXT => Some("MICROMAP_VERSION_INFO_EXT"),
Self::COPY_MICROMAP_INFO_EXT => Some("COPY_MICROMAP_INFO_EXT"),
@ -5752,6 +5828,21 @@ impl fmt::Debug for StructureType {
Self::ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT => {
Some("ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT")
}
Self::PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV => {
Some("PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV")
}
Self::PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV => {
Some("PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV")
}
Self::ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV => {
Some("ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV")
}
Self::PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI => {
Some("PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI")
}
Self::PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI => {
Some("PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI")
}
Self::PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT")
}
@ -5761,6 +5852,13 @@ impl fmt::Debug for StructureType {
Self::PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT")
}
Self::PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM => {
Some("PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM")
}
Self::PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT")
}
Self::IMAGE_VIEW_SLICED_CREATE_INFO_EXT => Some("IMAGE_VIEW_SLICED_CREATE_INFO_EXT"),
Self::PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE => {
Some("PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE")
}
@ -5866,6 +5964,16 @@ impl fmt::Debug for StructureType {
Self::PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT")
}
Self::PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR => {
Some("PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR")
}
Self::PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT")
}
Self::PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT => {
Some("PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT")
}
Self::SHADER_CREATE_INFO_EXT => Some("SHADER_CREATE_INFO_EXT"),
Self::PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM => {
Some("PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM")
}
@ -5895,6 +6003,21 @@ impl fmt::Debug for StructureType {
Self::PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM => {
Some("PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM")
}
Self::PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT")
}
Self::PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT")
}
Self::PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM => {
Some("PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM")
}
Self::MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM => {
Some("MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM")
}
Self::PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT => {
Some("PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT")
}
Self::PHYSICAL_DEVICE_SUBGROUP_PROPERTIES => {
Some("PHYSICAL_DEVICE_SUBGROUP_PROPERTIES")
}
@ -6550,6 +6673,7 @@ impl fmt::Debug for VendorId {
Self::CODEPLAY => Some("CODEPLAY"),
Self::MESA => Some("MESA"),
Self::POCL => Some("POCL"),
Self::MOBILEYE => Some("MOBILEYE"),
_ => None,
};
if let Some(x) = name {
@ -6728,6 +6852,21 @@ impl fmt::Debug for VideoEncodeContentFlagsKHR {
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for VideoEncodeFeedbackFlagsKHR {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(
VideoEncodeFeedbackFlagsKHR::BITSTREAM_BUFFER_OFFSET.0,
"BITSTREAM_BUFFER_OFFSET",
),
(
VideoEncodeFeedbackFlagsKHR::BITSTREAM_BYTES_WRITTEN.0,
"BITSTREAM_BYTES_WRITTEN",
),
];
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for VideoEncodeFlagsKHR {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[];
@ -6831,26 +6970,10 @@ impl fmt::Debug for VideoEncodeH264CapabilityFlagsEXT {
VideoEncodeH264CapabilityFlagsEXT::B_FRAME_IN_L1_LIST.0,
"B_FRAME_IN_L1_LIST",
),
];
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for VideoEncodeH264InputModeFlagsEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(VideoEncodeH264InputModeFlagsEXT::FRAME.0, "FRAME"),
(VideoEncodeH264InputModeFlagsEXT::SLICE.0, "SLICE"),
(VideoEncodeH264InputModeFlagsEXT::NON_VCL.0, "NON_VCL"),
];
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for VideoEncodeH264OutputModeFlagsEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(VideoEncodeH264OutputModeFlagsEXT::FRAME.0, "FRAME"),
(VideoEncodeH264OutputModeFlagsEXT::SLICE.0, "SLICE"),
(VideoEncodeH264OutputModeFlagsEXT::NON_VCL.0, "NON_VCL"),
(
VideoEncodeH264CapabilityFlagsEXT::DIFFERENT_REFERENCE_FINAL_LISTS.0,
"DIFFERENT_REFERENCE_FINAL_LISTS",
),
];
debug_flags(f, KNOWN, self.0)
}
@ -6977,6 +7100,10 @@ impl fmt::Debug for VideoEncodeH265CapabilityFlagsEXT {
VideoEncodeH265CapabilityFlagsEXT::B_FRAME_IN_L1_LIST.0,
"B_FRAME_IN_L1_LIST",
),
(
VideoEncodeH265CapabilityFlagsEXT::DIFFERENT_REFERENCE_FINAL_LISTS.0,
"DIFFERENT_REFERENCE_FINAL_LISTS",
),
];
debug_flags(f, KNOWN, self.0)
}
@ -6991,32 +7118,6 @@ impl fmt::Debug for VideoEncodeH265CtbSizeFlagsEXT {
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for VideoEncodeH265InputModeFlagsEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(VideoEncodeH265InputModeFlagsEXT::FRAME.0, "FRAME"),
(
VideoEncodeH265InputModeFlagsEXT::SLICE_SEGMENT.0,
"SLICE_SEGMENT",
),
(VideoEncodeH265InputModeFlagsEXT::NON_VCL.0, "NON_VCL"),
];
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for VideoEncodeH265OutputModeFlagsEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(VideoEncodeH265OutputModeFlagsEXT::FRAME.0, "FRAME"),
(
VideoEncodeH265OutputModeFlagsEXT::SLICE_SEGMENT.0,
"SLICE_SEGMENT",
),
(VideoEncodeH265OutputModeFlagsEXT::NON_VCL.0, "NON_VCL"),
];
debug_flags(f, KNOWN, self.0)
}
}
impl fmt::Debug for VideoEncodeH265RateControlStructureEXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match *self {
@ -7064,7 +7165,8 @@ impl fmt::Debug for VideoEncodeRateControlFlagsKHR {
impl fmt::Debug for VideoEncodeRateControlModeFlagsKHR {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[
(VideoEncodeRateControlModeFlagsKHR::NONE.0, "NONE"),
(VideoEncodeRateControlModeFlagsKHR::DEFAULT.0, "DEFAULT"),
(VideoEncodeRateControlModeFlagsKHR::DISABLED.0, "DISABLED"),
(VideoEncodeRateControlModeFlagsKHR::CBR.0, "CBR"),
(VideoEncodeRateControlModeFlagsKHR::VBR.0, "VBR"),
];

View File

@ -10,6 +10,7 @@ pub const MAX_MEMORY_HEAPS: usize = 16;
pub const LOD_CLAMP_NONE: f32 = 1000.00;
pub const REMAINING_MIP_LEVELS: u32 = !0;
pub const REMAINING_ARRAY_LAYERS: u32 = !0;
pub const REMAINING_3D_SLICES_EXT: u32 = !0;
pub const WHOLE_SIZE: u64 = !0;
pub const ATTACHMENT_UNUSED: u32 = !0;
pub const TRUE: Bool32 = 1;

File diff suppressed because it is too large Load Diff

View File

@ -1744,6 +1744,8 @@ impl VendorId {
pub const MESA: Self = Self(0x1_0005);
#[doc = "PoCL vendor ID"]
pub const POCL: Self = Self(0x1_0006);
#[doc = "Mobileye vendor ID"]
pub const MOBILEYE: Self = Self(0x1_0007);
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)]
@ -1808,6 +1810,8 @@ impl DriverId {
pub const MESA_DOZEN: Self = Self(23);
#[doc = "Mesa open source project"]
pub const MESA_NVK: Self = Self(24);
#[doc = "Imagination Technologies"]
pub const IMAGINATION_OPEN_SOURCE_MESA: Self = Self(25);
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)]
@ -2780,6 +2784,43 @@ impl DeviceFaultVendorBinaryHeaderVersionEXT {
impl DeviceFaultVendorBinaryHeaderVersionEXT {
pub const ONE: Self = Self(1);
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkDisplacementMicromapFormatNV.html>"]
pub struct DisplacementMicromapFormatNV(pub(crate) i32);
impl DisplacementMicromapFormatNV {
#[inline]
pub const fn from_raw(x: i32) -> Self {
Self(x)
}
#[inline]
pub const fn as_raw(self) -> i32 {
self.0
}
}
impl DisplacementMicromapFormatNV {
pub const TYPE_64_TRIANGLES_64_BYTES: Self = Self(1);
pub const TYPE_256_TRIANGLES_128_BYTES: Self = Self(2);
pub const TYPE_1024_TRIANGLES_128_BYTES: Self = Self(3);
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)]
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkShaderCodeTypeEXT.html>"]
pub struct ShaderCodeTypeEXT(pub(crate) i32);
impl ShaderCodeTypeEXT {
#[inline]
pub const fn from_raw(x: i32) -> Self {
Self(x)
}
#[inline]
pub const fn as_raw(self) -> i32 {
self.0
}
}
impl ShaderCodeTypeEXT {
pub const BINARY: Self = Self(0);
pub const SPIRV: Self = Self(1);
}
impl fmt::Debug for ObjectType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match *self {
@ -2828,6 +2869,7 @@ impl fmt::Debug for ObjectType {
Self::BUFFER_COLLECTION_FUCHSIA => Some("BUFFER_COLLECTION_FUCHSIA"),
Self::MICROMAP_EXT => Some("MICROMAP_EXT"),
Self::OPTICAL_FLOW_SESSION_NV => Some("OPTICAL_FLOW_SESSION_NV"),
Self::SHADER_EXT => Some("SHADER_EXT"),
Self::SAMPLER_YCBCR_CONVERSION => Some("SAMPLER_YCBCR_CONVERSION"),
Self::DESCRIPTOR_UPDATE_TEMPLATE => Some("DESCRIPTOR_UPDATE_TEMPLATE"),
Self::PRIVATE_DATA_SLOT => Some("PRIVATE_DATA_SLOT"),
@ -2898,7 +2940,13 @@ impl fmt::Debug for Result {
Self::THREAD_DONE_KHR => Some("THREAD_DONE_KHR"),
Self::OPERATION_DEFERRED_KHR => Some("OPERATION_DEFERRED_KHR"),
Self::OPERATION_NOT_DEFERRED_KHR => Some("OPERATION_NOT_DEFERRED_KHR"),
Self::ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR => {
Some("ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR")
}
Self::ERROR_COMPRESSION_EXHAUSTED_EXT => Some("ERROR_COMPRESSION_EXHAUSTED_EXT"),
Self::ERROR_INCOMPATIBLE_SHADER_BINARY_EXT => {
Some("ERROR_INCOMPATIBLE_SHADER_BINARY_EXT")
}
Self::ERROR_OUT_OF_POOL_MEMORY => Some("ERROR_OUT_OF_POOL_MEMORY"),
Self::ERROR_INVALID_EXTERNAL_HANDLE => Some("ERROR_INVALID_EXTERNAL_HANDLE"),
Self::ERROR_FRAGMENTATION => Some("ERROR_FRAGMENTATION"),

File diff suppressed because it is too large Load Diff

View File

@ -999,7 +999,7 @@ pub type PFN_vkCmdSetDepthBias = unsafe extern "system" fn(
);
#[allow(non_camel_case_types)]
pub type PFN_vkCmdSetBlendConstants =
unsafe extern "system" fn(command_buffer: CommandBuffer, blend_constants: *const [f32; 4]);
unsafe extern "system" fn(command_buffer: CommandBuffer, blend_constants: *const [f32; 4usize]);
#[allow(non_camel_case_types)]
pub type PFN_vkCmdSetDepthBounds = unsafe extern "system" fn(
command_buffer: CommandBuffer,
@ -2876,7 +2876,7 @@ impl DeviceFnV1_0 {
cmd_set_blend_constants: unsafe {
unsafe extern "system" fn cmd_set_blend_constants(
_command_buffer: CommandBuffer,
_blend_constants: *const [f32; 4],
_blend_constants: *const [f32; 4usize],
) {
panic!(concat!(
"Unable to load ",

View File

@ -1,4 +1,4 @@
/* automatically generated by rust-bindgen 0.61.0 */
/* automatically generated by rust-bindgen 0.64.0 */
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
@ -7050,42 +7050,48 @@ impl StdVideoEncodeH264ReferenceInfoFlags {
#[repr(C)]
#[repr(align(4))]
#[derive(Debug, Copy, Clone)]
pub struct StdVideoEncodeH264RefMgmtFlags {
pub struct StdVideoEncodeH264ReferenceListsInfoFlags {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>,
pub __bindgen_padding_0: [u8; 3usize],
}
#[test]
fn bindgen_test_layout_StdVideoEncodeH264RefMgmtFlags() {
fn bindgen_test_layout_StdVideoEncodeH264ReferenceListsInfoFlags() {
assert_eq!(
::std::mem::size_of::<StdVideoEncodeH264RefMgmtFlags>(),
::std::mem::size_of::<StdVideoEncodeH264ReferenceListsInfoFlags>(),
4usize,
concat!("Size of: ", stringify!(StdVideoEncodeH264RefMgmtFlags))
concat!(
"Size of: ",
stringify!(StdVideoEncodeH264ReferenceListsInfoFlags)
)
);
assert_eq!(
::std::mem::align_of::<StdVideoEncodeH264RefMgmtFlags>(),
::std::mem::align_of::<StdVideoEncodeH264ReferenceListsInfoFlags>(),
4usize,
concat!("Alignment of ", stringify!(StdVideoEncodeH264RefMgmtFlags))
concat!(
"Alignment of ",
stringify!(StdVideoEncodeH264ReferenceListsInfoFlags)
)
);
}
impl StdVideoEncodeH264RefMgmtFlags {
impl StdVideoEncodeH264ReferenceListsInfoFlags {
#[inline]
pub fn ref_pic_list_modification_l0_flag(&self) -> u32 {
pub fn ref_pic_list_modification_flag_l0(&self) -> u32 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
}
#[inline]
pub fn set_ref_pic_list_modification_l0_flag(&mut self, val: u32) {
pub fn set_ref_pic_list_modification_flag_l0(&mut self, val: u32) {
unsafe {
let val: u32 = ::std::mem::transmute(val);
self._bitfield_1.set(0usize, 1u8, val as u64)
}
}
#[inline]
pub fn ref_pic_list_modification_l1_flag(&self) -> u32 {
pub fn ref_pic_list_modification_flag_l1(&self) -> u32 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) }
}
#[inline]
pub fn set_ref_pic_list_modification_l1_flag(&mut self, val: u32) {
pub fn set_ref_pic_list_modification_flag_l1(&mut self, val: u32) {
unsafe {
let val: u32 = ::std::mem::transmute(val);
self._bitfield_1.set(1usize, 1u8, val as u64)
@ -7093,19 +7099,19 @@ impl StdVideoEncodeH264RefMgmtFlags {
}
#[inline]
pub fn new_bitfield_1(
ref_pic_list_modification_l0_flag: u32,
ref_pic_list_modification_l1_flag: u32,
ref_pic_list_modification_flag_l0: u32,
ref_pic_list_modification_flag_l1: u32,
) -> __BindgenBitfieldUnit<[u8; 1usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default();
__bindgen_bitfield_unit.set(0usize, 1u8, {
let ref_pic_list_modification_l0_flag: u32 =
unsafe { ::std::mem::transmute(ref_pic_list_modification_l0_flag) };
ref_pic_list_modification_l0_flag as u64
let ref_pic_list_modification_flag_l0: u32 =
unsafe { ::std::mem::transmute(ref_pic_list_modification_flag_l0) };
ref_pic_list_modification_flag_l0 as u64
});
__bindgen_bitfield_unit.set(1usize, 1u8, {
let ref_pic_list_modification_l1_flag: u32 =
unsafe { ::std::mem::transmute(ref_pic_list_modification_l1_flag) };
ref_pic_list_modification_l1_flag as u64
let ref_pic_list_modification_flag_l1: u32 =
unsafe { ::std::mem::transmute(ref_pic_list_modification_flag_l1) };
ref_pic_list_modification_flag_l1 as u64
});
__bindgen_bitfield_unit
}
@ -7255,34 +7261,39 @@ fn bindgen_test_layout_StdVideoEncodeH264RefPicMarkingEntry() {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct StdVideoEncodeH264RefMemMgmtCtrlOperations {
pub flags: StdVideoEncodeH264RefMgmtFlags,
pub struct StdVideoEncodeH264ReferenceListsInfo {
pub flags: StdVideoEncodeH264ReferenceListsInfoFlags,
pub refPicList0EntryCount: u8,
pub refPicList1EntryCount: u8,
pub refList0ModOpCount: u8,
pub pRefList0ModOperations: *const StdVideoEncodeH264RefListModEntry,
pub refList1ModOpCount: u8,
pub pRefList1ModOperations: *const StdVideoEncodeH264RefListModEntry,
pub refPicMarkingOpCount: u8,
pub reserved1: [u8; 7usize],
pub pRefPicList0Entries: *const u8,
pub pRefPicList1Entries: *const u8,
pub pRefList0ModOperations: *const StdVideoEncodeH264RefListModEntry,
pub pRefList1ModOperations: *const StdVideoEncodeH264RefListModEntry,
pub pRefPicMarkingOperations: *const StdVideoEncodeH264RefPicMarkingEntry,
}
#[test]
fn bindgen_test_layout_StdVideoEncodeH264RefMemMgmtCtrlOperations() {
const UNINIT: ::std::mem::MaybeUninit<StdVideoEncodeH264RefMemMgmtCtrlOperations> =
fn bindgen_test_layout_StdVideoEncodeH264ReferenceListsInfo() {
const UNINIT: ::std::mem::MaybeUninit<StdVideoEncodeH264ReferenceListsInfo> =
::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<StdVideoEncodeH264RefMemMgmtCtrlOperations>(),
48usize,
::std::mem::size_of::<StdVideoEncodeH264ReferenceListsInfo>(),
56usize,
concat!(
"Size of: ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations)
stringify!(StdVideoEncodeH264ReferenceListsInfo)
)
);
assert_eq!(
::std::mem::align_of::<StdVideoEncodeH264RefMemMgmtCtrlOperations>(),
::std::mem::align_of::<StdVideoEncodeH264ReferenceListsInfo>(),
8usize,
concat!(
"Alignment of ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations)
stringify!(StdVideoEncodeH264ReferenceListsInfo)
)
);
assert_eq!(
@ -7290,67 +7301,117 @@ fn bindgen_test_layout_StdVideoEncodeH264RefMemMgmtCtrlOperations() {
0usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations),
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(flags)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).refList0ModOpCount) as usize - ptr as usize },
unsafe { ::std::ptr::addr_of!((*ptr).refPicList0EntryCount) as usize - ptr as usize },
4usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations),
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(refPicList0EntryCount)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).refPicList1EntryCount) as usize - ptr as usize },
5usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(refPicList1EntryCount)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).refList0ModOpCount) as usize - ptr as usize },
6usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(refList0ModOpCount)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefList0ModOperations) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations),
"::",
stringify!(pRefList0ModOperations)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).refList1ModOpCount) as usize - ptr as usize },
16usize,
7usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations),
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(refList1ModOpCount)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefList1ModOperations) as usize - ptr as usize },
24usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations),
"::",
stringify!(pRefList1ModOperations)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).refPicMarkingOpCount) as usize - ptr as usize },
32usize,
8usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations),
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(refPicMarkingOpCount)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefPicMarkingOperations) as usize - ptr as usize },
unsafe { ::std::ptr::addr_of!((*ptr).reserved1) as usize - ptr as usize },
9usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(reserved1)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefPicList0Entries) as usize - ptr as usize },
16usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(pRefPicList0Entries)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefPicList1Entries) as usize - ptr as usize },
24usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(pRefPicList1Entries)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefList0ModOperations) as usize - ptr as usize },
32usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(pRefList0ModOperations)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefList1ModOperations) as usize - ptr as usize },
40usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations),
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(pRefList1ModOperations)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefPicMarkingOperations) as usize - ptr as usize },
48usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceListsInfo),
"::",
stringify!(pRefPicMarkingOperations)
)
@ -7362,6 +7423,7 @@ pub struct StdVideoEncodeH264PictureInfo {
pub flags: StdVideoEncodeH264PictureInfoFlags,
pub seq_parameter_set_id: u8,
pub pic_parameter_set_id: u8,
pub reserved1: u16,
pub pictureType: StdVideoH264PictureType,
pub frame_num: u32,
pub PicOrderCnt: i32,
@ -7411,6 +7473,16 @@ fn bindgen_test_layout_StdVideoEncodeH264PictureInfo() {
stringify!(pic_parameter_set_id)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).reserved1) as usize - ptr as usize },
6usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264PictureInfo),
"::",
stringify!(reserved1)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pictureType) as usize - ptr as usize },
8usize,
@ -7446,6 +7518,7 @@ fn bindgen_test_layout_StdVideoEncodeH264PictureInfo() {
#[derive(Debug, Copy, Clone)]
pub struct StdVideoEncodeH264ReferenceInfo {
pub flags: StdVideoEncodeH264ReferenceInfoFlags,
pub pictureType: StdVideoH264PictureType,
pub FrameNum: u32,
pub PicOrderCnt: i32,
pub long_term_pic_num: u16,
@ -7458,7 +7531,7 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() {
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<StdVideoEncodeH264ReferenceInfo>(),
16usize,
20usize,
concat!("Size of: ", stringify!(StdVideoEncodeH264ReferenceInfo))
);
assert_eq!(
@ -7477,8 +7550,18 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() {
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).FrameNum) as usize - ptr as usize },
unsafe { ::std::ptr::addr_of!((*ptr).pictureType) as usize - ptr as usize },
4usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceInfo),
"::",
stringify!(pictureType)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).FrameNum) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceInfo),
@ -7488,7 +7571,7 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() {
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).PicOrderCnt) as usize - ptr as usize },
8usize,
12usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceInfo),
@ -7498,7 +7581,7 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() {
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).long_term_pic_num) as usize - ptr as usize },
12usize,
16usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceInfo),
@ -7508,7 +7591,7 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() {
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).long_term_frame_idx) as usize - ptr as usize },
14usize,
18usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264ReferenceInfo),
@ -7530,6 +7613,8 @@ pub struct StdVideoEncodeH264SliceHeader {
pub disable_deblocking_filter_idc: StdVideoH264DisableDeblockingFilterIdc,
pub slice_alpha_c0_offset_div2: i8,
pub slice_beta_offset_div2: i8,
pub reserved1: u16,
pub reserved2: u32,
pub pWeightTable: *const StdVideoEncodeH264WeightTable,
}
#[test]
@ -7653,6 +7738,26 @@ fn bindgen_test_layout_StdVideoEncodeH264SliceHeader() {
stringify!(slice_beta_offset_div2)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).reserved1) as usize - ptr as usize },
26usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264SliceHeader),
"::",
stringify!(reserved1)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).reserved2) as usize - ptr as usize },
28usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH264SliceHeader),
"::",
stringify!(reserved2)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pWeightTable) as usize - ptr as usize },
32usize,
@ -8511,31 +8616,31 @@ fn bindgen_test_layout_StdVideoEncodeH265SliceSegmentHeader() {
#[repr(C)]
#[repr(align(4))]
#[derive(Debug, Copy, Clone)]
pub struct StdVideoEncodeH265ReferenceModificationFlags {
pub struct StdVideoEncodeH265ReferenceListsInfoFlags {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>,
pub __bindgen_padding_0: [u8; 3usize],
}
#[test]
fn bindgen_test_layout_StdVideoEncodeH265ReferenceModificationFlags() {
fn bindgen_test_layout_StdVideoEncodeH265ReferenceListsInfoFlags() {
assert_eq!(
::std::mem::size_of::<StdVideoEncodeH265ReferenceModificationFlags>(),
::std::mem::size_of::<StdVideoEncodeH265ReferenceListsInfoFlags>(),
4usize,
concat!(
"Size of: ",
stringify!(StdVideoEncodeH265ReferenceModificationFlags)
stringify!(StdVideoEncodeH265ReferenceListsInfoFlags)
)
);
assert_eq!(
::std::mem::align_of::<StdVideoEncodeH265ReferenceModificationFlags>(),
::std::mem::align_of::<StdVideoEncodeH265ReferenceListsInfoFlags>(),
4usize,
concat!(
"Alignment of ",
stringify!(StdVideoEncodeH265ReferenceModificationFlags)
stringify!(StdVideoEncodeH265ReferenceListsInfoFlags)
)
);
}
impl StdVideoEncodeH265ReferenceModificationFlags {
impl StdVideoEncodeH265ReferenceListsInfoFlags {
#[inline]
pub fn ref_pic_list_modification_flag_l0(&self) -> u32 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
@ -8579,32 +8684,35 @@ impl StdVideoEncodeH265ReferenceModificationFlags {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct StdVideoEncodeH265ReferenceModifications {
pub flags: StdVideoEncodeH265ReferenceModificationFlags,
pub referenceList0ModificationsCount: u8,
pub pReferenceList0Modifications: *const u8,
pub referenceList1ModificationsCount: u8,
pub pReferenceList1Modifications: *const u8,
pub struct StdVideoEncodeH265ReferenceListsInfo {
pub flags: StdVideoEncodeH265ReferenceListsInfoFlags,
pub num_ref_idx_l0_active_minus1: u8,
pub num_ref_idx_l1_active_minus1: u8,
pub reserved1: u16,
pub pRefPicList0Entries: *const u8,
pub pRefPicList1Entries: *const u8,
pub pRefList0Modifications: *const u8,
pub pRefList1Modifications: *const u8,
}
#[test]
fn bindgen_test_layout_StdVideoEncodeH265ReferenceModifications() {
const UNINIT: ::std::mem::MaybeUninit<StdVideoEncodeH265ReferenceModifications> =
fn bindgen_test_layout_StdVideoEncodeH265ReferenceListsInfo() {
const UNINIT: ::std::mem::MaybeUninit<StdVideoEncodeH265ReferenceListsInfo> =
::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<StdVideoEncodeH265ReferenceModifications>(),
32usize,
::std::mem::size_of::<StdVideoEncodeH265ReferenceListsInfo>(),
40usize,
concat!(
"Size of: ",
stringify!(StdVideoEncodeH265ReferenceModifications)
stringify!(StdVideoEncodeH265ReferenceListsInfo)
)
);
assert_eq!(
::std::mem::align_of::<StdVideoEncodeH265ReferenceModifications>(),
::std::mem::align_of::<StdVideoEncodeH265ReferenceListsInfo>(),
8usize,
concat!(
"Alignment of ",
stringify!(StdVideoEncodeH265ReferenceModifications)
stringify!(StdVideoEncodeH265ReferenceListsInfo)
)
);
assert_eq!(
@ -8612,57 +8720,83 @@ fn bindgen_test_layout_StdVideoEncodeH265ReferenceModifications() {
0usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceModifications),
stringify!(StdVideoEncodeH265ReferenceListsInfo),
"::",
stringify!(flags)
)
);
assert_eq!(
unsafe {
::std::ptr::addr_of!((*ptr).referenceList0ModificationsCount) as usize - ptr as usize
::std::ptr::addr_of!((*ptr).num_ref_idx_l0_active_minus1) as usize - ptr as usize
},
4usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceModifications),
stringify!(StdVideoEncodeH265ReferenceListsInfo),
"::",
stringify!(referenceList0ModificationsCount)
stringify!(num_ref_idx_l0_active_minus1)
)
);
assert_eq!(
unsafe {
::std::ptr::addr_of!((*ptr).pReferenceList0Modifications) as usize - ptr as usize
::std::ptr::addr_of!((*ptr).num_ref_idx_l1_active_minus1) as usize - ptr as usize
},
5usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceListsInfo),
"::",
stringify!(num_ref_idx_l1_active_minus1)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).reserved1) as usize - ptr as usize },
6usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceListsInfo),
"::",
stringify!(reserved1)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefPicList0Entries) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceModifications),
stringify!(StdVideoEncodeH265ReferenceListsInfo),
"::",
stringify!(pReferenceList0Modifications)
stringify!(pRefPicList0Entries)
)
);
assert_eq!(
unsafe {
::std::ptr::addr_of!((*ptr).referenceList1ModificationsCount) as usize - ptr as usize
},
unsafe { ::std::ptr::addr_of!((*ptr).pRefPicList1Entries) as usize - ptr as usize },
16usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceModifications),
stringify!(StdVideoEncodeH265ReferenceListsInfo),
"::",
stringify!(referenceList1ModificationsCount)
stringify!(pRefPicList1Entries)
)
);
assert_eq!(
unsafe {
::std::ptr::addr_of!((*ptr).pReferenceList1Modifications) as usize - ptr as usize
},
unsafe { ::std::ptr::addr_of!((*ptr).pRefList0Modifications) as usize - ptr as usize },
24usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceModifications),
stringify!(StdVideoEncodeH265ReferenceListsInfo),
"::",
stringify!(pReferenceList1Modifications)
stringify!(pRefList0Modifications)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).pRefList1Modifications) as usize - ptr as usize },
32usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceListsInfo),
"::",
stringify!(pRefList1Modifications)
)
);
}
@ -8786,8 +8920,8 @@ pub struct StdVideoEncodeH265PictureInfo {
pub sps_video_parameter_set_id: u8,
pub pps_seq_parameter_set_id: u8,
pub pps_pic_parameter_set_id: u8,
pub PicOrderCntVal: i32,
pub TemporalId: u8,
pub PicOrderCntVal: i32,
}
#[test]
fn bindgen_test_layout_StdVideoEncodeH265PictureInfo() {
@ -8796,7 +8930,7 @@ fn bindgen_test_layout_StdVideoEncodeH265PictureInfo() {
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<StdVideoEncodeH265PictureInfo>(),
20usize,
16usize,
concat!("Size of: ", stringify!(StdVideoEncodeH265PictureInfo))
);
assert_eq!(
@ -8854,6 +8988,16 @@ fn bindgen_test_layout_StdVideoEncodeH265PictureInfo() {
stringify!(pps_pic_parameter_set_id)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).TemporalId) as usize - ptr as usize },
11usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265PictureInfo),
"::",
stringify!(TemporalId)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).PicOrderCntVal) as usize - ptr as usize },
12usize,
@ -8864,16 +9008,6 @@ fn bindgen_test_layout_StdVideoEncodeH265PictureInfo() {
stringify!(PicOrderCntVal)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).TemporalId) as usize - ptr as usize },
16usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265PictureInfo),
"::",
stringify!(TemporalId)
)
);
}
#[repr(C)]
#[repr(align(4))]
@ -8947,6 +9081,7 @@ impl StdVideoEncodeH265ReferenceInfoFlags {
#[derive(Debug, Copy, Clone)]
pub struct StdVideoEncodeH265ReferenceInfo {
pub flags: StdVideoEncodeH265ReferenceInfoFlags,
pub PictureType: StdVideoH265PictureType,
pub PicOrderCntVal: i32,
pub TemporalId: u8,
}
@ -8957,7 +9092,7 @@ fn bindgen_test_layout_StdVideoEncodeH265ReferenceInfo() {
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<StdVideoEncodeH265ReferenceInfo>(),
12usize,
16usize,
concat!("Size of: ", stringify!(StdVideoEncodeH265ReferenceInfo))
);
assert_eq!(
@ -8976,8 +9111,18 @@ fn bindgen_test_layout_StdVideoEncodeH265ReferenceInfo() {
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).PicOrderCntVal) as usize - ptr as usize },
unsafe { ::std::ptr::addr_of!((*ptr).PictureType) as usize - ptr as usize },
4usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceInfo),
"::",
stringify!(PictureType)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).PicOrderCntVal) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceInfo),
@ -8987,7 +9132,7 @@ fn bindgen_test_layout_StdVideoEncodeH265ReferenceInfo() {
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).TemporalId) as usize - ptr as usize },
8usize,
12usize,
concat!(
"Offset of field: ",
stringify!(StdVideoEncodeH265ReferenceInfo),

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"e2e38d84cf514ad088ebc1909123ef4f707db6855528f938eb57d1e06c5a23ef","src/base.rs":"3764010f0c416db49be8a9e191fffb6848e8287edbdd5b12972613e301720ded","src/geometry.rs":"b94e50a16b8540dc6f37bfe4b1549ac68974cd6ba6c0bbd9209559f8a46d86eb","src/lib.rs":"31700ac9508fd32005bafd1c12a86a6803d198e9b1a71166a7391e642c091cd1"},"package":"3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"}
{"files":{"Cargo.toml":"cac07dfd7a2fcbb169a0c471a8a139ade8da91f92b7fbc198f3f2185d9c94d16","src/base.rs":"561db031cc746eab35a10fe72e10c314615b11e13cd48366fcdb2223196308a7","src/geometry.rs":"4ed03b07a4c5ba0f090689d31ef6eab8ec5b8f6eb7fb4e04fdf65e5ad8cd70ea","src/lib.rs":"31700ac9508fd32005bafd1c12a86a6803d198e9b1a71166a7391e642c091cd1"},"package":"2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33"}

View File

@ -3,31 +3,29 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
name = "core-graphics-types"
version = "0.1.1"
version = "0.1.2"
authors = ["The Servo Project Developers"]
description = "Bindings for some fundamental Core Graphics types"
homepage = "https://github.com/servo/core-foundation-rs"
license = "MIT / Apache-2.0"
license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/core-foundation-rs"
[package.metadata.docs.rs]
default-target = "x86_64-apple-darwin"
[dependencies.bitflags]
version = "1.0"
[dependencies.core-foundation]
version = "0.9"
[dependencies.foreign-types]
version = "0.3.0"
[dependencies.libc]
version = "0.2"

View File

@ -26,7 +26,18 @@ pub type CGFloat = libc::c_double;
#[cfg(not(target_pointer_width = "64"))]
pub type CGFloat = libc::c_float;
pub type CGError = libc::int32_t;
pub type CGError = i32;
pub type CGGlyph = libc::c_ushort;
pub const kCGErrorSuccess: CGError = 0;
pub const kCGErrorFailure: CGError = 1000;
pub const kCGErrorIllegalArgument: CGError = 1001;
pub const kCGErrorInvalidConnection: CGError = 1002;
pub const kCGErrorInvalidContext: CGError = 1003;
pub const kCGErrorCannotComplete: CGError = 1004;
pub const kCGErrorNotImplemented: CGError = 1006;
pub const kCGErrorRangeCheck: CGError = 1007;
pub const kCGErrorTypeCheck: CGError = 1008;
pub const kCGErrorInvalidOperation: CGError = 1010;
pub const kCGErrorNoneAvailable: CGError = 1011;

View File

@ -138,6 +138,11 @@ impl CGRect {
ffi::CGRectApplyAffineTransform(*self, *t)
}
}
#[inline]
pub fn contains(&self, point: &CGPoint) -> bool {
unsafe { ffi::CGRectContainsPoint(*self,*point) == 1 }
}
}
#[repr(C)]
@ -190,6 +195,8 @@ mod ffi {
pub fn CGPointApplyAffineTransform(point: CGPoint, t: CGAffineTransform) -> CGPoint;
pub fn CGRectApplyAffineTransform(rect: CGRect, t: CGAffineTransform) -> CGRect;
pub fn CGSizeApplyAffineTransform(size: CGSize, t: CGAffineTransform) -> CGSize;
pub fn CGRectContainsPoint(rect:CGRect, point: CGPoint) -> boolean_t;
}
}

View File

@ -1 +1 @@
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"453b079ac8a6df8842e7e8a37222318c500f68e1605db7adbdf87337830df593","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"6745c3c38183d2eda9b1fa265fb0a95018db5c110cbabc00b32327d951bbe2ea","src/base.rs":"838683ff67253f4aff1d4b4177531210ca73d4e61f05c5d96a8f196b2a88c787","src/color.rs":"4c8ec4ab828cbc1b2a1538a34a51f5b380927f2f1daf187dff6f732f57a43656","src/color_space.rs":"b3d7ee8a21703c789160867cb8eb2188bd1daa193e3d030f21adb6f1a6f872de","src/context.rs":"8bda7f9ecb5be768b09a29cc3b0a4f329f55d2a2ab74030d121610283862d833","src/data_provider.rs":"b25201fdea43ea1a019c68aa5e997725d04d0824a238354ddc9f2dd8a6835cc4","src/display.rs":"9db5e5440fd302849b13b48393cab4db95447df8d5057c4534a9d8be948ca480","src/event.rs":"17c601ca0b8a0d806fc576cc6cee63a784deaf4246793cf6ce3abcb562de15c5","src/event_source.rs":"d55a4f5b5e62789325028febc51bbf54c74b15ab1a4e70c6ad749a2f9753e081","src/font.rs":"2a7ac5024f17550dd2b6eb97f6971559f930c163eac3a6625d6d55703fd5e96e","src/geometry.rs":"8e12dc89835406bfa514de8fb58f5fd435724d1ddb97dc3a70392efbcf1c42ed","src/gradient.rs":"8ee8661706f36914d08e903840c4f07414b38ba40ea4a482d34b900ac6ac7cf9","src/image.rs":"a5a5df8c0f310455f038eeb16688015f481688cb417f8e8f424a4c1d2a1cdd57","src/lib.rs":"78264571227db6fc9194cb90d64beaff1738a501f88b5da55eb17ae42592d26f","src/path.rs":"c429afeaed999b02ac00f89a867b5fc64f1e223039079a4e0529306b734ff117","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"3077395beb77193530b713aa681cb61f7b86fa79e4e4060133b6d61cf9f47e09","src/window.rs":"2f6c3dc958ae2c0c9e2fc5033300b96e60ed0abee9823ea1f03797d64df0911a"},"package":"2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"}
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"a0088b6d4f15d2f3abbd411834b84eaa7179b374133fb57b8d3d2048149cc494","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"6745c3c38183d2eda9b1fa265fb0a95018db5c110cbabc00b32327d951bbe2ea","src/access.rs":"919937f8fe61966543c602e30d5d59d61e0b7313bb6b33c25aa600ec5e43345e","src/base.rs":"838683ff67253f4aff1d4b4177531210ca73d4e61f05c5d96a8f196b2a88c787","src/color.rs":"4c8ec4ab828cbc1b2a1538a34a51f5b380927f2f1daf187dff6f732f57a43656","src/color_space.rs":"6a0be06bb7ecdf9d20c461912359d22e0ffd7151c6977a8d9b3b0efdd7929442","src/context.rs":"93d543bd2b77ee6b3132b4378b1652576354fae9bb675cde63e0347d81fec334","src/data_provider.rs":"88e1cdd75c35cff44150f0aac75de6ac715acbf4328abef1b2f191b54401c650","src/display.rs":"391f24669ad1ad5dcd6d15b5e418b6b07731186d3c18d94c8c0935ab348fb3b9","src/event.rs":"7c2ce02fa67cd4613745709563846b57b12fdde105a65d16d29f7a300e9c0f7b","src/event_source.rs":"a81f8bbd41bf4c4e3e91d6a6eab31356728fbf08787aca899ed03259808dfe4a","src/font.rs":"43cad7dfcc49f5f2de408146c6e38843b2d0092b3f5880fbf80e43e18b100f25","src/geometry.rs":"8e12dc89835406bfa514de8fb58f5fd435724d1ddb97dc3a70392efbcf1c42ed","src/gradient.rs":"dd957f14b77d448fa1e51c2e67849364062aa1d5bd60405f060f9a094c628061","src/image.rs":"72076f34a805b1d2336e425cc29d2ec3583046b847e9284ef7413f7eca2acb9a","src/lib.rs":"ca6aabcc5f307a9b15cd3e531d7fb9f54bdf58d9717d38e007e4facf1ca8c9a4","src/path.rs":"9389719ee257d86f50075b294b1b9df8fb3fc93b3442deee868e188489613a2d","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"3077395beb77193530b713aa681cb61f7b86fa79e4e4060133b6d61cf9f47e09","src/window.rs":"2f6c3dc958ae2c0c9e2fc5033300b96e60ed0abee9823ea1f03797d64df0911a"},"package":"506752f2b58723339d41d013009be97e549860785a366e2a5e75dfbd9725b48e"}

View File

@ -3,23 +3,25 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
name = "core-graphics"
version = "0.22.3"
version = "0.23.0"
authors = ["The Servo Project Developers"]
description = "Bindings to Core Graphics for macOS"
homepage = "https://github.com/servo/core-graphics-rs"
license = "MIT / Apache-2.0"
homepage = "https://github.com/servo/core-foundation-rs"
readme = "README.md"
license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/core-foundation-rs"
[package.metadata.docs.rs]
default-target = "x86_64-apple-darwin"
[dependencies.bitflags]
version = "1.0"
@ -30,7 +32,7 @@ version = "0.9"
version = "0.1"
[dependencies.foreign-types]
version = "0.3.0"
version = "0.5.0"
[dependencies.libc]
version = "0.2"

View File

@ -0,0 +1,26 @@
pub use base::boolean_t;
#[derive(Default)]
pub struct ScreenCaptureAccess;
impl ScreenCaptureAccess {
/// If current app not in list, will open window.
/// Return the same result as preflight.
#[inline]
pub fn request(&self) -> bool {
unsafe { CGRequestScreenCaptureAccess() == 1 }
}
/// Return true if has access
#[inline]
pub fn preflight(&self) -> bool {
unsafe { CGPreflightScreenCaptureAccess() == 1 }
}
}
#[link(name = "CoreGraphics", kind = "framework")]
extern "C" {
// Screen Capture Access
fn CGRequestScreenCaptureAccess() -> boolean_t;
fn CGPreflightScreenCaptureAccess() -> boolean_t;
}

View File

@ -13,11 +13,11 @@ use foreign_types::ForeignType;
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGColorSpace;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGColorSpace;
pub struct CGColorSpaceRef;
pub unsafe type CGColorSpace {
type CType = ::sys::CGColorSpace;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
impl CGColorSpace {
@ -53,13 +53,61 @@ impl CGColorSpace {
#[link(name = "CoreGraphics", kind = "framework")]
extern {
/// The Display P3 color space, created by Apple.
pub static kCGColorSpaceDisplayP3: CFStringRef;
/// The Display P3 color space, using the HLG transfer function.
pub static kCGColorSpaceDisplayP3_HLG: CFStringRef;
/// The Display P3 color space with a linear transfer function
/// and extended-range values.
pub static kCGColorSpaceExtendedLinearDisplayP3: CFStringRef;
/// The standard Red Green Blue (sRGB) color space.
pub static kCGColorSpaceSRGB: CFStringRef;
pub static kCGColorSpaceAdobeRGB1998: CFStringRef;
pub static kCGColorSpaceGenericGray: CFStringRef;
pub static kCGColorSpaceGenericRGB: CFStringRef;
pub static kCGColorSpaceGenericCMYK: CFStringRef;
pub static kCGColorSpaceGenericRGBLinear: CFStringRef;
/// The sRGB color space with a linear transfer function.
pub static kCGColorSpaceLinearSRGB: CFStringRef;
/// The extended sRGB color space.
pub static kCGColorSpaceExtendedSRGB: CFStringRef;
/// The sRGB color space with a linear transfer function and
/// extended-range values.
pub static kCGColorSpaceExtendedLinearSRGB: CFStringRef;
/// The generic gray color space that has an exponential transfer
/// function with a power of 2.2.
pub static kCGColorSpaceGenericGrayGamma2_2: CFStringRef;
/// The gray color space using a linear transfer function.
pub static kCGColorSpaceLinearGray: CFStringRef;
/// The extended gray color space.
pub static kCGColorSpaceExtendedGray: CFStringRef;
/// The extended gray color space with a linear transfer function.
pub static kCGColorSpaceExtendedLinearGray: CFStringRef;
/// The generic RGB color space with a linear transfer function.
pub static kCGColorSpaceGenericRGBLinear: CFStringRef;
/// The generic CMYK color space.
pub static kCGColorSpaceGenericCMYK: CFStringRef;
/// The XYZ color space, as defined by the CIE 1931 standard.
pub static kCGColorSpaceGenericXYZ: CFStringRef;
/// The generic LAB color space.
pub static kCGColorSpaceGenericLab: CFStringRef;
/// The ACEScg color space.
pub static kCGColorSpaceACESCGLinear: CFStringRef;
/// The Adobe RGB (1998) color space.
pub static kCGColorSpaceAdobeRGB1998: CFStringRef;
/// The DCI P3 color space, which is the digital cinema standard.
pub static kCGColorSpaceDCIP3: CFStringRef;
/// The recommendation of the International Telecommunication Union
/// (ITU) Radiocommunication sector for the BT.709 color space.
pub static kCGColorSpaceITUR_709: CFStringRef;
/// The Reference Output Medium Metric (ROMM) RGB color space.
pub static kCGColorSpaceROMMRGB: CFStringRef;
/// The recommendation of the International Telecommunication Union
/// (ITU) Radiocommunication sector for the BT.2020 color space.
pub static kCGColorSpaceITUR_2020: CFStringRef;
/// The recommendation of the International Telecommunication Union
/// (ITU) Radiocommunication sector for the BT.2020 color space, with
/// a linear transfer function and extended range values.
pub static kCGColorSpaceExtendedLinearITUR_2020: CFStringRef;
/// The name of the generic RGB color space.
pub static kCGColorSpaceGenericRGB: CFStringRef;
/// The name of the generic gray color space.
pub static kCGColorSpaceGenericGray: CFStringRef;
fn CGColorSpaceCreateDeviceRGB() -> ::sys::CGColorSpaceRef;
fn CGColorSpaceCreateDeviceGray() -> ::sys::CGColorSpaceRef;

View File

@ -109,11 +109,11 @@ pub enum CGInterpolationQuality {
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGContext;
fn drop = |cs| CGContextRelease(cs);
fn clone = |p| CGContextRetain(p);
pub struct CGContext;
pub struct CGContextRef;
pub unsafe type CGContext {
type CType = ::sys::CGContext;
fn drop = |cs| CGContextRelease(cs);
fn clone = |p| CGContextRetain(p);
}
}
impl CGContext {
@ -389,6 +389,12 @@ impl CGContextRef {
}
}
pub fn reset_clip(&self) {
unsafe {
CGContextResetClip(self.as_ptr());
}
}
pub fn draw_path(&self, mode: CGPathDrawingMode) {
unsafe {
CGContextDrawPath(self.as_ptr(), mode);
@ -612,6 +618,12 @@ impl CGContextRef {
CGContextSetShadowWithColor(self.as_ptr(), offset, blur, color.as_concrete_TypeRef());
}
}
pub fn set_alpha(&self, alpha: CGFloat) {
unsafe {
CGContextSetAlpha(self.as_ptr(), alpha);
}
}
}
#[test]
@ -708,6 +720,7 @@ extern {
fn CGContextEOFillPath(c: ::sys::CGContextRef);
fn CGContextClip(c: ::sys::CGContextRef);
fn CGContextEOClip(c: ::sys::CGContextRef);
fn CGContextResetClip(c: ::sys::CGContextRef);
fn CGContextStrokePath(c: ::sys::CGContextRef);
fn CGContextSetRGBFillColor(context: ::sys::CGContextRef,
red: CGFloat,
@ -771,5 +784,7 @@ extern {
fn CGContextSetShadow(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat);
fn CGContextSetShadowWithColor(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat, color: ::sys::CGColorRef);
fn CGContextSetAlpha(c: ::sys::CGContextRef, alpha: CGFloat);
}

View File

@ -32,11 +32,11 @@ pub type CGDataProviderGetBytesAtPositionCallback = Option<unsafe extern fn (*mu
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGDataProvider;
fn drop = |cs| CFRelease(cs as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGDataProvider;
pub struct CGDataProviderRef;
pub unsafe type CGDataProvider {
type CType = ::sys::CGDataProvider;
fn drop = |cs| CFRelease(cs as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
impl CGDataProvider {

View File

@ -23,6 +23,7 @@ use foreign_types::ForeignType;
pub type CGDirectDisplayID = u32;
pub type CGWindowID = u32;
pub type CGWindowLevel = i32;
pub const kCGNullWindowID: CGWindowID = 0 as CGWindowID;
pub const kCGNullDirectDisplayID: CGDirectDisplayID = 0 as CGDirectDisplayID;
@ -68,6 +69,17 @@ pub const kDisplayModeNativeFlag: u32 = 0x02000000;
pub const kDisplayModeSafetyFlags: u32 = 0x00000007;
pub type CGDisplayBlendFraction = f32;
pub const kCGDisplayBlendNormal: CGDisplayBlendFraction = 0.0;
pub const kCGDisplayBlendSolidColor: CGDisplayBlendFraction = 1.0;
pub type CGDisplayFadeReservationToken = u32;
pub const kCGDisplayFadeReservationInvalidToken: CGDisplayFadeReservationToken = 0;
pub type CGDisplayFadeInterval = f32;
pub type CGDisplayReservationInterval = f32;
pub const kCGMaxDisplayReservationInterval: CGDisplayReservationInterval = 15.0;
pub const IO1BitIndexedPixels: &str = "P";
pub const IO2BitIndexedPixels: &str = "PP";
pub const IO4BitIndexedPixels: &str = "PPPP";
@ -104,11 +116,11 @@ pub struct CGDisplay {
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGDisplayMode;
fn drop = CGDisplayModeRelease;
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGDisplayMode;
pub struct CGDisplayModeRef;
pub unsafe type CGDisplayMode {
type CType = ::sys::CGDisplayMode;
fn drop = CGDisplayModeRelease;
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
impl CGDisplay {
@ -249,6 +261,19 @@ impl CGDisplay {
}
}
/// Returns an image containing the contents of a portion of the specified display.
#[inline]
pub fn image_for_rect(&self, bounds: CGRect) -> Option<CGImage> {
unsafe {
let image_ref = CGDisplayCreateImageForRect(self.id, bounds);
if !image_ref.is_null() {
Some(CGImage::from_ptr(image_ref))
} else {
None
}
}
}
/// Returns a composite image based on a dynamically generated list of
/// windows.
#[inline]
@ -604,7 +629,7 @@ impl CGDisplayMode {
16
} else if pixel_encoding.eq_ignore_ascii_case(IO8BitIndexedPixels) {
8
}else{
} else {
0
}
}
@ -621,6 +646,7 @@ extern "C" {
pub static kCGDisplayShowDuplicateLowResolutionModes: CFStringRef;
pub fn CGDisplayModeRetain(mode: ::sys::CGDisplayModeRef);
pub fn CGDisplayModeRelease(mode: ::sys::CGDisplayModeRef);
pub fn CGMainDisplayID() -> CGDirectDisplayID;
@ -657,7 +683,17 @@ extern "C" {
pub fn CGDisplayPixelsWide(display: CGDirectDisplayID) -> libc::size_t;
pub fn CGDisplayBounds(display: CGDirectDisplayID) -> CGRect;
pub fn CGDisplayCreateImage(display: CGDirectDisplayID) -> ::sys::CGImageRef;
pub fn CGDisplayCreateImageForRect(
display: CGDirectDisplayID,
rect: CGRect,
) -> ::sys::CGImageRef;
// Capturing and Releasing Displays
pub fn CGDisplayCapture(display: CGDirectDisplayID) -> CGError;
pub fn CGDisplayRelease(display: CGDirectDisplayID) -> CGError;
pub fn CGShieldingWindowLevel() -> CGWindowLevel;
// Configuring Displays
pub fn CGBeginDisplayConfiguration(config: *mut CGDisplayConfigRef) -> CGError;
pub fn CGCancelDisplayConfiguration(config: CGDisplayConfigRef) -> CGError;
pub fn CGCompleteDisplayConfiguration(
@ -681,6 +717,7 @@ extern "C" {
x: i32,
y: i32,
) -> CGError;
pub fn CGRestorePermanentDisplayConfiguration();
pub fn CGDisplayCopyDisplayMode(display: CGDirectDisplayID) -> ::sys::CGDisplayModeRef;
pub fn CGDisplayModeGetHeight(mode: ::sys::CGDisplayModeRef) -> libc::size_t;
@ -696,6 +733,11 @@ extern "C" {
display: CGDirectDisplayID,
options: CFDictionaryRef,
) -> CFArrayRef;
pub fn CGDisplaySetDisplayMode(
display: CGDirectDisplayID,
mode: ::sys::CGDisplayModeRef,
options: CFDictionaryRef,
) -> CGError;
// mouse stuff
pub fn CGDisplayHideCursor(display: CGDirectDisplayID) -> CGError;
@ -704,6 +746,32 @@ extern "C" {
pub fn CGWarpMouseCursorPosition(point: CGPoint) -> CGError;
pub fn CGAssociateMouseAndMouseCursorPosition(connected: boolean_t) -> CGError;
// Display Fade Effects
pub fn CGConfigureDisplayFadeEffect(
config: CGDisplayConfigRef,
fadeOutSeconds: CGDisplayFadeInterval,
fadeInSeconds: CGDisplayFadeInterval,
fadeRed: f32,
fadeGreen: f32,
fadeBlue: f32,
) -> CGError;
pub fn CGAcquireDisplayFadeReservation(
seconds: CGDisplayReservationInterval,
token: *mut CGDisplayFadeReservationToken,
) -> CGError;
pub fn CGDisplayFade(
token: CGDisplayFadeReservationToken,
duration: CGDisplayFadeInterval,
startBlend: CGDisplayBlendFraction,
endBlend: CGDisplayBlendFraction,
redBlend: f32,
greenBlend: f32,
blueBlend: f32,
synchronous: boolean_t,
) -> CGError;
// CGDisplayFadeOperationInProgress
pub fn CGReleaseDisplayFadeReservation(token: CGDisplayFadeReservationToken) -> CGError;
// Window Services Reference
pub fn CGWindowListCopyWindowInfo(
option: CGWindowListOption,

View File

@ -505,7 +505,7 @@ impl<'tap_life> CGEventTap<'tap_life> {
callback_ref: Box::from_raw(cbr),
})
} else {
Box::from_raw(cbr);
let _ = Box::from_raw(cbr);
Err(())
}
}
@ -518,11 +518,11 @@ impl<'tap_life> CGEventTap<'tap_life> {
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGEvent;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGEvent;
pub struct CGEventRef;
pub unsafe type CGEvent {
type CType = ::sys::CGEvent;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
impl CGEvent {
@ -607,12 +607,16 @@ impl CGEvent {
}
}
pub fn location(&self) -> CGPoint {
pub fn post_from_tap(&self, tap_proxy: CGEventTapProxy) {
unsafe {
CGEventGetLocation(self.as_ptr())
CGEventTapPostEvent(tap_proxy, self.as_ptr());
}
}
pub fn location(&self) -> CGPoint {
unsafe { CGEventGetLocation(self.as_ptr()) }
}
#[cfg(feature = "elcapitan")]
pub fn post_to_pid(&self, pid: libc::pid_t) {
unsafe {
@ -734,6 +738,8 @@ extern {
/// taps.
fn CGEventPost(tapLocation: CGEventTapLocation, event: ::sys::CGEventRef);
fn CGEventTapPostEvent(tapProxy: CGEventTapProxy, event: ::sys::CGEventRef);
#[cfg(feature = "elcapitan")]
/// Post an event to a specified process ID
fn CGEventPostToPid(pid: libc::pid_t, event: ::sys::CGEventRef);

View File

@ -12,11 +12,11 @@ pub enum CGEventSourceStateID {
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGEventSource;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGEventSource;
pub struct CGEventSourceRef;
pub unsafe type CGEventSource {
type CType = ::sys::CGEventSource;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
impl CGEventSource {

View File

@ -15,6 +15,7 @@ use core_foundation::string::{CFString, CFStringRef};
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
use data_provider::CGDataProvider;
use geometry::CGRect;
use std::ptr::NonNull;
use foreign_types::ForeignType;
@ -24,16 +25,13 @@ pub use core_graphics_types::base::CGGlyph;
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGFont;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGFont;
pub struct CGFontRef;
pub unsafe type CGFont: Send + Sync {
type CType = ::sys::CGFont;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
unsafe impl Send for CGFont {}
unsafe impl Sync for CGFont {}
impl CGFont {
pub fn type_id() -> CFTypeID {
unsafe {
@ -44,10 +42,9 @@ impl CGFont {
pub fn from_data_provider(provider: CGDataProvider) -> Result<CGFont, ()> {
unsafe {
let font_ref = CGFontCreateWithDataProvider(provider.as_ptr());
if !font_ref.is_null() {
Ok(CGFont::from_ptr(font_ref))
} else {
Err(())
match NonNull::new(font_ref) {
Some(font_ref) => Ok(CGFont(font_ref)),
None => Err(()),
}
}
}
@ -55,10 +52,9 @@ impl CGFont {
pub fn from_name(name: &CFString) -> Result<CGFont, ()> {
unsafe {
let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef());
if !font_ref.is_null() {
Ok(CGFont::from_ptr(font_ref))
} else {
Err(())
match NonNull::new(font_ref) {
Some(font_ref) => Ok(CGFont(font_ref)),
None => Err(()),
}
}
}
@ -67,10 +63,9 @@ impl CGFont {
unsafe {
let font_ref = CGFontCreateCopyWithVariations(self.as_ptr(),
vars.as_concrete_TypeRef());
if !font_ref.is_null() {
Ok(CGFont::from_ptr(font_ref))
} else {
Err(())
match NonNull::new(font_ref) {
Some(font_ref) => Ok(CGFont(font_ref)),
None => Err(()),
}
}
}

View File

@ -29,11 +29,11 @@ bitflags! {
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGGradient;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGGradient;
pub struct CGGradientRef;
pub unsafe type CGGradient {
type CType = ::sys::CGGradient;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
impl CGGradient {

View File

@ -32,11 +32,11 @@ pub enum CGImageByteOrderInfo {
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGImage;
fn drop = CGImageRelease;
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGImage;
pub struct CGImageRef;
pub unsafe type CGImage {
type CType = ::sys::CGImage;
fn drop = CGImageRelease;
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
impl CGImage {

View File

@ -41,3 +41,5 @@ pub mod private;
pub mod image;
pub mod path;
pub mod sys;
#[cfg(target_os = "macos")]
pub mod access;

View File

@ -21,11 +21,11 @@ use std::slice;
foreign_type! {
#[doc(hidden)]
type CType = ::sys::CGPath;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
pub struct CGPath;
pub struct CGPathRef;
pub unsafe type CGPath {
type CType = ::sys::CGPath;
fn drop = |p| CFRelease(p as *mut _);
fn clone = |p| CFRetain(p as *const _) as *mut _;
}
}
impl CGPath {
@ -35,7 +35,7 @@ impl CGPath {
None => ptr::null(),
Some(transform) => transform as *const CGAffineTransform,
};
CGPath(CGPathCreateWithRect(rect, transform))
CGPath::from_ptr(CGPathCreateWithRect(rect, transform))
}
}

View File

@ -1 +1 @@
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"26a527860e530d18a5ce446ffb595f63a178504506fb4a283993402295053afe","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"98d25015857a430aac32f34bdc979a1a66e672a0ea42c5f92dd9cfe23c1fccfd","src/font.rs":"17d957510eee8d96ef2bc1b5bc97491917ac0336ad3dbf48416dda3685cef579","src/font_collection.rs":"02de0ce2a61683314897a521d31ab9cc572a8b10ceda2ac47181fbe18bf4f235","src/font_descriptor.rs":"43a2fec6bca9689d8172f363ab20ce8c633696974e1653cad2e072e3af776528","src/font_manager.rs":"6e5056a42868187e1f4e696c181ca247423308652d3c68867c708616031876e4","src/frame.rs":"ed1e2aad7be9dafc3e9729f2caecefd4214a9552f834932a414239146142069a","src/framesetter.rs":"13e34b4111cee5f023aa05e2220d2a6f102e96fd18c51a356992bffd6c9fc7c1","src/lib.rs":"1c662e51874eb43ff52a8a1af131d1b2fd84095c3d949a271dc895bf56fd0fc6","src/line.rs":"02fab7f07c3f6a003a7c35ffeb3d37546ae58e4da7fe05f26e520f283397a602","src/run.rs":"b86e9b9b39effe4a79c6002880d95f214742d448029a3111e288734abe75b827","src/string_attributes.rs":"ea0f854d64097d3626a03002323e2276e28affae7a698aaadd89dd6b744dd80f"},"package":"99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"}
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7a776cd901d7f63a97ad6c1576b00f267ad782ef79ff4cdfbc2cb507a2c144d5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"98d25015857a430aac32f34bdc979a1a66e672a0ea42c5f92dd9cfe23c1fccfd","src/font.rs":"149d4646abc01a884e16d45dde77b44d3151cab27c301c65fa22dda638ff3c48","src/font_collection.rs":"02de0ce2a61683314897a521d31ab9cc572a8b10ceda2ac47181fbe18bf4f235","src/font_descriptor.rs":"43a2fec6bca9689d8172f363ab20ce8c633696974e1653cad2e072e3af776528","src/font_manager.rs":"6e5056a42868187e1f4e696c181ca247423308652d3c68867c708616031876e4","src/frame.rs":"ed1e2aad7be9dafc3e9729f2caecefd4214a9552f834932a414239146142069a","src/framesetter.rs":"13e34b4111cee5f023aa05e2220d2a6f102e96fd18c51a356992bffd6c9fc7c1","src/lib.rs":"1c662e51874eb43ff52a8a1af131d1b2fd84095c3d949a271dc895bf56fd0fc6","src/line.rs":"02fab7f07c3f6a003a7c35ffeb3d37546ae58e4da7fe05f26e520f283397a602","src/run.rs":"b86e9b9b39effe4a79c6002880d95f214742d448029a3111e288734abe75b827","src/string_attributes.rs":"ea0f854d64097d3626a03002323e2276e28affae7a698aaadd89dd6b744dd80f"},"package":"02083d15989d6247553e1a63753561555a72b2038bba1e4239db70602a798742"}

View File

@ -3,30 +3,32 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
name = "core-text"
version = "19.2.0"
version = "20.0.0"
authors = ["The Servo Project Developers"]
description = "Bindings to the Core Text framework."
license = "MIT/Apache-2.0"
readme = "README.md"
license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/core-foundation-rs"
[package.metadata.docs.rs]
default-target = "x86_64-apple-darwin"
[dependencies.core-foundation]
version = "0.9"
[dependencies.core-graphics]
version = "0.22.0"
version = "0.23.0"
[dependencies.foreign-types]
version = "0.3"
version = "0.5"
[dependencies.libc]
version = "0.2"

View File

@ -78,6 +78,54 @@ pub const kCTFontOptionsDefault: CTFontOptions = 0;
pub const kCTFontOptionsPreventAutoActivation: CTFontOptions = 1 << 0;
pub const kCTFontOptionsPreferSystemFont: CTFontOptions = 1 << 2;
pub enum CTFontNameSpecifier {
Copyright,
Family,
SubFamily,
Style,
Unique,
Full,
Version,
PostScript,
Trademark,
Manufacturer,
Designer,
Description,
VendorURL,
DesignerURL,
License,
LicenseURL,
SampleText,
PostScriptCID,
}
impl Into<CFStringRef> for CTFontNameSpecifier {
fn into(self) -> CFStringRef {
unsafe {
match self {
CTFontNameSpecifier::Copyright => kCTFontCopyrightNameKey,
CTFontNameSpecifier::Family => kCTFontFamilyNameKey,
CTFontNameSpecifier::SubFamily => kCTFontSubFamilyNameKey,
CTFontNameSpecifier::Style => kCTFontStyleNameKey,
CTFontNameSpecifier::Unique => kCTFontUniqueNameKey,
CTFontNameSpecifier::Full => kCTFontFullNameKey,
CTFontNameSpecifier::Version => kCTFontVersionNameKey,
CTFontNameSpecifier::PostScript => kCTFontPostScriptNameKey,
CTFontNameSpecifier::Trademark => kCTFontTrademarkNameKey,
CTFontNameSpecifier::Manufacturer => kCTFontManufacturerNameKey,
CTFontNameSpecifier::Designer => kCTFontDesignerNameKey,
CTFontNameSpecifier::Description => kCTFontDescriptionNameKey,
CTFontNameSpecifier::VendorURL => kCTFontVendorURLNameKey,
CTFontNameSpecifier::DesignerURL => kCTFontDesignerURLNameKey,
CTFontNameSpecifier::License => kCTFontLicenseNameKey,
CTFontNameSpecifier::LicenseURL => kCTFontLicenseURLNameKey,
CTFontNameSpecifier::SampleText => kCTFontSampleTextNameKey,
CTFontNameSpecifier::PostScriptCID => kCTFontPostScriptCIDNameKey,
}
}
}
}
#[repr(C)]
pub struct __CTFont(c_void);
@ -144,6 +192,29 @@ pub fn new_from_name(name: &str, pt_size: f64) -> Result<CTFont, ()> {
}
}
pub fn new_ui_font_for_language(ui_type: CTFontUIFontType,
size: f64,
language: Option<CFString>)
-> CTFont {
unsafe {
let font_ref = CTFontCreateUIFontForLanguage(
ui_type,
size,
language.as_ref()
.map(|x| x.as_concrete_TypeRef())
.unwrap_or(std::ptr::null()),
);
if font_ref.is_null() {
// CTFontCreateUIFontForLanguage can fail, but is unlikely to do so during
// normal usage (if you pass a bad ui_type it will). To make things more
// convenient, just panic if it fails.
panic!();
} else {
CTFont::wrap_under_create_rule(font_ref)
}
}
}
impl CTFont {
// Properties
pub fn symbolic_traits(&self) -> CTFontSymbolicTraits {
@ -198,46 +269,45 @@ impl CTFont {
}
// Names
pub fn family_name(&self) -> String {
pub fn get_string_by_name_key(&self, name_key: CTFontNameSpecifier) -> Option<String> {
unsafe {
let value = get_string_by_name_key(self, kCTFontFamilyNameKey);
value.expect("Fonts should always have a family name.")
let result = CTFontCopyName(self.as_concrete_TypeRef(), name_key.into());
if result.is_null() {
None
} else {
Some(CFString::wrap_under_create_rule(result).to_string())
}
}
}
pub fn family_name(&self) -> String {
let value = self.get_string_by_name_key(CTFontNameSpecifier::Family);
value.expect("Fonts should always have a family name.")
}
pub fn face_name(&self) -> String {
unsafe {
let value = get_string_by_name_key(self, kCTFontSubFamilyNameKey);
value.expect("Fonts should always have a face name.")
}
let value = self.get_string_by_name_key(CTFontNameSpecifier::SubFamily);
value.expect("Fonts should always have a face name.")
}
pub fn unique_name(&self) -> String {
unsafe {
let value = get_string_by_name_key(self, kCTFontUniqueNameKey);
value.expect("Fonts should always have a unique name.")
}
let value = self.get_string_by_name_key(CTFontNameSpecifier::Unique);
value.expect("Fonts should always have a unique name.")
}
pub fn postscript_name(&self) -> String {
unsafe {
let value = get_string_by_name_key(self, kCTFontPostScriptNameKey);
value.expect("Fonts should always have a PostScript name.")
}
let value = self.get_string_by_name_key(CTFontNameSpecifier::PostScript);
value.expect("Fonts should always have a PostScript name.")
}
pub fn display_name(&self) -> String {
unsafe {
let value = get_string_by_name_key(self, kCTFontFullNameKey);
value.expect("Fonts should always have a PostScript name.")
}
let value = self.get_string_by_name_key(CTFontNameSpecifier::Full);
value.expect("Fonts should always have a PostScript name.")
}
pub fn style_name(&self) -> String {
unsafe {
let value = get_string_by_name_key(self, kCTFontStyleNameKey);
value.expect("Fonts should always have a style name.")
}
let value = self.get_string_by_name_key(CTFontNameSpecifier::Style);
value.expect("Fonts should always have a style name.")
}
pub fn all_traits(&self) -> CTFontTraits {
@ -437,30 +507,17 @@ impl CTFont {
}
// Helper methods
fn get_string_by_name_key(font: &CTFont, name_key: CFStringRef) -> Option<String> {
unsafe {
let result = CTFontCopyName(font.as_concrete_TypeRef(), name_key);
if result.is_null() {
None
} else {
Some(CFString::wrap_under_create_rule(result).to_string())
}
}
}
pub fn debug_font_names(font: &CTFont) {
fn get_key(font: &CTFont, key: CFStringRef) -> String {
get_string_by_name_key(font, key).unwrap()
fn get_key(font: &CTFont, key: CTFontNameSpecifier) -> String {
font.get_string_by_name_key(key).unwrap()
}
unsafe {
println!("kCTFontFamilyNameKey: {}", get_key(font, kCTFontFamilyNameKey));
println!("kCTFontSubFamilyNameKey: {}", get_key(font, kCTFontSubFamilyNameKey));
println!("kCTFontStyleNameKey: {}", get_key(font, kCTFontStyleNameKey));
println!("kCTFontUniqueNameKey: {}", get_key(font, kCTFontUniqueNameKey));
println!("kCTFontFullNameKey: {}", get_key(font, kCTFontFullNameKey));
println!("kCTFontPostScriptNameKey: {}", get_key(font, kCTFontPostScriptNameKey));
}
println!("kCTFontFamilyNameKey: {}", get_key(font, CTFontNameSpecifier::Family));
println!("kCTFontSubFamilyNameKey: {}", get_key(font, CTFontNameSpecifier::SubFamily));
println!("kCTFontStyleNameKey: {}", get_key(font, CTFontNameSpecifier::Style));
println!("kCTFontUniqueNameKey: {}", get_key(font, CTFontNameSpecifier::Unique));
println!("kCTFontFullNameKey: {}", get_key(font, CTFontNameSpecifier::Full));
println!("kCTFontPostScriptNameKey: {}", get_key(font, CTFontNameSpecifier::PostScript));
}
pub fn debug_font_traits(font: &CTFont) {
@ -494,28 +551,30 @@ extern {
*/
/* Name Specifier Constants */
//static kCTFontCopyrightNameKey: CFStringRef;
static kCTFontCopyrightNameKey: CFStringRef;
static kCTFontFamilyNameKey: CFStringRef;
static kCTFontSubFamilyNameKey: CFStringRef;
static kCTFontStyleNameKey: CFStringRef;
static kCTFontUniqueNameKey: CFStringRef;
static kCTFontFullNameKey: CFStringRef;
//static kCTFontVersionNameKey: CFStringRef;
static kCTFontVersionNameKey: CFStringRef;
static kCTFontPostScriptNameKey: CFStringRef;
//static kCTFontTrademarkNameKey: CFStringRef;
//static kCTFontManufacturerNameKey: CFStringRef;
//static kCTFontDesignerNameKey: CFStringRef;
//static kCTFontDescriptionNameKey: CFStringRef;
//static kCTFontVendorURLNameKey: CFStringRef;
//static kCTFontDesignerURLNameKey: CFStringRef;
//static kCTFontLicenseNameKey: CFStringRef;
//static kCTFontLicenseURLNameKey: CFStringRef;
//static kCTFontSampleTextNameKey: CFStringRef;
//static kCTFontPostScriptCIDNameKey: CFStringRef;
static kCTFontTrademarkNameKey: CFStringRef;
static kCTFontManufacturerNameKey: CFStringRef;
static kCTFontDesignerNameKey: CFStringRef;
static kCTFontDescriptionNameKey: CFStringRef;
static kCTFontVendorURLNameKey: CFStringRef;
static kCTFontDesignerURLNameKey: CFStringRef;
static kCTFontLicenseNameKey: CFStringRef;
static kCTFontLicenseURLNameKey: CFStringRef;
static kCTFontSampleTextNameKey: CFStringRef;
static kCTFontPostScriptCIDNameKey: CFStringRef;
//static kCTFontVariationAxisIdentifierKey: CFStringRef;
#[cfg(test)]
static kCTFontVariationAxisIdentifierKey: CFStringRef;
//static kCTFontVariationAxisMinimumValueKey: CFStringRef;
//static kCTFontVariationAxisMaximumValueKey: CFStringRef;
#[cfg(test)]
static kCTFontVariationAxisMaximumValueKey: CFStringRef;
//static kCTFontVariationAxisDefaultValueKey: CFStringRef;
//static kCTFontVariationAxisNameKey: CFStringRef;
@ -539,7 +598,6 @@ extern {
fn CTFontCreateWithFontDescriptor(descriptor: CTFontDescriptorRef, size: CGFloat,
matrix: *const CGAffineTransform) -> CTFontRef;
//fn CTFontCreateWithFontDescriptorAndOptions
#[cfg(test)]
fn CTFontCreateUIFontForLanguage(uiType: CTFontUIFontType, size: CGFloat, language: CFStringRef) -> CTFontRef;
fn CTFontCreateCopyWithAttributes(font: CTFontRef, size: CGFloat, matrix: *const CGAffineTransform,
attributes: CTFontDescriptorRef) -> CTFontRef;
@ -691,11 +749,9 @@ fn macos_version() -> (i32, i32, i32) {
#[test]
fn copy_system_font() {
let small = unsafe {
CTFont::wrap_under_create_rule(
CTFontCreateUIFontForLanguage(kCTFontSystemDetailFontType, 19., std::ptr::null())
)
};
use crate::*;
let small = new_ui_font_for_language(kCTFontSystemDetailFontType, 19., None);
let big = small.clone_with_font_size(20.);
// ensure that we end up with different fonts for the different sizes before 10.15
@ -712,6 +768,12 @@ fn copy_system_font() {
let ctfont = new_from_descriptor(&desc, 20.);
assert_eq!(big.postscript_name(), ctfont.postscript_name());
// check that we can construct a new version by attributes
let attr = desc.attributes();
let desc_from_attr = font_descriptor::new_from_attributes(&attr);
let font_from_attr = new_from_descriptor(&desc_from_attr, 19.);
assert_eq!(font_from_attr.postscript_name(), small.postscript_name());
// on newer versions of macos we can't construct by name anymore
if macos_version() < (10, 13, 0) {
let ui_font_by_name = new_from_name(&small.postscript_name(), 19.).unwrap();
@ -741,4 +803,165 @@ fn copy_system_font() {
assert!(matching.attributes().find(CFString::from_static_string("NSFontSizeAttribute")).is_none());
assert_eq!(small.postscript_name(), cgfont.postscript_name());
}
}
// Tests what happens when variations have values not inbetween min and max
#[test]
fn out_of_range_variations() {
use crate::*;
let small = new_ui_font_for_language(kCTFontSystemDetailFontType, 19., None);
let axes = small.get_variation_axes();
if macos_version() < (10, 12, 0) {
assert!(axes.is_none());
return;
}
let axes = axes.unwrap();
let mut vals = Vec::new();
dbg!(&axes);
for axis in axes.iter() {
let tag = axis.find(unsafe { kCTFontVariationAxisIdentifierKey } )
.unwrap().downcast::<CFNumber>().unwrap().to_i64().unwrap();
let max = axis.find(unsafe { kCTFontVariationAxisMaximumValueKey } )
.unwrap().downcast::<CFNumber>().unwrap().to_f64().unwrap();
vals.push((CFNumber::from(tag), CFNumber::from(max + 1.)));
}
let vals_dict = CFDictionary::from_CFType_pairs(&vals);
let variation_attribute = unsafe { CFString::wrap_under_get_rule(font_descriptor::kCTFontVariationAttribute) };
let attrs_dict = CFDictionary::from_CFType_pairs(&[(variation_attribute.clone(), vals_dict)]);
let ct_var_font_desc = small.copy_descriptor().create_copy_with_attributes(attrs_dict.to_untyped()).unwrap();
let variation_font = crate::font::new_from_descriptor(&ct_var_font_desc, 19.);
let var_desc = variation_font.copy_descriptor();
let var_attrs = var_desc.attributes();
dbg!(&var_attrs);
// attributes greater than max are dropped on macOS <= 11
// on macOS 12 they seem to be preserved as is.
let var_attrs = var_attrs.find(variation_attribute);
if macos_version() >= (12, 0, 0) {
let var_attrs = var_attrs.unwrap().downcast::<CFDictionary>().unwrap();
assert!(!var_attrs.is_empty());
let var_attrs: CFDictionary<CFType, CFType> = unsafe { std::mem::transmute(var_attrs) };
// attributes greater than max remain
for axis in axes.iter() {
let tag = axis.find(unsafe { kCTFontVariationAxisIdentifierKey } )
.unwrap();
let max = axis.find(unsafe { kCTFontVariationAxisMaximumValueKey } )
.unwrap().downcast::<CFNumber>().unwrap().to_f64().unwrap();
let val = var_attrs.find(tag.clone()).unwrap().downcast::<CFNumber>().unwrap().to_f64().unwrap();
assert_eq!(val, max + 1.);
}
} else if macos_version() >= (10, 15, 0) {
assert!(var_attrs.is_none());
} else {
let var_attrs = var_attrs.unwrap().downcast::<CFDictionary>().unwrap();
assert!(var_attrs.is_empty());
}
}
#[test]
fn equal_descriptor_different_font() {
use crate::*;
let variation_attribute = unsafe { CFString::wrap_under_get_rule(font_descriptor::kCTFontVariationAttribute) };
let size_attribute = unsafe { CFString::wrap_under_get_rule(font_descriptor::kCTFontSizeAttribute) };
let sys_font = new_ui_font_for_language(kCTFontSystemDetailFontType, 19., None);
// but we can still construct the CGFont by name
let create_vars = |desc| {
let mut vals: Vec<(CFNumber, CFNumber)> = Vec::new();
vals.push((CFNumber::from(0x6f70737a), CFNumber::from(17.)));
let vals_dict = CFDictionary::from_CFType_pairs(&vals);
let attrs_dict = CFDictionary::from_CFType_pairs(&[(variation_attribute.clone(), vals_dict)]);
let size_attrs_dict = CFDictionary::from_CFType_pairs(&[(size_attribute.clone(), CFNumber::from(120.))]);
dbg!(&desc);
let from_font_desc = new_from_descriptor(&desc, 120.).copy_descriptor();
let resized_font_desc = desc.create_copy_with_attributes(size_attrs_dict.to_untyped()).unwrap();
if macos_version() >= (11, 0, 0) {
assert_eq!(from_font_desc, resized_font_desc);
} else {
// we won't have a name if we're using system font desc
if from_font_desc.attributes().find(unsafe { font_descriptor::kCTFontNameAttribute }).is_none() {
// it's surprising that desc's are the not equal but the attributes are
assert_ne!(from_font_desc, resized_font_desc);
assert_eq!(from_font_desc.attributes().to_untyped(), resized_font_desc.attributes().to_untyped());
} else {
if macos_version() >= (10, 13, 0) {
// this is unsurprising
assert_ne!(from_font_desc, resized_font_desc);
assert_ne!(from_font_desc.attributes().to_untyped(), resized_font_desc.attributes().to_untyped());
} else {
assert_ne!(from_font_desc, resized_font_desc);
assert_eq!(from_font_desc.attributes().to_untyped(), resized_font_desc.attributes().to_untyped());
}
}
}
let from_font_desc = from_font_desc.create_copy_with_attributes(attrs_dict.to_untyped()).unwrap();
let resized_font_desc = resized_font_desc.create_copy_with_attributes(attrs_dict.to_untyped()).unwrap();
(from_font_desc, resized_font_desc)
};
// setting the variation works properly if we use system font desc
let (from_font_desc, resized_font_desc) = create_vars(sys_font.copy_descriptor());
assert_eq!(from_font_desc, resized_font_desc);
assert!(resized_font_desc.attributes().find(variation_attribute.clone()).is_some());
// but doesn't if we refer to it by name
let ps = sys_font.postscript_name();
let cgfont = CGFont::from_name(&CFString::new(&ps)).unwrap();
let ctfont = new_from_CGFont(&cgfont, 0.);
let (from_font_desc, resized_font_desc) = create_vars(ctfont.copy_descriptor());
if macos_version() >= (10, 15, 0) {
assert_ne!(from_font_desc, resized_font_desc);
}
if macos_version() >= (10, 13, 0) {
assert!(from_font_desc.attributes().find(variation_attribute.clone()).is_some());
if macos_version() >= (11, 0, 0) {
assert!(resized_font_desc.attributes().find(variation_attribute).is_none());
} else {
assert!(resized_font_desc.attributes().find(variation_attribute).is_some());
};
}
}
#[test]
fn system_font_variation() {
use crate::*;
let small = new_ui_font_for_language(kCTFontSystemDetailFontType, 19., None);
// but we can still construct the CGFont by name
let ps = small.postscript_name();
let cgfont = CGFont::from_name(&CFString::new(&ps)).unwrap();
let cgfont = new_from_CGFont(&cgfont, 0.);
let desc = cgfont.copy_descriptor();
let mut vals: Vec<(CFNumber, CFNumber)> = Vec::new();
vals.push((CFNumber::from(0x6f70737a /* opsz */), CFNumber::from(17.)));
let vals_dict = CFDictionary::from_CFType_pairs(&vals);
let variation_attribute = unsafe { CFString::wrap_under_get_rule(font_descriptor::kCTFontVariationAttribute) };
let attrs_dict = CFDictionary::from_CFType_pairs(&[(variation_attribute, vals_dict)]);
let ct_var_font_desc = desc.create_copy_with_attributes(attrs_dict.to_untyped()).unwrap();
let attrs = ct_var_font_desc.attributes();
let var_attr = attrs.find(CFString::from_static_string("NSCTFontVariationAttribute"));
if macos_version() >= (11, 0, 0) {
// the variation goes away
assert!(var_attr.is_none());
} else {
assert!(var_attr.is_some());
}
dbg!(ct_var_font_desc);
}
#[test]
fn ui_font() {
// pass some garbagey inputs
new_ui_font_for_language(kCTFontSystemDetailFontType, 10000009., Some(CFString::from("Gofld")));
}

View File

@ -0,0 +1 @@
{"files":{"Cargo.toml":"829c9da0910b673669e0401c6affd6564c94c49cf9629740104ffabf46f54d08","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","src/build.rs":"bee8027592dff9052e1235a6b1bfd0ae715389265247131c3e1ed865e561ba40","src/lib.rs":"7bb43075bede4947ee8f07a05e4d1b00e0daedadbde15f1b386f97514853ad1c","src/parse.rs":"d8cc189b7108602dee81ff5436a9480dd45397101f7faad875027441e1477ef1"},"package":"1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"}

View File

@ -0,0 +1,35 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "foreign-types-macros"
version = "0.2.3"
authors = ["Steven Fackler <sfackler@gmail.com>"]
description = "An internal crate used by foreign-types"
license = "MIT/Apache-2.0"
repository = "https://github.com/sfackler/foreign-types"
[lib]
proc-macro = true
[dependencies.proc-macro2]
version = "1.0"
[dependencies.quote]
version = "1.0"
[dependencies.syn]
version = "2.0"
features = ["full"]
[features]
std = []

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,19 @@
Copyright (c) 2017 The foreign-types Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,261 @@
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Ident, Path};
use crate::parse::{ForeignType, Input};
fn ref_name(input: &ForeignType) -> Ident {
Ident::new(&format!("{}Ref", input.name), input.name.span())
}
pub fn build(input: Input) -> TokenStream {
let types = input
.types
.iter()
.map(|t| build_foreign_type(&input.crate_, t));
quote! {
#(#types)*
}
}
fn build_foreign_type(crate_: &Path, input: &ForeignType) -> TokenStream {
let decls = build_decls(crate_, input);
let oibits = build_oibits(crate_, input);
let foreign_impls = build_foreign_impls(crate_, input);
let drop_impl = build_drop_impl(crate_, input);
let deref_impls = build_deref_impls(crate_, input);
let borrow_impls = build_borrow_impls(crate_, input);
let as_ref_impls = build_as_ref_impls(crate_, input);
let clone_impl = build_clone_impl(crate_, input);
let to_owned_impl = build_to_owned_impl(crate_, input);
quote! {
#decls
#oibits
#foreign_impls
#drop_impl
#deref_impls
#borrow_impls
#as_ref_impls
#clone_impl
#to_owned_impl
}
}
fn build_decls(crate_: &Path, input: &ForeignType) -> TokenStream {
let attrs = &input.attrs;
let vis = &input.visibility;
let name = &input.name;
let generics = &input.generics;
let ctype = &input.ctype;
let phantom_data = input
.phantom_data
.as_ref()
.map(|d| quote!(, #crate_::export::PhantomData<#d>));
let ref_name = ref_name(input);
let ref_docs = format!(
"A borrowed reference to a [`{name}`](struct.{name}.html).",
name = name
);
quote! {
#(#attrs)*
#[repr(transparent)]
#vis struct #name #generics(#crate_::export::NonNull<#ctype> #phantom_data);
#[doc = #ref_docs]
#vis struct #ref_name #generics(#crate_::Opaque #phantom_data);
}
}
fn build_oibits(crate_: &Path, input: &ForeignType) -> TokenStream {
let oibits = input.oibits.iter().map(|t| build_oibit(crate_, input, t));
quote! {
#(#oibits)*
}
}
fn build_oibit(crate_: &Path, input: &ForeignType, oibit: &Ident) -> TokenStream {
let name = &input.name;
let ref_name = ref_name(input);
let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
quote! {
unsafe impl #impl_generics #crate_::export::#oibit for #name #ty_generics {}
unsafe impl #impl_generics #crate_::export::#oibit for #ref_name #ty_generics {}
}
}
fn build_foreign_impls(crate_: &Path, input: &ForeignType) -> TokenStream {
let name = &input.name;
let ctype = &input.ctype;
let ref_name = ref_name(input);
let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
let phantom_data = input
.phantom_data
.as_ref()
.map(|_| quote!(, #crate_::export::PhantomData));
quote! {
unsafe impl #impl_generics #crate_::ForeignType for #name #ty_generics {
type CType = #ctype;
type Ref = #ref_name #ty_generics;
#[inline]
unsafe fn from_ptr(ptr: *mut #ctype) -> #name #ty_generics {
debug_assert!(!ptr.is_null());
#name(<#crate_::export::NonNull<_>>::new_unchecked(ptr) #phantom_data)
}
#[inline]
fn as_ptr(&self) -> *mut #ctype {
<#crate_::export::NonNull<_>>::as_ptr(self.0)
}
}
unsafe impl #impl_generics #crate_::ForeignTypeRef for #ref_name #ty_generics {
type CType = #ctype;
}
}
}
fn build_drop_impl(crate_: &Path, input: &ForeignType) -> TokenStream {
let name = &input.name;
let drop = &input.drop;
let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
quote! {
impl #impl_generics #crate_::export::Drop for #name #ty_generics {
#[inline]
fn drop(&mut self) {
unsafe {
(#drop)(#crate_::ForeignType::as_ptr(self));
}
}
}
}
}
fn build_deref_impls(crate_: &Path, input: &ForeignType) -> TokenStream {
let name = &input.name;
let ref_name = ref_name(input);
let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
quote! {
impl #impl_generics #crate_::export::Deref for #name #ty_generics {
type Target = #ref_name #ty_generics;
#[inline]
fn deref(&self) -> &#ref_name #ty_generics {
unsafe {
#crate_::ForeignTypeRef::from_ptr(#crate_::ForeignType::as_ptr(self))
}
}
}
impl #impl_generics #crate_::export::DerefMut for #name #ty_generics {
#[inline]
fn deref_mut(&mut self) -> &mut #ref_name #ty_generics {
unsafe {
#crate_::ForeignTypeRef::from_ptr_mut(#crate_::ForeignType::as_ptr(self))
}
}
}
}
}
fn build_borrow_impls(crate_: &Path, input: &ForeignType) -> TokenStream {
let name = &input.name;
let ref_name = ref_name(input);
let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
quote! {
impl #impl_generics #crate_::export::Borrow<#ref_name #ty_generics> for #name #ty_generics {
#[inline]
fn borrow(&self) -> &#ref_name #ty_generics {
&**self
}
}
impl #impl_generics #crate_::export::BorrowMut<#ref_name #ty_generics> for #name #ty_generics {
#[inline]
fn borrow_mut(&mut self) -> &mut #ref_name #ty_generics {
&mut **self
}
}
}
}
fn build_as_ref_impls(crate_: &Path, input: &ForeignType) -> TokenStream {
let name = &input.name;
let ref_name = ref_name(input);
let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
quote! {
impl #impl_generics #crate_::export::AsRef<#ref_name #ty_generics> for #name #ty_generics {
#[inline]
fn as_ref(&self) -> &#ref_name #ty_generics {
&**self
}
}
impl #impl_generics #crate_::export::AsMut<#ref_name #ty_generics> for #name #ty_generics {
#[inline]
fn as_mut(&mut self) -> &mut #ref_name #ty_generics {
&mut **self
}
}
}
}
fn build_clone_impl(crate_: &Path, input: &ForeignType) -> TokenStream {
let clone = match &input.clone {
Some(clone) => clone,
None => return quote!(),
};
let name = &input.name;
let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
quote! {
impl #impl_generics #crate_::export::Clone for #name #ty_generics {
#[inline]
fn clone(&self) -> #name #ty_generics {
unsafe {
let ptr = (#clone)(#crate_::ForeignType::as_ptr(self));
#crate_::ForeignType::from_ptr(ptr)
}
}
}
}
}
#[cfg(feature = "std")]
fn build_to_owned_impl(crate_: &Path, input: &ForeignType) -> TokenStream {
let clone = match &input.clone {
Some(clone) => clone,
None => return quote!(),
};
let name = &input.name;
let ref_name = ref_name(input);
let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
quote! {
impl #impl_generics #crate_::export::ToOwned for #ref_name #ty_generics {
type Owned = #name #ty_generics;
#[inline]
fn to_owned(&self) -> #name #ty_generics {
unsafe {
let ptr = (#clone)(#crate_::ForeignTypeRef::as_ptr(self));
#crate_::ForeignType::from_ptr(ptr)
}
}
}
}
}
#[cfg(not(feature = "std"))]
fn build_to_owned_impl(_: &Path, _: &ForeignType) -> TokenStream {
quote!()
}

View File

@ -0,0 +1,15 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use syn::parse_macro_input;
use crate::parse::Input;
mod build;
mod parse;
#[proc_macro]
pub fn foreign_type_impl(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as Input);
build::build(input).into()
}

View File

@ -0,0 +1,140 @@
use syn::parse::{self, Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::token;
use syn::{braced, Attribute, Expr, Generics, Ident, Path, Token, Type, Visibility};
mod kw {
syn::custom_keyword!(Sync);
syn::custom_keyword!(Send);
syn::custom_keyword!(PhantomData);
syn::custom_keyword!(CType);
syn::custom_keyword!(drop);
syn::custom_keyword!(clone);
}
pub struct Input {
pub crate_: Path,
pub types: Vec<ForeignType>,
}
impl Parse for Input {
fn parse(input: ParseStream) -> parse::Result<Input> {
let crate_ = input.parse()?;
let mut types = vec![];
while !input.is_empty() {
types.push(input.parse()?);
}
Ok(Input { crate_, types })
}
}
pub struct ForeignType {
pub attrs: Vec<Attribute>,
pub visibility: Visibility,
pub name: Ident,
pub generics: Generics,
pub oibits: Punctuated<Ident, Token![+]>,
pub phantom_data: Option<Type>,
pub ctype: Type,
pub drop: Expr,
pub clone: Option<Expr>,
}
impl Parse for ForeignType {
fn parse(input: ParseStream) -> parse::Result<ForeignType> {
let attrs = input.call(Attribute::parse_outer)?;
let visibility = input.parse()?;
input.parse::<Token![unsafe]>()?;
input.parse::<Token![type]>()?;
let name = input.parse()?;
let generics = input.parse()?;
let oibits = input.call(parse_oibits)?;
let inner;
braced!(inner in input);
let ctype = inner.call(parse_type::<kw::CType>)?;
let phantom_data = inner.call(parse_phantom_data)?;
let drop = inner.call(parse_fn::<kw::drop>)?;
let clone = inner.call(parse_clone)?;
Ok(ForeignType {
attrs,
visibility,
name,
generics,
oibits,
ctype,
phantom_data,
drop,
clone,
})
}
}
fn parse_oibit(input: ParseStream) -> parse::Result<Ident> {
let lookahead = input.lookahead1();
if lookahead.peek(kw::Sync) || lookahead.peek(kw::Send) {
input.parse()
} else {
Err(lookahead.error())
}
}
fn parse_oibits(input: ParseStream) -> parse::Result<Punctuated<Ident, Token![+]>> {
let mut out = Punctuated::new();
if input.parse::<Option<Token![:]>>()?.is_some() {
loop {
out.push_value(input.call(parse_oibit)?);
if input.peek(token::Brace) {
break;
}
out.push_punct(input.parse()?);
if input.peek(token::Brace) {
break;
}
}
}
Ok(out)
}
fn parse_type<T>(input: ParseStream) -> parse::Result<Type>
where
T: Parse,
{
input.parse::<Token![type]>()?;
input.parse::<T>()?;
input.parse::<Token![=]>()?;
let type_ = input.parse()?;
input.parse::<Token![;]>()?;
Ok(type_)
}
fn parse_phantom_data(input: ParseStream) -> parse::Result<Option<Type>> {
if input.peek(Token![type]) && input.peek2(kw::PhantomData) {
input.call(parse_type::<kw::PhantomData>).map(Some)
} else {
Ok(None)
}
}
fn parse_fn<T>(input: ParseStream) -> parse::Result<Expr>
where
T: Parse,
{
input.parse::<Token![fn]>()?;
input.parse::<T>()?;
input.parse::<Token![=]>()?;
let path = input.parse()?;
input.parse::<Token![;]>()?;
Ok(path)
}
fn parse_clone(input: ParseStream) -> parse::Result<Option<Expr>> {
if input.peek(Token![fn]) && input.peek2(kw::clone) {
input.call(parse_fn::<kw::clone>).map(Some)
} else {
Ok(None)
}
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"6b91ae600fe7b521537096b2269ab7bfd606f8a1fcd97749634dd03ba18daf53","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","src/lib.rs":"77aed289fd36258c273f033e766e572ee05330249083c017d045f0a75662f5df"},"package":"00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"}
{"files":{"Cargo.toml":"096ac915be03aa1eb99b12ad4c5552a50bd550de4d1fb9a52e0799319f98f994","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","src/lib.rs":"60aa483e41abdbdc3b5057e3ff75abd63d0e92263d93a50d8fd739910a0b19e8"},"package":"aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"}

View File

@ -3,16 +3,16 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g. crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "foreign-types-shared"
version = "0.1.1"
version = "0.3.1"
authors = ["Steven Fackler <sfackler@gmail.com>"]
description = "An internal crate used by foreign-types"
license = "MIT/Apache-2.0"

View File

@ -2,17 +2,29 @@
#![no_std]
#![warn(missing_docs)]
#![doc(html_root_url="https://docs.rs/foreign-types-shared/0.1")]
#![doc(html_root_url = "https://docs.rs/foreign-types-shared/0.3")]
use core::cell::UnsafeCell;
use core::marker::PhantomData;
use core::mem;
/// An opaque type used to define `ForeignTypeRef` types.
///
/// A type implementing `ForeignTypeRef` should simply be a newtype wrapper around this type.
pub struct Opaque(UnsafeCell<()>);
pub struct Opaque(PhantomData<UnsafeCell<*mut ()>>);
/// A type implemented by wrappers over foreign types.
pub trait ForeignType: Sized {
///
/// # Safety
///
/// Implementations of `ForeignType` must guarantee the following:
/// - `Self::from_ptr(x).as_ptr() == x`
/// - `Self::from_ptr(x).into_ptr(x) == x`
/// - `Self::from_ptr(x).deref().as_ptr(x) == x`
/// - `Self::from_ptr(x).deref_mut().as_ptr(x) == x`
/// - `Self::from_ptr(x).as_ref().as_ptr(x) == x`
/// - `Self::from_ptr(x).as_mut().as_ptr(x) == x`
pub unsafe trait ForeignType: Sized {
/// The raw C type.
type CType;
@ -20,26 +32,55 @@ pub trait ForeignType: Sized {
type Ref: ForeignTypeRef<CType = Self::CType>;
/// Constructs an instance of this type from its raw type.
///
/// # Safety
///
/// `ptr` must be a valid, owned instance of the native type.
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self;
/// Returns a raw pointer to the wrapped value.
fn as_ptr(&self) -> *mut Self::CType;
/// Consumes the wrapper and returns the raw pointer.
#[inline]
fn into_ptr(self) -> *mut Self::CType {
let ptr = self.as_ptr();
mem::forget(self);
ptr
}
}
/// A trait implemented by types which reference borrowed foreign types.
pub trait ForeignTypeRef: Sized {
///
/// # Safety
///
/// Implementations of `ForeignTypeRef` must guarantee the following:
///
/// - `Self::from_ptr(x).as_ptr() == x`
/// - `Self::from_mut_ptr(x).as_ptr() == x`
pub unsafe trait ForeignTypeRef: Sized {
/// The raw C type.
type CType;
/// Constructs a shared instance of this type from its raw type.
///
/// # Safety
///
/// `ptr` must be a valid, immutable, instance of the type for the `'a` lifetime.
#[inline]
unsafe fn from_ptr<'a>(ptr: *mut Self::CType) -> &'a Self {
debug_assert!(!ptr.is_null());
&*(ptr as *mut _)
}
/// Constructs a mutable reference of this type from its raw type.
///
/// # Safety
///
/// `ptr` must be a valid, unique, instance of the type for the `'a` lifetime.
#[inline]
unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CType) -> &'a mut Self {
debug_assert!(!ptr.is_null());
&mut *(ptr as *mut _)
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"1a667c28f60115423b68fea369255c2dcb129b8dce10f30e0e1da73d05f9adab","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","README.md":"6f3f1429f2724a481df811842f318d0d3b83160ada953fd869d4b685f7fd72e4","src/lib.rs":"4f0a33bf8ec94a57d1b71e50f1af8ca410985e447f69fdc9c680545b03ea4566"},"package":"f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"}
{"files":{"Cargo.toml":"2e1b7838114ee31147555eb858dd837f1f8ac80d53f00c62b2c81c5a0121224d","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","README.md":"6f3f1429f2724a481df811842f318d0d3b83160ada953fd869d4b685f7fd72e4","src/lib.rs":"a0039cfb11b235119b81ba8d31987c19d8fd6e1d23abbde57e67747fdd8f0ad0","tests/test.rs":"7913e5e040b75e5b63bf813d25a0491cb8e9b51857a039cf3b56d7f10fc787d3"},"package":"d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"}

View File

@ -3,7 +3,7 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g. crates.io) dependencies
# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
@ -11,12 +11,20 @@
# will likely look very different (and much more reasonable)
[package]
edition = "2018"
name = "foreign-types"
version = "0.3.2"
version = "0.5.0"
authors = ["Steven Fackler <sfackler@gmail.com>"]
description = "A framework for Rust wrappers over C APIs"
readme = "README.md"
license = "MIT/Apache-2.0"
repository = "https://github.com/sfackler/foreign-types"
[dependencies.foreign-types-macros]
version = "0.2"
[dependencies.foreign-types-shared]
version = "0.1"
version = "0.3"
[features]
default = ["std"]
std = ["foreign-types-macros/std"]

View File

@ -15,6 +15,7 @@
//! ```
//! use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
//! use std::ops::{Deref, DerefMut};
//! use std::ptr::NonNull;
//!
//! mod foo_sys {
//! pub enum FOO {}
@ -30,7 +31,7 @@
//! // from raw C pointers.
//! pub struct FooRef(Opaque);
//!
//! impl ForeignTypeRef for FooRef {
//! unsafe impl ForeignTypeRef for FooRef {
//! type CType = foo_sys::FOO;
//! }
//!
@ -38,24 +39,36 @@
//! //
//! // It dereferences to `FooRef`, so methods that do not require ownership
//! // should be defined there.
//! pub struct Foo(*mut foo_sys::FOO);
//! pub struct Foo(NonNull<foo_sys::FOO>);
//!
//! unsafe impl Sync for FooRef {}
//! unsafe impl Send for FooRef {}
//!
//! unsafe impl Sync for Foo {}
//! unsafe impl Send for Foo {}
//!
//! impl Drop for Foo {
//! fn drop(&mut self) {
//! unsafe { foo_sys::FOO_free(self.0) }
//! unsafe { foo_sys::FOO_free(self.as_ptr()) }
//! }
//! }
//!
//! impl ForeignType for Foo {
//! unsafe impl ForeignType for Foo {
//! type CType = foo_sys::FOO;
//! type Ref = FooRef;
//!
//! unsafe fn from_ptr(ptr: *mut foo_sys::FOO) -> Foo {
//! Foo(ptr)
//! Foo(NonNull::new_unchecked(ptr))
//! }
//!
//! fn as_ptr(&self) -> *mut foo_sys::FOO {
//! self.0
//! self.0.as_ptr()
//! }
//!
//! fn into_ptr(self) -> *mut foo_sys::FOO {
//! let inner = self.as_ptr();
//! ::core::mem::forget(self);
//! inner
//! }
//! }
//!
@ -63,50 +76,60 @@
//! type Target = FooRef;
//!
//! fn deref(&self) -> &FooRef {
//! unsafe { FooRef::from_ptr(self.0) }
//! unsafe { FooRef::from_ptr(self.as_ptr()) }
//! }
//! }
//!
//! impl DerefMut for Foo {
//! fn deref_mut(&mut self) -> &mut FooRef {
//! unsafe { FooRef::from_ptr_mut(self.0) }
//! unsafe { FooRef::from_ptr_mut(self.as_ptr()) }
//! }
//! }
//!
//! // add in Borrow, BorrowMut, AsRef, AsRefMut, Clone, ToOwned...
//! ```
//!
//! The `foreign_type!` macro can generate this boilerplate for you:
//!
//! ```
//! #[macro_use]
//! extern crate foreign_types;
//! use foreign_types::foreign_type;
//!
//! mod foo_sys {
//! pub enum FOO {}
//!
//! extern {
//! pub fn FOO_free(foo: *mut FOO);
//! pub fn FOO_duplicate(foo: *mut FOO) -> *mut FOO; // Optional
//! pub fn FOO_duplicate(foo: *mut FOO) -> *mut FOO; // optional
//! }
//! }
//!
//! foreign_type! {
//! type CType = foo_sys::FOO;
//! fn drop = foo_sys::FOO_free;
//! fn clone = foo_sys::FOO_duplicate; // Optional
//! /// A Foo.
//! pub struct Foo;
//! /// A borrowed Foo.
//! pub struct FooRef;
//! pub unsafe type Foo
//! : Sync + Send // optional
//! {
//! type CType = foo_sys::FOO;
//! fn drop = foo_sys::FOO_free;
//! fn clone = foo_sys::FOO_duplicate; // optional
//! }
//!
//! /// A Foo with generic parameters.
//! pub unsafe type GenericFoo<T> {
//! type CType = foo_sys::FOO;
//! // This type is added as a `PhantomData` field to handle variance
//! // of the parameters. However, it has no impact on trait impls:
//! // `GenericFoo<T>` is always `Clone`, even if `T` is not.
//! type PhantomData = T;
//! fn drop = foo_sys::FOO_free;
//! fn clone = foo_sys::FOO_duplicate;
//! }
//! }
//!
//! # fn main() {}
//! ```
//!
//! If `fn clone` is specified, then it must take `CType` as an argument and return a copy of it as `CType`.
//! It will be used to implement `ToOwned` and `Clone`.
//!
//! `#[derive(…)] is permitted before the lines with `pub struct`.
//! `#[doc(hidden)]` before the `type CType` line will hide the `foreign_type!` implementations from documentation.
//! It will be used to implement `Clone`, and if the `std` Cargo feature is enabled, `ToOwned`.
//!
//! Say we then have a separate type in our C API that contains a `FOO`:
//!
@ -128,10 +151,7 @@
//! modify the `FOO`, so we'll define a pair of accessor methods, one immutable and one mutable:
//!
//! ```
//! #[macro_use]
//! extern crate foreign_types;
//!
//! use foreign_types::ForeignTypeRef;
//! use foreign_types::{ForeignTypeRef, foreign_type};
//!
//! mod foo_sys {
//! pub enum FOO {}
@ -145,22 +165,17 @@
//! }
//!
//! foreign_type! {
//! #[doc(hidden)]
//! type CType = foo_sys::FOO;
//! fn drop = foo_sys::FOO_free;
//! /// A Foo.
//! pub struct Foo;
//! /// A borrowed Foo.
//! pub struct FooRef;
//! }
//! pub unsafe type Foo: Sync + Send {
//! type CType = foo_sys::FOO;
//! fn drop = foo_sys::FOO_free;
//! }
//!
//! foreign_type! {
//! type CType = foo_sys::BAR;
//! fn drop = foo_sys::BAR_free;
//! /// A Foo.
//! pub struct Bar;
//! /// A borrowed Bar.
//! pub struct BarRef;
//! /// A Bar.
//! pub unsafe type Bar: Sync + Send {
//! type CType = foo_sys::BAR;
//! fn drop = foo_sys::BAR_free;
//! }
//! }
//!
//! impl BarRef {
@ -177,130 +192,59 @@
//! ```
#![no_std]
#![warn(missing_docs)]
#![doc(html_root_url="https://docs.rs/foreign-types/0.3")]
extern crate foreign_types_shared;
#![doc(html_root_url = "https://docs.rs/foreign-types/0.5")]
#[cfg(feature = "std")]
extern crate std;
#[doc(hidden)]
pub use foreign_types_macros::foreign_type_impl;
#[doc(inline)]
pub use foreign_types_shared::*;
pub use foreign_types_shared::{ForeignType, ForeignTypeRef, Opaque};
#[doc(hidden)]
pub mod export {
pub use core::borrow::{Borrow, BorrowMut};
pub use core::clone::Clone;
pub use core::convert::{AsMut, AsRef};
pub use core::marker::{PhantomData, Send, Sync};
pub use core::ops::{Deref, DerefMut, Drop};
pub use core::ptr::NonNull;
#[cfg(feature = "std")]
pub use std::borrow::ToOwned;
}
/// A macro to easily define wrappers for foreign types.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate foreign_types;
/// use foreign_types::foreign_type;
///
/// # mod openssl_sys { pub type SSL = (); pub unsafe fn SSL_free(_: *mut SSL) {} pub unsafe fn SSL_dup(x: *mut SSL) -> *mut SSL {x} }
/// # mod foo_sys { pub type THING = (); pub unsafe fn THING_free(_: *mut THING) {} }
/// foreign_type! {
/// type CType = openssl_sys::SSL;
/// fn drop = openssl_sys::SSL_free;
/// fn clone = openssl_sys::SSL_dup;
/// /// Documentation for the owned type.
/// pub struct Ssl;
/// /// Documentation for the borrowed type.
/// pub struct SslRef;
/// pub unsafe type Ssl: Sync + Send {
/// type CType = openssl_sys::SSL;
/// fn drop = openssl_sys::SSL_free;
/// fn clone = openssl_sys::SSL_dup;
/// }
///
/// /// This type immutably borrows other data and has a limited lifetime!
/// pub unsafe type Thing<'a>: Send {
/// type CType = foo_sys::THING;
/// type PhantomData = &'a ();
/// fn drop = foo_sys::THING_free;
/// }
/// }
///
/// # fn main() {}
/// ```
#[macro_export]
#[macro_export(local_inner_macros)]
macro_rules! foreign_type {
(
$(#[$impl_attr:meta])*
type CType = $ctype:ty;
fn drop = $drop:expr;
$(fn clone = $clone:expr;)*
$(#[$owned_attr:meta])*
pub struct $owned:ident;
$(#[$borrowed_attr:meta])*
pub struct $borrowed:ident;
) => {
$(#[$owned_attr])*
pub struct $owned(*mut $ctype);
$(#[$impl_attr])*
impl $crate::ForeignType for $owned {
type CType = $ctype;
type Ref = $borrowed;
#[inline]
unsafe fn from_ptr(ptr: *mut $ctype) -> $owned {
$owned(ptr)
}
#[inline]
fn as_ptr(&self) -> *mut $ctype {
self.0
}
}
impl Drop for $owned {
#[inline]
fn drop(&mut self) {
unsafe { $drop(self.0) }
}
}
$(
impl Clone for $owned {
#[inline]
fn clone(&self) -> $owned {
unsafe {
let handle: *mut $ctype = $clone(self.0);
$crate::ForeignType::from_ptr(handle)
}
}
}
impl ::std::borrow::ToOwned for $borrowed {
type Owned = $owned;
#[inline]
fn to_owned(&self) -> $owned {
unsafe {
let handle: *mut $ctype = $clone($crate::ForeignTypeRef::as_ptr(self));
$crate::ForeignType::from_ptr(handle)
}
}
}
)*
impl ::std::ops::Deref for $owned {
type Target = $borrowed;
#[inline]
fn deref(&self) -> &$borrowed {
unsafe { $crate::ForeignTypeRef::from_ptr(self.0) }
}
}
impl ::std::ops::DerefMut for $owned {
#[inline]
fn deref_mut(&mut self) -> &mut $borrowed {
unsafe { $crate::ForeignTypeRef::from_ptr_mut(self.0) }
}
}
impl ::std::borrow::Borrow<$borrowed> for $owned {
#[inline]
fn borrow(&self) -> &$borrowed {
&**self
}
}
impl ::std::convert::AsRef<$borrowed> for $owned {
#[inline]
fn as_ref(&self) -> &$borrowed {
&**self
}
}
$(#[$borrowed_attr])*
pub struct $borrowed($crate::Opaque);
$(#[$impl_attr])*
impl $crate::ForeignTypeRef for $borrowed {
type CType = $ctype;
}
}
($($t:tt)*) => {
$crate::foreign_type_impl!($crate $($t)*);
};
}

View File

@ -0,0 +1,22 @@
use foreign_types::foreign_type;
mod foo_sys {
pub enum FOO {}
pub unsafe extern "C" fn foo_drop(_: *mut FOO) {}
pub unsafe extern "C" fn foo_clone(ptr: *mut FOO) -> *mut FOO { ptr }
}
foreign_type! {
pub unsafe type Foo<'a, T>: Sync + Send {
type CType = foo_sys::FOO;
type PhantomData = &'a T;
fn drop = foo_sys::foo_drop;
fn clone = foo_sys::foo_clone;
}
pub unsafe type Foo2 {
type CType = foo_sys::FOO;
fn drop = foo_sys::foo_drop;
}
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"5ec80402fb950b3e70b291c64a49275dd951221b71ee74f8be5a16a74d42d296","src/device.rs":"1f44d08d50fc59d55bd3f92308e4965bde9134e7f5daa03594e122f7cdb1dfa2","src/lib.rs":"0f77c21a5770b54affa146e5f4c15abcb83599de551226d336ee48ec5185f866","src/types.rs":"8c6acec203faa11856076193835f6d9a1924469682e1fdf11a0325936a1255ee"},"package":"54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5"}
{"files":{"Cargo.toml":"ce92a2d32d4b2e50d617595e689b6bca736b7792280480c4057eaebef15bf325","README.md":"5a96b135d18e172f090bd6147830ab3a1b5cefac5f02be28f06cf88eea61b64f","src/device.rs":"8173609d5fb700f8b82d6335729c592ff62c306b12894a9bab9da45a47810e4a","src/lib.rs":"0f77c21a5770b54affa146e5f4c15abcb83599de551226d336ee48ec5185f866","src/types.rs":"aa861f891a63c232441c5a9fe5fed61cac2d62780108c01ebe6cb64a8547b4e2"},"package":"98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"}

View File

@ -3,24 +3,36 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "gpu-alloc-types"
version = "0.2.0"
version = "0.3.0"
authors = ["Zakarum <zakarumych@ya.ru>"]
description = "Core types of gpu-alloc crate"
homepage = "https://github.com/zakarumych/gpu-alloc"
documentation = "https://docs.rs/gpu-alloc-types/0.2.0"
keywords = ["gpu", "vulkan", "allocation", "no-std"]
documentation = "https://docs.rs/gpu-alloc-types"
readme = "README.md"
keywords = [
"gpu",
"vulkan",
"allocation",
"no-std",
]
categories = [
"graphics",
"memory-management",
"no-std",
"game-development",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/zakarumych/gpu-alloc"
[dependencies.bitflags]
version = "1.2"
version = "2.0"
default-features = false

View File

@ -0,0 +1,51 @@
# gpu-alloc
[![crates](https://img.shields.io/crates/v/gpu-alloc.svg?style=for-the-badge&label=gpu-alloc)](https://crates.io/crates/gpu-alloc)
[![docs](https://img.shields.io/badge/docs.rs-gpu--alloc-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white)](https://docs.rs/gpu-alloc)
[![actions](https://img.shields.io/github/workflow/status/zakarumych/gpu-alloc/Rust/main?style=for-the-badge)](https://github.com/zakarumych/gpu-alloc/actions?query=workflow%3ARust)
[![MIT/Apache](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](COPYING)
![loc](https://img.shields.io/tokei/lines/github/zakarumych/gpu-alloc?style=for-the-badge)
Implementation agnostic memory allocator for Vulkan like APIs.
This crate is intended to be used as part of safe API implementations.\
Use with caution. There are unsafe functions all over the place.
## Usage
Start with fetching `DeviceProperties` from `gpu-alloc-<backend>` crate for the backend of choice.\
Then create `GpuAllocator` instance and use it for all device memory allocations.\
`GpuAllocator` will take care for all necessary bookkeeping like memory object count limit,
heap budget and memory mapping.
#### Backends implementations
Backend supporting crates should not depend on this crate.\
Instead they should depend on `gpu-alloc-types` which is much more stable,
allowing to upgrade `gpu-alloc` version without `gpu-alloc-<backend>` upgrade.
Supported Rust Versions
The minimum supported version is 1.40.
The current version is not guaranteed to build on Rust versions earlier than the minimum supported version.
`gpu-alloc-erupt` crate requires version 1.48 or higher due to dependency on `erupt` crate.
## License
Licensed under either of
* Apache License, Version 2.0, ([license/APACHE](license/APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([license/MIT](license/MIT) or http://opensource.org/licenses/MIT)
at your option.
## Contributions
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
## Donate
[![Become a patron](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/zakarum)

View File

@ -67,6 +67,7 @@ pub struct DeviceProperties<'a> {
bitflags::bitflags! {
/// Allocation flags
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct AllocationFlags : u8 {
/// Specifies that the memory can be used for buffers created
/// with flag that allows fetching device address.
@ -84,7 +85,7 @@ pub trait MemoryDevice<M> {
/// # Safety
///
/// `memory_type` must be valid index for memory type associated with this device.
/// Retreiving this information is implementation specific.
/// Retrieving this information is implementation specific.
///
/// `flags` must be supported by the device.
unsafe fn allocate_memory(

View File

@ -1,6 +1,7 @@
bitflags::bitflags! {
/// Memory properties type.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct MemoryPropertyFlags: u8 {
/// This flag is set for device-local memory types.
/// Device-local memory is situated "close" to the GPU cores
@ -42,7 +43,7 @@ pub struct MemoryType {
/// Heap index of the memory type.
pub heap: u32,
/// Propety flags of the memory type.
/// Property flags of the memory type.
pub props: MemoryPropertyFlags,
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"d444caa50cc5b4e0ee201da5347df73c6e77d3eedaae9e69d007c24dd0bb7bfa","src/allocator.rs":"c06b84e062859e1dcd21fa5cd71c8faafcca325b53dcc7b2fee3df945163e820","src/block.rs":"6efc369712e3d880a0d16ab1ef18062a88fefae9bf0a4e626de301cbb1b962ee","src/buddy.rs":"f8eacc183f2ee66faba05dec6f33659afa797e765326c96be4a8bafa651c0e47","src/config.rs":"49bb14c27713c6b1c0c91c094b0f00be22bd26efa660ff979fb1ee1193e9d70e","src/error.rs":"11337a66fc32f3423a1355ffd597d2c7ea28c2b7ce07d707fd5905c330edba08","src/freelist.rs":"3fbbcb96e307e0e021b38df6fe04d129e5d954fcd5a0144e388371442ef20916","src/heap.rs":"03f7c623a0389263073ab48797a191ca06c5611006df7b79c9dc8615c130f495","src/lib.rs":"78800455337d231af24814d84f4e5eb61c5181b12daec06fdcee2d2a75ccb221","src/slab.rs":"2df136b7e0a85eec8a198c7f807678d3a2043c46233e7ec63cd2de72fe562477","src/usage.rs":"0e4788c437718807cdd0b88301228cc27a6b8398313a91e1b70c5f2ab04dcbfb","src/util.rs":"31a496ee3407eb6b0dea255e30e154d805a0d08d777be9c06bdf56d1135bf950"},"package":"7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d"}
{"files":{"Cargo.toml":"3647062a9589eedcc361f51f1e1f0852ae6be3c028d0dc8f8d3c0c944bbca61e","README.md":"5a96b135d18e172f090bd6147830ab3a1b5cefac5f02be28f06cf88eea61b64f","src/allocator.rs":"28f20bbfc3866b4eb94a025027925268178921393f5ab8eb5febad1acf94dce8","src/block.rs":"3553343eb171e7ef8b771a1582489cbbbe22b3a1aca4d54b9ff0174fd30bf0da","src/buddy.rs":"253df5f689b643cf97cfd27be6512ea84b84d3c2097a35f3f2d73f537ab353b3","src/config.rs":"1851264db7576f92f3b455e4667339e1c48b7f1b88f8fae7be95c6a9badde455","src/error.rs":"50e30bccc4ba3b23d99298a65155eec45f7d91b66773e828460907ebdcb8ee41","src/freelist.rs":"92c9241d899f3e92a70b0eb5af0b557a3a76aa14c4a6d23876c3ed7857b5f15b","src/heap.rs":"347c25a8560d39d1abb807fb5c34a6a51d4786c0be24a92293f9c8217bace340","src/lib.rs":"07077fb465fb471b39db99bb0311082133d1c2044c2e192d20f7bbb9e743dd0b","src/slab.rs":"6a2b818087850bd5615b085d912490dbd46bbca0df28daa86932505b3983c64a","src/usage.rs":"99009f2ff532904de3ef66520336cd25bd1b795afcb0158385e78a5908f8308f","src/util.rs":"ce3fd7a278eb4d4bd030d4db5495313f56dc91b0765c394f88d126f11c2b4e75"},"package":"fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"}

View File

@ -12,22 +12,33 @@
[package]
edition = "2018"
name = "gpu-alloc"
version = "0.5.3"
version = "0.6.0"
authors = ["Zakarum <zakarumych@ya.ru>"]
description = "Implementation agnostic memory allocator for Vulkan like APIs"
homepage = "https://github.com/zakarumych/gpu-alloc"
documentation = "https://docs.rs/gpu-alloc-types"
readme = "../README.md"
keywords = ["gpu", "vulkan", "allocation", "no-std"]
categories = ["graphics", "memory-management", "no-std", "game-development"]
readme = "README.md"
keywords = [
"gpu",
"vulkan",
"allocation",
"no-std",
]
categories = [
"graphics",
"memory-management",
"no-std",
"game-development",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/zakarumych/gpu-alloc"
[dependencies.bitflags]
version = "1.2"
version = "2.0"
default-features = false
[dependencies.gpu-alloc-types]
version = "0.2"
version = "=0.3.0"
[dependencies.serde]
version = "1.0"
@ -43,4 +54,8 @@ default-features = false
[features]
default = ["std"]
serde = [
"dep:serde",
"bitflags/serde",
]
std = []

51
third_party/rust/gpu-alloc/README.md vendored Normal file
View File

@ -0,0 +1,51 @@
# gpu-alloc
[![crates](https://img.shields.io/crates/v/gpu-alloc.svg?style=for-the-badge&label=gpu-alloc)](https://crates.io/crates/gpu-alloc)
[![docs](https://img.shields.io/badge/docs.rs-gpu--alloc-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white)](https://docs.rs/gpu-alloc)
[![actions](https://img.shields.io/github/workflow/status/zakarumych/gpu-alloc/Rust/main?style=for-the-badge)](https://github.com/zakarumych/gpu-alloc/actions?query=workflow%3ARust)
[![MIT/Apache](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](COPYING)
![loc](https://img.shields.io/tokei/lines/github/zakarumych/gpu-alloc?style=for-the-badge)
Implementation agnostic memory allocator for Vulkan like APIs.
This crate is intended to be used as part of safe API implementations.\
Use with caution. There are unsafe functions all over the place.
## Usage
Start with fetching `DeviceProperties` from `gpu-alloc-<backend>` crate for the backend of choice.\
Then create `GpuAllocator` instance and use it for all device memory allocations.\
`GpuAllocator` will take care for all necessary bookkeeping like memory object count limit,
heap budget and memory mapping.
#### Backends implementations
Backend supporting crates should not depend on this crate.\
Instead they should depend on `gpu-alloc-types` which is much more stable,
allowing to upgrade `gpu-alloc` version without `gpu-alloc-<backend>` upgrade.
Supported Rust Versions
The minimum supported version is 1.40.
The current version is not guaranteed to build on Rust versions earlier than the minimum supported version.
`gpu-alloc-erupt` crate requires version 1.48 or higher due to dependency on `erupt` crate.
## License
Licensed under either of
* Apache License, Version 2.0, ([license/APACHE](license/APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([license/MIT](license/MIT) or http://opensource.org/licenses/MIT)
at your option.
## Contributions
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
## Donate
[![Become a patron](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/zakarum)

File diff suppressed because it is too large Load Diff

View File

@ -1,327 +1,327 @@
use {
crate::{align_down, align_up, error::MapError},
alloc::sync::Arc,
core::{
convert::TryFrom as _,
ptr::{copy_nonoverlapping, NonNull},
// sync::atomic::{AtomicU8, Ordering::*},
},
gpu_alloc_types::{MappedMemoryRange, MemoryDevice, MemoryPropertyFlags},
};
#[derive(Debug)]
struct Relevant;
impl Drop for Relevant {
fn drop(&mut self) {
report_error_on_drop!("Memory block wasn't deallocated");
}
}
/// Memory block allocated by `GpuAllocator`.
#[derive(Debug)]
pub struct MemoryBlock<M> {
memory_type: u32,
props: MemoryPropertyFlags,
offset: u64,
size: u64,
atom_mask: u64,
mapped: bool,
flavor: MemoryBlockFlavor<M>,
relevant: Relevant,
}
impl<M> MemoryBlock<M> {
pub(crate) fn new(
memory_type: u32,
props: MemoryPropertyFlags,
offset: u64,
size: u64,
atom_mask: u64,
flavor: MemoryBlockFlavor<M>,
) -> Self {
isize::try_from(atom_mask).expect("`atom_mask` is too large");
MemoryBlock {
memory_type,
props,
offset,
size,
atom_mask,
flavor,
mapped: false,
relevant: Relevant,
}
}
pub(crate) fn deallocate(self) -> MemoryBlockFlavor<M> {
core::mem::forget(self.relevant);
self.flavor
}
}
unsafe impl<M> Sync for MemoryBlock<M> where M: Sync {}
unsafe impl<M> Send for MemoryBlock<M> where M: Send {}
#[derive(Debug)]
pub(crate) enum MemoryBlockFlavor<M> {
Dedicated {
memory: M,
},
Buddy {
chunk: usize,
index: usize,
ptr: Option<NonNull<u8>>,
memory: Arc<M>,
},
FreeList {
chunk: u64,
ptr: Option<NonNull<u8>>,
memory: Arc<M>,
},
}
impl<M> MemoryBlock<M> {
/// Returns reference to parent memory object.
#[inline(always)]
pub fn memory(&self) -> &M {
match &self.flavor {
MemoryBlockFlavor::Dedicated { memory } => memory,
MemoryBlockFlavor::Buddy { memory, .. } => &**memory,
MemoryBlockFlavor::FreeList { memory, .. } => &**memory,
}
}
/// Returns offset in bytes from start of memory object to start of this block.
#[inline(always)]
pub fn offset(&self) -> u64 {
self.offset
}
/// Returns size of this memory block.
#[inline(always)]
pub fn size(&self) -> u64 {
self.size
}
/// Returns memory property flags for parent memory object.
#[inline(always)]
pub fn props(&self) -> MemoryPropertyFlags {
self.props
}
/// Returns index of type of parent memory object.
#[inline(always)]
pub fn memory_type(&self) -> u32 {
self.memory_type
}
/// Returns pointer to mapped memory range of this block.
/// This blocks becomes mapped.
///
/// The user of returned pointer must guarantee that any previously submitted command that writes to this range has completed
/// before the host reads from or writes to that range,
/// and that any previously submitted command that reads from that range has completed
/// before the host writes to that region.
/// If the device memory was allocated without the `HOST_COHERENT` property flag set,
/// these guarantees must be made for an extended range:
/// the user must round down the start of the range to the nearest multiple of `non_coherent_atom_size`,
/// and round the end of the range up to the nearest multiple of `non_coherent_atom_size`.
///
/// # Panics
///
/// This function panics if block is currently mapped.
///
/// # Safety
///
/// `block` must have been allocated from specified `device`.
#[inline(always)]
pub unsafe fn map(
&mut self,
device: &impl MemoryDevice<M>,
offset: u64,
size: usize,
) -> Result<NonNull<u8>, MapError> {
let size_u64 = u64::try_from(size).expect("`size` doesn't fit device address space");
assert!(offset < self.size, "`offset` is out of memory block bounds");
assert!(
size_u64 <= self.size - offset,
"`offset + size` is out of memory block bounds"
);
let ptr = match &mut self.flavor {
MemoryBlockFlavor::Dedicated { memory } => {
let end = align_up(offset + size_u64, self.atom_mask)
.expect("mapping end doesn't fit device address space");
let aligned_offset = align_down(offset, self.atom_mask);
if !acquire_mapping(&mut self.mapped) {
return Err(MapError::AlreadyMapped);
}
let result =
device.map_memory(memory, self.offset + aligned_offset, end - aligned_offset);
match result {
// the overflow is checked in `Self::new()`
Ok(ptr) => {
let ptr_offset = (offset - aligned_offset) as isize;
ptr.as_ptr().offset(ptr_offset)
}
Err(err) => {
release_mapping(&mut self.mapped);
return Err(err.into());
}
}
}
MemoryBlockFlavor::FreeList { ptr: Some(ptr), .. }
| MemoryBlockFlavor::Buddy { ptr: Some(ptr), .. } => {
if !acquire_mapping(&mut self.mapped) {
return Err(MapError::AlreadyMapped);
}
let offset_isize = isize::try_from(offset)
.expect("Buddy and linear block should fit host address space");
ptr.as_ptr().offset(offset_isize)
}
_ => return Err(MapError::NonHostVisible),
};
Ok(NonNull::new_unchecked(ptr))
}
/// Unmaps memory range of this block that was previously mapped with `Block::map`.
/// This block becomes unmapped.
///
/// # Panics
///
/// This function panics if this block is not currently mapped.
///
/// # Safety
///
/// `block` must have been allocated from specified `device`.
#[inline(always)]
pub unsafe fn unmap(&mut self, device: &impl MemoryDevice<M>) -> bool {
if !release_mapping(&mut self.mapped) {
return false;
}
match &mut self.flavor {
MemoryBlockFlavor::Dedicated { memory } => {
device.unmap_memory(memory);
}
MemoryBlockFlavor::Buddy { .. } => {}
MemoryBlockFlavor::FreeList { .. } => {}
}
true
}
/// Transiently maps block memory range and copies specified data
/// to the mapped memory range.
///
/// # Panics
///
/// This function panics if block is currently mapped.
///
/// # Safety
///
/// `block` must have been allocated from specified `device`.
/// The caller must guarantee that any previously submitted command that reads or writes to this range has completed.
#[inline(always)]
pub unsafe fn write_bytes(
&mut self,
device: &impl MemoryDevice<M>,
offset: u64,
data: &[u8],
) -> Result<(), MapError> {
let size = data.len();
let ptr = self.map(device, offset, size)?;
copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), size);
let result = if !self.coherent() {
let aligned_offset = align_down(offset, self.atom_mask);
let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap();
device.flush_memory_ranges(&[MappedMemoryRange {
memory: self.memory(),
offset: self.offset + aligned_offset,
size: end - aligned_offset,
}])
} else {
Ok(())
};
self.unmap(device);
result.map_err(Into::into)
}
/// Transiently maps block memory range and copies specified data
/// from the mapped memory range.
///
/// # Panics
///
/// This function panics if block is currently mapped.
///
/// # Safety
///
/// `block` must have been allocated from specified `device`.
/// The caller must guarantee that any previously submitted command that reads to this range has completed.
#[inline(always)]
pub unsafe fn read_bytes(
&mut self,
device: &impl MemoryDevice<M>,
offset: u64,
data: &mut [u8],
) -> Result<(), MapError> {
#[cfg(feature = "tracing")]
{
if !self.cached() {
tracing::warn!("Reading from non-cached memory may be slow. Consider allocating HOST_CACHED memory block for host reads.")
}
}
let size = data.len();
let ptr = self.map(device, offset, size)?;
let result = if !self.coherent() {
let aligned_offset = align_down(offset, self.atom_mask);
let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap();
device.invalidate_memory_ranges(&[MappedMemoryRange {
memory: self.memory(),
offset: self.offset + aligned_offset,
size: end - aligned_offset,
}])
} else {
Ok(())
};
if result.is_ok() {
copy_nonoverlapping(ptr.as_ptr(), data.as_mut_ptr(), size);
}
self.unmap(device);
result.map_err(Into::into)
}
fn coherent(&self) -> bool {
self.props.contains(MemoryPropertyFlags::HOST_COHERENT)
}
#[cfg(feature = "tracing")]
fn cached(&self) -> bool {
self.props.contains(MemoryPropertyFlags::HOST_CACHED)
}
}
fn acquire_mapping(mapped: &mut bool) -> bool {
if *mapped {
false
} else {
*mapped = true;
true
}
}
fn release_mapping(mapped: &mut bool) -> bool {
if *mapped {
*mapped = false;
true
} else {
false
}
}
use {
crate::{align_down, align_up, error::MapError},
alloc::sync::Arc,
core::{
convert::TryFrom as _,
ptr::{copy_nonoverlapping, NonNull},
// sync::atomic::{AtomicU8, Ordering::*},
},
gpu_alloc_types::{MappedMemoryRange, MemoryDevice, MemoryPropertyFlags},
};
#[derive(Debug)]
struct Relevant;
impl Drop for Relevant {
fn drop(&mut self) {
report_error_on_drop!("Memory block wasn't deallocated");
}
}
/// Memory block allocated by `GpuAllocator`.
#[derive(Debug)]
pub struct MemoryBlock<M> {
memory_type: u32,
props: MemoryPropertyFlags,
offset: u64,
size: u64,
atom_mask: u64,
mapped: bool,
flavor: MemoryBlockFlavor<M>,
relevant: Relevant,
}
impl<M> MemoryBlock<M> {
pub(crate) fn new(
memory_type: u32,
props: MemoryPropertyFlags,
offset: u64,
size: u64,
atom_mask: u64,
flavor: MemoryBlockFlavor<M>,
) -> Self {
isize::try_from(atom_mask).expect("`atom_mask` is too large");
MemoryBlock {
memory_type,
props,
offset,
size,
atom_mask,
flavor,
mapped: false,
relevant: Relevant,
}
}
pub(crate) fn deallocate(self) -> MemoryBlockFlavor<M> {
core::mem::forget(self.relevant);
self.flavor
}
}
unsafe impl<M> Sync for MemoryBlock<M> where M: Sync {}
unsafe impl<M> Send for MemoryBlock<M> where M: Send {}
#[derive(Debug)]
pub(crate) enum MemoryBlockFlavor<M> {
Dedicated {
memory: M,
},
Buddy {
chunk: usize,
index: usize,
ptr: Option<NonNull<u8>>,
memory: Arc<M>,
},
FreeList {
chunk: u64,
ptr: Option<NonNull<u8>>,
memory: Arc<M>,
},
}
impl<M> MemoryBlock<M> {
/// Returns reference to parent memory object.
#[inline(always)]
pub fn memory(&self) -> &M {
match &self.flavor {
MemoryBlockFlavor::Dedicated { memory } => memory,
MemoryBlockFlavor::Buddy { memory, .. } => memory,
MemoryBlockFlavor::FreeList { memory, .. } => memory,
}
}
/// Returns offset in bytes from start of memory object to start of this block.
#[inline(always)]
pub fn offset(&self) -> u64 {
self.offset
}
/// Returns size of this memory block.
#[inline(always)]
pub fn size(&self) -> u64 {
self.size
}
/// Returns memory property flags for parent memory object.
#[inline(always)]
pub fn props(&self) -> MemoryPropertyFlags {
self.props
}
/// Returns index of type of parent memory object.
#[inline(always)]
pub fn memory_type(&self) -> u32 {
self.memory_type
}
/// Returns pointer to mapped memory range of this block.
/// This blocks becomes mapped.
///
/// The user of returned pointer must guarantee that any previously submitted command that writes to this range has completed
/// before the host reads from or writes to that range,
/// and that any previously submitted command that reads from that range has completed
/// before the host writes to that region.
/// If the device memory was allocated without the `HOST_COHERENT` property flag set,
/// these guarantees must be made for an extended range:
/// the user must round down the start of the range to the nearest multiple of `non_coherent_atom_size`,
/// and round the end of the range up to the nearest multiple of `non_coherent_atom_size`.
///
/// # Panics
///
/// This function panics if block is currently mapped.
///
/// # Safety
///
/// `block` must have been allocated from specified `device`.
#[inline(always)]
pub unsafe fn map(
&mut self,
device: &impl MemoryDevice<M>,
offset: u64,
size: usize,
) -> Result<NonNull<u8>, MapError> {
let size_u64 = u64::try_from(size).expect("`size` doesn't fit device address space");
assert!(offset < self.size, "`offset` is out of memory block bounds");
assert!(
size_u64 <= self.size - offset,
"`offset + size` is out of memory block bounds"
);
let ptr = match &mut self.flavor {
MemoryBlockFlavor::Dedicated { memory } => {
let end = align_up(offset + size_u64, self.atom_mask)
.expect("mapping end doesn't fit device address space");
let aligned_offset = align_down(offset, self.atom_mask);
if !acquire_mapping(&mut self.mapped) {
return Err(MapError::AlreadyMapped);
}
let result =
device.map_memory(memory, self.offset + aligned_offset, end - aligned_offset);
match result {
// the overflow is checked in `Self::new()`
Ok(ptr) => {
let ptr_offset = (offset - aligned_offset) as isize;
ptr.as_ptr().offset(ptr_offset)
}
Err(err) => {
release_mapping(&mut self.mapped);
return Err(err.into());
}
}
}
MemoryBlockFlavor::FreeList { ptr: Some(ptr), .. }
| MemoryBlockFlavor::Buddy { ptr: Some(ptr), .. } => {
if !acquire_mapping(&mut self.mapped) {
return Err(MapError::AlreadyMapped);
}
let offset_isize = isize::try_from(offset)
.expect("Buddy and linear block should fit host address space");
ptr.as_ptr().offset(offset_isize)
}
_ => return Err(MapError::NonHostVisible),
};
Ok(NonNull::new_unchecked(ptr))
}
/// Unmaps memory range of this block that was previously mapped with `Block::map`.
/// This block becomes unmapped.
///
/// # Panics
///
/// This function panics if this block is not currently mapped.
///
/// # Safety
///
/// `block` must have been allocated from specified `device`.
#[inline(always)]
pub unsafe fn unmap(&mut self, device: &impl MemoryDevice<M>) -> bool {
if !release_mapping(&mut self.mapped) {
return false;
}
match &mut self.flavor {
MemoryBlockFlavor::Dedicated { memory } => {
device.unmap_memory(memory);
}
MemoryBlockFlavor::Buddy { .. } => {}
MemoryBlockFlavor::FreeList { .. } => {}
}
true
}
/// Transiently maps block memory range and copies specified data
/// to the mapped memory range.
///
/// # Panics
///
/// This function panics if block is currently mapped.
///
/// # Safety
///
/// `block` must have been allocated from specified `device`.
/// The caller must guarantee that any previously submitted command that reads or writes to this range has completed.
#[inline(always)]
pub unsafe fn write_bytes(
&mut self,
device: &impl MemoryDevice<M>,
offset: u64,
data: &[u8],
) -> Result<(), MapError> {
let size = data.len();
let ptr = self.map(device, offset, size)?;
copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), size);
let result = if !self.coherent() {
let aligned_offset = align_down(offset, self.atom_mask);
let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap();
device.flush_memory_ranges(&[MappedMemoryRange {
memory: self.memory(),
offset: self.offset + aligned_offset,
size: end - aligned_offset,
}])
} else {
Ok(())
};
self.unmap(device);
result.map_err(Into::into)
}
/// Transiently maps block memory range and copies specified data
/// from the mapped memory range.
///
/// # Panics
///
/// This function panics if block is currently mapped.
///
/// # Safety
///
/// `block` must have been allocated from specified `device`.
/// The caller must guarantee that any previously submitted command that reads to this range has completed.
#[inline(always)]
pub unsafe fn read_bytes(
&mut self,
device: &impl MemoryDevice<M>,
offset: u64,
data: &mut [u8],
) -> Result<(), MapError> {
#[cfg(feature = "tracing")]
{
if !self.cached() {
tracing::warn!("Reading from non-cached memory may be slow. Consider allocating HOST_CACHED memory block for host reads.")
}
}
let size = data.len();
let ptr = self.map(device, offset, size)?;
let result = if !self.coherent() {
let aligned_offset = align_down(offset, self.atom_mask);
let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap();
device.invalidate_memory_ranges(&[MappedMemoryRange {
memory: self.memory(),
offset: self.offset + aligned_offset,
size: end - aligned_offset,
}])
} else {
Ok(())
};
if result.is_ok() {
copy_nonoverlapping(ptr.as_ptr(), data.as_mut_ptr(), size);
}
self.unmap(device);
result.map_err(Into::into)
}
fn coherent(&self) -> bool {
self.props.contains(MemoryPropertyFlags::HOST_COHERENT)
}
#[cfg(feature = "tracing")]
fn cached(&self) -> bool {
self.props.contains(MemoryPropertyFlags::HOST_CACHED)
}
}
fn acquire_mapping(mapped: &mut bool) -> bool {
if *mapped {
false
} else {
*mapped = true;
true
}
}
fn release_mapping(mapped: &mut bool) -> bool {
if *mapped {
*mapped = false;
true
} else {
false
}
}

View File

@ -1,458 +1,460 @@
use {
crate::{
align_up, error::AllocationError, heap::Heap, slab::Slab, unreachable_unchecked,
util::try_arc_unwrap, MemoryBounds,
},
alloc::{sync::Arc, vec::Vec},
core::{convert::TryFrom as _, mem::replace, ptr::NonNull},
gpu_alloc_types::{AllocationFlags, DeviceMapError, MemoryDevice, MemoryPropertyFlags},
};
#[derive(Debug)]
pub(crate) struct BuddyBlock<M> {
pub memory: Arc<M>,
pub ptr: Option<NonNull<u8>>,
pub offset: u64,
pub size: u64,
pub chunk: usize,
pub index: usize,
}
unsafe impl<M> Sync for BuddyBlock<M> where M: Sync {}
unsafe impl<M> Send for BuddyBlock<M> where M: Send {}
#[derive(Clone, Copy, Debug)]
enum PairState {
Exhausted,
Ready {
ready: Side,
next: usize,
prev: usize,
},
}
impl PairState {
unsafe fn replace_next(&mut self, value: usize) -> usize {
match self {
PairState::Exhausted => unreachable_unchecked(),
PairState::Ready { next, .. } => replace(next, value),
}
}
unsafe fn replace_prev(&mut self, value: usize) -> usize {
match self {
PairState::Exhausted => unreachable_unchecked(),
PairState::Ready { prev, .. } => replace(prev, value),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Side {
Left,
Right,
}
use Side::*;
#[derive(Debug)]
struct PairEntry {
state: PairState,
chunk: usize,
offset: u64,
parent: Option<usize>,
}
struct SizeBlockEntry {
chunk: usize,
offset: u64,
index: usize,
}
#[derive(Debug)]
struct Size {
next_ready: usize,
pairs: Slab<PairEntry>,
}
#[derive(Debug)]
enum Release {
None,
Parent(usize),
Chunk(usize),
}
impl Size {
fn new() -> Self {
Size {
pairs: Slab::new(),
next_ready: 0,
}
}
unsafe fn add_pair_and_acquire_left(
&mut self,
chunk: usize,
offset: u64,
parent: Option<usize>,
) -> SizeBlockEntry {
if self.next_ready < self.pairs.len() {
unreachable_unchecked()
}
let index = self.pairs.insert(PairEntry {
state: PairState::Exhausted,
chunk,
offset,
parent,
});
let entry = self.pairs.get_unchecked_mut(index);
entry.state = PairState::Ready {
next: index,
prev: index,
ready: Right, // Left is allocated.
};
self.next_ready = index;
SizeBlockEntry {
chunk,
offset,
index: index << 1,
}
}
fn acquire(&mut self, size: u64) -> Option<SizeBlockEntry> {
if self.next_ready >= self.pairs.len() {
return None;
}
let ready = self.next_ready;
let entry = unsafe { self.pairs.get_unchecked_mut(ready) };
let chunk = entry.chunk;
let offset = entry.offset;
let bit = match entry.state {
PairState::Exhausted => unsafe { unreachable_unchecked() },
PairState::Ready { ready, next, prev } => {
entry.state = PairState::Exhausted;
if prev == self.next_ready {
// The only ready entry.
debug_assert_eq!(next, self.next_ready);
self.next_ready = self.pairs.len();
} else {
let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) };
let prev_next = unsafe { prev_entry.state.replace_next(next) };
debug_assert_eq!(prev_next, self.next_ready);
let next_entry = unsafe { self.pairs.get_unchecked_mut(next) };
let next_prev = unsafe { next_entry.state.replace_prev(prev) };
debug_assert_eq!(next_prev, self.next_ready);
self.next_ready = next;
}
match ready {
Left => 0,
Right => 1,
}
}
};
Some(SizeBlockEntry {
chunk,
offset: offset + bit as u64 * size,
index: (ready << 1) | bit as usize,
})
}
fn release(&mut self, index: usize) -> Release {
let side = match index & 1 {
0 => Side::Left,
1 => Side::Right,
_ => unsafe { unreachable_unchecked() },
};
let entry_index = index >> 1;
let len = self.pairs.len();
let entry = self.pairs.get_mut(entry_index);
let chunk = entry.chunk;
let offset = entry.offset;
let parent = entry.parent;
match entry.state {
PairState::Exhausted => {
if self.next_ready == len {
entry.state = PairState::Ready {
ready: side,
next: entry_index,
prev: entry_index,
};
self.next_ready = entry_index;
} else {
debug_assert!(self.next_ready < len);
let next = self.next_ready;
let next_entry = unsafe { self.pairs.get_unchecked_mut(next) };
let prev = unsafe { next_entry.state.replace_prev(entry_index) };
let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) };
let prev_next = unsafe { prev_entry.state.replace_next(entry_index) };
debug_assert_eq!(prev_next, next);
let entry = unsafe { self.pairs.get_unchecked_mut(entry_index) };
entry.state = PairState::Ready {
ready: side,
next,
prev,
};
}
Release::None
}
PairState::Ready { ready, .. } if ready == side => {
panic!("Attempt to dealloate already free block")
}
PairState::Ready { next, prev, .. } => {
unsafe {
self.pairs.remove_unchecked(entry_index);
}
if prev == entry_index {
debug_assert_eq!(next, entry_index);
self.next_ready = self.pairs.len();
} else {
let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) };
let prev_next = unsafe { prev_entry.state.replace_next(next) };
debug_assert_eq!(prev_next, entry_index);
let next_entry = unsafe { self.pairs.get_unchecked_mut(next) };
let next_prev = unsafe { next_entry.state.replace_prev(prev) };
debug_assert_eq!(next_prev, entry_index);
self.next_ready = next;
}
match parent {
Some(parent) => Release::Parent(parent),
None => {
debug_assert_eq!(offset, 0);
Release::Chunk(chunk)
}
}
}
}
}
}
#[derive(Debug)]
struct Chunk<M> {
memory: Arc<M>,
ptr: Option<NonNull<u8>>,
size: u64,
}
#[derive(Debug)]
pub(crate) struct BuddyAllocator<M> {
minimal_size: u64,
chunks: Slab<Chunk<M>>,
sizes: Vec<Size>,
memory_type: u32,
props: MemoryPropertyFlags,
atom_mask: u64,
}
unsafe impl<M> Sync for BuddyAllocator<M> where M: Sync {}
unsafe impl<M> Send for BuddyAllocator<M> where M: Send {}
impl<M> BuddyAllocator<M>
where
M: MemoryBounds + 'static,
{
pub fn new(
minimal_size: u64,
initial_dedicated_size: u64,
memory_type: u32,
props: MemoryPropertyFlags,
atom_mask: u64,
) -> Self {
assert!(
minimal_size.is_power_of_two(),
"Minimal allocation size of buddy allocator must be power of two"
);
assert!(
initial_dedicated_size.is_power_of_two(),
"Dedicated allocation size of buddy allocator must be power of two"
);
let initial_sizes = (initial_dedicated_size
.trailing_zeros()
.saturating_sub(minimal_size.trailing_zeros())) as usize;
BuddyAllocator {
minimal_size,
chunks: Slab::new(),
sizes: (0..initial_sizes).map(|_| Size::new()).collect(),
memory_type,
props,
atom_mask: atom_mask | (minimal_size - 1),
}
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))]
pub unsafe fn alloc(
&mut self,
device: &impl MemoryDevice<M>,
size: u64,
align_mask: u64,
flags: AllocationFlags,
heap: &mut Heap,
allocations_remains: &mut u32,
) -> Result<BuddyBlock<M>, AllocationError> {
let align_mask = align_mask | self.atom_mask;
let size = align_up(size, align_mask)
.and_then(|size| size.checked_next_power_of_two())
.ok_or(AllocationError::OutOfDeviceMemory)?;
let size_index = size.trailing_zeros() - self.minimal_size.trailing_zeros();
let size_index =
usize::try_from(size_index).map_err(|_| AllocationError::OutOfDeviceMemory)?;
while self.sizes.len() <= size_index {
self.sizes.push(Size::new());
}
let host_visible = self.host_visible();
let mut candidate_size_index = size_index;
let (mut entry, entry_size_index) = loop {
let sizes_len = self.sizes.len();
let candidate_size_entry = &mut self.sizes[candidate_size_index];
let candidate_size = self.minimal_size << candidate_size_index;
if let Some(entry) = candidate_size_entry.acquire(candidate_size) {
break (entry, candidate_size_index);
}
if sizes_len == candidate_size_index + 1 {
// That's size of device allocation.
if *allocations_remains == 0 {
return Err(AllocationError::TooManyObjects);
}
let chunk_size = self.minimal_size << (candidate_size_index + 1);
let mut memory = device.allocate_memory(chunk_size, self.memory_type, flags)?;
*allocations_remains -= 1;
heap.alloc(chunk_size);
let ptr = if host_visible {
match device.map_memory(&mut memory, 0, chunk_size) {
Ok(ptr) => Some(ptr),
Err(DeviceMapError::OutOfDeviceMemory) => {
return Err(AllocationError::OutOfDeviceMemory)
}
Err(DeviceMapError::MapFailed) | Err(DeviceMapError::OutOfHostMemory) => {
return Err(AllocationError::OutOfHostMemory)
}
}
} else {
None
};
let chunk = self.chunks.insert(Chunk {
memory: Arc::new(memory),
ptr,
size: chunk_size,
});
let entry = candidate_size_entry.add_pair_and_acquire_left(chunk, 0, None);
break (entry, candidate_size_index);
}
candidate_size_index += 1;
};
for size_index in (size_index..entry_size_index).rev() {
let size_entry = &mut self.sizes[size_index];
entry =
size_entry.add_pair_and_acquire_left(entry.chunk, entry.offset, Some(entry.index));
}
let chunk_entry = self.chunks.get_unchecked(entry.chunk);
debug_assert!(
entry
.offset
.checked_add(size)
.map_or(false, |end| end <= chunk_entry.size),
"Offset + size is not in chunk bounds"
);
Ok(BuddyBlock {
memory: chunk_entry.memory.clone(),
ptr: chunk_entry
.ptr
.map(|ptr| NonNull::new_unchecked(ptr.as_ptr().add(entry.offset as usize))),
offset: entry.offset,
size,
chunk: entry.chunk,
index: entry.index,
})
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))]
pub unsafe fn dealloc(
&mut self,
device: &impl MemoryDevice<M>,
block: BuddyBlock<M>,
heap: &mut Heap,
allocations_remains: &mut u32,
) {
debug_assert!(block.size.is_power_of_two());
let size_index =
(block.size.trailing_zeros() - self.minimal_size.trailing_zeros()) as usize;
let mut release_index = block.index;
let mut release_size_index = size_index;
loop {
match self.sizes[release_size_index].release(release_index) {
Release::Parent(parent) => {
release_size_index += 1;
release_index = parent;
}
Release::Chunk(chunk) => {
debug_assert_eq!(chunk, block.chunk);
debug_assert_eq!(
self.chunks.get(chunk).size,
self.minimal_size << (release_size_index + 1)
);
let chunk = self.chunks.remove(chunk);
drop(block);
let memory = try_arc_unwrap(chunk.memory)
.expect("Memory shared after last block deallocated");
device.deallocate_memory(memory);
*allocations_remains += 1;
heap.dealloc(chunk.size);
return;
}
Release::None => return,
}
}
}
fn host_visible(&self) -> bool {
self.props.contains(MemoryPropertyFlags::HOST_VISIBLE)
}
}
use {
crate::{
align_up, error::AllocationError, heap::Heap, slab::Slab, unreachable_unchecked,
util::try_arc_unwrap, MemoryBounds,
},
alloc::{sync::Arc, vec::Vec},
core::{convert::TryFrom as _, mem::replace, ptr::NonNull},
gpu_alloc_types::{AllocationFlags, DeviceMapError, MemoryDevice, MemoryPropertyFlags},
};
#[derive(Debug)]
pub(crate) struct BuddyBlock<M> {
pub memory: Arc<M>,
pub ptr: Option<NonNull<u8>>,
pub offset: u64,
pub size: u64,
pub chunk: usize,
pub index: usize,
}
unsafe impl<M> Sync for BuddyBlock<M> where M: Sync {}
unsafe impl<M> Send for BuddyBlock<M> where M: Send {}
#[derive(Clone, Copy, Debug)]
enum PairState {
Exhausted,
Ready {
ready: Side,
next: usize,
prev: usize,
},
}
impl PairState {
unsafe fn replace_next(&mut self, value: usize) -> usize {
match self {
PairState::Exhausted => unreachable_unchecked(),
PairState::Ready { next, .. } => replace(next, value),
}
}
unsafe fn replace_prev(&mut self, value: usize) -> usize {
match self {
PairState::Exhausted => unreachable_unchecked(),
PairState::Ready { prev, .. } => replace(prev, value),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Side {
Left,
Right,
}
use Side::*;
#[derive(Debug)]
struct PairEntry {
state: PairState,
chunk: usize,
offset: u64,
parent: Option<usize>,
}
struct SizeBlockEntry {
chunk: usize,
offset: u64,
index: usize,
}
#[derive(Debug)]
struct Size {
next_ready: usize,
pairs: Slab<PairEntry>,
}
#[derive(Debug)]
enum Release {
None,
Parent(usize),
Chunk(usize),
}
impl Size {
fn new() -> Self {
Size {
pairs: Slab::new(),
next_ready: 0,
}
}
unsafe fn add_pair_and_acquire_left(
&mut self,
chunk: usize,
offset: u64,
parent: Option<usize>,
) -> SizeBlockEntry {
if self.next_ready < self.pairs.len() {
unreachable_unchecked()
}
let index = self.pairs.insert(PairEntry {
state: PairState::Exhausted,
chunk,
offset,
parent,
});
let entry = self.pairs.get_unchecked_mut(index);
entry.state = PairState::Ready {
next: index,
prev: index,
ready: Right, // Left is allocated.
};
self.next_ready = index;
SizeBlockEntry {
chunk,
offset,
index: index << 1,
}
}
fn acquire(&mut self, size: u64) -> Option<SizeBlockEntry> {
if self.next_ready >= self.pairs.len() {
return None;
}
let ready = self.next_ready;
let entry = unsafe { self.pairs.get_unchecked_mut(ready) };
let chunk = entry.chunk;
let offset = entry.offset;
let bit = match entry.state {
PairState::Exhausted => unsafe { unreachable_unchecked() },
PairState::Ready { ready, next, prev } => {
entry.state = PairState::Exhausted;
if prev == self.next_ready {
// The only ready entry.
debug_assert_eq!(next, self.next_ready);
self.next_ready = self.pairs.len();
} else {
let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) };
let prev_next = unsafe { prev_entry.state.replace_next(next) };
debug_assert_eq!(prev_next, self.next_ready);
let next_entry = unsafe { self.pairs.get_unchecked_mut(next) };
let next_prev = unsafe { next_entry.state.replace_prev(prev) };
debug_assert_eq!(next_prev, self.next_ready);
self.next_ready = next;
}
match ready {
Left => 0,
Right => 1,
}
}
};
Some(SizeBlockEntry {
chunk,
offset: offset + bit as u64 * size,
index: (ready << 1) | bit as usize,
})
}
fn release(&mut self, index: usize) -> Release {
let side = match index & 1 {
0 => Side::Left,
1 => Side::Right,
_ => unsafe { unreachable_unchecked() },
};
let entry_index = index >> 1;
let len = self.pairs.len();
let entry = self.pairs.get_mut(entry_index);
let chunk = entry.chunk;
let offset = entry.offset;
let parent = entry.parent;
match entry.state {
PairState::Exhausted => {
if self.next_ready == len {
entry.state = PairState::Ready {
ready: side,
next: entry_index,
prev: entry_index,
};
self.next_ready = entry_index;
} else {
debug_assert!(self.next_ready < len);
let next = self.next_ready;
let next_entry = unsafe { self.pairs.get_unchecked_mut(next) };
let prev = unsafe { next_entry.state.replace_prev(entry_index) };
let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) };
let prev_next = unsafe { prev_entry.state.replace_next(entry_index) };
debug_assert_eq!(prev_next, next);
let entry = unsafe { self.pairs.get_unchecked_mut(entry_index) };
entry.state = PairState::Ready {
ready: side,
next,
prev,
};
}
Release::None
}
PairState::Ready { ready, .. } if ready == side => {
panic!("Attempt to dealloate already free block")
}
PairState::Ready { next, prev, .. } => {
unsafe {
self.pairs.remove_unchecked(entry_index);
}
if prev == entry_index {
debug_assert_eq!(next, entry_index);
self.next_ready = self.pairs.len();
} else {
let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) };
let prev_next = unsafe { prev_entry.state.replace_next(next) };
debug_assert_eq!(prev_next, entry_index);
let next_entry = unsafe { self.pairs.get_unchecked_mut(next) };
let next_prev = unsafe { next_entry.state.replace_prev(prev) };
debug_assert_eq!(next_prev, entry_index);
self.next_ready = next;
}
match parent {
Some(parent) => Release::Parent(parent),
None => {
debug_assert_eq!(offset, 0);
Release::Chunk(chunk)
}
}
}
}
}
}
#[derive(Debug)]
struct Chunk<M> {
memory: Arc<M>,
ptr: Option<NonNull<u8>>,
size: u64,
}
#[derive(Debug)]
pub(crate) struct BuddyAllocator<M> {
minimal_size: u64,
chunks: Slab<Chunk<M>>,
sizes: Vec<Size>,
memory_type: u32,
props: MemoryPropertyFlags,
atom_mask: u64,
}
unsafe impl<M> Sync for BuddyAllocator<M> where M: Sync {}
unsafe impl<M> Send for BuddyAllocator<M> where M: Send {}
impl<M> BuddyAllocator<M>
where
M: MemoryBounds + 'static,
{
pub fn new(
minimal_size: u64,
initial_dedicated_size: u64,
memory_type: u32,
props: MemoryPropertyFlags,
atom_mask: u64,
) -> Self {
assert!(
minimal_size.is_power_of_two(),
"Minimal allocation size of buddy allocator must be power of two"
);
assert!(
initial_dedicated_size.is_power_of_two(),
"Dedicated allocation size of buddy allocator must be power of two"
);
let initial_sizes = (initial_dedicated_size
.trailing_zeros()
.saturating_sub(minimal_size.trailing_zeros())) as usize;
BuddyAllocator {
minimal_size,
chunks: Slab::new(),
sizes: (0..initial_sizes).map(|_| Size::new()).collect(),
memory_type,
props,
atom_mask: atom_mask | (minimal_size - 1),
}
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))]
pub unsafe fn alloc(
&mut self,
device: &impl MemoryDevice<M>,
size: u64,
align_mask: u64,
flags: AllocationFlags,
heap: &mut Heap,
allocations_remains: &mut u32,
) -> Result<BuddyBlock<M>, AllocationError> {
let align_mask = align_mask | self.atom_mask;
let size = align_up(size, align_mask)
.and_then(|size| size.checked_next_power_of_two())
.ok_or(AllocationError::OutOfDeviceMemory)?;
let size = size.max(self.minimal_size);
let size_index = size.trailing_zeros() - self.minimal_size.trailing_zeros();
let size_index =
usize::try_from(size_index).map_err(|_| AllocationError::OutOfDeviceMemory)?;
while self.sizes.len() <= size_index {
self.sizes.push(Size::new());
}
let host_visible = self.host_visible();
let mut candidate_size_index = size_index;
let (mut entry, entry_size_index) = loop {
let sizes_len = self.sizes.len();
let candidate_size_entry = &mut self.sizes[candidate_size_index];
let candidate_size = self.minimal_size << candidate_size_index;
if let Some(entry) = candidate_size_entry.acquire(candidate_size) {
break (entry, candidate_size_index);
}
if sizes_len == candidate_size_index + 1 {
// That's size of device allocation.
if *allocations_remains == 0 {
return Err(AllocationError::TooManyObjects);
}
let chunk_size = self.minimal_size << (candidate_size_index + 1);
let mut memory = device.allocate_memory(chunk_size, self.memory_type, flags)?;
*allocations_remains -= 1;
heap.alloc(chunk_size);
let ptr = if host_visible {
match device.map_memory(&mut memory, 0, chunk_size) {
Ok(ptr) => Some(ptr),
Err(DeviceMapError::OutOfDeviceMemory) => {
return Err(AllocationError::OutOfDeviceMemory)
}
Err(DeviceMapError::MapFailed) | Err(DeviceMapError::OutOfHostMemory) => {
return Err(AllocationError::OutOfHostMemory)
}
}
} else {
None
};
let chunk = self.chunks.insert(Chunk {
memory: Arc::new(memory),
ptr,
size: chunk_size,
});
let entry = candidate_size_entry.add_pair_and_acquire_left(chunk, 0, None);
break (entry, candidate_size_index);
}
candidate_size_index += 1;
};
for size_index in (size_index..entry_size_index).rev() {
let size_entry = &mut self.sizes[size_index];
entry =
size_entry.add_pair_and_acquire_left(entry.chunk, entry.offset, Some(entry.index));
}
let chunk_entry = self.chunks.get_unchecked(entry.chunk);
debug_assert!(
entry
.offset
.checked_add(size)
.map_or(false, |end| end <= chunk_entry.size),
"Offset + size is not in chunk bounds"
);
Ok(BuddyBlock {
memory: chunk_entry.memory.clone(),
ptr: chunk_entry
.ptr
.map(|ptr| NonNull::new_unchecked(ptr.as_ptr().add(entry.offset as usize))),
offset: entry.offset,
size,
chunk: entry.chunk,
index: entry.index,
})
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))]
pub unsafe fn dealloc(
&mut self,
device: &impl MemoryDevice<M>,
block: BuddyBlock<M>,
heap: &mut Heap,
allocations_remains: &mut u32,
) {
debug_assert!(block.size.is_power_of_two());
let size_index =
(block.size.trailing_zeros() - self.minimal_size.trailing_zeros()) as usize;
let mut release_index = block.index;
let mut release_size_index = size_index;
loop {
match self.sizes[release_size_index].release(release_index) {
Release::Parent(parent) => {
release_size_index += 1;
release_index = parent;
}
Release::Chunk(chunk) => {
debug_assert_eq!(chunk, block.chunk);
debug_assert_eq!(
self.chunks.get(chunk).size,
self.minimal_size << (release_size_index + 1)
);
let chunk = self.chunks.remove(chunk);
drop(block);
let memory = try_arc_unwrap(chunk.memory)
.expect("Memory shared after last block deallocated");
device.deallocate_memory(memory);
*allocations_remains += 1;
heap.dealloc(chunk.size);
return;
}
Release::None => return,
}
}
}
fn host_visible(&self) -> bool {
self.props.contains(MemoryPropertyFlags::HOST_VISIBLE)
}
}

View File

@ -1,77 +1,77 @@
/// Configuration for [`GpuAllocator`]
///
/// [`GpuAllocator`]: type.GpuAllocator
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Config {
/// Size in bytes of request that will be served by dedicated memory object.
/// This value should be large enough to not exhaust memory object limit
/// and not use slow memory object allocation when it is not necessary.
pub dedicated_threshold: u64,
/// Size in bytes of request that will be served by dedicated memory object if preferred.
/// This value should be large enough to not exhaust memory object limit
/// and not use slow memory object allocation when it is not necessary.
///
/// This won't make much sense if this value is larger than `dedicated_threshold`.
pub preferred_dedicated_threshold: u64,
/// Size in bytes of transient memory request that will be served by dedicated memory object.
/// This value should be large enough to not exhaust memory object limit
/// and not use slow memory object allocation when it is not necessary.
///
/// This won't make much sense if this value is lesser than `dedicated_threshold`.
pub transient_dedicated_threshold: u64,
/// Size in bytes of first chunk in free-list allocator.
pub starting_free_list_chunk: u64,
/// Upper limit for size in bytes of chunks in free-list allocator.
pub final_free_list_chunk: u64,
/// Minimal size for buddy allocator.
pub minimal_buddy_size: u64,
/// Initial memory object size for buddy allocator.
/// If less than `minimal_buddy_size` then `minimal_buddy_size` is used instead.
pub initial_buddy_dedicated_size: u64,
}
impl Config {
/// Returns default configuration.
///
/// This is not `Default` implementation to discourage usage outside of
/// prototyping.
///
/// Proper configuration should depend on hardware and intended usage.\
/// But those values can be used as starting point.\
/// Note that they can simply not work for some platforms with lesser
/// memory capacity than today's "modern" GPU (year 2020).
pub fn i_am_prototyping() -> Self {
// Assume that today's modern GPU is made of 1024 potatoes.
let potato = Config::i_am_potato();
Config {
dedicated_threshold: potato.dedicated_threshold * 1024,
preferred_dedicated_threshold: potato.preferred_dedicated_threshold * 1024,
transient_dedicated_threshold: potato.transient_dedicated_threshold * 1024,
starting_free_list_chunk: potato.starting_free_list_chunk * 1024,
final_free_list_chunk: potato.final_free_list_chunk * 1024,
minimal_buddy_size: potato.minimal_buddy_size * 1024,
initial_buddy_dedicated_size: potato.initial_buddy_dedicated_size * 1024,
}
}
/// Returns default configuration for average sized potato.
pub fn i_am_potato() -> Self {
Config {
dedicated_threshold: 32 * 1024,
preferred_dedicated_threshold: 1024,
transient_dedicated_threshold: 128 * 1024,
starting_free_list_chunk: 8 * 1024,
final_free_list_chunk: 128 * 1024,
minimal_buddy_size: 1,
initial_buddy_dedicated_size: 8 * 1024,
}
}
}
/// Configuration for [`GpuAllocator`]
///
/// [`GpuAllocator`]: type.GpuAllocator
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Config {
/// Size in bytes of request that will be served by dedicated memory object.
/// This value should be large enough to not exhaust memory object limit
/// and not use slow memory object allocation when it is not necessary.
pub dedicated_threshold: u64,
/// Size in bytes of request that will be served by dedicated memory object if preferred.
/// This value should be large enough to not exhaust memory object limit
/// and not use slow memory object allocation when it is not necessary.
///
/// This won't make much sense if this value is larger than `dedicated_threshold`.
pub preferred_dedicated_threshold: u64,
/// Size in bytes of transient memory request that will be served by dedicated memory object.
/// This value should be large enough to not exhaust memory object limit
/// and not use slow memory object allocation when it is not necessary.
///
/// This won't make much sense if this value is lesser than `dedicated_threshold`.
pub transient_dedicated_threshold: u64,
/// Size in bytes of first chunk in free-list allocator.
pub starting_free_list_chunk: u64,
/// Upper limit for size in bytes of chunks in free-list allocator.
pub final_free_list_chunk: u64,
/// Minimal size for buddy allocator.
pub minimal_buddy_size: u64,
/// Initial memory object size for buddy allocator.
/// If less than `minimal_buddy_size` then `minimal_buddy_size` is used instead.
pub initial_buddy_dedicated_size: u64,
}
impl Config {
/// Returns default configuration.
///
/// This is not `Default` implementation to discourage usage outside of
/// prototyping.
///
/// Proper configuration should depend on hardware and intended usage.\
/// But those values can be used as starting point.\
/// Note that they can simply not work for some platforms with lesser
/// memory capacity than today's "modern" GPU (year 2020).
pub fn i_am_prototyping() -> Self {
// Assume that today's modern GPU is made of 1024 potatoes.
let potato = Config::i_am_potato();
Config {
dedicated_threshold: potato.dedicated_threshold * 1024,
preferred_dedicated_threshold: potato.preferred_dedicated_threshold * 1024,
transient_dedicated_threshold: potato.transient_dedicated_threshold * 1024,
starting_free_list_chunk: potato.starting_free_list_chunk * 1024,
final_free_list_chunk: potato.final_free_list_chunk * 1024,
minimal_buddy_size: potato.minimal_buddy_size * 1024,
initial_buddy_dedicated_size: potato.initial_buddy_dedicated_size * 1024,
}
}
/// Returns default configuration for average sized potato.
pub fn i_am_potato() -> Self {
Config {
dedicated_threshold: 32 * 1024,
preferred_dedicated_threshold: 1024,
transient_dedicated_threshold: 128 * 1024,
starting_free_list_chunk: 8 * 1024,
final_free_list_chunk: 128 * 1024,
minimal_buddy_size: 1,
initial_buddy_dedicated_size: 8 * 1024,
}
}
}

View File

@ -1,116 +1,116 @@
use {
core::fmt::{self, Display},
gpu_alloc_types::{DeviceMapError, OutOfMemory},
};
/// Enumeration of possible errors that may occur during memory allocation.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AllocationError {
/// Backend reported that device memory has been exhausted.\
/// Deallocating device memory from the same heap may increase chance
/// that another allocation would succeed.
OutOfDeviceMemory,
/// Backend reported that host memory has been exhausted.\
/// Deallocating host memory may increase chance that another allocation would succeed.
OutOfHostMemory,
/// Allocation request cannot be fulfilled as no available memory types allowed
/// by `Request.memory_types` mask is compatible with `request.usage`.
NoCompatibleMemoryTypes,
/// Reached limit on allocated memory objects count.\
/// Deallocating device memory may increase chance that another allocation would succeed.
/// Especially dedicated memory blocks.
///
/// If this error is returned when memory heaps are far from exhausted
/// `Config` should be tweaked to allocate larger memory objects.
TooManyObjects,
}
impl From<OutOfMemory> for AllocationError {
fn from(err: OutOfMemory) -> Self {
match err {
OutOfMemory::OutOfDeviceMemory => AllocationError::OutOfDeviceMemory,
OutOfMemory::OutOfHostMemory => AllocationError::OutOfHostMemory,
}
}
}
impl Display for AllocationError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AllocationError::OutOfDeviceMemory => fmt.write_str("Device memory exhausted"),
AllocationError::OutOfHostMemory => fmt.write_str("Host memory exhausted"),
AllocationError::NoCompatibleMemoryTypes => fmt.write_str(
"No compatible memory types from requested types support requested usage",
),
AllocationError::TooManyObjects => {
fmt.write_str("Reached limit on allocated memory objects count")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for AllocationError {}
/// Enumeration of possible errors that may occur during memory mapping.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum MapError {
/// Backend reported that device memory has been exhausted.\
/// Deallocating device memory from the same heap may increase chance
/// that another mapping would succeed.
OutOfDeviceMemory,
/// Backend reported that host memory has been exhausted.\
/// Deallocating host memory may increase chance that another mapping would succeed.
OutOfHostMemory,
/// Attempt to map memory block with non-host-visible memory type.\
/// Ensure to include `UsageFlags::HOST_ACCESS` into allocation request
/// when memory mapping is intended.
NonHostVisible,
/// Map failed for implementation specific reason.\
/// For Vulkan backend this includes failed attempt
/// to allocate large enough virtual address space.
MapFailed,
/// Mapping failed due to block being already mapped.
AlreadyMapped,
}
impl From<DeviceMapError> for MapError {
fn from(err: DeviceMapError) -> Self {
match err {
DeviceMapError::OutOfDeviceMemory => MapError::OutOfDeviceMemory,
DeviceMapError::OutOfHostMemory => MapError::OutOfHostMemory,
DeviceMapError::MapFailed => MapError::MapFailed,
}
}
}
impl From<OutOfMemory> for MapError {
fn from(err: OutOfMemory) -> Self {
match err {
OutOfMemory::OutOfDeviceMemory => MapError::OutOfDeviceMemory,
OutOfMemory::OutOfHostMemory => MapError::OutOfHostMemory,
}
}
}
impl Display for MapError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MapError::OutOfDeviceMemory => fmt.write_str("Device memory exhausted"),
MapError::OutOfHostMemory => fmt.write_str("Host memory exhausted"),
MapError::MapFailed => fmt.write_str("Failed to map memory object"),
MapError::NonHostVisible => fmt.write_str("Impossible to map non-host-visible memory"),
MapError::AlreadyMapped => fmt.write_str("Block is already mapped"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for MapError {}
use {
core::fmt::{self, Display},
gpu_alloc_types::{DeviceMapError, OutOfMemory},
};
/// Enumeration of possible errors that may occur during memory allocation.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AllocationError {
/// Backend reported that device memory has been exhausted.\
/// Deallocating device memory from the same heap may increase chance
/// that another allocation would succeed.
OutOfDeviceMemory,
/// Backend reported that host memory has been exhausted.\
/// Deallocating host memory may increase chance that another allocation would succeed.
OutOfHostMemory,
/// Allocation request cannot be fulfilled as no available memory types allowed
/// by `Request.memory_types` mask is compatible with `request.usage`.
NoCompatibleMemoryTypes,
/// Reached limit on allocated memory objects count.\
/// Deallocating device memory may increase chance that another allocation would succeed.
/// Especially dedicated memory blocks.
///
/// If this error is returned when memory heaps are far from exhausted
/// `Config` should be tweaked to allocate larger memory objects.
TooManyObjects,
}
impl From<OutOfMemory> for AllocationError {
fn from(err: OutOfMemory) -> Self {
match err {
OutOfMemory::OutOfDeviceMemory => AllocationError::OutOfDeviceMemory,
OutOfMemory::OutOfHostMemory => AllocationError::OutOfHostMemory,
}
}
}
impl Display for AllocationError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AllocationError::OutOfDeviceMemory => fmt.write_str("Device memory exhausted"),
AllocationError::OutOfHostMemory => fmt.write_str("Host memory exhausted"),
AllocationError::NoCompatibleMemoryTypes => fmt.write_str(
"No compatible memory types from requested types support requested usage",
),
AllocationError::TooManyObjects => {
fmt.write_str("Reached limit on allocated memory objects count")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for AllocationError {}
/// Enumeration of possible errors that may occur during memory mapping.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum MapError {
/// Backend reported that device memory has been exhausted.\
/// Deallocating device memory from the same heap may increase chance
/// that another mapping would succeed.
OutOfDeviceMemory,
/// Backend reported that host memory has been exhausted.\
/// Deallocating host memory may increase chance that another mapping would succeed.
OutOfHostMemory,
/// Attempt to map memory block with non-host-visible memory type.\
/// Ensure to include `UsageFlags::HOST_ACCESS` into allocation request
/// when memory mapping is intended.
NonHostVisible,
/// Map failed for implementation specific reason.\
/// For Vulkan backend this includes failed attempt
/// to allocate large enough virtual address space.
MapFailed,
/// Mapping failed due to block being already mapped.
AlreadyMapped,
}
impl From<DeviceMapError> for MapError {
fn from(err: DeviceMapError) -> Self {
match err {
DeviceMapError::OutOfDeviceMemory => MapError::OutOfDeviceMemory,
DeviceMapError::OutOfHostMemory => MapError::OutOfHostMemory,
DeviceMapError::MapFailed => MapError::MapFailed,
}
}
}
impl From<OutOfMemory> for MapError {
fn from(err: OutOfMemory) -> Self {
match err {
OutOfMemory::OutOfDeviceMemory => MapError::OutOfDeviceMemory,
OutOfMemory::OutOfHostMemory => MapError::OutOfHostMemory,
}
}
}
impl Display for MapError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MapError::OutOfDeviceMemory => fmt.write_str("Device memory exhausted"),
MapError::OutOfHostMemory => fmt.write_str("Host memory exhausted"),
MapError::MapFailed => fmt.write_str("Failed to map memory object"),
MapError::NonHostVisible => fmt.write_str("Impossible to map non-host-visible memory"),
MapError::AlreadyMapped => fmt.write_str("Block is already mapped"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for MapError {}

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,32 @@
#[derive(Debug)]
pub(crate) struct Heap {
size: u64,
used: u64,
allocated: u128,
deallocated: u128,
}
impl Heap {
pub(crate) fn new(size: u64) -> Self {
Heap {
size,
used: 0,
allocated: 0,
deallocated: 0,
}
}
pub(crate) fn size(&mut self) -> u64 {
self.size
}
pub(crate) fn alloc(&mut self, size: u64) {
self.used += size;
self.allocated += u128::from(size);
}
pub(crate) fn dealloc(&mut self, size: u64) {
self.used -= size;
self.deallocated += u128::from(size);
}
}
#[derive(Debug)]
pub(crate) struct Heap {
size: u64,
used: u64,
allocated: u128,
deallocated: u128,
}
impl Heap {
pub(crate) fn new(size: u64) -> Self {
Heap {
size,
used: 0,
allocated: 0,
deallocated: 0,
}
}
pub(crate) fn size(&mut self) -> u64 {
self.size
}
pub(crate) fn alloc(&mut self, size: u64) {
self.used += size;
self.allocated += u128::from(size);
}
pub(crate) fn dealloc(&mut self, size: u64) {
self.used -= size;
self.deallocated += u128::from(size);
}
}

View File

@ -1,124 +1,124 @@
//!
//! Implementation agnostic memory allocator for Vulkan like APIs.
//!
//! This crate is intended to be used as part of safe API implementations.\
//! Use with caution. There are unsafe functions all over the place.
//!
//! # Usage
//!
//! Start with fetching `DeviceProperties` from `gpu-alloc-<backend>` crate for the backend of choice.\
//! Then create `GpuAllocator` instance and use it for all device memory allocations.\
//! `GpuAllocator` will take care for all necessary bookkeeping like memory object count limit,
//! heap budget and memory mapping.
//!
//! ### Backends implementations
//!
//! Backend supporting crates should not depend on this crate.\
//! Instead they should depend on `gpu-alloc-types` which is much more stable,
//! allowing to upgrade `gpu-alloc` version without `gpu-alloc-<backend>` upgrade.
//!
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[cfg(feature = "tracing")]
macro_rules! report_error_on_drop {
($($tokens:tt)*) => {{
#[cfg(feature = "std")]
{
if std::thread::panicking() {
return;
}
}
tracing::error!($($tokens)*)
}};
}
#[cfg(all(not(feature = "tracing"), feature = "std"))]
macro_rules! report_error_on_drop {
($($tokens:tt)*) => {{
if std::thread::panicking() {
return;
}
eprintln!($($tokens)*)
}};
}
#[cfg(all(not(feature = "tracing"), not(feature = "std")))]
macro_rules! report_error_on_drop {
($($tokens:tt)*) => {{
panic!($($tokens)*)
}};
}
mod allocator;
mod block;
mod buddy;
mod config;
mod error;
mod freelist;
mod heap;
mod slab;
mod usage;
mod util;
pub use {
self::{allocator::*, block::MemoryBlock, config::*, error::*, usage::*},
gpu_alloc_types::*,
};
/// Memory request for allocator.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Request {
/// Minimal size of memory block required.
/// Returned block may have larger size,
/// use `MemoryBlock::size` to learn actual size of returned block.
pub size: u64,
/// Minimal alignment mask required.
/// Returned block may have larger alignment,
/// use `MemoryBlock::align` to learn actual alignment of returned block.
pub align_mask: u64,
/// Intended memory usage.
/// Returned block may support additional usages,
/// use `MemoryBlock::props` to learn memory properties of returned block.
pub usage: UsageFlags,
/// Bitset for memory types.
/// Returned block will be from memory type corresponding to one of set bits,
/// use `MemoryBlock::memory_type` to learn memory type index of returned block.
pub memory_types: u32,
}
/// Aligns `value` up to `align_mask`
/// Returns smallest integer not lesser than `value` aligned by `align_mask`.
/// Returns `None` on overflow.
pub(crate) fn align_up(value: u64, align_mask: u64) -> Option<u64> {
Some(value.checked_add(align_mask)? & !align_mask)
}
/// Align `value` down to `align_mask`
/// Returns largest integer not bigger than `value` aligned by `align_mask`.
pub(crate) fn align_down(value: u64, align_mask: u64) -> u64 {
value & !align_mask
}
#[cfg(debug_assertions)]
#[allow(unused_unsafe)]
unsafe fn unreachable_unchecked() -> ! {
unreachable!()
}
#[cfg(not(debug_assertions))]
unsafe fn unreachable_unchecked() -> ! {
core::hint::unreachable_unchecked()
}
// #[cfg(feature = "tracing")]
use core::fmt::Debug as MemoryBounds;
// #[cfg(not(feature = "tracing"))]
// use core::any::Any as MemoryBounds;
//!
//! Implementation agnostic memory allocator for Vulkan like APIs.
//!
//! This crate is intended to be used as part of safe API implementations.\
//! Use with caution. There are unsafe functions all over the place.
//!
//! # Usage
//!
//! Start with fetching `DeviceProperties` from `gpu-alloc-<backend>` crate for the backend of choice.\
//! Then create `GpuAllocator` instance and use it for all device memory allocations.\
//! `GpuAllocator` will take care for all necessary bookkeeping like memory object count limit,
//! heap budget and memory mapping.
//!
//! ### Backends implementations
//!
//! Backend supporting crates should not depend on this crate.\
//! Instead they should depend on `gpu-alloc-types` which is much more stable,
//! allowing to upgrade `gpu-alloc` version without `gpu-alloc-<backend>` upgrade.
//!
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[cfg(feature = "tracing")]
macro_rules! report_error_on_drop {
($($tokens:tt)*) => {{
#[cfg(feature = "std")]
{
if std::thread::panicking() {
return;
}
}
tracing::error!($($tokens)*)
}};
}
#[cfg(all(not(feature = "tracing"), feature = "std"))]
macro_rules! report_error_on_drop {
($($tokens:tt)*) => {{
if std::thread::panicking() {
return;
}
eprintln!($($tokens)*)
}};
}
#[cfg(all(not(feature = "tracing"), not(feature = "std")))]
macro_rules! report_error_on_drop {
($($tokens:tt)*) => {{
panic!($($tokens)*)
}};
}
mod allocator;
mod block;
mod buddy;
mod config;
mod error;
mod freelist;
mod heap;
mod slab;
mod usage;
mod util;
pub use {
self::{allocator::*, block::MemoryBlock, config::*, error::*, usage::*},
gpu_alloc_types::*,
};
/// Memory request for allocator.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Request {
/// Minimal size of memory block required.
/// Returned block may have larger size,
/// use `MemoryBlock::size` to learn actual size of returned block.
pub size: u64,
/// Minimal alignment mask required.
/// Returned block may have larger alignment,
/// use `MemoryBlock::align` to learn actual alignment of returned block.
pub align_mask: u64,
/// Intended memory usage.
/// Returned block may support additional usages,
/// use `MemoryBlock::props` to learn memory properties of returned block.
pub usage: UsageFlags,
/// Bitset for memory types.
/// Returned block will be from memory type corresponding to one of set bits,
/// use `MemoryBlock::memory_type` to learn memory type index of returned block.
pub memory_types: u32,
}
/// Aligns `value` up to `align_mask`
/// Returns smallest integer not lesser than `value` aligned by `align_mask`.
/// Returns `None` on overflow.
pub(crate) fn align_up(value: u64, align_mask: u64) -> Option<u64> {
Some(value.checked_add(align_mask)? & !align_mask)
}
/// Align `value` down to `align_mask`
/// Returns largest integer not bigger than `value` aligned by `align_mask`.
pub(crate) fn align_down(value: u64, align_mask: u64) -> u64 {
value & !align_mask
}
#[cfg(debug_assertions)]
#[allow(unused_unsafe)]
unsafe fn unreachable_unchecked() -> ! {
unreachable!()
}
#[cfg(not(debug_assertions))]
unsafe fn unreachable_unchecked() -> ! {
core::hint::unreachable_unchecked()
}
// #[cfg(feature = "tracing")]
use core::fmt::Debug as MemoryBounds;
// #[cfg(not(feature = "tracing"))]
// use core::any::Any as MemoryBounds;

View File

@ -1,97 +1,97 @@
use {crate::unreachable_unchecked, alloc::vec::Vec, core::mem::replace};
#[derive(Debug)]
enum Entry<T> {
Vacant(usize),
Occupied(T),
}
#[derive(Debug)]
pub(crate) struct Slab<T> {
next_vacant: usize,
entries: Vec<Entry<T>>,
}
impl<T> Slab<T> {
pub fn new() -> Self {
Slab {
next_vacant: !0,
entries: Vec::new(),
}
}
/// Inserts value into this linked vec and returns index
/// at which value can be accessed in constant time.
pub fn insert(&mut self, value: T) -> usize {
if self.next_vacant >= self.entries.len() {
self.entries.push(Entry::Occupied(value));
self.entries.len() - 1
} else {
match *unsafe { self.entries.get_unchecked(self.next_vacant) } {
Entry::Vacant(next_vacant) => {
unsafe {
*self.entries.get_unchecked_mut(self.next_vacant) = Entry::Occupied(value);
}
replace(&mut self.next_vacant, next_vacant)
}
_ => unsafe { unreachable_unchecked() },
}
}
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
debug_assert!(index < self.len());
match self.entries.get_unchecked(index) {
Entry::Occupied(value) => value,
_ => unreachable_unchecked(),
}
}
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
debug_assert!(index < self.len());
match self.entries.get_unchecked_mut(index) {
Entry::Occupied(value) => value,
_ => unreachable_unchecked(),
}
}
pub fn get(&self, index: usize) -> &T {
match self.entries.get(index) {
Some(Entry::Occupied(value)) => value,
_ => panic!("Invalid index"),
}
}
pub fn get_mut(&mut self, index: usize) -> &mut T {
match self.entries.get_mut(index) {
Some(Entry::Occupied(value)) => value,
_ => panic!("Invalid index"),
}
}
pub unsafe fn remove_unchecked(&mut self, index: usize) -> T {
let entry = replace(
self.entries.get_unchecked_mut(index),
Entry::Vacant(self.next_vacant),
);
self.next_vacant = index;
match entry {
Entry::Occupied(value) => value,
_ => unreachable_unchecked(),
}
}
pub fn remove(&mut self, index: usize) -> T {
match self.entries.get_mut(index) {
Some(Entry::Occupied(_)) => unsafe { self.remove_unchecked(index) },
_ => panic!("Invalid index"),
}
}
}
use {crate::unreachable_unchecked, alloc::vec::Vec, core::mem::replace};
#[derive(Debug)]
enum Entry<T> {
Vacant(usize),
Occupied(T),
}
#[derive(Debug)]
pub(crate) struct Slab<T> {
next_vacant: usize,
entries: Vec<Entry<T>>,
}
impl<T> Slab<T> {
pub fn new() -> Self {
Slab {
next_vacant: !0,
entries: Vec::new(),
}
}
/// Inserts value into this linked vec and returns index
/// at which value can be accessed in constant time.
pub fn insert(&mut self, value: T) -> usize {
if self.next_vacant >= self.entries.len() {
self.entries.push(Entry::Occupied(value));
self.entries.len() - 1
} else {
match *unsafe { self.entries.get_unchecked(self.next_vacant) } {
Entry::Vacant(next_vacant) => {
unsafe {
*self.entries.get_unchecked_mut(self.next_vacant) = Entry::Occupied(value);
}
replace(&mut self.next_vacant, next_vacant)
}
_ => unsafe { unreachable_unchecked() },
}
}
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
debug_assert!(index < self.len());
match self.entries.get_unchecked(index) {
Entry::Occupied(value) => value,
_ => unreachable_unchecked(),
}
}
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
debug_assert!(index < self.len());
match self.entries.get_unchecked_mut(index) {
Entry::Occupied(value) => value,
_ => unreachable_unchecked(),
}
}
pub fn get(&self, index: usize) -> &T {
match self.entries.get(index) {
Some(Entry::Occupied(value)) => value,
_ => panic!("Invalid index"),
}
}
pub fn get_mut(&mut self, index: usize) -> &mut T {
match self.entries.get_mut(index) {
Some(Entry::Occupied(value)) => value,
_ => panic!("Invalid index"),
}
}
pub unsafe fn remove_unchecked(&mut self, index: usize) -> T {
let entry = replace(
self.entries.get_unchecked_mut(index),
Entry::Vacant(self.next_vacant),
);
self.next_vacant = index;
match entry {
Entry::Occupied(value) => value,
_ => unreachable_unchecked(),
}
}
pub fn remove(&mut self, index: usize) -> T {
match self.entries.get_mut(index) {
Some(Entry::Occupied(_)) => unsafe { self.remove_unchecked(index) },
_ => panic!("Invalid index"),
}
}
}

View File

@ -1,167 +1,176 @@
use {
core::fmt::{self, Debug},
gpu_alloc_types::{MemoryPropertyFlags, MemoryType},
};
bitflags::bitflags! {
/// Memory usage type.
/// Bits set define intended usage for requested memory.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UsageFlags: u8 {
/// Hints for allocator to find memory with faster device access.
/// If no flags is specified than `FAST_DEVICE_ACCESS` is implied.
const FAST_DEVICE_ACCESS = 0x01;
/// Memory will be accessed from host.
/// This flags guarantees that host memory operations will be available.
/// Otherwise implementation is encouraged to use non-host-accessible memory.
const HOST_ACCESS = 0x02;
/// Hints allocator that memory will be used for data downloading.
/// Allocator will strongly prefer host-cached memory.
/// Implies `HOST_ACCESS` flag.
const DOWNLOAD = 0x04;
/// Hints allocator that memory will be used for data uploading.
/// If `DOWNLOAD` flag is not set then allocator will assume that
/// host will access memory in write-only manner and may
/// pick not host-cached.
/// Implies `HOST_ACCESS` flag.
const UPLOAD = 0x08;
/// Hints allocator that memory will be used for short duration
/// allowing to use faster algorithm with less memory overhead.
/// If use holds returned memory block for too long then
/// effective memory overhead increases instead.
/// Best use case is for staging buffer for single batch of operations.
const TRANSIENT = 0x10;
/// Requests memory that can be addressed with `u64`.
/// Allows fetching device address for resources bound to that memory.
const DEVICE_ADDRESS = 0x20;
}
}
#[derive(Clone, Copy, Debug)]
struct MemoryForOneUsage {
mask: u32,
types: [u32; 32],
types_count: u32,
}
pub(crate) struct MemoryForUsage {
usages: [MemoryForOneUsage; 64],
}
impl Debug for MemoryForUsage {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("MemoryForUsage")
.field("usages", &&self.usages[..])
.finish()
}
}
impl MemoryForUsage {
pub fn new(memory_types: &[MemoryType]) -> Self {
assert!(
memory_types.len() <= 32,
"Only up to 32 memory types supported"
);
let mut mfu = MemoryForUsage {
usages: [MemoryForOneUsage {
mask: 0,
types: [0; 32],
types_count: 0,
}; 64],
};
for usage in 0..64 {
mfu.usages[usage as usize] =
one_usage(UsageFlags::from_bits_truncate(usage), memory_types);
}
mfu
}
/// Returns mask with bits set for memory type indices that support the
/// usage.
pub fn mask(&self, usage: UsageFlags) -> u32 {
self.usages[usage.bits() as usize].mask
}
/// Returns slice of memory type indices that support the usage.
/// Earlier memory type has priority over later.
pub fn types(&self, usage: UsageFlags) -> &[u32] {
let usage = &self.usages[usage.bits() as usize];
&usage.types[..usage.types_count as usize]
}
}
fn one_usage(usage: UsageFlags, memory_types: &[MemoryType]) -> MemoryForOneUsage {
let mut types = [0; 32];
let mut types_count = 0;
for (index, mt) in memory_types.iter().enumerate() {
if compatible(usage, mt.props) {
types[types_count as usize] = index as u32;
types_count += 1;
}
}
types[..types_count as usize]
.sort_unstable_by_key(|&index| priority(usage, memory_types[index as usize].props));
let mask = types[..types_count as usize]
.iter()
.fold(0u32, |mask, index| mask | 1u32 << index);
MemoryForOneUsage {
mask,
types,
types_count,
}
}
fn compatible(usage: UsageFlags, flags: MemoryPropertyFlags) -> bool {
type Flags = MemoryPropertyFlags;
if flags.contains(Flags::LAZILY_ALLOCATED) || flags.contains(Flags::PROTECTED) {
// Unsupported
false
} else if usage.intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD)
{
// Requires HOST_VISIBLE
flags.contains(Flags::HOST_VISIBLE)
} else {
true
}
}
/// Returns priority of memory with specified flags for specified usage.
/// Lesser value returned = more prioritized.
fn priority(usage: UsageFlags, flags: MemoryPropertyFlags) -> u32 {
type Flags = MemoryPropertyFlags;
// Highly prefer device local memory when `FAST_DEVICE_ACCESS` usage is specified
// or usage is empty.
let device_local: bool = flags.contains(Flags::DEVICE_LOCAL)
^ (usage.is_empty() || usage.contains(UsageFlags::FAST_DEVICE_ACCESS));
assert!(
flags.contains(Flags::HOST_VISIBLE)
|| !usage
.intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD)
);
// Prefer cached memory for downloads.
// Or non-cached if downloads are not expected.
let cached: bool = flags.contains(Flags::HOST_CACHED) ^ usage.contains(UsageFlags::DOWNLOAD);
// Prefer coherent for both uploads and downloads.
// Prefer non-coherent if neither flags is set.
let coherent: bool = flags.contains(Flags::HOST_COHERENT)
^ (usage.intersects(UsageFlags::UPLOAD | UsageFlags::DOWNLOAD));
// Each boolean is false if flags are preferred.
device_local as u32 * 4 + cached as u32 * 2 + coherent as u32
}
use {
core::fmt::{self, Debug},
gpu_alloc_types::{MemoryPropertyFlags, MemoryType},
};
bitflags::bitflags! {
/// Memory usage type.
/// Bits set define intended usage for requested memory.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UsageFlags: u8 {
/// Hints for allocator to find memory with faster device access.
/// If no flags is specified than `FAST_DEVICE_ACCESS` is implied.
const FAST_DEVICE_ACCESS = 0x01;
/// Memory will be accessed from host.
/// This flags guarantees that host memory operations will be available.
/// Otherwise implementation is encouraged to use non-host-accessible memory.
const HOST_ACCESS = 0x02;
/// Hints allocator that memory will be used for data downloading.
/// Allocator will strongly prefer host-cached memory.
/// Implies `HOST_ACCESS` flag.
const DOWNLOAD = 0x04;
/// Hints allocator that memory will be used for data uploading.
/// If `DOWNLOAD` flag is not set then allocator will assume that
/// host will access memory in write-only manner and may
/// pick not host-cached.
/// Implies `HOST_ACCESS` flag.
const UPLOAD = 0x08;
/// Hints allocator that memory will be used for short duration
/// allowing to use faster algorithm with less memory overhead.
/// If use holds returned memory block for too long then
/// effective memory overhead increases instead.
/// Best use case is for staging buffer for single batch of operations.
const TRANSIENT = 0x10;
/// Requests memory that can be addressed with `u64`.
/// Allows fetching device address for resources bound to that memory.
const DEVICE_ADDRESS = 0x20;
}
}
#[derive(Clone, Copy, Debug)]
struct MemoryForOneUsage {
mask: u32,
types: [u32; 32],
types_count: u32,
}
pub(crate) struct MemoryForUsage {
usages: [MemoryForOneUsage; 64],
}
impl Debug for MemoryForUsage {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("MemoryForUsage")
.field("usages", &&self.usages[..])
.finish()
}
}
impl MemoryForUsage {
pub fn new(memory_types: &[MemoryType]) -> Self {
assert!(
memory_types.len() <= 32,
"Only up to 32 memory types supported"
);
let mut mfu = MemoryForUsage {
usages: [MemoryForOneUsage {
mask: 0,
types: [0; 32],
types_count: 0,
}; 64],
};
for usage in 0..64 {
mfu.usages[usage as usize] =
one_usage(UsageFlags::from_bits_truncate(usage), memory_types);
}
mfu
}
/// Returns mask with bits set for memory type indices that support the
/// usage.
pub fn mask(&self, usage: UsageFlags) -> u32 {
self.usages[usage.bits() as usize].mask
}
/// Returns slice of memory type indices that support the usage.
/// Earlier memory type has priority over later.
pub fn types(&self, usage: UsageFlags) -> &[u32] {
let usage = &self.usages[usage.bits() as usize];
&usage.types[..usage.types_count as usize]
}
}
fn one_usage(usage: UsageFlags, memory_types: &[MemoryType]) -> MemoryForOneUsage {
let mut types = [0; 32];
let mut types_count = 0;
for (index, mt) in memory_types.iter().enumerate() {
if compatible(usage, mt.props) {
types[types_count as usize] = index as u32;
types_count += 1;
}
}
types[..types_count as usize]
.sort_unstable_by_key(|&index| reverse_priority(usage, memory_types[index as usize].props));
let mask = types[..types_count as usize]
.iter()
.fold(0u32, |mask, index| mask | 1u32 << index);
MemoryForOneUsage {
mask,
types,
types_count,
}
}
fn compatible(usage: UsageFlags, flags: MemoryPropertyFlags) -> bool {
type Flags = MemoryPropertyFlags;
if flags.contains(Flags::LAZILY_ALLOCATED) || flags.contains(Flags::PROTECTED) {
// Unsupported
false
} else if usage.intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD)
{
// Requires HOST_VISIBLE
flags.contains(Flags::HOST_VISIBLE)
} else {
true
}
}
/// Returns reversed priority of memory with specified flags for specified usage.
/// Lesser value returned = more prioritized.
fn reverse_priority(usage: UsageFlags, flags: MemoryPropertyFlags) -> u32 {
type Flags = MemoryPropertyFlags;
// Highly prefer device local memory when `FAST_DEVICE_ACCESS` usage is specified
// or usage is empty.
let device_local: bool = flags.contains(Flags::DEVICE_LOCAL)
^ (usage.is_empty() || usage.contains(UsageFlags::FAST_DEVICE_ACCESS));
assert!(
flags.contains(Flags::HOST_VISIBLE)
|| !usage
.intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD)
);
// Prefer non-host-visible memory when host access is not required.
let host_visible: bool = flags.contains(Flags::HOST_VISIBLE)
^ usage.intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD);
// Prefer cached memory for downloads.
// Or non-cached if downloads are not expected.
let host_cached: bool =
flags.contains(Flags::HOST_CACHED) ^ usage.contains(UsageFlags::DOWNLOAD);
// Prefer coherent for both uploads and downloads.
// Prefer non-coherent if neither flags is set.
let host_coherent: bool = flags.contains(Flags::HOST_COHERENT)
^ (usage.intersects(UsageFlags::UPLOAD | UsageFlags::DOWNLOAD));
// Each boolean is false if flags are preferred.
device_local as u32 * 8
+ host_visible as u32 * 4
+ host_cached as u32 * 2
+ host_coherent as u32
}

View File

@ -1,44 +1,44 @@
use alloc::sync::Arc;
/// Guarantees uniqueness only if `Weak` pointers are never created
/// from this `Arc` or clones.
pub(crate) fn is_arc_unique<M>(arc: &mut Arc<M>) -> bool {
let strong_count = Arc::strong_count(&*arc);
debug_assert_ne!(strong_count, 0, "This Arc should exist");
debug_assert!(
strong_count > 1 || Arc::get_mut(arc).is_some(),
"`Weak` pointer exists"
);
strong_count == 1
}
/// Can be used instead of `Arc::try_unwrap(arc).unwrap()`
/// when it is guaranteed to succeed.
pub(crate) unsafe fn arc_unwrap<M>(mut arc: Arc<M>) -> M {
use core::{mem::ManuallyDrop, ptr::read};
debug_assert!(is_arc_unique(&mut arc));
// Get raw pointer to inner value.
let raw = Arc::into_raw(arc);
// As `Arc` is unique and no Weak pointers exist
// it won't be dereferenced elsewhere.
let inner = read(raw);
// Cast to `ManuallyDrop` which guarantees to have same layout
// and will skip dropping.
drop(Arc::from_raw(raw as *const ManuallyDrop<M>));
inner
}
/// Can be used instead of `Arc::try_unwrap`
/// only if `Weak` pointers are never created from this `Arc` or clones.
pub(crate) unsafe fn try_arc_unwrap<M>(mut arc: Arc<M>) -> Option<M> {
if is_arc_unique(&mut arc) {
Some(arc_unwrap(arc))
} else {
None
}
}
use alloc::sync::Arc;
/// Guarantees uniqueness only if `Weak` pointers are never created
/// from this `Arc` or clones.
pub(crate) fn is_arc_unique<M>(arc: &mut Arc<M>) -> bool {
let strong_count = Arc::strong_count(&*arc);
debug_assert_ne!(strong_count, 0, "This Arc should exist");
debug_assert!(
strong_count > 1 || Arc::get_mut(arc).is_some(),
"`Weak` pointer exists"
);
strong_count == 1
}
/// Can be used instead of `Arc::try_unwrap(arc).unwrap()`
/// when it is guaranteed to succeed.
pub(crate) unsafe fn arc_unwrap<M>(mut arc: Arc<M>) -> M {
use core::{mem::ManuallyDrop, ptr::read};
debug_assert!(is_arc_unique(&mut arc));
// Get raw pointer to inner value.
let raw = Arc::into_raw(arc);
// As `Arc` is unique and no Weak pointers exist
// it won't be dereferenced elsewhere.
let inner = read(raw);
// Cast to `ManuallyDrop` which guarantees to have same layout
// and will skip dropping.
drop(Arc::from_raw(raw as *const ManuallyDrop<M>));
inner
}
/// Can be used instead of `Arc::try_unwrap`
/// only if `Weak` pointers are never created from this `Arc` or clones.
pub(crate) unsafe fn try_arc_unwrap<M>(mut arc: Arc<M>) -> Option<M> {
if is_arc_unique(&mut arc) {
Some(arc_unwrap(arc))
} else {
None
}
}

File diff suppressed because one or more lines are too long

1121
third_party/rust/metal/Cargo.lock generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,9 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
edition = "2021"
name = "metal"
version = "0.24.0"
version = "0.25.0"
authors = ["GFX Developers"]
exclude = [
"guide/**/*",
@ -45,6 +45,9 @@ name = "headless-render"
[[example]]
name = "library"
[[example]]
name = "raytracing"
[[example]]
name = "reflection"
@ -101,7 +104,7 @@ version = "0.2"
optional = true
[dependencies.foreign-types]
version = "0.3.2"
version = "0.5"
[dependencies.log]
version = "0.4"
@ -110,20 +113,29 @@ version = "0.4"
version = "0.2.4"
features = ["objc_exception"]
[dependencies.paste]
version = "1"
[dev-dependencies.cocoa]
version = "0.24.0"
[dev-dependencies.cty]
version = "0.2.1"
[dev-dependencies.glam]
version = "0.22"
[dev-dependencies.png]
version = "0.16"
version = "0.17"
[dev-dependencies.rand]
version = "0.8"
[dev-dependencies.sema]
version = "0.1.4"
[dev-dependencies.winit]
version = "0.24"
version = "0.27"
[features]
default = []

View File

@ -10,3 +10,7 @@ window:
circle:
xcrun -sdk macosx metal -c examples/circle/shaders.metal -o examples/circle/shaders.air
xcrun -sdk macosx metallib examples/circle/shaders.air -o examples/circle/shaders.metallib
raytracing:
xcrun -sdk macosx metal -c -g examples/raytracing/shaders.metal -o examples/raytracing/shaders.air
xcrun -sdk macosx metallib examples/raytracing/shaders.air -o examples/raytracing/shaders.metallib

View File

@ -2,7 +2,18 @@
[![Actions Status](https://github.com/gfx-rs/metal-rs/workflows/ci/badge.svg)](https://github.com/gfx-rs/metal-rs/actions)
[![Crates.io](https://img.shields.io/crates/v/metal.svg?label=metal)](https://crates.io/crates/metal)
Unsafe Rust bindings for the Metal 3D Graphics API.
<p align="center">
<img width="150" height="150" src="./assets/metal.svg">
</p>
<p align="center">Unsafe Rust bindings for the Metal 3D Graphics API.</p>
## Documentation
Note that [docs.rs](docs.rs) will fail to build the (albeit limited) documentation for this crate!
They build in a Linux container, but of course this will only compile on MacOS.
Please build the documentation yourself with `cargo docs`.
## Examples

Some files were not shown because too many files have changed in this diff Show More