Bump Many Dependencies and MSRV (#5241)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
This commit is contained in:
dependabot[bot] 2024-02-27 14:43:05 -05:00 committed by GitHub
parent d365927903
commit 744454b9e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 413 additions and 416 deletions

View File

@ -40,7 +40,7 @@ env:
# Once 1.76 coes out, we can use that instead of nightly. # Once 1.76 coes out, we can use that instead of nightly.
DOCS_RUST_VERSION: "nightly-2023-12-17" DOCS_RUST_VERSION: "nightly-2023-12-17"
# This is the MSRV used by `wgpu` itself and all surrounding infrastructure. # This is the MSRV used by `wgpu` itself and all surrounding infrastructure.
REPO_MSRV: "1.71" REPO_MSRV: "1.76"
# This is the MSRV used by the `wgpu-core`, `wgpu-hal`, and `wgpu-types` crates, # This is the MSRV used by the `wgpu-core`, `wgpu-hal`, and `wgpu-types` crates,
# to ensure that they can be used with firefox. # to ensure that they can be used with firefox.
CORE_MSRV: "1.70" CORE_MSRV: "1.70"

539
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -114,7 +114,7 @@ renderdoc-sys = "1.0.0"
ron = "0.8" ron = "0.8"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
serde = "1" serde = "1"
serde_json = "1.0.111" serde_json = "1.0.113"
smallvec = "1" smallvec = "1"
static_assertions = "1.1.0" static_assertions = "1.1.0"
thiserror = "1" thiserror = "1"
@ -159,7 +159,7 @@ console_error_panic_hook = "0.1.7"
console_log = "1" console_log = "1"
js-sys = "0.3.67" js-sys = "0.3.67"
wasm-bindgen = "0.2.87" wasm-bindgen = "0.2.87"
wasm-bindgen-futures = "0.4.40" wasm-bindgen-futures = "0.4.41"
wasm-bindgen-test = "0.3" wasm-bindgen-test = "0.3"
web-sys = "0.3.67" web-sys = "0.3.67"
web-time = "0.2.4" web-time = "0.2.4"
@ -171,7 +171,7 @@ deno_url = "0.125.0"
deno_web = "0.156.0" deno_web = "0.156.0"
deno_webidl = "0.125.0" deno_webidl = "0.125.0"
deno_webgpu = { version = "0.85.0", path = "./deno_webgpu" } deno_webgpu = { version = "0.85.0", path = "./deno_webgpu" }
tokio = "1.35.1" tokio = "1.36.0"
termcolor = "1.4.1" termcolor = "1.4.1"
[patch."https://github.com/gfx-rs/naga"] [patch."https://github.com/gfx-rs/naga"]

View File

@ -119,8 +119,9 @@ On Linux, you can point to them using `LD_LIBRARY_PATH` environment.
### MSRV policy ### MSRV policy
Due to complex dependants, we have two MSRV policies: Due to complex dependants, we have two MSRV policies:
- `d3d12`, `naga`, `wgpu-core`, `wgpu-hal`, and `wgpu-types`'s MSRV is **1.70**. - `d3d12`, `naga`, `wgpu-core`, `wgpu-hal`, and `wgpu-types`'s MSRV is **1.70**.
- The rest of the workspace has an MSRV of **1.71**. - The rest of the workspace has an MSRV of **1.76**.
It is enforced on CI (in "/.github/workflows/ci.yml") with the `CORE_MSRV` and `REPO_MSRV` variables. It is enforced on CI (in "/.github/workflows/ci.yml") with the `CORE_MSRV` and `REPO_MSRV` variables.
This version can only be upgraded in breaking releases, though we release a breaking version every three months. This version can only be upgraded in breaking releases, though we release a breaking version every three months.

View File

@ -118,13 +118,7 @@ mod native {
deno_core::error::get_custom_error_class(e) deno_core::error::get_custom_error_class(e)
.or_else(|| deno_webgpu::error::get_error_class_name(e)) .or_else(|| deno_webgpu::error::get_error_class_name(e))
.unwrap_or_else(|| { .unwrap_or_else(|| {
panic!( panic!("Error '{e}' contains boxed error of unsupported type: {e:#}");
"Error '{}' contains boxed error of unsupported type:{}",
e,
e.chain()
.map(|e| format!("\n {:?}", e))
.collect::<String>()
);
}) })
} }

