Vendor things

This commit is contained in:
John Doty 2024-03-08 11:03:01 -08:00
parent 5deceec006
commit 977e3c17e5
19434 changed files with 10682014 additions and 0 deletions

View file

@ -0,0 +1 @@
{"files":{"Cargo.toml":"e813a2e6eafc5201be20df1e359eb73d482ca4311e41a488f78dd83abc0c2614","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","Makefile":"416f06b5e6b93962775f1423f7bb38dbdaadfbf3628c28824b620a527fac41a0","README.md":"1e9b72809941c693cd534cf73a705b31c8351af7bccfb245222bd8a3ebe2159d","src/backend/direct.rs":"31df9574071796069e06013df252705deb0df72b0000ee6477c5404746e2cb79","src/backend/mod.rs":"2603cc214a6eb4dbbe9ce72d487b76bf3091c40410a031cf828aba55689384c6","src/backend/web.rs":"8000a4435bfe4bc71b7aa4a90626c0e234845d8130a33931bcb1d2e1ebeee0a3","src/context.rs":"d7f67d29c4a3b17f8fc65f066a0e60108bfd3d644484cd524c2ade02219ce976","src/lib.rs":"c6a72c41510133eeaadcacc97441bd0bf71d60de338ace21108860c85d42a7c2","src/macros.rs":"721c5f67bc5a54d6dbd6fc7bdfb68d5f865d40d64a91129652ae75f1f28650ba","src/util/belt.rs":"0526f9d7e3cc7770a971f2e50c895ebb00992effb778c3209be675ec025e0513","src/util/device.rs":"bf49a9d2d89ecfe5b422c48b226d0ff61508c3370de324e9123f54feba35ec09","src/util/encoder.rs":"52d0c46fd5ca6c2f80149da18444448ce90c1d76a603ee61a0d47a784e1f3f15","src/util/indirect.rs":"e895429d037ca0720bc0ab8f5912c5fa9510f24fa57c9b3f5ec6b3e283789aaa","src/util/init.rs":"e28d6db4bd5be84ad53f8cd0f9481ff941e8e6131648fc7afaa27c2dc55555b8","src/util/mod.rs":"0504276b0edcc5b6e5ffec108fc4af1b6fa5eabe24beefa6ad81cd81c15130e0"},"package":"752e44d3998ef35f71830dd1ad3da513e628e2e4d4aedb0ab580f850827a0b41"}

317
third-party/vendor/wgpu/Cargo.toml vendored Normal file
View file

