mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
Add typos
to Repository CI (#5191)
Co-authored-by: Andreas Reich <r_andreas2@web.de>
This commit is contained in:
parent
c2c0d5f400
commit
faed98b45c
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@ -596,7 +596,7 @@ jobs:
|
|||||||
# runtime is normally 15 seconds
|
# runtime is normally 15 seconds
|
||||||
timeout-minutes: 2
|
timeout-minutes: 2
|
||||||
|
|
||||||
name: Format
|
name: Format & Typos
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: checkout repo
|
- name: checkout repo
|
||||||
@ -613,6 +613,9 @@ jobs:
|
|||||||
cargo fmt -- --check
|
cargo fmt -- --check
|
||||||
cargo fmt --manifest-path xtask/Cargo.toml -- --check
|
cargo fmt --manifest-path xtask/Cargo.toml -- --check
|
||||||
|
|
||||||
|
- name: Check for typos
|
||||||
|
uses: crate-ci/typos@v1.18.0
|
||||||
|
|
||||||
check-cts-runner:
|
check-cts-runner:
|
||||||
# runtime is normally 2 minutes
|
# runtime is normally 2 minutes
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
16
CHANGELOG.md
16
CHANGELOG.md
@ -532,7 +532,7 @@ By @wumpf in [#4147](https://github.com/gfx-rs/wgpu/pull/4147)
|
|||||||
|
|
||||||
The instance descriptor grew two more fields: `flags` and `gles_minor_version`.
|
The instance descriptor grew two more fields: `flags` and `gles_minor_version`.
|
||||||
|
|
||||||
`flags` allow you to toggle the underlying api validation layers, debug information about shaders and objects in capture programs, and the ability to discard lables
|
`flags` allow you to toggle the underlying api validation layers, debug information about shaders and objects in capture programs, and the ability to discard labels
|
||||||
|
|
||||||
`gles_minor_version` is a rather niche feature that allows you to force the GLES backend to use a specific minor version, this is useful to get ANGLE to enable more than GLES 3.0.
|
`gles_minor_version` is a rather niche feature that allows you to force the GLES backend to use a specific minor version, this is useful to get ANGLE to enable more than GLES 3.0.
|
||||||
|
|
||||||
@ -1108,11 +1108,11 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non
|
|||||||
|
|
||||||
#### `Queue::copy_external_image_to_texture` on WebAssembly
|
#### `Queue::copy_external_image_to_texture` on WebAssembly
|
||||||
|
|
||||||
A new api, `Queue::copy_external_image_to_texture`, allows you to create wgpu textures from various web image primitives. Specificically from `HtmlVideoElement`, `HtmlCanvasElement`, `OffscreenCanvas`, and `ImageBitmap`. This provides multiple low-copy ways of interacting with the browser. WebGL is also supported, though WebGL has some additional restrictions, represented by the `UNRESTRICTED_EXTERNAL_IMAGE_COPIES` downlevel flag. By @cwfitzgerald in [#3288](https://github.com/gfx-rs/wgpu/pull/3288)
|
A new api, `Queue::copy_external_image_to_texture`, allows you to create wgpu textures from various web image primitives. Specifically from `HtmlVideoElement`, `HtmlCanvasElement`, `OffscreenCanvas`, and `ImageBitmap`. This provides multiple low-copy ways of interacting with the browser. WebGL is also supported, though WebGL has some additional restrictions, represented by the `UNRESTRICTED_EXTERNAL_IMAGE_COPIES` downlevel flag. By @cwfitzgerald in [#3288](https://github.com/gfx-rs/wgpu/pull/3288)
|
||||||
|
|
||||||
#### Instance creation now takes `InstanceDescriptor` instead of `Backends`
|
#### Instance creation now takes `InstanceDescriptor` instead of `Backends`
|
||||||
|
|
||||||
`Instance::new()` and `hub::Global::new()` now take an `InstanceDescriptor` struct which cointains both the existing `Backends` selection as well as a new `Dx12Compiler` field for selecting which Dx12 shader compiler to use.
|
`Instance::new()` and `hub::Global::new()` now take an `InstanceDescriptor` struct which contains both the existing `Backends` selection as well as a new `Dx12Compiler` field for selecting which Dx12 shader compiler to use.
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
- let instance = Instance::new(wgpu::Backends::all());
|
- let instance = Instance::new(wgpu::Backends::all());
|
||||||
@ -1423,7 +1423,7 @@ both `raw_window_handle::HasRawWindowHandle` and `raw_window_handle::HasRawDispl
|
|||||||
- Free `StagingBuffers` even when an error occurs in the operation that consumes them. By @jimblandy in [#2961](https://github.com/gfx-rs/wgpu/pull/2961)
|
- Free `StagingBuffers` even when an error occurs in the operation that consumes them. By @jimblandy in [#2961](https://github.com/gfx-rs/wgpu/pull/2961)
|
||||||
- Avoid overflow when checking that texture copies fall within bounds. By @jimblandy in [#2963](https://github.com/gfx-rs/wgpu/pull/2963)
|
- Avoid overflow when checking that texture copies fall within bounds. By @jimblandy in [#2963](https://github.com/gfx-rs/wgpu/pull/2963)
|
||||||
- Improve the validation and error reporting of buffer mappings by @nical in [#2848](https://github.com/gfx-rs/wgpu/pull/2848)
|
- Improve the validation and error reporting of buffer mappings by @nical in [#2848](https://github.com/gfx-rs/wgpu/pull/2848)
|
||||||
- Fix compilation errors when using wgpu-core in isolation while targetting `wasm32-unknown-unknown` by @Seamooo in [#2922](https://github.com/gfx-rs/wgpu/pull/2922)
|
- Fix compilation errors when using wgpu-core in isolation while targeting `wasm32-unknown-unknown` by @Seamooo in [#2922](https://github.com/gfx-rs/wgpu/pull/2922)
|
||||||
- Fixed opening of RenderDoc library by @abuffseagull in [#2930](https://github.com/gfx-rs/wgpu/pull/2930)
|
- Fixed opening of RenderDoc library by @abuffseagull in [#2930](https://github.com/gfx-rs/wgpu/pull/2930)
|
||||||
- Added missing validation for `BufferUsages` mismatches when `Features::MAPPABLE_PRIMARY_BUFFERS` is not
|
- Added missing validation for `BufferUsages` mismatches when `Features::MAPPABLE_PRIMARY_BUFFERS` is not
|
||||||
enabled. By @imberflur in [#3023](https://github.com/gfx-rs/wgpu/pull/3023)
|
enabled. By @imberflur in [#3023](https://github.com/gfx-rs/wgpu/pull/3023)
|
||||||
@ -1520,7 +1520,7 @@ both `raw_window_handle::HasRawWindowHandle` and `raw_window_handle::HasRawDispl
|
|||||||
|
|
||||||
### Full API Diff
|
### Full API Diff
|
||||||
|
|
||||||
Manual concatination of `cargo public-api --diff-git-checkouts v0.13.2 v0.14.0 -p wgpu` and `cargo public-api --diff-git-checkouts v0.13.2 v0.14.0 -p wgpu-types`
|
Manual concatenation of `cargo public-api --diff-git-checkouts v0.13.2 v0.14.0 -p wgpu` and `cargo public-api --diff-git-checkouts v0.13.2 v0.14.0 -p wgpu-types`
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
Removed items from the public API
|
Removed items from the public API
|
||||||
@ -1797,7 +1797,7 @@ DeviceDescriptor {
|
|||||||
- Permit non-struct, non-array types as buffers. by @jimblandy in [#2584](https://github.com/gfx-rs/wgpu/pull/2584)
|
- Permit non-struct, non-array types as buffers. by @jimblandy in [#2584](https://github.com/gfx-rs/wgpu/pull/2584)
|
||||||
- Return `queue_empty` for Device::poll by @xiaopengli89 in [#2643](https://github.com/gfx-rs/wgpu/pull/2643)
|
- Return `queue_empty` for Device::poll by @xiaopengli89 in [#2643](https://github.com/gfx-rs/wgpu/pull/2643)
|
||||||
- Add `SHADER_FLOAT16` feature by @jinleili in [#2646](https://github.com/gfx-rs/wgpu/pull/2646)
|
- Add `SHADER_FLOAT16` feature by @jinleili in [#2646](https://github.com/gfx-rs/wgpu/pull/2646)
|
||||||
- Add DEPTH32FLOAT_STENCIL8 featue by @jinleili in [#2664](https://github.com/gfx-rs/wgpu/pull/2664)
|
- Add DEPTH32FLOAT_STENCIL8 feature by @jinleili in [#2664](https://github.com/gfx-rs/wgpu/pull/2664)
|
||||||
- Add DEPTH24UNORM_STENCIL8 feature by @jinleili in [#2689](https://github.com/gfx-rs/wgpu/pull/2689)
|
- Add DEPTH24UNORM_STENCIL8 feature by @jinleili in [#2689](https://github.com/gfx-rs/wgpu/pull/2689)
|
||||||
- Implement submission indexes by @cwfitzgerald in [#2700](https://github.com/gfx-rs/wgpu/pull/2700)
|
- Implement submission indexes by @cwfitzgerald in [#2700](https://github.com/gfx-rs/wgpu/pull/2700)
|
||||||
- [WebGL] Add a downlevel capability for rendering to floating point textures by @expenses in [#2729](https://github.com/gfx-rs/wgpu/pull/2729)
|
- [WebGL] Add a downlevel capability for rendering to floating point textures by @expenses in [#2729](https://github.com/gfx-rs/wgpu/pull/2729)
|
||||||
@ -1848,7 +1848,7 @@ DeviceDescriptor {
|
|||||||
#### Emscripten
|
#### Emscripten
|
||||||
|
|
||||||
- feature: emscripten by @caiiiycuk in [#2422](https://github.com/gfx-rs/wgpu/pull/2422)
|
- feature: emscripten by @caiiiycuk in [#2422](https://github.com/gfx-rs/wgpu/pull/2422)
|
||||||
- feature = emscripten, compability fixes for wgpu-native by @caiiiycuk in [#2450](https://github.com/gfx-rs/wgpu/pull/2450)
|
- feature = emscripten, compatibility fixes for wgpu-native by @caiiiycuk in [#2450](https://github.com/gfx-rs/wgpu/pull/2450)
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
@ -2351,7 +2351,7 @@ DeviceDescriptor {
|
|||||||
- Updated default storage buffer/image limit to `8` from `4`.
|
- Updated default storage buffer/image limit to `8` from `4`.
|
||||||
- Fixed:
|
- Fixed:
|
||||||
- `Buffer::get_mapped_range` can now have a range of zero.
|
- `Buffer::get_mapped_range` can now have a range of zero.
|
||||||
- Fixed output spirv requiring the "kernal" capability.
|
- Fixed output spirv requiring the "kernel" capability.
|
||||||
- Fixed segfault due to improper drop order.
|
- Fixed segfault due to improper drop order.
|
||||||
- Fixed incorrect dynamic stencil reference for Replace ops.
|
- Fixed incorrect dynamic stencil reference for Replace ops.
|
||||||
- Fixed tracking of temporary resources.
|
- Fixed tracking of temporary resources.
|
||||||
|
@ -121,7 +121,7 @@ impl<T: Interface> Hash for ComPtr<T> {
|
|||||||
/// Three function names need to be attached to each variant. The examples are given for the MyComObject1 variant below:
|
/// Three function names need to be attached to each variant. The examples are given for the MyComObject1 variant below:
|
||||||
/// - the from function (`ComPtr<actual::ComObject1> -> Self`)
|
/// - the from function (`ComPtr<actual::ComObject1> -> Self`)
|
||||||
/// - the as function (`&self -> Option<ComPtr<actual::ComObject1>>`)
|
/// - the as function (`&self -> Option<ComPtr<actual::ComObject1>>`)
|
||||||
/// - the unwrap function (`&self -> ComPtr<actual::ComObject1>` panicing on failure to cast)
|
/// - the unwrap function (`&self -> ComPtr<actual::ComObject1>` panicking on failure to cast)
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # pub use d3d12::weak_com_inheritance_chain;
|
/// # pub use d3d12::weak_com_inheritance_chain;
|
||||||
|
@ -108,7 +108,7 @@ function assertDeviceMatch(
|
|||||||
const resourceDevice = assertDevice(resource, prefix, resourceContext);
|
const resourceDevice = assertDevice(resource, prefix, resourceContext);
|
||||||
if (resourceDevice.rid !== self.rid) {
|
if (resourceDevice.rid !== self.rid) {
|
||||||
throw new DOMException(
|
throw new DOMException(
|
||||||
`${prefix}: ${resourceContext} belongs to a diffent device than ${selfContext}.`,
|
`${prefix}: ${resourceContext} belongs to a different device than ${selfContext}.`,
|
||||||
"OperationError",
|
"OperationError",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1918,7 +1918,7 @@ class GPUBuffer {
|
|||||||
device.pushErrorPromise(promise);
|
device.pushErrorPromise(promise);
|
||||||
const err = await promise;
|
const err = await promise;
|
||||||
if (err) {
|
if (err) {
|
||||||
throw new DOMException("validation error occured", "OperationError");
|
throw new DOMException("validation error occurred", "OperationError");
|
||||||
}
|
}
|
||||||
this[_state] = "mapped";
|
this[_state] = "mapped";
|
||||||
this[_mappingRange] = [offset, offset + rangeSize];
|
this[_mappingRange] = [offset, offset + rangeSize];
|
||||||
|
@ -142,7 +142,7 @@ impl SurfaceWrapper {
|
|||||||
/// a surface (and hence a canvas) to be present to create the adapter.
|
/// a surface (and hence a canvas) to be present to create the adapter.
|
||||||
///
|
///
|
||||||
/// We cannot unconditionally create a surface here, as Android requires
|
/// We cannot unconditionally create a surface here, as Android requires
|
||||||
/// us to wait until we recieve the `Resumed` event to do so.
|
/// us to wait until we receive the `Resumed` event to do so.
|
||||||
fn pre_adapter(&mut self, instance: &Instance, window: Arc<Window>) {
|
fn pre_adapter(&mut self, instance: &Instance, window: Arc<Window>) {
|
||||||
if cfg!(target_arch = "wasm32") {
|
if cfg!(target_arch = "wasm32") {
|
||||||
self.surface = Some(instance.create_surface(window).unwrap());
|
self.surface = Some(instance.create_surface(window).unwrap());
|
||||||
@ -160,7 +160,7 @@ impl SurfaceWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when an event which matches [`Self::start_condition`] is recieved.
|
/// Called when an event which matches [`Self::start_condition`] is received.
|
||||||
///
|
///
|
||||||
/// On all native platforms, this is where we create the surface.
|
/// On all native platforms, this is where we create the surface.
|
||||||
///
|
///
|
||||||
|
@ -22,7 +22,7 @@ cargo run --bin wgpu-examples hello_workgroups
|
|||||||
- No two workgroups can be guaranteed to be executed in parallel.
|
- No two workgroups can be guaranteed to be executed in parallel.
|
||||||
- No two workgroups can be guaranteed NOT to be executed in parallel.
|
- No two workgroups can be guaranteed NOT to be executed in parallel.
|
||||||
- No set of workgroups can be guaranteed to execute in any predictable or reliable order in relation to each other.
|
- No set of workgroups can be guaranteed to execute in any predictable or reliable order in relation to each other.
|
||||||
- Ths size of a workgroup is defined with the `@workgroup_size` attribute on a compute shader main function.
|
- The size of a workgroup is defined with the `@workgroup_size` attribute on a compute shader main function.
|
||||||
- The location of an invocation within its workgroup grid can be got with `@builtin(local_invocation_id)`.
|
- The location of an invocation within its workgroup grid can be got with `@builtin(local_invocation_id)`.
|
||||||
- The location of an invocation within the entire compute shader grid can be gotten with `@builtin(global_invocation_id)`.
|
- The location of an invocation within the entire compute shader grid can be gotten with `@builtin(global_invocation_id)`.
|
||||||
- The location of an invocation's workgroup within the dispatch grid can be gotten with `@builtin(workgroup_id)`.
|
- The location of an invocation's workgroup within the dispatch grid can be gotten with `@builtin(workgroup_id)`.
|
||||||
|
@ -101,7 +101,7 @@ async fn compute(local_buffer: &mut [u32], context: &WgpuContext) {
|
|||||||
// buffered and receiving will just pick that up.
|
// buffered and receiving will just pick that up.
|
||||||
//
|
//
|
||||||
// It may also be worth noting that although on native, the usage of asynchronous
|
// It may also be worth noting that although on native, the usage of asynchronous
|
||||||
// channels is wholely unnecessary, for the sake of portability to WASM (std channels
|
// channels is wholly unnecessary, for the sake of portability to WASM (std channels
|
||||||
// don't work on WASM,) we'll use async channels that work on both native and WASM.
|
// don't work on WASM,) we'll use async channels that work on both native and WASM.
|
||||||
let (sender, receiver) = flume::bounded(1);
|
let (sender, receiver) = flume::bounded(1);
|
||||||
buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap());
|
buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap());
|
||||||
|
@ -112,7 +112,7 @@ impl crate::framework::Example for Example {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let non_uniform_shader_module;
|
let non_uniform_shader_module;
|
||||||
// TODO: Because naga's capibilities are evaluated on validate, not on write, we cannot make a shader module with unsupported
|
// TODO: Because naga's capabilities are evaluated on validate, not on write, we cannot make a shader module with unsupported
|
||||||
// capabilities even if we don't use it. So for now put it in a separate module.
|
// capabilities even if we don't use it. So for now put it in a separate module.
|
||||||
let fragment_shader_module = if !uniform_workaround {
|
let fragment_shader_module = if !uniform_workaround {
|
||||||
non_uniform_shader_module =
|
non_uniform_shader_module =
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Some credit to https://github.com/paulgb/wgsl-playground/tree/main.
|
// Some credit to https://github.com/paulgb/wgsl-playground/tree/main.
|
||||||
|
|
||||||
// We use seperate the x and y instead of using a vec2 to avoid wgsl padding.
|
// We use separate the x and y instead of using a vec2 to avoid wgsl padding.
|
||||||
struct AppState {
|
struct AppState {
|
||||||
pos_x: f32,
|
pos_x: f32,
|
||||||
pos_y: f32,
|
pos_y: f32,
|
||||||
|
@ -363,7 +363,7 @@ SPV-IN
|
|||||||
- Fix clippy lints for 1.63 by @JCapucho in https://github.com/gfx-rs/naga/pull/2026
|
- Fix clippy lints for 1.63 by @JCapucho in https://github.com/gfx-rs/naga/pull/2026
|
||||||
- Saturate by @evahop in https://github.com/gfx-rs/naga/pull/2025
|
- Saturate by @evahop in https://github.com/gfx-rs/naga/pull/2025
|
||||||
- Use `Option::as_deref` as appropriate. by @jimblandy in https://github.com/gfx-rs/naga/pull/2040
|
- Use `Option::as_deref` as appropriate. by @jimblandy in https://github.com/gfx-rs/naga/pull/2040
|
||||||
- Explicitely enable std for indexmap by @maxammann in https://github.com/gfx-rs/naga/pull/2062
|
- Explicitly enable std for indexmap by @maxammann in https://github.com/gfx-rs/naga/pull/2062
|
||||||
- Fix compiler warning by @Gordon-F in https://github.com/gfx-rs/naga/pull/2074
|
- Fix compiler warning by @Gordon-F in https://github.com/gfx-rs/naga/pull/2074
|
||||||
|
|
||||||
API
|
API
|
||||||
@ -466,7 +466,7 @@ Main breaking changes
|
|||||||
- `findLsb` -> `firstTrailingBit`
|
- `findLsb` -> `firstTrailingBit`
|
||||||
- `findMsb` -> `firstLeadingBit`
|
- `findMsb` -> `firstLeadingBit`
|
||||||
|
|
||||||
Specification Changes (relavant changes have also been applied to the WGSL backend)
|
Specification Changes (relevant changes have also been applied to the WGSL backend)
|
||||||
|
|
||||||
- Add support for `break if` ([#1993](https://github.com/gfx-rs/naga/pull/1993)) **@JCapucho**
|
- Add support for `break if` ([#1993](https://github.com/gfx-rs/naga/pull/1993)) **@JCapucho**
|
||||||
- Update number literal format ([#1863](https://github.com/gfx-rs/naga/pull/1863)) **@teoxoy**
|
- Update number literal format ([#1863](https://github.com/gfx-rs/naga/pull/1863)) **@teoxoy**
|
||||||
@ -479,7 +479,7 @@ Specification Changes (relavant changes have also been applied to the WGSL backe
|
|||||||
- Use commas to separate struct members instead of semicolons ([#1773](https://github.com/gfx-rs/naga/pull/1773)) **@Gordon-F**
|
- Use commas to separate struct members instead of semicolons ([#1773](https://github.com/gfx-rs/naga/pull/1773)) **@Gordon-F**
|
||||||
- Rename `findLsb`/`findMsb` to `firstTrailingBit`/`firstLeadingBit` ([#1735](https://github.com/gfx-rs/naga/pull/1735)) **@kvark**
|
- Rename `findLsb`/`findMsb` to `firstTrailingBit`/`firstLeadingBit` ([#1735](https://github.com/gfx-rs/naga/pull/1735)) **@kvark**
|
||||||
- Make parenthesis optional for `if` and `switch` statements ([#1725](https://github.com/gfx-rs/naga/pull/1725)) **@Gordon-F**
|
- Make parenthesis optional for `if` and `switch` statements ([#1725](https://github.com/gfx-rs/naga/pull/1725)) **@Gordon-F**
|
||||||
- Declare attribtues with `@attrib` instead of `[[attrib]]` ([#1676](https://github.com/gfx-rs/naga/pull/1676)) **@kvark**
|
- Declare attributes with `@attrib` instead of `[[attrib]]` ([#1676](https://github.com/gfx-rs/naga/pull/1676)) **@kvark**
|
||||||
- Allow non-structure buffer types ([#1682](https://github.com/gfx-rs/naga/pull/1682)) **@kvark**
|
- Allow non-structure buffer types ([#1682](https://github.com/gfx-rs/naga/pull/1682)) **@kvark**
|
||||||
- Remove `stride` attribute ([#1681](https://github.com/gfx-rs/naga/pull/1681)) **@kvark**
|
- Remove `stride` attribute ([#1681](https://github.com/gfx-rs/naga/pull/1681)) **@kvark**
|
||||||
|
|
||||||
@ -516,7 +516,7 @@ SPV-IN
|
|||||||
GLSL-IN
|
GLSL-IN
|
||||||
|
|
||||||
- Don't allow empty last case in switch ([#1981](https://github.com/gfx-rs/naga/pull/1981)) **@JCapucho**
|
- Don't allow empty last case in switch ([#1981](https://github.com/gfx-rs/naga/pull/1981)) **@JCapucho**
|
||||||
- Fix last case falltrough and empty switch ([#1981](https://github.com/gfx-rs/naga/pull/1981)) **@JCapucho**
|
- Fix last case fallthrough and empty switch ([#1981](https://github.com/gfx-rs/naga/pull/1981)) **@JCapucho**
|
||||||
- Splat inputs for smoothstep if needed ([#1976](https://github.com/gfx-rs/naga/pull/1976)) **@JCapucho**
|
- Splat inputs for smoothstep if needed ([#1976](https://github.com/gfx-rs/naga/pull/1976)) **@JCapucho**
|
||||||
- Fix parameter not changing to depth ([#1967](https://github.com/gfx-rs/naga/pull/1967)) **@JCapucho**
|
- Fix parameter not changing to depth ([#1967](https://github.com/gfx-rs/naga/pull/1967)) **@JCapucho**
|
||||||
- Fix matrix multiplication check ([#1953](https://github.com/gfx-rs/naga/pull/1953)) **@JCapucho**
|
- Fix matrix multiplication check ([#1953](https://github.com/gfx-rs/naga/pull/1953)) **@JCapucho**
|
||||||
|
@ -75,7 +75,7 @@ env_logger = "0.10"
|
|||||||
hlsl-snapshots = { path = "./hlsl-snapshots" }
|
hlsl-snapshots = { path = "./hlsl-snapshots" }
|
||||||
# Require at least version 0.7.1 of ron, this version changed how floating points are
|
# Require at least version 0.7.1 of ron, this version changed how floating points are
|
||||||
# serialized by forcing them to always have the decimal part, this makes it backwards
|
# serialized by forcing them to always have the decimal part, this makes it backwards
|
||||||
# incompatible with our tests because we do a syntatic diff and not a semantic one.
|
# incompatible with our tests because we do a syntactic diff and not a semantic one.
|
||||||
ron = "0.8.0"
|
ron = "0.8.0"
|
||||||
rspirv = { version = "0.11", git = "https://github.com/gfx-rs/rspirv", rev = "b969f175d5663258b4891e44b76c1544da9661ab" }
|
rspirv = { version = "0.11", git = "https://github.com/gfx-rs/rspirv", rev = "b969f175d5663258b4891e44b76c1544da9661ab" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
@ -433,7 +433,7 @@ impl<'a, W> Writer<'a, W> {
|
|||||||
{
|
{
|
||||||
for (_, expr) in expressions.iter() {
|
for (_, expr) in expressions.iter() {
|
||||||
match *expr {
|
match *expr {
|
||||||
// Check for queries that neeed aditonal features
|
// Check for queries that need aditonal features
|
||||||
Expression::ImageQuery {
|
Expression::ImageQuery {
|
||||||
image,
|
image,
|
||||||
query,
|
query,
|
||||||
|
@ -146,7 +146,7 @@ impl Version {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if targetting WebGL
|
/// Returns true if targeting WebGL
|
||||||
const fn is_webgl(&self) -> bool {
|
const fn is_webgl(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Version::Desktop(_) => false,
|
Version::Desktop(_) => false,
|
||||||
@ -340,9 +340,9 @@ pub struct TextureMapping {
|
|||||||
///
|
///
|
||||||
/// Push constants are emulated using traditional uniforms in OpenGL.
|
/// Push constants are emulated using traditional uniforms in OpenGL.
|
||||||
///
|
///
|
||||||
/// These are composed of a set of primatives (scalar, vector, matrix) that
|
/// These are composed of a set of primitives (scalar, vector, matrix) that
|
||||||
/// are given names. Because they are not backed by the concept of a buffer,
|
/// are given names. Because they are not backed by the concept of a buffer,
|
||||||
/// we must do the work of calculating the offset of each primative in the
|
/// we must do the work of calculating the offset of each primitive in the
|
||||||
/// push constant block.
|
/// push constant block.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PushConstantItem {
|
pub struct PushConstantItem {
|
||||||
@ -394,11 +394,11 @@ impl IdGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assorted options needed for generting varyings.
|
/// Assorted options needed for generating varyings.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
struct VaryingOptions {
|
struct VaryingOptions {
|
||||||
output: bool,
|
output: bool,
|
||||||
targetting_webgl: bool,
|
targeting_webgl: bool,
|
||||||
draw_parameters: bool,
|
draw_parameters: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +406,7 @@ impl VaryingOptions {
|
|||||||
const fn from_writer_options(options: &Options, output: bool) -> Self {
|
const fn from_writer_options(options: &Options, output: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
output,
|
output,
|
||||||
targetting_webgl: options.version.is_webgl(),
|
targeting_webgl: options.version.is_webgl(),
|
||||||
draw_parameters: options.writer_flags.contains(WriterFlags::DRAW_PARAMETERS),
|
draw_parameters: options.writer_flags.contains(WriterFlags::DRAW_PARAMETERS),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1849,7 +1849,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||||||
size: usize,
|
size: usize,
|
||||||
ctx: &back::FunctionCtx,
|
ctx: &back::FunctionCtx,
|
||||||
) -> BackendResult {
|
) -> BackendResult {
|
||||||
// Write parantheses around the dot product expression to prevent operators
|
// Write parentheses around the dot product expression to prevent operators
|
||||||
// with different precedences from applying earlier.
|
// with different precedences from applying earlier.
|
||||||
write!(self.out, "(")?;
|
write!(self.out, "(")?;
|
||||||
|
|
||||||
@ -3795,11 +3795,11 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||||||
// Sampled images inherit the policy from the user passed policies
|
// Sampled images inherit the policy from the user passed policies
|
||||||
crate::ImageClass::Sampled { .. } => ("texelFetch", self.policies.image_load),
|
crate::ImageClass::Sampled { .. } => ("texelFetch", self.policies.image_load),
|
||||||
crate::ImageClass::Storage { .. } => {
|
crate::ImageClass::Storage { .. } => {
|
||||||
// OpenGL ES 3.1 mentiones in Chapter "8.22 Texture Image Loads and Stores" that:
|
// OpenGL ES 3.1 mentions in Chapter "8.22 Texture Image Loads and Stores" that:
|
||||||
// "Invalid image loads will return a vector where the value of R, G, and B components
|
// "Invalid image loads will return a vector where the value of R, G, and B components
|
||||||
// is 0 and the value of the A component is undefined."
|
// is 0 and the value of the A component is undefined."
|
||||||
//
|
//
|
||||||
// OpenGL 4.2 Core mentiones in Chapter "3.9.20 Texture Image Loads and Stores" that:
|
// OpenGL 4.2 Core mentions in Chapter "3.9.20 Texture Image Loads and Stores" that:
|
||||||
// "Invalid image loads will return zero."
|
// "Invalid image loads will return zero."
|
||||||
//
|
//
|
||||||
// So, we only inject bounds checks for ES
|
// So, we only inject bounds checks for ES
|
||||||
@ -3832,7 +3832,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||||||
// expressions so we can be sure that after we test a
|
// expressions so we can be sure that after we test a
|
||||||
// condition it will be true for the next ones
|
// condition it will be true for the next ones
|
||||||
|
|
||||||
// Write parantheses around the ternary operator to prevent problems with
|
// Write parentheses around the ternary operator to prevent problems with
|
||||||
// expressions emitted before or after it having more precedence
|
// expressions emitted before or after it having more precedence
|
||||||
write!(self.out, "(",)?;
|
write!(self.out, "(",)?;
|
||||||
|
|
||||||
@ -3856,7 +3856,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We now need to write the size checks for the coordinates and array index
|
// We now need to write the size checks for the coordinates and array index
|
||||||
// first we write the comparation function in case the image is 1D non arrayed
|
// first we write the comparison function in case the image is 1D non arrayed
|
||||||
// (and no 1D to 2D hack was needed) we are comparing scalars so the less than
|
// (and no 1D to 2D hack was needed) we are comparing scalars so the less than
|
||||||
// operator will suffice, but otherwise we'll be comparing two vectors so we'll
|
// operator will suffice, but otherwise we'll be comparing two vectors so we'll
|
||||||
// need to use the `lessThan` function but it returns a vector of booleans (one
|
// need to use the `lessThan` function but it returns a vector of booleans (one
|
||||||
@ -3883,7 +3883,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||||||
// coordinates from the image size.
|
// coordinates from the image size.
|
||||||
write!(self.out, ", ")?;
|
write!(self.out, ", ")?;
|
||||||
} else {
|
} else {
|
||||||
// If we didn't use it (ie. 1D images) we perform the comparsion
|
// If we didn't use it (ie. 1D images) we perform the comparison
|
||||||
// using the less than operator.
|
// using the less than operator.
|
||||||
write!(self.out, " < ")?;
|
write!(self.out, " < ")?;
|
||||||
}
|
}
|
||||||
@ -4002,7 +4002,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||||||
// Get the kind of the output value.
|
// Get the kind of the output value.
|
||||||
let kind = match class {
|
let kind = match class {
|
||||||
// Only sampled images can reach here since storage images
|
// Only sampled images can reach here since storage images
|
||||||
// don't need bounds checks and depth images aren't implmented
|
// don't need bounds checks and depth images aren't implemented
|
||||||
crate::ImageClass::Sampled { kind, .. } => kind,
|
crate::ImageClass::Sampled { kind, .. } => kind,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
@ -4018,7 +4018,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||||||
self.write_zero_init_scalar(kind)?;
|
self.write_zero_init_scalar(kind)?;
|
||||||
// Close the zero value constructor
|
// Close the zero value constructor
|
||||||
write!(self.out, ")")?;
|
write!(self.out, ")")?;
|
||||||
// Close the parantheses surrounding our ternary
|
// Close the parentheses surrounding our ternary
|
||||||
write!(self.out, ")")?;
|
write!(self.out, ")")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4376,7 +4376,7 @@ const fn glsl_built_in(built_in: crate::BuiltIn, options: VaryingOptions) -> &'s
|
|||||||
"gl_FragCoord"
|
"gl_FragCoord"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Bi::ViewIndex if options.targetting_webgl => "int(gl_ViewID_OVR)",
|
Bi::ViewIndex if options.targeting_webgl => "int(gl_ViewID_OVR)",
|
||||||
Bi::ViewIndex => "gl_ViewIndex",
|
Bi::ViewIndex => "gl_ViewIndex",
|
||||||
// vertex
|
// vertex
|
||||||
Bi::BaseInstance => "uint(gl_BaseInstance)",
|
Bi::BaseInstance => "uint(gl_BaseInstance)",
|
||||||
@ -4387,7 +4387,7 @@ const fn glsl_built_in(built_in: crate::BuiltIn, options: VaryingOptions) -> &'s
|
|||||||
if options.draw_parameters {
|
if options.draw_parameters {
|
||||||
"(uint(gl_InstanceID) + uint(gl_BaseInstanceARB))"
|
"(uint(gl_InstanceID) + uint(gl_BaseInstanceARB))"
|
||||||
} else {
|
} else {
|
||||||
// Must match FISRT_INSTANCE_BINDING
|
// Must match FIRST_INSTANCE_BINDING
|
||||||
"(uint(gl_InstanceID) + naga_vs_first_instance)"
|
"(uint(gl_InstanceID) + naga_vs_first_instance)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2269,7 +2269,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||||||
index: u32,
|
index: u32,
|
||||||
) -> BackendResult {
|
) -> BackendResult {
|
||||||
match *resolved {
|
match *resolved {
|
||||||
// We specifcally lift the ValuePointer to this case. While `[0]` is valid
|
// We specifically lift the ValuePointer to this case. While `[0]` is valid
|
||||||
// HLSL for any vector behind a value pointer, FXC completely miscompiles
|
// HLSL for any vector behind a value pointer, FXC completely miscompiles
|
||||||
// it and generates completely nonsensical DXBC.
|
// it and generates completely nonsensical DXBC.
|
||||||
//
|
//
|
||||||
|
@ -1166,7 +1166,7 @@ impl<W: Write> Writer<W> {
|
|||||||
size: usize,
|
size: usize,
|
||||||
context: &ExpressionContext,
|
context: &ExpressionContext,
|
||||||
) -> BackendResult {
|
) -> BackendResult {
|
||||||
// Write parantheses around the dot product expression to prevent operators
|
// Write parentheses around the dot product expression to prevent operators
|
||||||
// with different precedences from applying earlier.
|
// with different precedences from applying earlier.
|
||||||
write!(self.out, "(")?;
|
write!(self.out, "(")?;
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ trait Access {
|
|||||||
/// the level of detail, and `sample_id` is the index of the sample to
|
/// the level of detail, and `sample_id` is the index of the sample to
|
||||||
/// access in a multisampled texel.
|
/// access in a multisampled texel.
|
||||||
///
|
///
|
||||||
/// Ths method assumes that `coordinates_id` has already had the image array
|
/// This method assumes that `coordinates_id` has already had the image array
|
||||||
/// index, if any, folded in, as done by `write_image_coordinates`.
|
/// index, if any, folded in, as done by `write_image_coordinates`.
|
||||||
///
|
///
|
||||||
/// Return the value id produced by the instruction, if any.
|
/// Return the value id produced by the instruction, if any.
|
||||||
|
@ -72,7 +72,7 @@ pub fn compact(module: &mut crate::Module) {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Similiarly, observe what each entry point actually uses.
|
// Similarly, observe what each entry point actually uses.
|
||||||
log::trace!("tracing entry points");
|
log::trace!("tracing entry points");
|
||||||
let entry_point_maps: Vec<FunctionMap> = module
|
let entry_point_maps: Vec<FunctionMap> = module
|
||||||
.entry_points
|
.entry_points
|
||||||
|
@ -98,9 +98,9 @@ pub struct EntryArg {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct VariableReference {
|
pub struct VariableReference {
|
||||||
pub expr: Handle<Expression>,
|
pub expr: Handle<Expression>,
|
||||||
/// Wether the variable is of a pointer type (and needs loading) or not
|
/// Whether the variable is of a pointer type (and needs loading) or not
|
||||||
pub load: bool,
|
pub load: bool,
|
||||||
/// Wether the value of the variable can be changed or not
|
/// Whether the value of the variable can be changed or not
|
||||||
pub mutable: bool,
|
pub mutable: bool,
|
||||||
pub constant: Option<(Handle<Constant>, Handle<Type>)>,
|
pub constant: Option<(Handle<Constant>, Handle<Type>)>,
|
||||||
pub entry_arg: Option<usize>,
|
pub entry_arg: Option<usize>,
|
||||||
|
@ -1057,7 +1057,7 @@ impl<'a> Context<'a> {
|
|||||||
//
|
//
|
||||||
// The ternary operator is defined to only evaluate one of the two possible
|
// The ternary operator is defined to only evaluate one of the two possible
|
||||||
// expressions which means that it's behavior is that of an `if` statement,
|
// expressions which means that it's behavior is that of an `if` statement,
|
||||||
// and it's merely syntatic sugar for it.
|
// and it's merely syntactic sugar for it.
|
||||||
HirExprKind::Conditional {
|
HirExprKind::Conditional {
|
||||||
condition,
|
condition,
|
||||||
accept,
|
accept,
|
||||||
@ -1164,7 +1164,7 @@ impl<'a> Context<'a> {
|
|||||||
meta,
|
meta,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Note: `Expression::Load` must be emited before it's used so make
|
// Note: `Expression::Load` must be emitted before it's used so make
|
||||||
// sure the emitter is active here.
|
// sure the emitter is active here.
|
||||||
self.add_expression(
|
self.add_expression(
|
||||||
Expression::Load {
|
Expression::Load {
|
||||||
|
@ -50,7 +50,7 @@ type Result<T> = std::result::Result<T, Error>;
|
|||||||
pub struct Options {
|
pub struct Options {
|
||||||
/// The shader stage in the pipeline.
|
/// The shader stage in the pipeline.
|
||||||
pub stage: ShaderStage,
|
pub stage: ShaderStage,
|
||||||
/// Preprocesor definitions to be used, akin to having
|
/// Preprocessor definitions to be used, akin to having
|
||||||
/// ```glsl
|
/// ```glsl
|
||||||
/// #define key value
|
/// #define key value
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -49,7 +49,7 @@ impl<'source> ParsingContext<'source> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Type names can identify either declaration statements or type constructors
|
// Type names can identify either declaration statements or type constructors
|
||||||
// depending on wether the token following the type name is a `(` (LeftParen)
|
// depending on whether the token following the type name is a `(` (LeftParen)
|
||||||
if self.peek_type_name(frontend) {
|
if self.peek_type_name(frontend) {
|
||||||
// Start by consuming the type name so that we can peek the token after it
|
// Start by consuming the type name so that we can peek the token after it
|
||||||
let token = self.bump(frontend)?;
|
let token = self.bump(frontend)?;
|
||||||
|
@ -13,7 +13,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
impl<'source> ParsingContext<'source> {
|
impl<'source> ParsingContext<'source> {
|
||||||
/// Parses an optional array_specifier returning wether or not it's present
|
/// Parses an optional array_specifier returning whether or not it's present
|
||||||
/// and modifying the type handle if it exists
|
/// and modifying the type handle if it exists
|
||||||
pub fn parse_array_specifier(
|
pub fn parse_array_specifier(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -151,7 +151,7 @@ impl ops::Index<Handle<crate::Expression>> for Typifier {
|
|||||||
|
|
||||||
/// Type representing a lexical scope, associating a name to a single variable
|
/// Type representing a lexical scope, associating a name to a single variable
|
||||||
///
|
///
|
||||||
/// The scope is generic over the variable representation and name representaion
|
/// The scope is generic over the variable representation and name representation
|
||||||
/// in order to allow larger flexibility on the frontends on how they might
|
/// in order to allow larger flexibility on the frontends on how they might
|
||||||
/// represent them.
|
/// represent them.
|
||||||
type Scope<Name, Var> = FastHashMap<Name, Var>;
|
type Scope<Name, Var> = FastHashMap<Name, Var>;
|
||||||
|
@ -2559,7 +2559,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
|
|||||||
}
|
}
|
||||||
Op::ShiftRightLogical => {
|
Op::ShiftRightLogical => {
|
||||||
inst.expect(5)?;
|
inst.expect(5)?;
|
||||||
//TODO: convert input and result to usigned
|
//TODO: convert input and result to unsigned
|
||||||
parse_expr_op!(crate::BinaryOperator::ShiftRight, SHIFT)?;
|
parse_expr_op!(crate::BinaryOperator::ShiftRight, SHIFT)?;
|
||||||
}
|
}
|
||||||
Op::ShiftRightArithmetic => {
|
Op::ShiftRightArithmetic => {
|
||||||
@ -3387,7 +3387,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
|
|||||||
|
|
||||||
// Check if any previous case already used this target block id, if so
|
// Check if any previous case already used this target block id, if so
|
||||||
// group them together to reorder them later so that no weird
|
// group them together to reorder them later so that no weird
|
||||||
// falltrough cases happen.
|
// fallthrough cases happen.
|
||||||
if let Some(&mut (_, ref mut literals)) = self.switch_cases.get_mut(&target)
|
if let Some(&mut (_, ref mut literals)) = self.switch_cases.get_mut(&target)
|
||||||
{
|
{
|
||||||
literals.push(literal as i32);
|
literals.push(literal as i32);
|
||||||
@ -3411,11 +3411,11 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
|
|||||||
|
|
||||||
// Loop trough the collected target blocks creating a new case for each
|
// Loop trough the collected target blocks creating a new case for each
|
||||||
// literal pointing to it, only one case will have the true body and all the
|
// literal pointing to it, only one case will have the true body and all the
|
||||||
// others will be empty falltrough so that they all execute the same body
|
// others will be empty fallthrough so that they all execute the same body
|
||||||
// without duplicating code.
|
// without duplicating code.
|
||||||
//
|
//
|
||||||
// Since `switch_cases` is an indexmap the order of insertion is preserved
|
// Since `switch_cases` is an indexmap the order of insertion is preserved
|
||||||
// this is needed because spir-v defines falltrough order in the switch
|
// this is needed because spir-v defines fallthrough order in the switch
|
||||||
// instruction.
|
// instruction.
|
||||||
let mut cases = Vec::with_capacity((inst.wc as usize - 3) / 2);
|
let mut cases = Vec::with_capacity((inst.wc as usize - 3) / 2);
|
||||||
for &(case_body_idx, ref literals) in self.switch_cases.values() {
|
for &(case_body_idx, ref literals) in self.switch_cases.values() {
|
||||||
|
@ -184,7 +184,7 @@ pub enum Error<'a> {
|
|||||||
NonPowerOfTwoAlignAttribute(Span),
|
NonPowerOfTwoAlignAttribute(Span),
|
||||||
InconsistentBinding(Span),
|
InconsistentBinding(Span),
|
||||||
TypeNotConstructible(Span),
|
TypeNotConstructible(Span),
|
||||||
TypeNotInferrable(Span),
|
TypeNotInferable(Span),
|
||||||
InitializationTypeMismatch {
|
InitializationTypeMismatch {
|
||||||
name: Span,
|
name: Span,
|
||||||
expected: String,
|
expected: String,
|
||||||
@ -500,7 +500,7 @@ impl<'a> Error<'a> {
|
|||||||
labels: vec![(span, "type is not constructible".into())],
|
labels: vec![(span, "type is not constructible".into())],
|
||||||
notes: vec![],
|
notes: vec![],
|
||||||
},
|
},
|
||||||
Error::TypeNotInferrable(span) => ParseError {
|
Error::TypeNotInferable(span) => ParseError {
|
||||||
message: "type can't be inferred".to_string(),
|
message: "type can't be inferred".to_string(),
|
||||||
labels: vec![(span, "type can't be inferred".into())],
|
labels: vec![(span, "type can't be inferred".into())],
|
||||||
notes: vec![],
|
notes: vec![],
|
||||||
|
@ -167,7 +167,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||||||
| Constructor::PartialArray => {
|
| Constructor::PartialArray => {
|
||||||
// We have no arguments from which to infer the result type, so
|
// We have no arguments from which to infer the result type, so
|
||||||
// partial constructors aren't acceptable here.
|
// partial constructors aren't acceptable here.
|
||||||
return Err(Error::TypeNotInferrable(ty_span));
|
return Err(Error::TypeNotInferable(ty_span));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -765,7 +765,7 @@ pub enum TypeInner {
|
|||||||
space: AddressSpace,
|
space: AddressSpace,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Homogenous list of elements.
|
/// Homogeneous list of elements.
|
||||||
///
|
///
|
||||||
/// The `base` type must be a [`SIZED`], [`DATA`] type.
|
/// The `base` type must be a [`SIZED`], [`DATA`] type.
|
||||||
///
|
///
|
||||||
|
@ -725,7 +725,7 @@ impl GlobalCtx<'_> {
|
|||||||
/// Normally, this would just be an iterator over `components`. However,
|
/// Normally, this would just be an iterator over `components`. However,
|
||||||
/// `Compose` expressions can concatenate vectors, in which case the i'th
|
/// `Compose` expressions can concatenate vectors, in which case the i'th
|
||||||
/// value being composed is not generally the i'th element of `components`.
|
/// value being composed is not generally the i'th element of `components`.
|
||||||
/// This function consults `ty` to decide if this concatenation is occuring,
|
/// This function consults `ty` to decide if this concatenation is occurring,
|
||||||
/// and returns an iterator that produces the components of the result of
|
/// and returns an iterator that produces the components of the result of
|
||||||
/// the `Compose` expression in either case.
|
/// the `Compose` expression in either case.
|
||||||
pub fn flatten_compose<'arenas>(
|
pub fn flatten_compose<'arenas>(
|
||||||
|
@ -106,7 +106,7 @@ pub enum FunctionError {
|
|||||||
MissingDefaultCase,
|
MissingDefaultCase,
|
||||||
#[error("Multiple `default` cases are present")]
|
#[error("Multiple `default` cases are present")]
|
||||||
MultipleDefaultCases,
|
MultipleDefaultCases,
|
||||||
#[error("The last `switch` case contains a `falltrough`")]
|
#[error("The last `switch` case contains a `fallthrough`")]
|
||||||
LastCaseFallTrough,
|
LastCaseFallTrough,
|
||||||
#[error("The pointer {0:?} doesn't relate to a valid destination for a store")]
|
#[error("The pointer {0:?} doesn't relate to a valid destination for a store")]
|
||||||
InvalidStorePointer(Handle<crate::Expression>),
|
InvalidStorePointer(Handle<crate::Expression>),
|
||||||
|
@ -619,7 +619,7 @@ impl super::Validator {
|
|||||||
ctx.validate(fr.ty, fr.binding.as_ref())
|
ctx.validate(fr.ty, fr.binding.as_ref())
|
||||||
.map_err_inner(|e| EntryPointError::Result(e).with_span())?;
|
.map_err_inner(|e| EntryPointError::Result(e).with_span())?;
|
||||||
if ctx.second_blend_source {
|
if ctx.second_blend_source {
|
||||||
// Only the first location may be used whhen dual source blending
|
// Only the first location may be used when dual source blending
|
||||||
if ctx.location_mask.len() == 1 && ctx.location_mask.contains(0) {
|
if ctx.location_mask.len() == 1 && ctx.location_mask.contains(0) {
|
||||||
info.dual_source_blending = true;
|
info.dual_source_blending = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,7 +104,7 @@ bitflags::bitflags! {
|
|||||||
const MULTISAMPLED_SHADING = 0x800;
|
const MULTISAMPLED_SHADING = 0x800;
|
||||||
/// Support for ray queries and acceleration structures.
|
/// Support for ray queries and acceleration structures.
|
||||||
const RAY_QUERY = 0x1000;
|
const RAY_QUERY = 0x1000;
|
||||||
/// Support for generating two sources for blending from fragement shaders.
|
/// Support for generating two sources for blending from fragment shaders.
|
||||||
const DUAL_SOURCE_BLENDING = 0x2000;
|
const DUAL_SOURCE_BLENDING = 0x2000;
|
||||||
/// Support for arrayed cube textures.
|
/// Support for arrayed cube textures.
|
||||||
const CUBE_ARRAY_TEXTURES = 0x4000;
|
const CUBE_ARRAY_TEXTURES = 0x4000;
|
||||||
|
@ -296,7 +296,7 @@ vec3 point_light(PointLight light, float roughness, float NdotV, vec3 N, vec3 V,
|
|||||||
// f(v,l) = (f_d(v,l) + f_r(v,l)) * light_color
|
// f(v,l) = (f_d(v,l) + f_r(v,l)) * light_color
|
||||||
// Φ is light intensity
|
// Φ is light intensity
|
||||||
|
|
||||||
// our rangeAttentuation = 1 / d^2 multiplied with an attenuation factor for smoothing at the edge of the non-physical maximum light radius
|
// our rangeAttenuation = 1 / d^2 multiplied with an attenuation factor for smoothing at the edge of the non-physical maximum light radius
|
||||||
// It's not 100% clear where the 1/4π goes in the derivation, but we follow the filament shader and leave it out
|
// It's not 100% clear where the 1/4π goes in the derivation, but we follow the filament shader and leave it out
|
||||||
|
|
||||||
// See https://google.github.io/filament/Filament.html#mjx-eqn-pointLightLuminanceEquation
|
// See https://google.github.io/filament/Filament.html#mjx-eqn-pointLightLuminanceEquation
|
||||||
|
@ -181,7 +181,7 @@ fn type_not_constructible() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn type_not_inferrable() {
|
fn type_not_inferable() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
fn x() {
|
fn x() {
|
||||||
|
@ -292,8 +292,8 @@ pub struct FailureReason {
|
|||||||
/// Match a particular message of a failure result.
|
/// Match a particular message of a failure result.
|
||||||
///
|
///
|
||||||
/// If `None`, matches any message. If `Some`, a case-insensitive sub-string
|
/// If `None`, matches any message. If `Some`, a case-insensitive sub-string
|
||||||
/// test is performed. Allowing `"error occured"` to match a message like
|
/// test is performed. Allowing `"error occurred"` to match a message like
|
||||||
/// `"An unexpected Error occured!"`.
|
/// `"An unexpected Error occurred!"`.
|
||||||
message: Option<&'static str>,
|
message: Option<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,8 +324,8 @@ impl FailureReason {
|
|||||||
/// Match an error with a message.
|
/// Match an error with a message.
|
||||||
///
|
///
|
||||||
/// If specified, a case-insensitive sub-string test is performed. Allowing
|
/// If specified, a case-insensitive sub-string test is performed. Allowing
|
||||||
/// `"error occured"` to match a message like `"An unexpected Error
|
/// `"error occurred"` to match a message like `"An unexpected Error
|
||||||
/// occured!"`.
|
/// occurred!"`.
|
||||||
pub fn with_message(self, message: &'static str) -> Self {
|
pub fn with_message(self, message: &'static str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
message: Some(message),
|
message: Some(message),
|
||||||
|
@ -222,7 +222,7 @@ pub async fn compare_image_output(
|
|||||||
all_passed &= check.check(&mut pool);
|
all_passed &= check.check(&mut pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the error values to a false color reprensentation
|
// Convert the error values to a false color representation
|
||||||
let magma_image = error_map_flip
|
let magma_image = error_map_flip
|
||||||
.apply_color_lut(&nv_flip::magma_lut())
|
.apply_color_lut(&nv_flip::magma_lut())
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
@ -4,7 +4,7 @@ use wgpu_test::{fail, gpu_test, FailureCase, GpuTestConfiguration, TestParameter
|
|||||||
static CROSS_DEVICE_BIND_GROUP_USAGE: GpuTestConfiguration = GpuTestConfiguration::new()
|
static CROSS_DEVICE_BIND_GROUP_USAGE: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||||
.parameters(TestParameters::default().expect_fail(FailureCase::always()))
|
.parameters(TestParameters::default().expect_fail(FailureCase::always()))
|
||||||
.run_async(|ctx| async move {
|
.run_async(|ctx| async move {
|
||||||
// Create a bind group uisng a layout from another device. This should be a validation
|
// Create a bind group using a layout from another device. This should be a validation
|
||||||
// error but currently crashes.
|
// error but currently crashes.
|
||||||
let (device2, _) =
|
let (device2, _) =
|
||||||
pollster::block_on(ctx.adapter.request_device(&Default::default(), None)).unwrap();
|
pollster::block_on(ctx.adapter.request_device(&Default::default(), None)).unwrap();
|
||||||
@ -116,7 +116,7 @@ async fn request_device_error_message() {
|
|||||||
// This is a test of device behavior after device.destroy. Specifically, all operations
|
// This is a test of device behavior after device.destroy. Specifically, all operations
|
||||||
// should trigger errors since the device is lost.
|
// should trigger errors since the device is lost.
|
||||||
//
|
//
|
||||||
// On DX12 this test fails with a validation error in the very artifical actions taken
|
// On DX12 this test fails with a validation error in the very artificial actions taken
|
||||||
// after lose the device. The error is "ID3D12CommandAllocator::Reset: The command
|
// after lose the device. The error is "ID3D12CommandAllocator::Reset: The command
|
||||||
// allocator cannot be reset because a command list is currently being recorded with the
|
// allocator cannot be reset because a command list is currently being recorded with the
|
||||||
// allocator." That may indicate that DX12 doesn't like opened command buffers staying
|
// allocator." That may indicate that DX12 doesn't like opened command buffers staying
|
||||||
@ -265,7 +265,7 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne
|
|||||||
// TODO: change these fail calls to check for the specific errors which indicate that
|
// TODO: change these fail calls to check for the specific errors which indicate that
|
||||||
// the device is not valid.
|
// the device is not valid.
|
||||||
|
|
||||||
// Creating a commmand encoder should fail.
|
// Creating a command encoder should fail.
|
||||||
fail(&ctx.device, || {
|
fail(&ctx.device, || {
|
||||||
ctx.device
|
ctx.device
|
||||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
|
||||||
|
@ -159,7 +159,7 @@ static IMAGE_BITMAP_IMPORT: GpuTestConfiguration =
|
|||||||
// Layer count of the destination texture
|
// Layer count of the destination texture
|
||||||
let mut dest_layers = 1;
|
let mut dest_layers = 1;
|
||||||
|
|
||||||
// If the test is suppoed to be valid call to copyExternal.
|
// If the test is supposed to be valid call to copyExternal.
|
||||||
let mut valid = true;
|
let mut valid = true;
|
||||||
match case {
|
match case {
|
||||||
TestCase::Normal => {}
|
TestCase::Normal => {}
|
||||||
|
@ -21,9 +21,9 @@ fn vs_main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
|
|||||||
@group(0) @binding(2) var tex_uv: texture_2d<f32>;
|
@group(0) @binding(2) var tex_uv: texture_2d<f32>;
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(v_ouput: VertexOutput) -> @location(0) vec4<f32> {
|
fn fs_main(v_output: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let luminance = textureSample(tex_y, s, v_ouput.uv).r;
|
let luminance = textureSample(tex_y, s, v_output.uv).r;
|
||||||
let chrominance = textureSample(tex_uv, s, v_ouput.uv).rg;
|
let chrominance = textureSample(tex_uv, s, v_output.uv).rg;
|
||||||
let rgb = mat3x3<f32>(
|
let rgb = mat3x3<f32>(
|
||||||
1.000000, 1.000000, 1.000000,
|
1.000000, 1.000000, 1.000000,
|
||||||
0.000000,-0.187324, 1.855600,
|
0.000000,-0.187324, 1.855600,
|
||||||
|
@ -5,7 +5,7 @@ use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters, TestingContext};
|
|||||||
/// We want to test that partial updates to push constants work as expected.
|
/// We want to test that partial updates to push constants work as expected.
|
||||||
///
|
///
|
||||||
/// As such, we dispatch two compute passes, one which writes the values
|
/// As such, we dispatch two compute passes, one which writes the values
|
||||||
/// before a parital update, and one which writes the values after the partial update.
|
/// before a partial update, and one which writes the values after the partial update.
|
||||||
///
|
///
|
||||||
/// If the update code is working correctly, the values not written to by the second update
|
/// If the update code is working correctly, the values not written to by the second update
|
||||||
/// will remain unchanged.
|
/// will remain unchanged.
|
||||||
|
@ -21,7 +21,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration =
|
|||||||
.device
|
.device
|
||||||
.create_shader_module(include_wgsl!("issue_3457.wgsl"));
|
.create_shader_module(include_wgsl!("issue_3457.wgsl"));
|
||||||
|
|
||||||
// We use two separate vertex buffers so we can delete one in between submisions
|
// We use two separate vertex buffers so we can delete one in between submissions
|
||||||
let vertex_buffer1 = ctx.device.create_buffer(&BufferDescriptor {
|
let vertex_buffer1 = ctx.device.create_buffer(&BufferDescriptor {
|
||||||
label: Some("vertex buffer 1"),
|
label: Some("vertex buffer 1"),
|
||||||
size: 3 * 16,
|
size: 3 * 16,
|
||||||
|
@ -11,7 +11,7 @@ use wgpu::*;
|
|||||||
/// callback is invoked.
|
/// callback is invoked.
|
||||||
///
|
///
|
||||||
/// We previously immediately invoked on_submitted_work_done callbacks if there was no active submission
|
/// We previously immediately invoked on_submitted_work_done callbacks if there was no active submission
|
||||||
/// to add them to. This is incorrect, as we do not immediatley invoke map_async callbacks.
|
/// to add them to. This is incorrect, as we do not immediately invoke map_async callbacks.
|
||||||
#[gpu_test]
|
#[gpu_test]
|
||||||
static QUEUE_SUBMITTED_CALLBACK_ORDERING: GpuTestConfiguration = GpuTestConfiguration::new()
|
static QUEUE_SUBMITTED_CALLBACK_ORDERING: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||||
.run_async(|ctx| async move {
|
.run_async(|ctx| async move {
|
||||||
|
22
typos.toml
Normal file
22
typos.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[files]
|
||||||
|
extend-exclude = [
|
||||||
|
# spirv-asm isn't real source code
|
||||||
|
'*.spvasm'
|
||||||
|
]
|
||||||
|
|
||||||
|
# Corrections take the form of a key/value pair. The key is the incorrect word
|
||||||
|
# and the value is the correct word. If the key and value are the same, the
|
||||||
|
# word is treated as always correct. If the value is an empty string, the word
|
||||||
|
# is treated as always incorrect.
|
||||||
|
|
||||||
|
[default.extend-words]
|
||||||
|
# Things that aren't typos
|
||||||
|
lod = "lod"
|
||||||
|
inout = "inout"
|
||||||
|
derivate = "derivate"
|
||||||
|
implace = "implace"
|
||||||
|
Ded = "Ded" # This shows up in "ANDed"
|
||||||
|
|
||||||
|
# Usernames
|
||||||
|
Healthire = "Healthire"
|
||||||
|
REASY = "REASY"
|
@ -36,7 +36,7 @@ api_log_info = []
|
|||||||
## Log resource lifecycle management at info instead of trace level.
|
## Log resource lifecycle management at info instead of trace level.
|
||||||
resource_log_info = []
|
resource_log_info = []
|
||||||
|
|
||||||
## Use static linking for libraries. Disale to manually link. Enabled by default.
|
## Use static linking for libraries. Disable to manually link. Enabled by default.
|
||||||
link = ["hal/link"]
|
link = ["hal/link"]
|
||||||
|
|
||||||
## Support the Renderdoc graphics debugger:
|
## Support the Renderdoc graphics debugger:
|
||||||
|
@ -580,7 +580,7 @@ pub enum PushConstantUploadError {
|
|||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct PipelineLayoutDescriptor<'a> {
|
pub struct PipelineLayoutDescriptor<'a> {
|
||||||
/// Debug label of the pipeine layout.
|
/// Debug label of the pipeline layout.
|
||||||
///
|
///
|
||||||
/// This will show up in graphics debuggers for easy identification.
|
/// This will show up in graphics debuggers for easy identification.
|
||||||
pub label: Label<'a>,
|
pub label: Label<'a>,
|
||||||
|
@ -423,7 +423,7 @@ impl Global {
|
|||||||
.map_pass_err(pass_scope)?;
|
.map_pass_err(pass_scope)?;
|
||||||
|
|
||||||
// Unlike in render passes we can't delay resetting the query sets since
|
// Unlike in render passes we can't delay resetting the query sets since
|
||||||
// there is no auxillary pass.
|
// there is no auxiliary pass.
|
||||||
let range = if let (Some(index_a), Some(index_b)) =
|
let range = if let (Some(index_a), Some(index_b)) =
|
||||||
(tw.beginning_of_pass_write_index, tw.end_of_pass_write_index)
|
(tw.beginning_of_pass_write_index, tw.end_of_pass_write_index)
|
||||||
{
|
{
|
||||||
|
@ -379,7 +379,7 @@ impl VertexState {
|
|||||||
fn update_limits(&mut self) {
|
fn update_limits(&mut self) {
|
||||||
// Implements the validation from https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-draw
|
// Implements the validation from https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-draw
|
||||||
// Except that the formula is shuffled to extract the number of vertices in order
|
// Except that the formula is shuffled to extract the number of vertices in order
|
||||||
// to carry the bulk of the computation when changing states intead of when producing
|
// to carry the bulk of the computation when changing states instead of when producing
|
||||||
// draws. Draw calls tend to happen at a higher frequency. Here we determine vertex
|
// draws. Draw calls tend to happen at a higher frequency. Here we determine vertex
|
||||||
// limits that can be cheaply checked for each draw call.
|
// limits that can be cheaply checked for each draw call.
|
||||||
self.vertex_limit = u32::MAX as u64;
|
self.vertex_limit = u32::MAX as u64;
|
||||||
@ -395,7 +395,7 @@ impl VertexState {
|
|||||||
} else {
|
} else {
|
||||||
if vbs.step.stride == 0 {
|
if vbs.step.stride == 0 {
|
||||||
// We already checked that the last stride fits, the same
|
// We already checked that the last stride fits, the same
|
||||||
// vertex will be repeated so this slot can accomodate any number of
|
// vertex will be repeated so this slot can accommodate any number of
|
||||||
// vertices.
|
// vertices.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1640,7 +1640,7 @@ impl Global {
|
|||||||
|
|
||||||
// Initialize each `vertex.inputs[i].step` from
|
// Initialize each `vertex.inputs[i].step` from
|
||||||
// `pipeline.vertex_steps[i]`. Enlarge `vertex.inputs`
|
// `pipeline.vertex_steps[i]`. Enlarge `vertex.inputs`
|
||||||
// as necessary to accomodate all slots in the
|
// as necessary to accommodate all slots in the
|
||||||
// pipeline. If `vertex.inputs` is longer, fill the
|
// pipeline. If `vertex.inputs` is longer, fill the
|
||||||
// extra entries with default `VertexStep`s.
|
// extra entries with default `VertexStep`s.
|
||||||
while state.vertex.inputs.len() < vertex_steps_len {
|
while state.vertex.inputs.len() < vertex_steps_len {
|
||||||
|
@ -69,7 +69,7 @@ pub enum TransferError {
|
|||||||
dimension: TextureErrorDimension,
|
dimension: TextureErrorDimension,
|
||||||
side: CopySide,
|
side: CopySide,
|
||||||
},
|
},
|
||||||
#[error("Unable to select texture aspect {aspect:?} from fromat {format:?}")]
|
#[error("Unable to select texture aspect {aspect:?} from format {format:?}")]
|
||||||
InvalidTextureAspect {
|
InvalidTextureAspect {
|
||||||
format: wgt::TextureFormat,
|
format: wgt::TextureFormat,
|
||||||
aspect: wgt::TextureAspect,
|
aspect: wgt::TextureAspect,
|
||||||
@ -252,7 +252,7 @@ pub(crate) fn validate_linear_texture_data(
|
|||||||
) -> Result<(BufferAddress, BufferAddress), TransferError> {
|
) -> Result<(BufferAddress, BufferAddress), TransferError> {
|
||||||
// Convert all inputs to BufferAddress (u64) to avoid some of the overflow issues
|
// Convert all inputs to BufferAddress (u64) to avoid some of the overflow issues
|
||||||
// Note: u64 is not always enough to prevent overflow, especially when multiplying
|
// Note: u64 is not always enough to prevent overflow, especially when multiplying
|
||||||
// something with a potentially large depth value, so it is preferrable to validate
|
// something with a potentially large depth value, so it is preferable to validate
|
||||||
// the copy size before calling this function (for example via `validate_texture_copy_range`).
|
// the copy size before calling this function (for example via `validate_texture_copy_range`).
|
||||||
let copy_width = copy_size.width as BufferAddress;
|
let copy_width = copy_size.width as BufferAddress;
|
||||||
let copy_height = copy_size.height as BufferAddress;
|
let copy_height = copy_size.height as BufferAddress;
|
||||||
|
@ -38,7 +38,7 @@ impl AnyDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: The pointer returned by Arc::into_raw is gauranteed to be
|
// SAFETY: The pointer returned by Arc::into_raw is guaranteed to be
|
||||||
// non-null.
|
// non-null.
|
||||||
let data = unsafe { NonNull::new_unchecked(Arc::into_raw(device).cast_mut()) };
|
let data = unsafe { NonNull::new_unchecked(Arc::into_raw(device).cast_mut()) };
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ pub enum Origin {
|
|||||||
#[derive(Debug, Default, Clone, Eq)]
|
#[derive(Debug, Default, Clone, Eq)]
|
||||||
pub struct EntryMap {
|
pub struct EntryMap {
|
||||||
/// We use a IndexMap here so that we can sort the entries by their binding index,
|
/// We use a IndexMap here so that we can sort the entries by their binding index,
|
||||||
/// guarenteeing that the hash of equivilant layouts will be the same.
|
/// guaranteeing that the hash of equivalent layouts will be the same.
|
||||||
inner: FastIndexMap<u32, wgt::BindGroupLayoutEntry>,
|
inner: FastIndexMap<u32, wgt::BindGroupLayoutEntry>,
|
||||||
/// We keep track of whether the map is sorted or not, so that we can assert that
|
/// We keep track of whether the map is sorted or not, so that we can assert that
|
||||||
/// it is sorted, so that PartialEq and Hash will be stable.
|
/// it is sorted, so that PartialEq and Hash will be stable.
|
||||||
|
@ -328,7 +328,7 @@ impl Global {
|
|||||||
|
|
||||||
/// Assign `id_in` an error with the given `label`.
|
/// Assign `id_in` an error with the given `label`.
|
||||||
///
|
///
|
||||||
/// See `create_buffer_error` for more context and explaination.
|
/// See `create_buffer_error` for more context and explanation.
|
||||||
pub fn create_texture_error<A: HalApi>(&self, id_in: Option<id::TextureId>, label: Label) {
|
pub fn create_texture_error<A: HalApi>(&self, id_in: Option<id::TextureId>, label: Label) {
|
||||||
let hub = A::hub(self);
|
let hub = A::hub(self);
|
||||||
let fid = hub.textures.prepare(id_in);
|
let fid = hub.textures.prepare(id_in);
|
||||||
@ -2084,7 +2084,7 @@ impl Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "replay")]
|
#[cfg(feature = "replay")]
|
||||||
/// Only triange suspected resource IDs. This helps us to avoid ID collisions
|
/// Only triangle suspected resource IDs. This helps us to avoid ID collisions
|
||||||
/// upon creating new resources when re-playing a trace.
|
/// upon creating new resources when re-playing a trace.
|
||||||
pub fn device_maintain_ids<A: HalApi>(&self, device_id: DeviceId) -> Result<(), InvalidDevice> {
|
pub fn device_maintain_ids<A: HalApi>(&self, device_id: DeviceId) -> Result<(), InvalidDevice> {
|
||||||
let hub = A::hub(self);
|
let hub = A::hub(self);
|
||||||
@ -2519,7 +2519,7 @@ impl Global {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ptr points to the beginning of the range we mapped in map_async
|
// ptr points to the beginning of the range we mapped in map_async
|
||||||
// rather thant the beginning of the buffer.
|
// rather than the beginning of the buffer.
|
||||||
let relative_offset = (offset - range.start) as isize;
|
let relative_offset = (offset - range.start) as isize;
|
||||||
unsafe { Ok((ptr.as_ptr().offset(relative_offset), range_size)) }
|
unsafe { Ok((ptr.as_ptr().offset(relative_offset), range_size)) }
|
||||||
}
|
}
|
||||||
|
@ -409,7 +409,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
|||||||
Some(active) => {
|
Some(active) => {
|
||||||
active.work_done_closures.push(closure);
|
active.work_done_closures.push(closure);
|
||||||
}
|
}
|
||||||
// We must defer the closure until all previously occuring map_async closures
|
// We must defer the closure until all previously occurring map_async closures
|
||||||
// have fired. This is required by the spec.
|
// have fired. This is required by the spec.
|
||||||
None => {
|
None => {
|
||||||
self.work_done_closures.push(closure);
|
self.work_done_closures.push(closure);
|
||||||
@ -439,8 +439,8 @@ impl<A: HalApi> LifetimeTracker<A> {
|
|||||||
let is_removed = trackers.remove_abandoned(id);
|
let is_removed = trackers.remove_abandoned(id);
|
||||||
if is_removed {
|
if is_removed {
|
||||||
removed_resources.push(resource.clone());
|
removed_resources.push(resource.clone());
|
||||||
if let Some(ressources) = non_referenced_resources {
|
if let Some(resources) = non_referenced_resources {
|
||||||
get_resource_map(ressources).insert(id, resource.clone());
|
get_resource_map(resources).insert(id, resource.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
!is_removed
|
!is_removed
|
||||||
|
@ -71,7 +71,7 @@ use super::{
|
|||||||
/// 1. `self.trace` is locked last (unenforced)
|
/// 1. `self.trace` is locked last (unenforced)
|
||||||
///
|
///
|
||||||
/// Right now avoid locking twice same resource or registry in a call execution
|
/// Right now avoid locking twice same resource or registry in a call execution
|
||||||
/// and minimize the locking to the minimum scope possibile
|
/// and minimize the locking to the minimum scope possible
|
||||||
/// Unless otherwise specified, no lock may be acquired while holding another lock.
|
/// Unless otherwise specified, no lock may be acquired while holding another lock.
|
||||||
/// This means that you must inspect function calls made while a lock is held
|
/// This means that you must inspect function calls made while a lock is held
|
||||||
/// to see what locks the callee may try to acquire.
|
/// to see what locks the callee may try to acquire.
|
||||||
|
@ -80,7 +80,7 @@ impl RawId {
|
|||||||
/// Coerce a slice of identifiers into a slice of optional raw identifiers.
|
/// Coerce a slice of identifiers into a slice of optional raw identifiers.
|
||||||
///
|
///
|
||||||
/// There's two reasons why we know this is correct:
|
/// There's two reasons why we know this is correct:
|
||||||
/// * `Option<T>` is guarnateed to be niche-filled to 0's.
|
/// * `Option<T>` is guaranteed to be niche-filled to 0's.
|
||||||
/// * The `T` in `Option<T>` can inhabit any representation except 0's, since
|
/// * The `T` in `Option<T>` can inhabit any representation except 0's, since
|
||||||
/// its underlying representation is `NonZero*`.
|
/// its underlying representation is `NonZero*`.
|
||||||
pub fn as_option_slice<T: Marker>(ids: &[Id<T>]) -> &[Option<Id<T>>] {
|
pub fn as_option_slice<T: Marker>(ids: &[Id<T>]) -> &[Option<Id<T>>] {
|
||||||
|
@ -327,7 +327,7 @@ mod test {
|
|||||||
vec![900..1000]
|
vec![900..1000]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Splitted ranges.
|
// Split ranges.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracker.drain(5..1003).collect::<Vec<Range<u32>>>(),
|
tracker.drain(5..1003).collect::<Vec<Range<u32>>>(),
|
||||||
vec![5..21, 42..900, 1000..1003]
|
vec![5..21, 42..900, 1000..1003]
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//!
|
//!
|
||||||
//! - **`api_log_info`** --- Log all API entry points at info instead of trace level.
|
//! - **`api_log_info`** --- Log all API entry points at info instead of trace level.
|
||||||
//! - **`resource_log_info`** --- Log resource lifecycle management at info instead of trace level.
|
//! - **`resource_log_info`** --- Log resource lifecycle management at info instead of trace level.
|
||||||
//! - **`link`** _(enabled by default)_ --- Use static linking for libraries. Disale to manually
|
//! - **`link`** _(enabled by default)_ --- Use static linking for libraries. Disable to manually
|
||||||
//! link. Enabled by default.
|
//! link. Enabled by default.
|
||||||
//! - **`renderdoc`** --- Support the Renderdoc graphics debugger:
|
//! - **`renderdoc`** --- Support the Renderdoc graphics debugger:
|
||||||
//! [https://renderdoc.org/](https://renderdoc.org/)
|
//! [https://renderdoc.org/](https://renderdoc.org/)
|
||||||
@ -58,7 +58,7 @@
|
|||||||
clippy::needless_lifetimes,
|
clippy::needless_lifetimes,
|
||||||
// No need for defaults in the internal types.
|
// No need for defaults in the internal types.
|
||||||
clippy::new_without_default,
|
clippy::new_without_default,
|
||||||
// Needless updates are more scaleable, easier to play with features.
|
// Needless updates are more scalable, easier to play with features.
|
||||||
clippy::needless_update,
|
clippy::needless_update,
|
||||||
// Need many arguments for some core functions to be able to re-use code in many situations.
|
// Need many arguments for some core functions to be able to re-use code in many situations.
|
||||||
clippy::too_many_arguments,
|
clippy::too_many_arguments,
|
||||||
|
@ -377,7 +377,7 @@ pub enum ColorStateError {
|
|||||||
FormatNotBlendable(wgt::TextureFormat),
|
FormatNotBlendable(wgt::TextureFormat),
|
||||||
#[error("Format {0:?} does not have a color aspect")]
|
#[error("Format {0:?} does not have a color aspect")]
|
||||||
FormatNotColor(wgt::TextureFormat),
|
FormatNotColor(wgt::TextureFormat),
|
||||||
#[error("Sample count {0} is not supported by format {1:?} on this device. The WebGPU spec guarentees {2:?} samples are supported by this format. With the TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES feature your device supports {3:?}.")]
|
#[error("Sample count {0} is not supported by format {1:?} on this device. The WebGPU spec guarantees {2:?} samples are supported by this format. With the TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES feature your device supports {3:?}.")]
|
||||||
InvalidSampleCount(u32, wgt::TextureFormat, Vec<u32>, Vec<u32>),
|
InvalidSampleCount(u32, wgt::TextureFormat, Vec<u32>, Vec<u32>),
|
||||||
#[error("Output format {pipeline} is incompatible with the shader {shader}")]
|
#[error("Output format {pipeline} is incompatible with the shader {shader}")]
|
||||||
IncompatibleFormat {
|
IncompatibleFormat {
|
||||||
@ -399,7 +399,7 @@ pub enum DepthStencilStateError {
|
|||||||
FormatNotDepth(wgt::TextureFormat),
|
FormatNotDepth(wgt::TextureFormat),
|
||||||
#[error("Format {0:?} does not have a stencil aspect, but stencil test/write is enabled")]
|
#[error("Format {0:?} does not have a stencil aspect, but stencil test/write is enabled")]
|
||||||
FormatNotStencil(wgt::TextureFormat),
|
FormatNotStencil(wgt::TextureFormat),
|
||||||
#[error("Sample count {0} is not supported by format {1:?} on this device. The WebGPU spec guarentees {2:?} samples are supported by this format. With the TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES feature your device supports {3:?}.")]
|
#[error("Sample count {0} is not supported by format {1:?} on this device. The WebGPU spec guarantees {2:?} samples are supported by this format. With the TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES feature your device supports {3:?}.")]
|
||||||
InvalidSampleCount(u32, wgt::TextureFormat, Vec<u32>, Vec<u32>),
|
InvalidSampleCount(u32, wgt::TextureFormat, Vec<u32>, Vec<u32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ impl<K: Clone + Eq + Hash, V> ResourcePool<K, V> {
|
|||||||
|
|
||||||
drop(map_guard);
|
drop(map_guard);
|
||||||
|
|
||||||
// Some other thread may beat us to initializing the entry, but OnceCell guarentees that only one thread
|
// Some other thread may beat us to initializing the entry, but OnceCell guarantees that only one thread
|
||||||
// will actually initialize the entry.
|
// will actually initialize the entry.
|
||||||
//
|
//
|
||||||
// We pass the strong reference outside of the closure to keep it alive while we're the only one keeping a reference to it.
|
// We pass the strong reference outside of the closure to keep it alive while we're the only one keeping a reference to it.
|
||||||
|
@ -155,7 +155,7 @@ pub trait Resource: 'static + Sized + WasmNotSendSync {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum BufferMapAsyncStatus {
|
pub enum BufferMapAsyncStatus {
|
||||||
/// The Buffer is sucessfully mapped, `get_mapped_range` can be called.
|
/// The Buffer is successfully mapped, `get_mapped_range` can be called.
|
||||||
///
|
///
|
||||||
/// All other variants of this enum represent failures to map the buffer.
|
/// All other variants of this enum represent failures to map the buffer.
|
||||||
Success,
|
Success,
|
||||||
@ -1155,7 +1155,7 @@ pub enum CreateTextureError {
|
|||||||
InvalidMultisampledStorageBinding,
|
InvalidMultisampledStorageBinding,
|
||||||
#[error("Format {0:?} does not support multisampling")]
|
#[error("Format {0:?} does not support multisampling")]
|
||||||
InvalidMultisampledFormat(wgt::TextureFormat),
|
InvalidMultisampledFormat(wgt::TextureFormat),
|
||||||
#[error("Sample count {0} is not supported by format {1:?} on this device. The WebGPU spec guarentees {2:?} samples are supported by this format. With the TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES feature your device supports {3:?}.")]
|
#[error("Sample count {0} is not supported by format {1:?} on this device. The WebGPU spec guarantees {2:?} samples are supported by this format. With the TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES feature your device supports {3:?}.")]
|
||||||
InvalidSampleCount(u32, wgt::TextureFormat, Vec<u32>, Vec<u32>),
|
InvalidSampleCount(u32, wgt::TextureFormat, Vec<u32>, Vec<u32>),
|
||||||
#[error("Multisampled textures must have RENDER_ATTACHMENT usage")]
|
#[error("Multisampled textures must have RENDER_ATTACHMENT usage")]
|
||||||
MultisampledNotRenderAttachment,
|
MultisampledNotRenderAttachment,
|
||||||
|
@ -12,7 +12,7 @@ pub struct ExclusiveSnatchGuard<'a>(RwLockWriteGuard<'a, ()>);
|
|||||||
/// it early.
|
/// it early.
|
||||||
///
|
///
|
||||||
/// In order to safely access the underlying data, the device's global snatchable
|
/// In order to safely access the underlying data, the device's global snatchable
|
||||||
/// lock must be taken. To guarentee it, methods take a read or write guard of that
|
/// lock must be taken. To guarantee it, methods take a read or write guard of that
|
||||||
/// special lock.
|
/// special lock.
|
||||||
pub struct Snatchable<T> {
|
pub struct Snatchable<T> {
|
||||||
value: UnsafeCell<Option<T>>,
|
value: UnsafeCell<Option<T>>,
|
||||||
@ -68,7 +68,7 @@ impl SnatchLock {
|
|||||||
/// The safety of `Snatchable::get` and `Snatchable::snatch` rely on their using of the
|
/// The safety of `Snatchable::get` and `Snatchable::snatch` rely on their using of the
|
||||||
/// right SnatchLock (the one associated to the same device). This method is unsafe
|
/// right SnatchLock (the one associated to the same device). This method is unsafe
|
||||||
/// to force force sers to think twice about creating a SnatchLock. The only place this
|
/// to force force sers to think twice about creating a SnatchLock. The only place this
|
||||||
/// method sould be called is when creating the device.
|
/// method should be called is when creating the device.
|
||||||
pub unsafe fn new() -> Self {
|
pub unsafe fn new() -> Self {
|
||||||
SnatchLock {
|
SnatchLock {
|
||||||
lock: RwLock::new(()),
|
lock: RwLock::new(()),
|
||||||
|
@ -165,7 +165,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn insert_error(&mut self, id: Id<T::Marker>, label: &str) {
|
pub(crate) fn insert_error(&mut self, id: Id<T::Marker>, label: &str) {
|
||||||
log::trace!("User is insering as error {}{:?}", T::TYPE, id);
|
log::trace!("User is inserting as error {}{:?}", T::TYPE, id);
|
||||||
let (index, epoch, _) = id.unzip();
|
let (index, epoch, _) = id.unzip();
|
||||||
self.insert_impl(
|
self.insert_impl(
|
||||||
index as usize,
|
index as usize,
|
||||||
|
@ -60,7 +60,7 @@ impl<A: HalApi> BufferBindGroupState<A> {
|
|||||||
/// Optimize the buffer bind group state by sorting it by ID.
|
/// Optimize the buffer bind group state by sorting it by ID.
|
||||||
///
|
///
|
||||||
/// When this list of states is merged into a tracker, the memory
|
/// When this list of states is merged into a tracker, the memory
|
||||||
/// accesses will be in a constant assending order.
|
/// accesses will be in a constant ascending order.
|
||||||
#[allow(clippy::pattern_type_mismatch)]
|
#[allow(clippy::pattern_type_mismatch)]
|
||||||
pub(crate) fn optimize(&self) {
|
pub(crate) fn optimize(&self) {
|
||||||
let mut buffers = self.buffers.lock();
|
let mut buffers = self.buffers.lock();
|
||||||
|
@ -205,7 +205,7 @@ fn invalid_resource_state<T: ResourceUses>(state: T) -> bool {
|
|||||||
/// a barrier.
|
/// a barrier.
|
||||||
fn skip_barrier<T: ResourceUses>(old_state: T, new_state: T) -> bool {
|
fn skip_barrier<T: ResourceUses>(old_state: T, new_state: T) -> bool {
|
||||||
// If the state didn't change and all the usages are ordered, the hardware
|
// If the state didn't change and all the usages are ordered, the hardware
|
||||||
// will guarentee the order of accesses, so we do not need to issue a barrier at all
|
// will guarantee the order of accesses, so we do not need to issue a barrier at all
|
||||||
old_state == new_state && old_state.all_ordered()
|
old_state == new_state && old_state.all_ordered()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +313,7 @@ impl<T: ResourceUses> fmt::Display for InvalidUse<T> {
|
|||||||
/// and may include conflicting uses. This is fully compliant by the WebGPU spec.
|
/// and may include conflicting uses. This is fully compliant by the WebGPU spec.
|
||||||
///
|
///
|
||||||
/// All bind group states are sorted by their ID so that when adding to a tracker,
|
/// All bind group states are sorted by their ID so that when adding to a tracker,
|
||||||
/// they are added in the most efficient order possible (assending order).
|
/// they are added in the most efficient order possible (ascending order).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct BindGroupStates<A: HalApi> {
|
pub(crate) struct BindGroupStates<A: HalApi> {
|
||||||
pub buffers: BufferBindGroupState<A>,
|
pub buffers: BufferBindGroupState<A>,
|
||||||
@ -335,7 +335,7 @@ impl<A: HalApi> BindGroupStates<A> {
|
|||||||
/// Optimize the bind group states by sorting them by ID.
|
/// Optimize the bind group states by sorting them by ID.
|
||||||
///
|
///
|
||||||
/// When this list of states is merged into a tracker, the memory
|
/// When this list of states is merged into a tracker, the memory
|
||||||
/// accesses will be in a constant assending order.
|
/// accesses will be in a constant ascending order.
|
||||||
pub fn optimize(&mut self) {
|
pub fn optimize(&mut self) {
|
||||||
self.buffers.optimize();
|
self.buffers.optimize();
|
||||||
self.textures.optimize();
|
self.textures.optimize();
|
||||||
|
@ -31,7 +31,7 @@ impl<T: Resource> StatelessBindGroupSate<T> {
|
|||||||
/// Optimize the buffer bind group state by sorting it by ID.
|
/// Optimize the buffer bind group state by sorting it by ID.
|
||||||
///
|
///
|
||||||
/// When this list of states is merged into a tracker, the memory
|
/// When this list of states is merged into a tracker, the memory
|
||||||
/// accesses will be in a constant assending order.
|
/// accesses will be in a constant ascending order.
|
||||||
pub(crate) fn optimize(&self) {
|
pub(crate) fn optimize(&self) {
|
||||||
let mut resources = self.resources.lock();
|
let mut resources = self.resources.lock();
|
||||||
resources.sort_unstable_by_key(|&(id, _)| id.unzip().0);
|
resources.sort_unstable_by_key(|&(id, _)| id.unzip().0);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/*! Texture Trackers
|
/*! Texture Trackers
|
||||||
*
|
*
|
||||||
* Texture trackers are signifigantly more complicated than
|
* Texture trackers are significantly more complicated than
|
||||||
* the buffer trackers because textures can be in a "complex"
|
* the buffer trackers because textures can be in a "complex"
|
||||||
* state where each individual subresource can potentially be
|
* state where each individual subresource can potentially be
|
||||||
* in a different state from every other subtresource. These
|
* in a different state from every other subtresource. These
|
||||||
* complex states are stored seperately from the simple states
|
* complex states are stored separately from the simple states
|
||||||
* because they are signifignatly more difficult to track and
|
* because they are signifignatly more difficult to track and
|
||||||
* most resources spend the vast majority of their lives in
|
* most resources spend the vast majority of their lives in
|
||||||
* simple states.
|
* simple states.
|
||||||
@ -170,7 +170,7 @@ impl<A: HalApi> TextureBindGroupState<A> {
|
|||||||
/// Optimize the texture bind group state by sorting it by ID.
|
/// Optimize the texture bind group state by sorting it by ID.
|
||||||
///
|
///
|
||||||
/// When this list of states is merged into a tracker, the memory
|
/// When this list of states is merged into a tracker, the memory
|
||||||
/// accesses will be in a constant assending order.
|
/// accesses will be in a constant ascending order.
|
||||||
pub(crate) fn optimize(&self) {
|
pub(crate) fn optimize(&self) {
|
||||||
let mut textures = self.textures.lock();
|
let mut textures = self.textures.lock();
|
||||||
textures.sort_unstable_by_key(|v| v.texture.as_info().id().unzip().0);
|
textures.sort_unstable_by_key(|v| v.texture.as_info().id().unzip().0);
|
||||||
@ -1026,7 +1026,7 @@ unsafe fn insert<A: HalApi>(
|
|||||||
|
|
||||||
log::trace!("\ttex {index}: insert end {state:?}");
|
log::trace!("\ttex {index}: insert end {state:?}");
|
||||||
|
|
||||||
// We only need to insert into the end, as there is guarenteed to be
|
// We only need to insert into the end, as there is guaranteed to be
|
||||||
// a start state provider.
|
// a start state provider.
|
||||||
unsafe { *end_state.simple.get_unchecked_mut(index) = state };
|
unsafe { *end_state.simple.get_unchecked_mut(index) = state };
|
||||||
}
|
}
|
||||||
@ -1039,7 +1039,7 @@ unsafe fn insert<A: HalApi>(
|
|||||||
|
|
||||||
log::trace!("\ttex {index}: insert end {complex:?}");
|
log::trace!("\ttex {index}: insert end {complex:?}");
|
||||||
|
|
||||||
// We only need to insert into the end, as there is guarenteed to be
|
// We only need to insert into the end, as there is guaranteed to be
|
||||||
// a start state provider.
|
// a start state provider.
|
||||||
unsafe { *end_state.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
|
unsafe { *end_state.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
|
||||||
end_state.complex.insert(index, complex);
|
end_state.complex.insert(index, complex);
|
||||||
|
@ -10,12 +10,12 @@ use winapi::{
|
|||||||
// lock everyone out until we have registered or unregistered the
|
// lock everyone out until we have registered or unregistered the
|
||||||
// exception handler, otherwise really nasty races could happen.
|
// exception handler, otherwise really nasty races could happen.
|
||||||
//
|
//
|
||||||
// By routing all the registration through these functions we can guarentee
|
// By routing all the registration through these functions we can guarantee
|
||||||
// there is either 1 or 0 exception handlers registered, not multiple.
|
// there is either 1 or 0 exception handlers registered, not multiple.
|
||||||
static EXCEPTION_HANLDER_COUNT: Mutex<usize> = Mutex::const_new(parking_lot::RawMutex::INIT, 0);
|
static EXCEPTION_HANDLER_COUNT: Mutex<usize> = Mutex::const_new(parking_lot::RawMutex::INIT, 0);
|
||||||
|
|
||||||
pub fn register_exception_handler() {
|
pub fn register_exception_handler() {
|
||||||
let mut count_guard = EXCEPTION_HANLDER_COUNT.lock();
|
let mut count_guard = EXCEPTION_HANDLER_COUNT.lock();
|
||||||
if *count_guard == 0 {
|
if *count_guard == 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
errhandlingapi::AddVectoredExceptionHandler(0, Some(output_debug_string_handler))
|
errhandlingapi::AddVectoredExceptionHandler(0, Some(output_debug_string_handler))
|
||||||
@ -25,7 +25,7 @@ pub fn register_exception_handler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn unregister_exception_handler() {
|
pub fn unregister_exception_handler() {
|
||||||
let mut count_guard = EXCEPTION_HANLDER_COUNT.lock();
|
let mut count_guard = EXCEPTION_HANDLER_COUNT.lock();
|
||||||
if *count_guard == 1 {
|
if *count_guard == 1 {
|
||||||
unsafe {
|
unsafe {
|
||||||
errhandlingapi::RemoveVectoredExceptionHandler(output_debug_string_handler as *mut _)
|
errhandlingapi::RemoveVectoredExceptionHandler(output_debug_string_handler as *mut _)
|
||||||
|
@ -57,7 +57,7 @@ pub fn enumerate_adapters(factory: d3d12::DxgiFactory) -> Vec<d3d12::DxgiAdapter
|
|||||||
for cur_index in 0.. {
|
for cur_index in 0.. {
|
||||||
if let Some(factory6) = factory.as_factory6() {
|
if let Some(factory6) = factory.as_factory6() {
|
||||||
profiling::scope!("IDXGIFactory6::EnumAdapterByGpuPreference");
|
profiling::scope!("IDXGIFactory6::EnumAdapterByGpuPreference");
|
||||||
// We're already at dxgi1.6, we can grab IDXGIAdapater4 directly
|
// We're already at dxgi1.6, we can grab IDXGIAdapter4 directly
|
||||||
let mut adapter4 = d3d12::ComPtr::<dxgi1_6::IDXGIAdapter4>::null();
|
let mut adapter4 = d3d12::ComPtr::<dxgi1_6::IDXGIAdapter4>::null();
|
||||||
let hr = unsafe {
|
let hr = unsafe {
|
||||||
factory6.EnumAdapterByGpuPreference(
|
factory6.EnumAdapterByGpuPreference(
|
||||||
@ -100,7 +100,7 @@ pub fn enumerate_adapters(factory: d3d12::DxgiFactory) -> Vec<d3d12::DxgiAdapter
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the most aggressive casts first, skipping Adpater4 as we definitely don't have dxgi1_6.
|
// Do the most aggressive casts first, skipping Adapter4 as we definitely don't have dxgi1_6.
|
||||||
|
|
||||||
// Adapter1 -> Adapter3
|
// Adapter1 -> Adapter3
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -189,7 +189,7 @@ pub(super) struct CpuPool {
|
|||||||
device: d3d12::Device,
|
device: d3d12::Device,
|
||||||
ty: d3d12::DescriptorHeapType,
|
ty: d3d12::DescriptorHeapType,
|
||||||
heaps: Vec<FixedSizeHeap>,
|
heaps: Vec<FixedSizeHeap>,
|
||||||
avaliable_heap_indices: BitSet,
|
available_heap_indices: BitSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CpuPool {
|
impl CpuPool {
|
||||||
@ -198,13 +198,13 @@ impl CpuPool {
|
|||||||
device,
|
device,
|
||||||
ty,
|
ty,
|
||||||
heaps: Vec::new(),
|
heaps: Vec::new(),
|
||||||
avaliable_heap_indices: BitSet::new(),
|
available_heap_indices: BitSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn alloc_handle(&mut self) -> Result<Handle, crate::DeviceError> {
|
pub(super) fn alloc_handle(&mut self) -> Result<Handle, crate::DeviceError> {
|
||||||
let heap_index = self
|
let heap_index = self
|
||||||
.avaliable_heap_indices
|
.available_heap_indices
|
||||||
.iter()
|
.iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or(self.heaps.len());
|
.unwrap_or(self.heaps.len());
|
||||||
@ -212,7 +212,7 @@ impl CpuPool {
|
|||||||
// Allocate a new heap
|
// Allocate a new heap
|
||||||
if heap_index == self.heaps.len() {
|
if heap_index == self.heaps.len() {
|
||||||
self.heaps.push(FixedSizeHeap::new(&self.device, self.ty)?);
|
self.heaps.push(FixedSizeHeap::new(&self.device, self.ty)?);
|
||||||
self.avaliable_heap_indices.insert(heap_index);
|
self.available_heap_indices.insert(heap_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
let heap = &mut self.heaps[heap_index];
|
let heap = &mut self.heaps[heap_index];
|
||||||
@ -221,7 +221,7 @@ impl CpuPool {
|
|||||||
heap_index,
|
heap_index,
|
||||||
};
|
};
|
||||||
if heap.is_full() {
|
if heap.is_full() {
|
||||||
self.avaliable_heap_indices.remove(heap_index);
|
self.available_heap_indices.remove(heap_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(handle)
|
Ok(handle)
|
||||||
@ -229,7 +229,7 @@ impl CpuPool {
|
|||||||
|
|
||||||
pub(super) fn free_handle(&mut self, handle: Handle) {
|
pub(super) fn free_handle(&mut self, handle: Handle) {
|
||||||
self.heaps[handle.heap_index].free_handle(handle.raw);
|
self.heaps[handle.heap_index].free_handle(handle.raw);
|
||||||
self.avaliable_heap_indices.insert(handle.heap_index);
|
self.available_heap_indices.insert(handle.heap_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,7 +748,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
// (bind group [2]) - Space=0
|
// (bind group [2]) - Space=0
|
||||||
// Special constant buffer: Space=0
|
// Special constant buffer: Space=0
|
||||||
|
|
||||||
//TODO: put lower bind group indices futher down the root signature. See:
|
//TODO: put lower bind group indices further down the root signature. See:
|
||||||
// https://microsoft.github.io/DirectX-Specs/d3d/ResourceBinding.html#binding-model
|
// https://microsoft.github.io/DirectX-Specs/d3d/ResourceBinding.html#binding-model
|
||||||
// Currently impossible because wgpu-core only re-binds the descriptor sets based
|
// Currently impossible because wgpu-core only re-binds the descriptor sets based
|
||||||
// on Vulkan-like layout compatibility rules.
|
// on Vulkan-like layout compatibility rules.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*!
|
/*!
|
||||||
# DirectX12 API internals.
|
# DirectX12 API internals.
|
||||||
|
|
||||||
Generally the mapping is straightforwad.
|
Generally the mapping is straightforward.
|
||||||
|
|
||||||
## Resource transitions
|
## Resource transitions
|
||||||
|
|
||||||
|
@ -776,7 +776,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
) {
|
) {
|
||||||
// There is nothing preventing the user from trying to update a single value within
|
// There is nothing preventing the user from trying to update a single value within
|
||||||
// a vector or matrix in the set_push_constant call, as to the user, all of this is
|
// a vector or matrix in the set_push_constant call, as to the user, all of this is
|
||||||
// just memory. However OpenGL does not allow parital uniform updates.
|
// just memory. However OpenGL does not allow partial uniform updates.
|
||||||
//
|
//
|
||||||
// As such, we locally keep a copy of the current state of the push constant memory
|
// As such, we locally keep a copy of the current state of the push constant memory
|
||||||
// block. If the user tries to update a single value, we have the data to update the entirety
|
// block. If the user tries to update a single value, we have the data to update the entirety
|
||||||
|
@ -215,7 +215,7 @@ bitflags::bitflags! {
|
|||||||
// (https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4972/diffs?diff_id=75888#22f5d1004713c9bbf857988c7efb81631ab88f99_323_327)
|
// (https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4972/diffs?diff_id=75888#22f5d1004713c9bbf857988c7efb81631ab88f99_323_327)
|
||||||
// seems to indicate all skylake models are effected.
|
// seems to indicate all skylake models are effected.
|
||||||
const MESA_I915_SRGB_SHADER_CLEAR = 1 << 0;
|
const MESA_I915_SRGB_SHADER_CLEAR = 1 << 0;
|
||||||
/// Buffer map must emulated becuase it is not supported natively
|
/// Buffer map must emulated because it is not supported natively
|
||||||
const EMULATE_BUFFER_MAP = 1 << 1;
|
const EMULATE_BUFFER_MAP = 1 << 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ fn load_gl_func(name: &str, module: Option<HMODULE>) -> *const c_void {
|
|||||||
ptr.cast()
|
ptr.cast()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extensions(extra: &Wgl, dc: HDC) -> HashSet<String> {
|
fn get_extensions(extra: &Wgl, dc: HDC) -> HashSet<String> {
|
||||||
if extra.GetExtensionsStringARB.is_loaded() {
|
if extra.GetExtensionsStringARB.is_loaded() {
|
||||||
unsafe { CStr::from_ptr(extra.GetExtensionsStringARB(dc as *const _)) }
|
unsafe { CStr::from_ptr(extra.GetExtensionsStringARB(dc as *const _)) }
|
||||||
.to_str()
|
.to_str()
|
||||||
@ -449,9 +449,9 @@ impl crate::Instance<super::Api> for Instance {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let extra = Wgl::load_with(|name| load_gl_func(name, None));
|
let extra = Wgl::load_with(|name| load_gl_func(name, None));
|
||||||
let extentions = extensions(&extra, dc);
|
let extensions = get_extensions(&extra, dc);
|
||||||
|
|
||||||
let can_use_profile = extentions.contains("WGL_ARB_create_context_profile")
|
let can_use_profile = extensions.contains("WGL_ARB_create_context_profile")
|
||||||
&& extra.CreateContextAttribsARB.is_loaded();
|
&& extra.CreateContextAttribsARB.is_loaded();
|
||||||
|
|
||||||
let context = if can_use_profile {
|
let context = if can_use_profile {
|
||||||
@ -494,10 +494,10 @@ impl crate::Instance<super::Api> for Instance {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let extra = Wgl::load_with(|name| load_gl_func(name, None));
|
let extra = Wgl::load_with(|name| load_gl_func(name, None));
|
||||||
let extentions = extensions(&extra, dc);
|
let extensions = get_extensions(&extra, dc);
|
||||||
|
|
||||||
let srgb_capable = extentions.contains("WGL_EXT_framebuffer_sRGB")
|
let srgb_capable = extensions.contains("WGL_EXT_framebuffer_sRGB")
|
||||||
|| extentions.contains("WGL_ARB_framebuffer_sRGB")
|
|| extensions.contains("WGL_ARB_framebuffer_sRGB")
|
||||||
|| gl
|
|| gl
|
||||||
.supported_extensions()
|
.supported_extensions()
|
||||||
.contains("GL_ARB_framebuffer_sRGB");
|
.contains("GL_ARB_framebuffer_sRGB");
|
||||||
@ -742,8 +742,8 @@ impl crate::Surface<super::Api> for Surface {
|
|||||||
|
|
||||||
// Setup presentation mode
|
// Setup presentation mode
|
||||||
let extra = Wgl::load_with(|name| load_gl_func(name, None));
|
let extra = Wgl::load_with(|name| load_gl_func(name, None));
|
||||||
let extentions = extensions(&extra, dc.device);
|
let extensions = get_extensions(&extra, dc.device);
|
||||||
if !(extentions.contains("WGL_EXT_swap_control") && extra.SwapIntervalEXT.is_loaded()) {
|
if !(extensions.contains("WGL_EXT_swap_control") && extra.SwapIntervalEXT.is_loaded()) {
|
||||||
log::error!("WGL_EXT_swap_control is unsupported");
|
log::error!("WGL_EXT_swap_control is unsupported");
|
||||||
return Err(crate::SurfaceError::Other(
|
return Err(crate::SurfaceError::Other(
|
||||||
"WGL_EXT_swap_control is unsupported",
|
"WGL_EXT_swap_control is unsupported",
|
||||||
|
@ -412,7 +412,7 @@ pub trait Queue<A: Api>: WasmNotSendSync {
|
|||||||
/// Valid usage:
|
/// Valid usage:
|
||||||
/// - all of the command buffers were created from command pools
|
/// - all of the command buffers were created from command pools
|
||||||
/// that are associated with this queue.
|
/// that are associated with this queue.
|
||||||
/// - all of the command buffers had `CommadBuffer::finish()` called.
|
/// - all of the command buffers had `CommandBuffer::finish()` called.
|
||||||
/// - all surface textures that the command buffers write to must be
|
/// - all surface textures that the command buffers write to must be
|
||||||
/// passed to the surface_textures argument.
|
/// passed to the surface_textures argument.
|
||||||
unsafe fn submit(
|
unsafe fn submit(
|
||||||
@ -512,7 +512,7 @@ pub trait CommandEncoder<A: Api>: WasmNotSendSync + fmt::Debug {
|
|||||||
// pass common
|
// pass common
|
||||||
|
|
||||||
/// Sets the bind group at `index` to `group`, assuming the layout
|
/// Sets the bind group at `index` to `group`, assuming the layout
|
||||||
/// of all the preceeding groups to be taken from `layout`.
|
/// of all the preceding groups to be taken from `layout`.
|
||||||
unsafe fn set_bind_group(
|
unsafe fn set_bind_group(
|
||||||
&mut self,
|
&mut self,
|
||||||
layout: &A::PipelineLayout,
|
layout: &A::PipelineLayout,
|
||||||
@ -1465,7 +1465,7 @@ impl ValidationCanary {
|
|||||||
self.inner.lock().push(msg);
|
self.inner.lock().push(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns any API validation errors that hav occurred in this process
|
/// Returns any API validation errors that have occurred in this process
|
||||||
/// since the last call to this function.
|
/// since the last call to this function.
|
||||||
pub fn get_and_reset(&self) -> Vec<String> {
|
pub fn get_and_reset(&self) -> Vec<String> {
|
||||||
self.inner.lock().drain(..).collect()
|
self.inner.lock().drain(..).collect()
|
||||||
|
@ -538,7 +538,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
.geometry(vk::AccelerationStructureGeometryDataKHR {
|
.geometry(vk::AccelerationStructureGeometryDataKHR {
|
||||||
triangles: *triangle_data,
|
triangles: *triangle_data,
|
||||||
})
|
})
|
||||||
.flags(conv::map_acceleration_structure_geomety_flags(
|
.flags(conv::map_acceleration_structure_geometry_flags(
|
||||||
triangles.flags,
|
triangles.flags,
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -570,7 +570,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
.geometry(vk::AccelerationStructureGeometryDataKHR {
|
.geometry(vk::AccelerationStructureGeometryDataKHR {
|
||||||
aabbs: *aabbs_data,
|
aabbs: *aabbs_data,
|
||||||
})
|
})
|
||||||
.flags(conv::map_acceleration_structure_geomety_flags(aabb.flags));
|
.flags(conv::map_acceleration_structure_geometry_flags(aabb.flags));
|
||||||
|
|
||||||
geometries.push(*geometry);
|
geometries.push(*geometry);
|
||||||
ranges.push(*range);
|
ranges.push(*range);
|
||||||
|
@ -924,7 +924,7 @@ pub fn map_acceleration_structure_flags(
|
|||||||
vk_flags
|
vk_flags
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_acceleration_structure_geomety_flags(
|
pub fn map_acceleration_structure_geometry_flags(
|
||||||
flags: crate::AccelerationStructureGeometryFlags,
|
flags: crate::AccelerationStructureGeometryFlags,
|
||||||
) -> vk::GeometryFlagsKHR {
|
) -> vk::GeometryFlagsKHR {
|
||||||
let mut vk_flags = vk::GeometryFlagsKHR::empty();
|
let mut vk_flags = vk::GeometryFlagsKHR::empty();
|
||||||
|
@ -2149,7 +2149,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
.geometry(vk::AccelerationStructureGeometryDataKHR {
|
.geometry(vk::AccelerationStructureGeometryDataKHR {
|
||||||
triangles: *triangle_data,
|
triangles: *triangle_data,
|
||||||
})
|
})
|
||||||
.flags(conv::map_acceleration_structure_geomety_flags(
|
.flags(conv::map_acceleration_structure_geometry_flags(
|
||||||
triangles.flags,
|
triangles.flags,
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -2171,7 +2171,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
let geometry = vk::AccelerationStructureGeometryKHR::builder()
|
let geometry = vk::AccelerationStructureGeometryKHR::builder()
|
||||||
.geometry_type(vk::GeometryTypeKHR::AABBS)
|
.geometry_type(vk::GeometryTypeKHR::AABBS)
|
||||||
.geometry(vk::AccelerationStructureGeometryDataKHR { aabbs: *aabbs_data })
|
.geometry(vk::AccelerationStructureGeometryDataKHR { aabbs: *aabbs_data })
|
||||||
.flags(conv::map_acceleration_structure_geomety_flags(aabb.flags));
|
.flags(conv::map_acceleration_structure_geometry_flags(aabb.flags));
|
||||||
|
|
||||||
geometries.push(*geometry);
|
geometries.push(*geometry);
|
||||||
primitive_counts.push(aabb.count);
|
primitive_counts.push(aabb.count);
|
||||||
|
@ -53,7 +53,7 @@ unsafe extern "system" fn debug_utils_messenger_callback(
|
|||||||
// Silence Vulkan Validation error "VUID-VkRenderPassBeginInfo-framebuffer-04627"
|
// Silence Vulkan Validation error "VUID-VkRenderPassBeginInfo-framebuffer-04627"
|
||||||
// if the OBS layer is enabled. This is a bug in the OBS layer. As the OBS layer
|
// if the OBS layer is enabled. This is a bug in the OBS layer. As the OBS layer
|
||||||
// does not have a version number they increment, there is no way to qualify the
|
// does not have a version number they increment, there is no way to qualify the
|
||||||
// supression of the error to a specific version of the OBS layer.
|
// suppression of the error to a specific version of the OBS layer.
|
||||||
//
|
//
|
||||||
// See https://github.com/obsproject/obs-studio/issues/9353
|
// See https://github.com/obsproject/obs-studio/issues/9353
|
||||||
const VUID_VKRENDERPASSBEGININFO_FRAMEBUFFER_04627: i32 = 0x45125641;
|
const VUID_VKRENDERPASSBEGININFO_FRAMEBUFFER_04627: i32 = 0x45125641;
|
||||||
@ -279,7 +279,7 @@ impl super::Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VK_EXT_swapchain_colorspace
|
// VK_EXT_swapchain_colorspace
|
||||||
// Provid wide color gamut
|
// Provides wide color gamut
|
||||||
extensions.push(vk::ExtSwapchainColorspaceFn::name());
|
extensions.push(vk::ExtSwapchainColorspaceFn::name());
|
||||||
|
|
||||||
// VK_KHR_get_physical_device_properties2
|
// VK_KHR_get_physical_device_properties2
|
||||||
@ -968,7 +968,7 @@ impl crate::Surface<super::Api> for super::Surface {
|
|||||||
sc.next_surface_index += 1;
|
sc.next_surface_index += 1;
|
||||||
sc.next_surface_index %= sc.surface_semaphores.len();
|
sc.next_surface_index %= sc.surface_semaphores.len();
|
||||||
|
|
||||||
// special case for Intel Vulkan returning bizzare values (ugh)
|
// special case for Intel Vulkan returning bizarre values (ugh)
|
||||||
if sc.device.vendor_id == crate::auxil::db::intel::VENDOR && index > 0x100 {
|
if sc.device.vendor_id == crate::auxil::db::intel::VENDOR && index > 0x100 {
|
||||||
return Err(crate::SurfaceError::Outdated);
|
return Err(crate::SurfaceError::Outdated);
|
||||||
}
|
}
|
||||||
|
@ -1553,7 +1553,7 @@ bitflags::bitflags! {
|
|||||||
/// If this is false, calls to `CommandEncoder::resolve_query_set` will be performed on the device (i.e. cpu) timeline
|
/// If this is false, calls to `CommandEncoder::resolve_query_set` will be performed on the device (i.e. cpu) timeline
|
||||||
/// and will block that timeline until the query has data. You may work around this limitation by waiting until the submit
|
/// and will block that timeline until the query has data. You may work around this limitation by waiting until the submit
|
||||||
/// whose queries you are resolving is fully finished (through use of `queue.on_submitted_work_done`) and only
|
/// whose queries you are resolving is fully finished (through use of `queue.on_submitted_work_done`) and only
|
||||||
/// then submitting the resolve_query_set command. The queries will be guarenteed finished, so will not block.
|
/// then submitting the resolve_query_set command. The queries will be guaranteed finished, so will not block.
|
||||||
///
|
///
|
||||||
/// Supported by:
|
/// Supported by:
|
||||||
/// - Vulkan,
|
/// - Vulkan,
|
||||||
@ -6403,7 +6403,7 @@ impl<T> ImageCopyTexture<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// View of an external texture that cna be used to copy to a texture.
|
/// View of an external texture that can be used to copy to a texture.
|
||||||
///
|
///
|
||||||
/// Corresponds to [WebGPU `GPUImageCopyExternalImage`](
|
/// Corresponds to [WebGPU `GPUImageCopyExternalImage`](
|
||||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopyexternalimage).
|
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopyexternalimage).
|
||||||
@ -6441,7 +6441,7 @@ pub enum ExternalImageSource {
|
|||||||
HTMLCanvasElement(web_sys::HtmlCanvasElement),
|
HTMLCanvasElement(web_sys::HtmlCanvasElement),
|
||||||
/// Copy from a off-screen canvas.
|
/// Copy from a off-screen canvas.
|
||||||
///
|
///
|
||||||
/// Requies [`DownlevelFlags::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES`]
|
/// Requires [`DownlevelFlags::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES`]
|
||||||
OffscreenCanvas(web_sys::OffscreenCanvas),
|
OffscreenCanvas(web_sys::OffscreenCanvas),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,10 +254,10 @@ fn map_texture_format(texture_format: wgt::TextureFormat) -> web_sys::GpuTexture
|
|||||||
wgt::AstcBlock::B12x12 => tf::Astc12x12UnormSrgb,
|
wgt::AstcBlock::B12x12 => tf::Astc12x12UnormSrgb,
|
||||||
},
|
},
|
||||||
wgt::AstcChannel::Hdr => {
|
wgt::AstcChannel::Hdr => {
|
||||||
unimplemented!("Format {texture_format:?} has no WebGPU equivilant")
|
unimplemented!("Format {texture_format:?} has no WebGPU equivalent")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => unimplemented!("Format {texture_format:?} has no WebGPU equivilant"),
|
_ => unimplemented!("Format {texture_format:?} has no WebGPU equivalent"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2152,7 +2152,7 @@ impl crate::context::Context for ContextWebGpu {
|
|||||||
_pipeline_layout: &Self::PipelineLayoutId,
|
_pipeline_layout: &Self::PipelineLayoutId,
|
||||||
_pipeline_layout_data: &Self::PipelineLayoutData,
|
_pipeline_layout_data: &Self::PipelineLayoutData,
|
||||||
) {
|
) {
|
||||||
// Dropped automaticaly
|
// Dropped automatically
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shader_module_drop(
|
fn shader_module_drop(
|
||||||
|
@ -4936,7 +4936,7 @@ impl Surface<'_> {
|
|||||||
pub struct Id<T>(NonZeroU64, PhantomData<*mut T>);
|
pub struct Id<T>(NonZeroU64, PhantomData<*mut T>);
|
||||||
|
|
||||||
impl<T> Id<T> {
|
impl<T> Id<T> {
|
||||||
/// For testing use only. We provide no guarentees about the actual value of the ids.
|
/// For testing use only. We provide no guarantees about the actual value of the ids.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn inner(&self) -> u64 {
|
pub fn inner(&self) -> u64 {
|
||||||
self.0.get()
|
self.0.get()
|
||||||
|
Loading…
Reference in New Issue
Block a user