View File

@ -1,3 +1,5 @@
#![allow(clippy::arc_with_non_send_sync)] // False positive on wasm
pub mod framework; pub mod framework;
pub mod utils; pub mod utils;

View File

@ -54,8 +54,8 @@ indexmap = { version = "2", features = ["std"] }
log = "0.4" log = "0.4"
num-traits = "0.2" num-traits = "0.2"
spirv = { version = "0.3", optional = true } spirv = { version = "0.3", optional = true }
thiserror = "1.0.56" thiserror = "1.0.57"
serde = { version = "1.0.195", features = ["derive"], optional = true } serde = { version = "1.0.196", features = ["derive"], optional = true }
petgraph = { version = "0.6", optional = true } petgraph = { version = "0.6", optional = true }
pp-rs = { version = "0.2.1", optional = true } pp-rs = { version = "0.2.1", optional = true }
hexf-parse = { version = "0.2.1", optional = true } hexf-parse = { version = "0.2.1", optional = true }

View File

@ -12,4 +12,4 @@ test = false
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
nanoserde = "0.1.32" nanoserde = "0.1.37"

View File

@ -3048,7 +3048,7 @@ impl<W: Write> Writer<W> {
for statement in statements { for statement in statements {
if let crate::Statement::Emit(ref range) = *statement { if let crate::Statement::Emit(ref range) = *statement {
for handle in range.clone() { for handle in range.clone() {
self.named_expressions.remove(&handle); self.named_expressions.shift_remove(&handle);
} }
} }
} }

View File

@ -109,7 +109,7 @@ impl<W: Write> Writer<W> {
self.reset(module); self.reset(module);
// Save all ep result types // Save all ep result types
for (_, ep) in module.entry_points.iter().enumerate() { for ep in &module.entry_points {
if let Some(ref result) = ep.function.result { if let Some(ref result) = ep.function.result {
self.ep_results.push((ep.stage, result.ty)); self.ep_results.push((ep.stage, result.ty));
} }

View File

@ -160,7 +160,7 @@ impl Frontend {
} => self.matrix_one_arg(ctx, ty, columns, rows, scalar, (value, expr_meta), meta)?, } => self.matrix_one_arg(ctx, ty, columns, rows, scalar, (value, expr_meta), meta)?,
TypeInner::Struct { ref members, .. } => { TypeInner::Struct { ref members, .. } => {
let scalar_components = members let scalar_components = members
.get(0) .first()
.and_then(|member| scalar_components(&ctx.module.types[member.ty].inner)); .and_then(|member| scalar_components(&ctx.module.types[member.ty].inner));
if let Some(scalar) = scalar_components { if let Some(scalar) = scalar_components {
ctx.implicit_conversion(&mut value, expr_meta, scalar)?; ctx.implicit_conversion(&mut value, expr_meta, scalar)?;

View File

@ -5320,6 +5320,21 @@ pub fn parse_u8_slice(data: &[u8], options: &Options) -> Result<crate::Module, E
Frontend::new(words, options).parse() Frontend::new(words, options).parse()
} }
/// Helper function to check if `child` is in the scope of `parent`
fn is_parent(mut child: usize, parent: usize, block_ctx: &BlockContext) -> bool {
loop {
if child == parent {
// The child is in the scope parent
break true;
} else if child == 0 {
// Searched finished at the root the child isn't in the parent's body
break false;
}
child = block_ctx.bodies[child].parent;
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
#[test] #[test]
@ -5336,18 +5351,3 @@ mod test {
let _ = super::parse_u8_slice(&bin, &Default::default()).unwrap(); let _ = super::parse_u8_slice(&bin, &Default::default()).unwrap();
} }
} }
/// Helper function to check if `child` is in the scope of `parent`
fn is_parent(mut child: usize, parent: usize, block_ctx: &BlockContext) -> bool {
loop {
if child == parent {
// The child is in the scope parent
break true;
} else if child == 0 {
// Searched finished at the root the child isn't in the parent's body
break false;
}
child = block_ctx.bodies[child].parent;
}
}

View File

@ -87,7 +87,7 @@ impl ParseError {
/// Returns a [`SourceLocation`] for the first label in the error message. /// Returns a [`SourceLocation`] for the first label in the error message.
pub fn location(&self, source: &str) -> Option<SourceLocation> { pub fn location(&self, source: &str) -> Option<SourceLocation> {
self.labels.get(0).map(|label| label.0.location(source)) self.labels.first().map(|label| label.0.location(source))
} }
} }

View File

@ -252,7 +252,8 @@ An override expression can be evaluated at pipeline creation time.
clippy::collapsible_if, clippy::collapsible_if,
clippy::derive_partial_eq_without_eq, clippy::derive_partial_eq_without_eq,
clippy::needless_borrowed_reference, clippy::needless_borrowed_reference,
clippy::single_match clippy::single_match,
clippy::enum_variant_names
)] )]
#![warn( #![warn(
trivial_casts, trivial_casts,