@ -0,0 +1,317 @@
# 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 = "2021"
name = "wgpu"
version = "0.17.2"
authors = ["wgpu developers"]
exclude = ["Cargo.lock"]
description = "Rusty WebGPU API wrapper"
homepage = "https://wgpu.rs/"
readme = "README.md"
keywords = ["graphics"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/gfx-rs/wgpu"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = [
"--cfg",
"docsrs",
]
targets = [
"x86_64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
"wasm32-unknown-unknown",
]
[lib]
[dependencies.arrayvec]
version = "0.7"
[dependencies.cfg-if]
version = "1"
[dependencies.log]
version = "0.4"
[dependencies.naga]
version = "0.13.0"
features = ["clone"]
optional = true
[dependencies.parking_lot]
version = ">=0.11,<0.13"
[dependencies.profiling]
version = "1"
default-features = false
[dependencies.raw-window-handle]
version = "0.5"
[dependencies.serde]
version = "1"
features = ["derive"]
optional = true
[dependencies.smallvec]
version = "1"
[dependencies.static_assertions]
version = "1.1.0"
[dependencies.wgc]
version = "0.17"
features = [
"raw-window-handle",
"gles",
]
optional = true
package = "wgpu-core"
[dependencies.wgt]
version = "0.17"
package = "wgpu-types"
[dev-dependencies.naga]
version = "0.13.0"
features = ["wgsl-in"]
[features]
angle = ["wgc/angle"]
default = ["wgsl"]
expose-ids = []
fragile-send-sync-non-atomic-wasm = [
"hal/fragile-send-sync-non-atomic-wasm",
"wgc/fragile-send-sync-non-atomic-wasm",
"wgt/fragile-send-sync-non-atomic-wasm",
]
glsl = ["naga/glsl-in"]
replay = [
"serde",
"wgc/replay",
]
spirv = ["naga/spv-in"]
strict_asserts = [
"wgc?/strict_asserts",
"wgt/strict_asserts",
]
trace = [
"serde",
"wgc/trace",
]
vulkan-portability = ["wgc/vulkan"]
webgl = [
"hal",
"wgc",
]
wgsl = ["wgc?/wgsl"]
[target."cfg(all(not(target_arch = \"wasm32\"), unix, not(target_os = \"ios\"), not(target_os = \"macos\")))".dependencies.hal]
version = "0.17"
features = ["renderdoc"]
package = "wgpu-hal"
[target."cfg(any(not(target_arch = \"wasm32\"), target_os = \"emscripten\"))".dependencies.hal]
version = "0.17"
package = "wgpu-hal"
[target."cfg(any(not(target_arch = \"wasm32\"), target_os = \"emscripten\"))".dependencies.wgc]
version = "0.17"
features = [
"raw-window-handle",
"gles",
]
package = "wgpu-core"
[target."cfg(any(target_os = \"macos\", target_os = \"ios\"))".dependencies.wgc]
version = "0.17"
features = ["metal"]
package = "wgpu-core"
[target."cfg(any(windows, all(unix, not(target_os = \"emscripten\"), not(target_os = \"ios\"), not(target_os = \"macos\"))))".dependencies.wgc]
version = "0.17"
features = ["vulkan"]
package = "wgpu-core"
[target."cfg(target_arch = \"wasm32\")".dependencies.hal]
version = "0.17"
optional = true
package = "wgpu-hal"
[target."cfg(target_arch = \"wasm32\")".dependencies.js-sys]
version = "0.3.64"
[target."cfg(target_arch = \"wasm32\")".dependencies.naga]
version = "0.13.0"
features = ["wgsl-out"]
[target."cfg(target_arch = \"wasm32\")".dependencies.parking_lot]
version = ">=0.11,<0.13"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
version = "0.2.87"
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen-futures]
version = "0.4.34"
[target."cfg(target_arch = \"wasm32\")".dependencies.web-sys]
version = "0.3.65"
features = [
"Document",
"Navigator",
"Node",
"NodeList",
"Gpu",
"GpuAdapter",
"GpuAddressMode",
"GpuAutoLayoutMode",
"GpuBindGroup",
"GpuBindGroupDescriptor",
"GpuBindGroupEntry",
"GpuBindGroupLayout",
"GpuBindGroupLayoutDescriptor",
"GpuBindGroupLayoutEntry",
"GpuBlendComponent",
"GpuBlendFactor",
"GpuBlendOperation",
"GpuBlendState",
"GpuBuffer",
"GpuBufferBinding",
"GpuBufferBindingLayout",
"GpuBufferBindingType",
"GpuBufferDescriptor",
"GpuCanvasAlphaMode",
"GpuCanvasContext",
"GpuCanvasConfiguration",
"GpuColorDict",
"GpuColorTargetState",
"GpuCommandBuffer",
"GpuCommandBufferDescriptor",
"GpuCommandEncoder",
"GpuCommandEncoderDescriptor",
"GpuCompareFunction",
"GpuCompilationInfo",
"GpuCompilationMessage",
"GpuCompilationMessageType",
"GpuComputePassDescriptor",
"GpuComputePassEncoder",
"GpuComputePipeline",
"GpuComputePipelineDescriptor",
"GpuCullMode",
"GpuDepthStencilState",
"GpuDevice",
"GpuDeviceDescriptor",
"GpuDeviceLostInfo",
"GpuDeviceLostReason",
"GpuError",
"GpuErrorFilter",
"GpuExtent3dDict",
"GpuFeatureName",
"GpuFilterMode",
"GpuFragmentState",
"GpuFrontFace",
"GpuImageCopyBuffer",
"GpuImageCopyExternalImage",
"GpuImageCopyTexture",
"GpuImageCopyTextureTagged",
"GpuImageDataLayout",
"GpuIndexFormat",
"GpuLoadOp",
"gpu_map_mode",
"GpuMipmapFilterMode",
"GpuMultisampleState",
"GpuObjectDescriptorBase",
"GpuOrigin2dDict",
"GpuOrigin3dDict",
"GpuOutOfMemoryError",
"GpuPipelineDescriptorBase",
"GpuPipelineLayout",
"GpuPipelineLayoutDescriptor",
"GpuPowerPreference",
"GpuPrimitiveState",
"GpuPrimitiveTopology",
"GpuProgrammableStage",
"GpuQuerySet",
"GpuQuerySetDescriptor",
"GpuQueryType",
"GpuQueue",
"GpuRenderBundle",
"GpuRenderBundleDescriptor",
"GpuRenderBundleEncoder",
"GpuRenderBundleEncoderDescriptor",
"GpuRenderPassColorAttachment",
"GpuRenderPassDepthStencilAttachment",
"GpuRenderPassDescriptor",
"GpuRenderPassEncoder",
"GpuRenderPipeline",
"GpuRenderPipelineDescriptor",
"GpuRequestAdapterOptions",
"GpuSampler",
"GpuSamplerBindingLayout",
"GpuSamplerBindingType",
"GpuSamplerDescriptor",
"GpuShaderModule",
"GpuShaderModuleDescriptor",
"GpuStencilFaceState",
"GpuStencilOperation",
"GpuStorageTextureAccess",
"GpuStorageTextureBindingLayout",
"GpuStoreOp",
"GpuSupportedFeatures",
"GpuSupportedLimits",
"GpuTexture",
"GpuTextureAspect",
"GpuTextureBindingLayout",
"GpuTextureDescriptor",
"GpuTextureDimension",
"GpuTextureFormat",
"GpuTextureSampleType",
"GpuTextureView",
"GpuTextureViewDescriptor",
"GpuTextureViewDimension",
"GpuUncapturedErrorEvent",
"GpuUncapturedErrorEventInit",
"GpuValidationError",
"GpuVertexAttribute",
"GpuVertexBufferLayout",
"GpuVertexFormat",
"GpuVertexState",
"GpuVertexStepMode",
"HtmlCanvasElement",
"OffscreenCanvas",
"ImageBitmap",
"ImageBitmapRenderingContext",
"Window",
"WorkerGlobalScope",
"WorkerNavigator",
]
[target."cfg(windows)".dependencies.hal]
version = "0.17"
features = [
"dxc_shader_compiler",
"renderdoc",
"windows_rs",
]
package = "wgpu-hal"
[target."cfg(windows)".dependencies.wgc]
version = "0.17"
features = [
"dx11",
"dx12",
]
package = "wgpu-core"

176
third-party/vendor/wgpu/LICENSE.APACHE vendored Normal file
View file

@ -0,0 +1,176 @@
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

21
third-party/vendor/wgpu/LICENSE.MIT vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 The gfx-rs 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.

20
third-party/vendor/wgpu/Makefile vendored Normal file
View file