View File

@ -1877,6 +1877,95 @@ impl<'a> ConstantEvaluator<'a> {
} }
} }
/// Trait for conversions of abstract values to concrete types.
trait TryFromAbstract<T>: Sized {
/// Convert an abstract literal `value` to `Self`.
///
/// Since Naga's `AbstractInt` and `AbstractFloat` exist to support
/// WGSL, we follow WGSL's conversion rules here:
///
/// - WGSL §6.1.2. Conversion Rank says that automatic conversions
/// to integers are either lossless or an error.
///
/// - WGSL §14.6.4 Floating Point Conversion says that conversions
/// to floating point in constant expressions and override
/// expressions are errors if the value is out of range for the
/// destination type, but rounding is okay.
///
/// [`AbstractInt`]: crate::Literal::AbstractInt
/// [`Float`]: crate::Literal::Float
fn try_from_abstract(value: T) -> Result<Self, ConstantEvaluatorError>;
}
impl TryFromAbstract<i64> for i32 {
fn try_from_abstract(value: i64) -> Result<i32, ConstantEvaluatorError> {
i32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
value: format!("{value:?}"),
to_type: "i32",
})
}
}
impl TryFromAbstract<i64> for u32 {
fn try_from_abstract(value: i64) -> Result<u32, ConstantEvaluatorError> {
u32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
value: format!("{value:?}"),
to_type: "u32",
})
}
}
impl TryFromAbstract<i64> for f32 {
fn try_from_abstract(value: i64) -> Result<Self, ConstantEvaluatorError> {
let f = value as f32;
// The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of
// `f32` is roughly ±3.4 × 10³⁸, so there's no opportunity for
// overflow here.
Ok(f)
}
}
impl TryFromAbstract<f64> for f32 {
fn try_from_abstract(value: f64) -> Result<f32, ConstantEvaluatorError> {
let f = value as f32;
if f.is_infinite() {
return Err(ConstantEvaluatorError::AutomaticConversionLossy {
value: format!("{value:?}"),
to_type: "f32",
});
}
Ok(f)
}
}
impl TryFromAbstract<i64> for f64 {
fn try_from_abstract(value: i64) -> Result<Self, ConstantEvaluatorError> {
let f = value as f64;
// The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of
// `f64` is roughly ±1.8 × 10³⁰⁸, so there's no opportunity for
// overflow here.
Ok(f)
}
}
impl TryFromAbstract<f64> for f64 {
fn try_from_abstract(value: f64) -> Result<f64, ConstantEvaluatorError> {
Ok(value)
}
}
impl TryFromAbstract<f64> for i32 {
fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "i32" })
}
}
impl TryFromAbstract<f64> for u32 {
fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "u32" })
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::vec; use std::vec;
@ -2384,92 +2473,3 @@ mod tests {
} }
} }
} }
/// Trait for conversions of abstract values to concrete types.
trait TryFromAbstract<T>: Sized {
/// Convert an abstract literal `value` to `Self`.
///
/// Since Naga's `AbstractInt` and `AbstractFloat` exist to support
/// WGSL, we follow WGSL's conversion rules here:
///
/// - WGSL §6.1.2. Conversion Rank says that automatic conversions
/// to integers are either lossless or an error.
///
/// - WGSL §14.6.4 Floating Point Conversion says that conversions
/// to floating point in constant expressions and override
/// expressions are errors if the value is out of range for the
/// destination type, but rounding is okay.
///
/// [`AbstractInt`]: crate::Literal::AbstractInt
/// [`Float`]: crate::Literal::Float
fn try_from_abstract(value: T) -> Result<Self, ConstantEvaluatorError>;
}
impl TryFromAbstract<i64> for i32 {
fn try_from_abstract(value: i64) -> Result<i32, ConstantEvaluatorError> {
i32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
value: format!("{value:?}"),
to_type: "i32",
})
}
}
impl TryFromAbstract<i64> for u32 {
fn try_from_abstract(value: i64) -> Result<u32, ConstantEvaluatorError> {
u32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
value: format!("{value:?}"),
to_type: "u32",
})
}
}
impl TryFromAbstract<i64> for f32 {
fn try_from_abstract(value: i64) -> Result<Self, ConstantEvaluatorError> {
let f = value as f32;
// The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of
// `f32` is roughly ±3.4 × 10³⁸, so there's no opportunity for
// overflow here.
Ok(f)
}
}
impl TryFromAbstract<f64> for f32 {
fn try_from_abstract(value: f64) -> Result<f32, ConstantEvaluatorError> {
let f = value as f32;
if f.is_infinite() {
return Err(ConstantEvaluatorError::AutomaticConversionLossy {
value: format!("{value:?}"),
to_type: "f32",
});
}
Ok(f)
}
}
impl TryFromAbstract<i64> for f64 {
fn try_from_abstract(value: i64) -> Result<Self, ConstantEvaluatorError> {
let f = value as f64;
// The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of
// `f64` is roughly ±1.8 × 10³⁰⁸, so there's no opportunity for
// overflow here.
Ok(f)
}
}
impl TryFromAbstract<f64> for f64 {
fn try_from_abstract(value: f64) -> Result<f64, ConstantEvaluatorError> {
Ok(value)
}
}
impl TryFromAbstract<f64> for i32 {
fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "i32" })
}
}
impl TryFromAbstract<f64> for u32 {
fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "u32" })
}
}

View File

@ -871,6 +871,7 @@ macro_rules! check_one_validation {
( $source:expr, $pattern:pat $( if $guard:expr )? ) => { ( $source:expr, $pattern:pat $( if $guard:expr )? ) => {
let source = $source; let source = $source;
let error = validation_error($source); let error = validation_error($source);
#[allow(clippy::redundant_pattern_matching)]
if ! matches!(&error, $pattern $( if $guard )? ) { if ! matches!(&error, $pattern $( if $guard )? ) {
eprintln!("validation error does not match pattern:\n\ eprintln!("validation error does not match pattern:\n\
source code: {}\n\ source code: {}\n\

View File

@ -5,6 +5,6 @@
# to the user in the error, instead of "error: invalid channel name '[toolchain]'". # to the user in the error, instead of "error: invalid channel name '[toolchain]'".
[toolchain] [toolchain]
channel = "1.71" # Needed for deno & cts_runner. Firefox's MSRV is 1.70 channel = "1.76" # Needed for deno & cts_runner. Firefox's MSRV is 1.70
components = ["rustfmt", "clippy"] components = ["rustfmt", "clippy"]
targets = ["wasm32-unknown-unknown"] targets = ["wasm32-unknown-unknown"]

View File

@ -1,5 +1,7 @@
//! Test utilities for the wgpu repository. //! Test utilities for the wgpu repository.
#![allow(clippy::arc_with_non_send_sync)] // False positive on wasm
mod config; mod config;
mod expectations; mod expectations;
pub mod image; pub mod image;

View File

@ -424,7 +424,6 @@ impl RenderBundleEncoder {
} }
// Identify the next `num_dynamic_offsets` entries from `base.dynamic_offsets`. // Identify the next `num_dynamic_offsets` entries from `base.dynamic_offsets`.
let num_dynamic_offsets = num_dynamic_offsets;
let offsets_range = let offsets_range =
next_dynamic_offset..next_dynamic_offset + num_dynamic_offsets; next_dynamic_offset..next_dynamic_offset + num_dynamic_offsets;
next_dynamic_offset = offsets_range.end; next_dynamic_offset = offsets_range.end;

View File

@ -343,7 +343,8 @@ impl<A: HalApi> Device<A> {
let Some(bind_group) = bind_group.upgrade() else { let Some(bind_group) = bind_group.upgrade() else {
continue; continue;
}; };
let Some(raw_bind_group) = bind_group.raw.snatch(self.snatchable_lock.write()) else { let Some(raw_bind_group) = bind_group.raw.snatch(self.snatchable_lock.write())
else {
continue; continue;
}; };

View File

@ -275,7 +275,7 @@ where
{ {
#[inline] #[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0) Some(self.cmp(other))
} }
} }

View File

@ -1309,7 +1309,9 @@ pub fn validate_color_attachment_bytes_per_sample(
) -> Result<(), u32> { ) -> Result<(), u32> {
let mut total_bytes_per_sample = 0; let mut total_bytes_per_sample = 0;
for format in attachment_formats { for format in attachment_formats {
let Some(format) = format else { continue; }; let Some(format) = format else {
continue;
};
let byte_cost = format.target_pixel_byte_cost().unwrap(); let byte_cost = format.target_pixel_byte_cost().unwrap();
let alignment = format.target_component_alignment().unwrap(); let alignment = format.target_component_alignment().unwrap();

View File

@ -238,6 +238,9 @@ struct DeviceShared {
heap_samplers: descriptor::GeneralHeap, heap_samplers: descriptor::GeneralHeap,
} }
unsafe impl Send for DeviceShared {}
unsafe impl Sync for DeviceShared {}
pub struct Device { pub struct Device {
raw: d3d12::Device, raw: d3d12::Device,
present_queue: d3d12::CommandQueue, present_queue: d3d12::CommandQueue,

View File

@ -13,7 +13,7 @@ use crate::auxil::dxgi::result::HResult;
pub(super) fn compile_fxc( pub(super) fn compile_fxc(
device: &super::Device, device: &super::Device,
source: &String, source: &str,
source_name: &str, source_name: &str,
raw_ep: &std::ffi::CString, raw_ep: &std::ffi::CString,
stage_bit: wgt::ShaderStages, stage_bit: wgt::ShaderStages,

View File

@ -783,6 +783,7 @@ impl crate::Instance<super::Api> for Instance {
(display, Some(Rc::new(display_owner)), WindowKind::AngleX11) (display, Some(Rc::new(display_owner)), WindowKind::AngleX11)
} else if client_ext_str.contains("EGL_MESA_platform_surfaceless") { } else if client_ext_str.contains("EGL_MESA_platform_surfaceless") {
log::warn!("No windowing system present. Using surfaceless platform"); log::warn!("No windowing system present. Using surfaceless platform");
#[allow(clippy::unnecessary_literal_unwrap)] // This is only a literal on Emscripten
let egl = egl1_5.expect("Failed to get EGL 1.5 for surfaceless"); let egl = egl1_5.expect("Failed to get EGL 1.5 for surfaceless");
let display = unsafe { let display = unsafe {
egl.get_platform_display( egl.get_platform_display(

View File

@ -160,6 +160,9 @@ struct Inner {
context: WglContext, context: WglContext,
} }
unsafe impl Send for Inner {}
unsafe impl Sync for Inner {}
pub struct Instance { pub struct Instance {
srgb_capable: bool, srgb_capable: bool,
inner: Arc<Mutex<Inner>>, inner: Arc<Mutex<Inner>>,

View File

@ -16,6 +16,8 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![allow( #![allow(
// this happens on the GL backend, where it is both thread safe and non-thread safe in the same code.
clippy::arc_with_non_send_sync,
// for `if_then_panic` until it reaches stable // for `if_then_panic` until it reaches stable
unknown_lints, unknown_lints,
// We use loops for getting early-out of scope without closures. // We use loops for getting early-out of scope without closures.

View File

@ -46,4 +46,4 @@ web-sys = { version = "0.3.67", features = [
[dev-dependencies] [dev-dependencies]
serde = { version = "1", features = ["serde_derive"] } serde = { version = "1", features = ["serde_derive"] }
serde_json = "1.0.111" serde_json = "1.0.113"

View File

@ -4777,11 +4777,11 @@ impl Surface<'_> {
let caps = self.get_capabilities(adapter); let caps = self.get_capabilities(adapter);
Some(SurfaceConfiguration { Some(SurfaceConfiguration {
usage: wgt::TextureUsages::RENDER_ATTACHMENT, usage: wgt::TextureUsages::RENDER_ATTACHMENT,
format: *caps.formats.get(0)?, format: *caps.formats.first()?,
width, width,
height, height,
desired_maximum_frame_latency: 2, desired_maximum_frame_latency: 2,
present_mode: *caps.present_modes.get(0)?, present_mode: *caps.present_modes.first()?,
alpha_mode: wgt::CompositeAlphaMode::Auto, alpha_mode: wgt::CompositeAlphaMode::Auto,
view_formats: vec![], view_formats: vec![],
}) })
@ -4931,7 +4931,7 @@ impl<T> Eq for Id<T> {}
impl<T> PartialOrd for Id<T> { impl<T> PartialOrd for Id<T> {
fn partial_cmp(&self, other: &Id<T>) -> Option<Ordering> { fn partial_cmp(&self, other: &Id<T>) -> Option<Ordering> {
self.0.partial_cmp(&other.0) Some(self.cmp(other))
} }
} }

View File

@ -117,6 +117,7 @@ impl StagingBelt {
} else { } else {
let size = self.chunk_size.max(size.get()); let size = self.chunk_size.max(size.get());
Chunk { Chunk {
#[allow(clippy::arc_with_non_send_sync)] // False positive on emscripten
buffer: Arc::new(device.create_buffer(&BufferDescriptor { buffer: Arc::new(device.create_buffer(&BufferDescriptor {
label: Some("(wgpu internal) StagingBelt staging buffer"), label: Some("(wgpu internal) StagingBelt staging buffer"),
size, size,

View File

@ -100,6 +100,7 @@ impl DownloadBuffer {
None => buffer.buffer.map_context.lock().total_size - buffer.offset, None => buffer.buffer.map_context.lock().total_size - buffer.offset,
}; };
#[allow(clippy::arc_with_non_send_sync)] // False positive on emscripten
let download = Arc::new(device.create_buffer(&super::BufferDescriptor { let download = Arc::new(device.create_buffer(&super::BufferDescriptor {
size, size,
usage: super::BufferUsages::COPY_DST | super::BufferUsages::MAP_READ, usage: super::BufferUsages::COPY_DST | super::BufferUsages::MAP_READ,