@ -0,0 +1,20 @@
# This Makefile generates SPIR-V shaders from GLSL shaders in the examples.
shader_compiler = glslangValidator
# All input shaders.
glsls = $(wildcard examples/*/*.vert examples/*/*.frag examples/*/*.comp)
# All SPIR-V targets.
spirvs = $(addsuffix .spv,$(glsls))
.PHONY: default
default: $(spirvs)
# Rule for making a SPIR-V target.
$(spirvs): %.spv: %
$(shader_compiler) -V $< -o $@
.PHONY: clean
clean:
rm -f $(spirvs)

60
third-party/vendor/wgpu/README.md vendored Normal file
View file

@ -0,0 +1,60 @@
<img align="right" width="25%" src="https://raw.githubusercontent.com/gfx-rs/wgpu/master/logo.png">
wgpu-rs is an idiomatic Rust wrapper over [wgpu-core](https://github.com/gfx-rs/wgpu). It's designed to be suitable for general purpose graphics and computation needs of Rust community.
wgpu-rs can target both the natively supported backends and Wasm directly.
See our [gallery](https://wgpu.rs/#showcase) and the [wiki page](https://github.com/gfx-rs/wgpu/wiki/Users) for the list of libraries and applications using `wgpu-rs`.
## Usage
### How to Run Examples
All examples are located under the [examples](examples) directory.
These examples use the default syntax for running examples, as found in the [Cargo](https://doc.rust-lang.org/cargo/reference/manifest.html#examples) documentation. For example, to run the `cube` example:
```bash
cargo run --bin cube
```
The `hello*` examples show bare-bones setup without any helper code. For `hello-compute`, pass 4 numbers separated by spaces as arguments:
```bash
cargo run --bin hello-compute 1 2 3 4
```
The following environment variables can be used to configure how the framework examples run:
- `WGPU_BACKEND`
Options: `vulkan`, `metal`, `dx11`, `dx12`, `gl`, `webgpu`
If unset a default backend is chosen based on what is supported
by your system.
- `WGPU_POWER_PREF`
Options: `low`, `high`
If unset a low power adapter is preferred.
- `WGPU_ADAPTER_NAME`
Select a specific adapter by specifying a substring of the adapter name.
#### Run Examples on the Web (`wasm32-unknown-unknown`)
See [wiki article](https://github.com/gfx-rs/wgpu/wiki/Running-on-the-Web-with-WebGPU-and-WebGL).
## Shaders
[WGSL](https://gpuweb.github.io/gpuweb/wgsl/) is the main shading language of WebGPU.
Users can run the [naga](https://github.com/gfx-rs/naga) binary in the following way to convert their SPIR-V shaders to WGSL:
```bash
cargo run -- <input.spv> <output.wgsl>
```
In addition, SPIR-V can be used by enabling the `spirv` feature and GLSL can be enabled by enabling the `glsl` feature at the cost of slightly increased build times.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,23 @@
#[cfg(all(
target_arch = "wasm32",
not(any(target_os = "emscripten", feature = "webgl"))
))]
mod web;
#[cfg(all(
target_arch = "wasm32",
not(any(target_os = "emscripten", feature = "webgl"))
))]
pub(crate) use web::Context;
#[cfg(any(
not(target_arch = "wasm32"),
target_os = "emscripten",
feature = "webgl"
))]
mod direct;
#[cfg(any(
not(target_arch = "wasm32"),
target_os = "emscripten",
feature = "webgl"
))]
pub(crate) use direct::Context;

3318
third-party/vendor/wgpu/src/backend/web.rs vendored Normal file

File diff suppressed because it is too large Load diff

4021
third-party/vendor/wgpu/src/context.rs vendored Normal file

File diff suppressed because it is too large Load diff

5069
third-party/vendor/wgpu/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load diff

93
third-party/vendor/wgpu/src/macros.rs vendored Normal file
View file

@ -0,0 +1,93 @@
//! Convenience macros
/// Macro to produce an array of [`VertexAttribute`](crate::VertexAttribute).
///
/// Output has type: `[VertexAttribute; _]`. Usage is as follows:
/// ```
/// # use wgpu::vertex_attr_array;
/// let attrs = vertex_attr_array![0 => Float32x2, 1 => Float32, 2 => Uint16x4];
/// ```
/// This example specifies a list of three [`VertexAttribute`](crate::VertexAttribute),
/// each with the given `shader_location` and `format`.
/// Offsets are calculated automatically.
#[macro_export]
macro_rules! vertex_attr_array {
($($loc:expr => $fmt:ident),* $(,)?) => {
$crate::vertex_attr_array!([] ; 0; $($loc => $fmt ,)*)
};
([$($t:expr,)*] ; $off:expr ;) => { [$($t,)*] };
([$($t:expr,)*] ; $off:expr ; $loc:expr => $item:ident, $($ll:expr => $ii:ident ,)*) => {
$crate::vertex_attr_array!(
[$($t,)*
$crate::VertexAttribute {
format: $crate::VertexFormat :: $item,
offset: $off,
shader_location: $loc,
},];
$off + $crate::VertexFormat :: $item.size();
$($ll => $ii ,)*
)
};
}
#[test]
fn test_vertex_attr_array() {
let attrs = vertex_attr_array![0 => Float32x2, 3 => Uint16x4];
// VertexAttribute does not support PartialEq, so we cannot test directly
assert_eq!(attrs.len(), 2);
assert_eq!(attrs[0].offset, 0);
assert_eq!(attrs[0].shader_location, 0);
assert_eq!(attrs[1].offset, std::mem::size_of::<(f32, f32)>() as u64);
assert_eq!(attrs[1].shader_location, 3);
}
/// Macro to load a SPIR-V module statically.
///
/// It ensures the word alignment as well as the magic number.
///
/// Return type: [`crate::ShaderModuleDescriptor`]
#[macro_export]
#[cfg(feature = "spirv")]
macro_rules! include_spirv {
($($token:tt)*) => {
{
//log::info!("including '{}'", $($token)*);
$crate::ShaderModuleDescriptor {
label: Some($($token)*),
source: $crate::util::make_spirv(include_bytes!($($token)*)),
}
}
};
}
/// Macro to load raw SPIR-V data statically, for use with [`Features::SPIRV_SHADER_PASSTHROUGH`].
///
/// It ensures the word alignment as well as the magic number.
///
/// [`Features::SPIRV_SHADER_PASSTHROUGH`]: crate::Features::SPIRV_SHADER_PASSTHROUGH
#[macro_export]
macro_rules! include_spirv_raw {
($($token:tt)*) => {
{
//log::info!("including '{}'", $($token)*);
$crate::ShaderModuleDescriptorSpirV {
label: Some($($token)*),
source: $crate::util::make_spirv_raw(include_bytes!($($token)*)),
}
}
};
}
/// Macro to load a WGSL module statically.
#[macro_export]
macro_rules! include_wgsl {
($($token:tt)*) => {
{
//log::info!("including '{}'", $($token)*);
$crate::ShaderModuleDescriptor {
label: Some($($token)*),
source: $crate::ShaderSource::Wgsl(include_str!($($token)*).into()),
}
}
};
}

183
third-party/vendor/wgpu/src/util/belt.rs vendored Normal file
View file

@ -0,0 +1,183 @@
use crate::{
util::align_to, Buffer, BufferAddress, BufferDescriptor, BufferSize, BufferUsages,
BufferViewMut, CommandEncoder, Device, MapMode,
};
use std::fmt;
use std::sync::{mpsc, Arc};
struct Chunk {
buffer: Arc<Buffer>,
size: BufferAddress,
offset: BufferAddress,
}
/// Efficiently performs many buffer writes by sharing and reusing temporary buffers.
///
/// Internally it uses a ring-buffer of staging buffers that are sub-allocated.
/// It has an advantage over [`Queue::write_buffer()`] in a way that it returns a mutable slice,
/// which you can fill to avoid an extra data copy.
///
/// Using a staging belt is slightly complicated, and generally goes as follows:
/// 1. Write to buffers that need writing to using [`StagingBelt::write_buffer()`].
/// 2. Call [`StagingBelt::finish()`].
/// 3. Submit all command encoders that were used in step 1.
/// 4. Call [`StagingBelt::recall()`].
///
/// [`Queue::write_buffer()`]: crate::Queue::write_buffer
pub struct StagingBelt {
chunk_size: BufferAddress,
/// Chunks into which we are accumulating data to be transferred.
active_chunks: Vec<Chunk>,
/// Chunks that have scheduled transfers already; they are unmapped and some
/// command encoder has one or more `copy_buffer_to_buffer` commands with them
/// as source.
closed_chunks: Vec<Chunk>,
/// Chunks that are back from the GPU and ready to be mapped for write and put
/// into `active_chunks`.
free_chunks: Vec<Chunk>,
/// When closed chunks are mapped again, the map callback sends them here.
sender: mpsc::Sender<Chunk>,
/// Free chunks are received here to be put on `self.free_chunks`.
receiver: mpsc::Receiver<Chunk>,
}
impl StagingBelt {
/// Create a new staging belt.
///
/// The `chunk_size` is the unit of internal buffer allocation; writes will be
/// sub-allocated within each chunk. Therefore, for optimal use of memory, the
/// chunk size should be:
///
/// * larger than the largest single [`StagingBelt::write_buffer()`] operation;
/// * 1-4 times less than the total amount of data uploaded per submission
/// (per [`StagingBelt::finish()`]); and
/// * bigger is better, within these bounds.
pub fn new(chunk_size: BufferAddress) -> Self {
let (sender, receiver) = mpsc::channel();
StagingBelt {
chunk_size,
active_chunks: Vec::new(),
closed_chunks: Vec::new(),
free_chunks: Vec::new(),
sender,
receiver,
}
}
/// Allocate the staging belt slice of `size` to be uploaded into the `target` buffer
/// at the specified offset.
///
/// The upload will be placed into the provided command encoder. This encoder
/// must be submitted after [`StagingBelt::finish()`] is called and before
/// [`StagingBelt::recall()`] is called.
///
/// If the `size` is greater than the size of any free internal buffer, a new buffer
/// will be allocated for it. Therefore, the `chunk_size` passed to [`StagingBelt::new()`]
/// should ideally be larger than every such size.
pub fn write_buffer(
&mut self,
encoder: &mut CommandEncoder,
target: &Buffer,
offset: BufferAddress,
size: BufferSize,
device: &Device,
) -> BufferViewMut {
let mut chunk = if let Some(index) = self
.active_chunks
.iter()
.position(|chunk| chunk.offset + size.get() <= chunk.size)
{
self.active_chunks.swap_remove(index)
} else {
self.receive_chunks(); // ensure self.free_chunks is up to date
if let Some(index) = self
.free_chunks
.iter()
.position(|chunk| size.get() <= chunk.size)
{
self.free_chunks.swap_remove(index)
} else {
let size = self.chunk_size.max(size.get());
Chunk {
buffer: Arc::new(device.create_buffer(&BufferDescriptor {
label: Some("(wgpu internal) StagingBelt staging buffer"),
size,
usage: BufferUsages::MAP_WRITE | BufferUsages::COPY_SRC,
mapped_at_creation: true,
})),
size,
offset: 0,
}
}
};
encoder.copy_buffer_to_buffer(&chunk.buffer, chunk.offset, target, offset, size.get());
let old_offset = chunk.offset;
chunk.offset = align_to(chunk.offset + size.get(), crate::MAP_ALIGNMENT);
self.active_chunks.push(chunk);
self.active_chunks
.last()
.unwrap()
.buffer
.slice(old_offset..old_offset + size.get())
.get_mapped_range_mut()
}
/// Prepare currently mapped buffers for use in a submission.
///
/// This must be called before the command encoder(s) provided to
/// [`StagingBelt::write_buffer()`] are submitted.
///
/// At this point, all the partially used staging buffers are closed (cannot be used for
/// further writes) until after [`StagingBelt::recall()`] is called *and* the GPU is done
/// copying the data from them.
pub fn finish(&mut self) {
for chunk in self.active_chunks.drain(..) {
chunk.buffer.unmap();
self.closed_chunks.push(chunk);
}
}
/// Recall all of the closed buffers back to be reused.
///
/// This must only be called after the command encoder(s) provided to
/// [`StagingBelt::write_buffer()`] are submitted. Additional calls are harmless.
/// Not calling this as soon as possible may result in increased buffer memory usage.
pub fn recall(&mut self) {
self.receive_chunks();
let sender = &self.sender;
for chunk in self.closed_chunks.drain(..) {
let sender = sender.clone();
chunk
.buffer
.clone()
.slice(..)
.map_async(MapMode::Write, move |_| {
let _ = sender.send(chunk);
});
}
}
/// Move all chunks that the GPU is done with (and are now mapped again)
/// from `self.receiver` to `self.free_chunks`.
fn receive_chunks(&mut self) {
while let Ok(mut chunk) = self.receiver.try_recv() {
chunk.offset = 0;
self.free_chunks.push(chunk);
}
}
}
impl fmt::Debug for StagingBelt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("StagingBelt")
.field("chunk_size", &self.chunk_size)
.field("active_chunks", &self.active_chunks.len())
.field("closed_chunks", &self.closed_chunks.len())
.field("free_chunks", &self.free_chunks.len())
.finish_non_exhaustive()
}
}

View file

@ -0,0 +1,145 @@
/// Describes a [Buffer](crate::Buffer) when allocating.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct BufferInitDescriptor<'a> {
/// Debug label of a buffer. This will show up in graphics debuggers for easy identification.
pub label: crate::Label<'a>,
/// Contents of a buffer on creation.
pub contents: &'a [u8],
/// Usages of a buffer. If the buffer is used in any way that isn't specified here, the operation
/// will panic.
pub usage: crate::BufferUsages,
}
/// Utility methods not meant to be in the main API.
pub trait DeviceExt {
/// Creates a [Buffer](crate::Buffer) with data to initialize it.
fn create_buffer_init(&self, desc: &BufferInitDescriptor) -> crate::Buffer;
/// Upload an entire texture and its mipmaps from a source buffer.
///
/// Expects all mipmaps to be tightly packed in the data buffer.
///
/// If the texture is a 2DArray texture, uploads each layer in order, expecting
/// each layer and its mips to be tightly packed.
///
/// Example:
/// Layer0Mip0 Layer0Mip1 Layer0Mip2 ... Layer1Mip0 Layer1Mip1 Layer1Mip2 ...
///
/// Implicitly adds the `COPY_DST` usage if it is not present in the descriptor,
/// as it is required to be able to upload the data to the gpu.
fn create_texture_with_data(
&self,
queue: &crate::Queue,
desc: &crate::TextureDescriptor,
data: &[u8],
) -> crate::Texture;
}
impl DeviceExt for crate::Device {
fn create_buffer_init(&self, descriptor: &BufferInitDescriptor<'_>) -> crate::Buffer {
// Skip mapping if the buffer is zero sized
if descriptor.contents.is_empty() {
let wgt_descriptor = crate::BufferDescriptor {
label: descriptor.label,
size: 0,
usage: descriptor.usage,
mapped_at_creation: false,
};
self.create_buffer(&wgt_descriptor)
} else {
let unpadded_size = descriptor.contents.len() as crate::BufferAddress;
// Valid vulkan usage is
// 1. buffer size must be a multiple of COPY_BUFFER_ALIGNMENT.
// 2. buffer size must be greater than 0.
// Therefore we round the value up to the nearest multiple, and ensure it's at least COPY_BUFFER_ALIGNMENT.
let align_mask = crate::COPY_BUFFER_ALIGNMENT - 1;
let padded_size =
((unpadded_size + align_mask) & !align_mask).max(crate::COPY_BUFFER_ALIGNMENT);
let wgt_descriptor = crate::BufferDescriptor {
label: descriptor.label,
size: padded_size,
usage: descriptor.usage,
mapped_at_creation: true,
};
let buffer = self.create_buffer(&wgt_descriptor);
buffer.slice(..).get_mapped_range_mut()[..unpadded_size as usize]
.copy_from_slice(descriptor.contents);
buffer.unmap();
buffer
}
}
fn create_texture_with_data(
&self,
queue: &crate::Queue,
desc: &crate::TextureDescriptor,
data: &[u8],
) -> crate::Texture {
// Implicitly add the COPY_DST usage
let mut desc = desc.to_owned();
desc.usage |= crate::TextureUsages::COPY_DST;
let texture = self.create_texture(&desc);
// Will return None only if it's a combined depth-stencil format
// If so, default to 4, validation will fail later anyway since the depth or stencil
// aspect needs to be written to individually
let block_size = desc.format.block_size(None).unwrap_or(4);
let (block_width, block_height) = desc.format.block_dimensions();
let layer_iterations = desc.array_layer_count();
let mut binary_offset = 0;
for layer in 0..layer_iterations {
for mip in 0..desc.mip_level_count {
let mut mip_size = desc.mip_level_size(mip).unwrap();
// copying layers separately
if desc.dimension != wgt::TextureDimension::D3 {
mip_size.depth_or_array_layers = 1;
}
// When uploading mips of compressed textures and the mip is supposed to be
// a size that isn't a multiple of the block size, the mip needs to be uploaded
// as its "physical size" which is the size rounded up to the nearest block size.
let mip_physical = mip_size.physical_size(desc.format);
// All these calculations are performed on the physical size as that's the
// data that exists in the buffer.
let width_blocks = mip_physical.width / block_width;
let height_blocks = mip_physical.height / block_height;
let bytes_per_row = width_blocks * block_size;
let data_size = bytes_per_row * height_blocks * mip_size.depth_or_array_layers;
let end_offset = binary_offset + data_size as usize;
queue.write_texture(
crate::ImageCopyTexture {
texture: &texture,
mip_level: mip,
origin: crate::Origin3d {
x: 0,
y: 0,
z: layer,
},
aspect: wgt::TextureAspect::All,
},
&data[binary_offset..end_offset],
crate::ImageDataLayout {
offset: 0,
bytes_per_row: Some(bytes_per_row),
rows_per_image: Some(height_blocks),
},
mip_physical,
);
binary_offset = end_offset;
}
}
texture
}
}

View file

@ -0,0 +1,202 @@
use std::ops::Range;
use wgt::{BufferAddress, DynamicOffset, IndexFormat};
use crate::{BindGroup, Buffer, BufferSlice, RenderBundleEncoder, RenderPass, RenderPipeline};
/// Methods shared by [`RenderPass`] and [`RenderBundleEncoder`].
pub trait RenderEncoder<'a> {
/// Sets the active bind group for a given bind group index. The bind group layout
/// in the active pipeline when any `draw()` function is called must match the layout of this bind group.
///
/// If the bind group have dynamic offsets, provide them in order of their declaration.
fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]);
/// Sets the active render pipeline.
///
/// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
fn set_pipeline(&mut self, pipeline: &'a RenderPipeline);
/// Sets the active index buffer.
///
/// Subsequent calls to [`draw_indexed`](RenderEncoder::draw_indexed) on this [`RenderEncoder`] will
/// use `buffer` as the source index buffer.
fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat);
/// Assign a vertex buffer to a slot.
///
/// Subsequent calls to [`draw`] and [`draw_indexed`] on this
/// [`RenderEncoder`] will use `buffer` as one of the source vertex buffers.
///
/// The `slot` refers to the index of the matching descriptor in
/// [VertexState::buffers](crate::VertexState::buffers).
///
/// [`draw`]: RenderEncoder::draw
/// [`draw_indexed`]: RenderEncoder::draw_indexed
fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>);
/// Draws primitives from the active vertex buffer(s).
///
/// The active vertex buffers can be set with [`RenderEncoder::set_vertex_buffer`].
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>);
/// Draws indexed primitives using the active index buffer and the active vertex buffers.
///
/// The active index buffer can be set with [`RenderEncoder::set_index_buffer`], while the active
/// vertex buffers can be set with [`RenderEncoder::set_vertex_buffer`].
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
/// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
///
/// The active vertex buffers can be set with [`RenderEncoder::set_vertex_buffer`].
///
/// The structure expected in `indirect_buffer` must conform to [`DrawIndirect`](crate::util::DrawIndirect).
fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress);
/// Draws indexed primitives using the active index buffer and the active vertex buffers,
/// based on the contents of the `indirect_buffer`.
///
/// The active index buffer can be set with [`RenderEncoder::set_index_buffer`], while the active
/// vertex buffers can be set with [`RenderEncoder::set_vertex_buffer`].
///
/// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirect`](crate::util::DrawIndexedIndirect).
fn draw_indexed_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: BufferAddress,
);
/// [`wgt::Features::PUSH_CONSTANTS`] must be enabled on the device in order to call this function.
///
/// Set push constant data.
///
/// Offset is measured in bytes, but must be a multiple of [`wgt::PUSH_CONSTANT_ALIGNMENT`].
///
/// Data size must be a multiple of 4 and must be aligned to the 4s, so we take an array of u32.
/// For example, with an offset of 4 and an array of `[u32; 3]`, that will write to the range
/// of 4..16.
///
/// For each byte in the range of push constant data written, the union of the stages of all push constant
/// ranges that covers that byte must be exactly `stages`. There's no good way of explaining this simply,
/// so here are some examples:
///
/// ```text
/// For the given ranges:
/// - 0..4 Vertex
/// - 4..8 Fragment
/// ```
///
/// You would need to upload this in two set_push_constants calls. First for the `Vertex` range, second for the `Fragment` range.
///
/// ```text
/// For the given ranges:
/// - 0..8 Vertex
/// - 4..12 Fragment
/// ```
///
/// You would need to upload this in three set_push_constants calls. First for the `Vertex` only range 0..4, second
/// for the `Vertex | Fragment` range 4..8, third for the `Fragment` range 8..12.
fn set_push_constants(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]);
}
impl<'a> RenderEncoder<'a> for RenderPass<'a> {
#[inline(always)]
fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) {
Self::set_bind_group(self, index, bind_group, offsets);
}
#[inline(always)]
fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
Self::set_pipeline(self, pipeline);
}
#[inline(always)]
fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) {
Self::set_index_buffer(self, buffer_slice, index_format);
}
#[inline(always)]
fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
Self::set_vertex_buffer(self, slot, buffer_slice);
}
#[inline(always)]
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
Self::draw(self, vertices, instances);
}
#[inline(always)]
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
Self::draw_indexed(self, indices, base_vertex, instances);
}
#[inline(always)]
fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
Self::draw_indirect(self, indirect_buffer, indirect_offset);
}
#[inline(always)]
fn draw_indexed_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: BufferAddress,
) {
Self::draw_indexed_indirect(self, indirect_buffer, indirect_offset);
}
#[inline(always)]
fn set_push_constants(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]) {
Self::set_push_constants(self, stages, offset, data);
}
}
impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> {
#[inline(always)]
fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) {
Self::set_bind_group(self, index, bind_group, offsets);
}
#[inline(always)]
fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
Self::set_pipeline(self, pipeline);
}
#[inline(always)]
fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) {
Self::set_index_buffer(self, buffer_slice, index_format);
}
#[inline(always)]
fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
Self::set_vertex_buffer(self, slot, buffer_slice);
}
#[inline(always)]
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
Self::draw(self, vertices, instances);
}
#[inline(always)]
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
Self::draw_indexed(self, indices, base_vertex, instances);
}
#[inline(always)]
fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
Self::draw_indirect(self, indirect_buffer, indirect_offset);
}
#[inline(always)]
fn draw_indexed_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: BufferAddress,
) {
Self::draw_indexed_indirect(self, indirect_buffer, indirect_offset);
}
#[inline(always)]
fn set_push_constants(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]) {
Self::set_push_constants(self, stages, offset, data);
}
}

View file

@ -0,0 +1,81 @@
/// The structure expected in `indirect_buffer` for [`RenderEncoder::draw_indirect`](crate::util::RenderEncoder::draw_indirect).
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct DrawIndirect {
/// The number of vertices to draw.
pub vertex_count: u32,
/// The number of instances to draw.
pub instance_count: u32,
/// The Index of the first vertex to draw.
pub base_vertex: u32,
/// The instance ID of the first instance to draw.
/// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled.
pub base_instance: u32,
}
impl DrawIndirect {
/// Returns the bytes representation of the struct, ready to be written in a [`Buffer`](crate::Buffer).
pub fn as_bytes(&self) -> &[u8] {
unsafe {
std::mem::transmute(std::slice::from_raw_parts(
self as *const _ as *const u8,
std::mem::size_of::<Self>(),
))
}
}
}
/// The structure expected in `indirect_buffer` for [`RenderEncoder::draw_indexed_indirect`](crate::util::RenderEncoder::draw_indexed_indirect).
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct DrawIndexedIndirect {
/// The number of vertices to draw.
pub vertex_count: u32,
/// The number of instances to draw.
pub instance_count: u32,
/// The base index within the index buffer.
pub base_index: u32,
/// The value added to the vertex index before indexing into the vertex buffer.
pub vertex_offset: i32,
/// The instance ID of the first instance to draw.
/// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled.
pub base_instance: u32,
}
impl DrawIndexedIndirect {
/// Returns the bytes representation of the struct, ready to be written in a [`Buffer`](crate::Buffer).
pub fn as_bytes(&self) -> &[u8] {
unsafe {
std::mem::transmute(std::slice::from_raw_parts(
self as *const _ as *const u8,
std::mem::size_of::<Self>(),
))
}
}
}
/// The structure expected in `indirect_buffer` for [`ComputePass::dispatch_workgroups_indirect`](crate::ComputePass::dispatch_workgroups_indirect).
///
/// x, y and z denote the number of work groups to dispatch in each dimension.
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct DispatchIndirect {
/// The number of work groups in X dimension.
pub x: u32,
/// The number of work groups in Y dimension.
pub y: u32,
/// The number of work groups in Z dimension.
pub z: u32,
}
impl DispatchIndirect {
/// Returns the bytes representation of the struct, ready to be written in a [`Buffer`](crate::Buffer).
pub fn as_bytes(&self) -> &[u8] {
unsafe {
std::mem::transmute(std::slice::from_raw_parts(
self as *const _ as *const u8,
std::mem::size_of::<Self>(),
))
}
}
}

116
third-party/vendor/wgpu/src/util/init.rs vendored Normal file
View file

@ -0,0 +1,116 @@
use wgt::{Backends, PowerPreference, RequestAdapterOptions};
use crate::{Adapter, Instance, Surface};
#[cfg(any(not(target_arch = "wasm32"), feature = "wgc"))]
pub use wgc::instance::parse_backends_from_comma_list;
/// Always returns WEBGPU on wasm over webgpu.
#[cfg(all(target_arch = "wasm32", not(feature = "wgc")))]
pub fn parse_backends_from_comma_list(_string: &str) -> Backends {
Backends::BROWSER_WEBGPU
}
/// Get a set of backend bits from the environment variable WGPU_BACKEND.
pub fn backend_bits_from_env() -> Option<Backends> {
std::env::var("WGPU_BACKEND")
.as_deref()
.map(str::to_lowercase)
.ok()
.as_deref()
.map(parse_backends_from_comma_list)
}
/// Get a power preference from the environment variable WGPU_POWER_PREF
pub fn power_preference_from_env() -> Option<PowerPreference> {
Some(
match std::env::var("WGPU_POWER_PREF")
.as_deref()
.map(str::to_lowercase)
.as_deref()
{
Ok("low") => PowerPreference::LowPower,
Ok("high") => PowerPreference::HighPerformance,
_ => return None,
},
)
}
/// Initialize the adapter obeying the WGPU_ADAPTER_NAME environment variable.
#[cfg(not(target_arch = "wasm32"))]
pub fn initialize_adapter_from_env(
instance: &Instance,
compatible_surface: Option<&Surface>,
) -> Option<Adapter> {
let desired_adapter_name = std::env::var("WGPU_ADAPTER_NAME")
.as_deref()
.map(str::to_lowercase)
.ok()?;
let adapters = instance.enumerate_adapters(Backends::all());
let mut chosen_adapter = None;
for adapter in adapters {
let info = adapter.get_info();
if let Some(surface) = compatible_surface {
if !adapter.is_surface_supported(surface) {
continue;
}
}
if info.name.to_lowercase().contains(&desired_adapter_name) {
chosen_adapter = Some(adapter);
break;
}
}
Some(chosen_adapter.expect("WGPU_ADAPTER_NAME set but no matching adapter found!"))
}
/// Initialize the adapter obeying the WGPU_ADAPTER_NAME environment variable.
#[cfg(target_arch = "wasm32")]
pub fn initialize_adapter_from_env(
_instance: &Instance,
_compatible_surface: Option<&Surface>,
) -> Option<Adapter> {
None
}
/// Initialize the adapter obeying the WGPU_ADAPTER_NAME environment variable and if it doesn't exist fall back on a default adapter.
pub async fn initialize_adapter_from_env_or_default(
instance: &Instance,
compatible_surface: Option<&Surface>,
) -> Option<Adapter> {
match initialize_adapter_from_env(instance, compatible_surface) {
Some(a) => Some(a),
None => {
instance
.request_adapter(&RequestAdapterOptions {
power_preference: power_preference_from_env().unwrap_or_default(),
force_fallback_adapter: false,
compatible_surface,
})
.await
}
}
}
/// Choose which DX12 shader compiler to use from the environment variable `WGPU_DX12_COMPILER`.
///
/// Possible values are `dxc` and `fxc`. Case insensitive.
pub fn dx12_shader_compiler_from_env() -> Option<wgt::Dx12Compiler> {
Some(
match std::env::var("WGPU_DX12_COMPILER")
.as_deref()
.map(str::to_lowercase)
.as_deref()
{
Ok("dxc") => wgt::Dx12Compiler::Dxc {
dxil_path: None,
dxc_path: None,
},
Ok("fxc") => wgt::Dx12Compiler::Fxc,
_ => return None,
},
)
}

143
third-party/vendor/wgpu/src/util/mod.rs vendored Normal file
View file

@ -0,0 +1,143 @@
//! Utility structures and functions that are built on top of the main `wgpu` API.
//!
//! Nothing in this module is a part of the WebGPU API specification;
//! they are unique to the `wgpu` library.
mod belt;
mod device;
mod encoder;
mod indirect;
mod init;
use std::sync::Arc;
use std::{
borrow::Cow,
mem::{align_of, size_of},
ptr::copy_nonoverlapping,
};
pub use belt::StagingBelt;
pub use device::{BufferInitDescriptor, DeviceExt};
pub use encoder::RenderEncoder;
pub use indirect::*;
pub use init::*;
pub use wgt::math::*;
/// Treat the given byte slice as a SPIR-V module.
///
/// # Panic
///
/// This function panics if:
///
/// - Input length isn't multiple of 4
/// - Input is longer than [`usize::max_value`]
/// - Input is empty
/// - SPIR-V magic number is missing from beginning of stream
#[cfg(feature = "spirv")]
pub fn make_spirv(data: &[u8]) -> super::ShaderSource {
super::ShaderSource::SpirV(make_spirv_raw(data))
}
/// Version of make_spirv intended for use with [`Device::create_shader_module_spirv`].
/// Returns raw slice instead of ShaderSource.
///
/// [`Device::create_shader_module_spirv`]: crate::Device::create_shader_module_spirv
pub fn make_spirv_raw(data: &[u8]) -> Cow<[u32]> {
const MAGIC_NUMBER: u32 = 0x0723_0203;
assert_eq!(
data.len() % size_of::<u32>(),
0,
"data size is not a multiple of 4"
);
assert_ne!(data.len(), 0, "data size must be larger than zero");
//If the data happens to be aligned, directly use the byte array,
// otherwise copy the byte array in an owned vector and use that instead.
let mut words = if data.as_ptr().align_offset(align_of::<u32>()) == 0 {
let (pre, words, post) = unsafe { data.align_to::<u32>() };
debug_assert!(pre.is_empty());
debug_assert!(post.is_empty());
Cow::from(words)
} else {
let mut words = vec![0u32; data.len() / size_of::<u32>()];
unsafe {
copy_nonoverlapping(data.as_ptr(), words.as_mut_ptr() as *mut u8, data.len());
}
Cow::from(words)
};
// Before checking if the data starts with the magic, check if it starts
// with the magic in non-native endianness, own & swap the data if so.
if words[0] == MAGIC_NUMBER.swap_bytes() {
for word in Cow::to_mut(&mut words) {
*word = word.swap_bytes();
}
}
assert_eq!(
words[0], MAGIC_NUMBER,
"wrong magic word {:x}. Make sure you are using a binary SPIRV file.",
words[0]
);
words
}
/// CPU accessible buffer used to download data back from the GPU.
pub struct DownloadBuffer(
Arc<super::Buffer>,
Box<dyn crate::context::BufferMappedRange>,
);
impl DownloadBuffer {
/// Asynchronously read the contents of a buffer.
pub fn read_buffer(
device: &super::Device,
queue: &super::Queue,
buffer: &super::BufferSlice,
callback: impl FnOnce(Result<Self, super::BufferAsyncError>) + Send + 'static,
) {
let size = match buffer.size {
Some(size) => size.into(),
None => buffer.buffer.map_context.lock().total_size - buffer.offset,
};
let download = Arc::new(device.create_buffer(&super::BufferDescriptor {
size,
usage: super::BufferUsages::COPY_DST | super::BufferUsages::MAP_READ,
mapped_at_creation: false,
label: None,
}));
let mut encoder =
device.create_command_encoder(&super::CommandEncoderDescriptor { label: None });
encoder.copy_buffer_to_buffer(buffer.buffer, buffer.offset, &download, 0, size);
let command_buffer: super::CommandBuffer = encoder.finish();
queue.submit(Some(command_buffer));
download
.clone()
.slice(..)
.map_async(super::MapMode::Read, move |result| {
if let Err(e) = result {
callback(Err(e));
return;
}
let mapped_range = super::DynContext::buffer_get_mapped_range(
&*download.context,
&download.id,
download.data.as_ref(),
0..size,
);
callback(Ok(Self(download, mapped_range)));
});
}
}
impl std::ops::Deref for DownloadBuffer {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.1.slice()
}
}