From a25d2ea415c155a9b916e96c7a8f0dc1123e8a58 Mon Sep 17 00:00:00 2001 From: Teodor Tanasoaia Date: Fri, 7 Jul 2023 14:38:12 +0000 Subject: [PATCH] Bug 1838493 - Update `wgpu` to revision dcad7dfba92dd85c3ca21bb553a61834e01b04f5. r=webgpu-reviewers,gfx-reviewers,supply-chain-reviewers,glandium,ErichDonGubler Bug 1838493 - Update `foreign-types`, `core-graphics` and `core-text`. r=#gfx-reviewers Bug 1838493 - Vet `wgpu` and `naga` commits. r=#supply-chain-reviewers Bug 1838493 - Vendor `wgpu` changes. r=#webgpu-reviewers Differential Revision: https://phabricator.services.mozilla.com/D182578 --- .cargo/config.in | 8 +- Cargo.lock | 67 +- build/rust/bitflags/Cargo.toml | 3 + gfx/webrender_bindings/Cargo.toml | 4 +- gfx/wgpu_bindings/Cargo.toml | 12 +- gfx/wgpu_bindings/moz.yaml | 4 +- gfx/wgpu_bindings/src/client.rs | 2 +- gfx/wgpu_bindings/src/identity.rs | 38 +- gfx/wgpu_bindings/src/server.rs | 12 +- gfx/wr/Cargo.lock | 77 +- gfx/wr/servo-tidy.toml | 6 + gfx/wr/wr_glyph_rasterizer/Cargo.toml | 4 +- gfx/wr/wrench/Cargo.toml | 2 +- supply-chain/audits.toml | 75 + third_party/rust/ash/.cargo-checksum.json | 2 +- third_party/rust/ash/Cargo.toml | 11 +- third_party/rust/ash/README.md | 1 + third_party/rust/ash/build.rs | 4 +- third_party/rust/ash/src/device.rs | 56 +- third_party/rust/ash/src/entry.rs | 33 +- .../extensions/ext/full_screen_exclusive.rs | 27 +- .../rust/ash/src/extensions/ext/mod.rs | 4 + .../src/extensions/ext/pipeline_properties.rs | 52 + .../ash/src/extensions/ext/shader_object.rs | 719 ++ .../ash/src/extensions/khr/device_group.rs | 26 +- .../extensions/khr/device_group_creation.rs | 6 + .../src/extensions/khr/external_memory_fd.rs | 4 +- .../ash/src/extensions/khr/maintenance4.rs | 16 +- .../rust/ash/src/extensions/khr/mod.rs | 2 + .../src/extensions/khr/performance_query.rs | 121 + .../rust/ash/src/extensions/khr/swapchain.rs | 27 +- third_party/rust/ash/src/instance.rs | 16 +- third_party/rust/ash/src/prelude.rs | 32 +- third_party/rust/ash/src/util.rs | 3 +- third_party/rust/ash/src/vk/aliases.rs | 2 + third_party/rust/ash/src/vk/bitflags.rs | 66 +- third_party/rust/ash/src/vk/const_debugs.rs | 300 +- third_party/rust/ash/src/vk/constants.rs | 1 + third_party/rust/ash/src/vk/definitions.rs | 2684 ++++++-- third_party/rust/ash/src/vk/enums.rs | 48 + third_party/rust/ash/src/vk/extensions.rs | 2467 ++++++- third_party/rust/ash/src/vk/features.rs | 4 +- third_party/rust/ash/src/vk/native.rs | 379 +- .../core-graphics-types/.cargo-checksum.json | 2 +- .../rust/core-graphics-types/Cargo.toml | 18 +- .../rust/core-graphics-types/src/base.rs | 13 +- .../rust/core-graphics-types/src/geometry.rs | 7 + .../rust/core-graphics/.cargo-checksum.json | 2 +- third_party/rust/core-graphics/Cargo.toml | 20 +- third_party/rust/core-graphics/src/access.rs | 26 + .../rust/core-graphics/src/color_space.rs | 68 +- third_party/rust/core-graphics/src/context.rs | 25 +- .../rust/core-graphics/src/data_provider.rs | 10 +- third_party/rust/core-graphics/src/display.rs | 80 +- third_party/rust/core-graphics/src/event.rs | 22 +- .../rust/core-graphics/src/event_source.rs | 10 +- third_party/rust/core-graphics/src/font.rs | 35 +- .../rust/core-graphics/src/gradient.rs | 10 +- third_party/rust/core-graphics/src/image.rs | 10 +- third_party/rust/core-graphics/src/lib.rs | 2 + third_party/rust/core-graphics/src/path.rs | 12 +- .../rust/core-text/.cargo-checksum.json | 2 +- third_party/rust/core-text/Cargo.toml | 20 +- third_party/rust/core-text/src/font.rs | 353 +- .../foreign-types-macros/.cargo-checksum.json | 1 + .../rust/foreign-types-macros/Cargo.toml | 35 + .../rust/foreign-types-macros/LICENSE-APACHE | 202 + .../rust/foreign-types-macros/LICENSE-MIT | 19 + .../rust/foreign-types-macros/src/build.rs | 261 + .../rust/foreign-types-macros/src/lib.rs | 15 + .../rust/foreign-types-macros/src/parse.rs | 140 + .../foreign-types-shared/.cargo-checksum.json | 2 +- .../rust/foreign-types-shared/Cargo.toml | 12 +- .../rust/foreign-types-shared/src/lib.rs | 49 +- .../rust/foreign-types/.cargo-checksum.json | 2 +- third_party/rust/foreign-types/Cargo.toml | 14 +- third_party/rust/foreign-types/src/lib.rs | 240 +- third_party/rust/foreign-types/tests/test.rs | 22 + .../rust/gpu-alloc-types/.cargo-checksum.json | 2 +- third_party/rust/gpu-alloc-types/Cargo.toml | 30 +- third_party/rust/gpu-alloc-types/README.md | 51 + .../rust/gpu-alloc-types/src/device.rs | 3 +- third_party/rust/gpu-alloc-types/src/types.rs | 3 +- .../rust/gpu-alloc/.cargo-checksum.json | 2 +- third_party/rust/gpu-alloc/Cargo.toml | 27 +- third_party/rust/gpu-alloc/README.md | 51 + third_party/rust/gpu-alloc/src/allocator.rs | 1121 ++-- third_party/rust/gpu-alloc/src/block.rs | 654 +- third_party/rust/gpu-alloc/src/buddy.rs | 918 +-- third_party/rust/gpu-alloc/src/config.rs | 154 +- third_party/rust/gpu-alloc/src/error.rs | 232 +- third_party/rust/gpu-alloc/src/freelist.rs | 1056 +-- third_party/rust/gpu-alloc/src/heap.rs | 64 +- third_party/rust/gpu-alloc/src/lib.rs | 248 +- third_party/rust/gpu-alloc/src/slab.rs | 194 +- third_party/rust/gpu-alloc/src/usage.rs | 343 +- third_party/rust/gpu-alloc/src/util.rs | 88 +- third_party/rust/metal/.cargo-checksum.json | 2 +- third_party/rust/metal/Cargo.lock | 1121 ++-- third_party/rust/metal/Cargo.toml | 22 +- third_party/rust/metal/Makefile | 4 + third_party/rust/metal/README.md | 13 +- third_party/rust/metal/assets/metal.svg | 15 + .../rust/metal/examples/circle/main.rs | 134 +- .../rust/metal/examples/compute/main.rs | 201 +- .../metal/examples/headless-render/main.rs | 2 +- .../rust/metal/examples/mesh-shader/main.rs | 118 + .../metal/examples/mesh-shader/shaders.metal | 30 + .../examples/mesh-shader/shaders.metallib | Bin 0 -> 6314 bytes third_party/rust/metal/examples/mps/main.rs | 21 +- .../rust/metal/examples/raytracing/README.md | 11 + .../rust/metal/examples/raytracing/camera.rs | 20 + .../metal/examples/raytracing/geometry.rs | 448 ++ .../rust/metal/examples/raytracing/main.rs | 87 + .../metal/examples/raytracing/renderer.rs | 512 ++ .../rust/metal/examples/raytracing/scene.rs | 135 + .../metal/examples/raytracing/screenshot.png | Bin 0 -> 2245032 bytes .../metal/examples/raytracing/shaders.metal | 598 ++ .../examples/raytracing/shaders.metallib | Bin 0 -> 211489 bytes .../rust/metal/examples/reflection/main.rs | 46 +- .../rust/metal/examples/shader-dylib/main.rs | 4 +- .../rust/metal/src/accelerator_structure.rs | 348 + third_party/rust/metal/src/argument.rs | 20 +- third_party/rust/metal/src/buffer.rs | 8 +- .../rust/metal/src/capturedescriptor.rs | 29 +- third_party/rust/metal/src/capturemanager.rs | 18 +- third_party/rust/metal/src/commandbuffer.rs | 22 +- third_party/rust/metal/src/commandqueue.rs | 2 +- third_party/rust/metal/src/computepass.rs | 103 + third_party/rust/metal/src/constants.rs | 1 + third_party/rust/metal/src/counters.rs | 102 + third_party/rust/metal/src/depthstencil.rs | 8 +- third_party/rust/metal/src/device.rs | 115 +- third_party/rust/metal/src/drawable.rs | 2 +- third_party/rust/metal/src/encoder.rs | 515 +- third_party/rust/metal/src/heap.rs | 6 +- .../rust/metal/src/indirect_encoder.rs | 11 +- third_party/rust/metal/src/lib.rs | 165 +- third_party/rust/metal/src/library.rs | 49 +- third_party/rust/metal/src/mps.rs | 44 +- .../rust/metal/src/pipeline/compute.rs | 27 +- third_party/rust/metal/src/pipeline/mod.rs | 5 +- third_party/rust/metal/src/pipeline/render.rs | 280 +- third_party/rust/metal/src/renderpass.rs | 131 +- third_party/rust/metal/src/resource.rs | 14 +- third_party/rust/metal/src/sampler.rs | 8 +- third_party/rust/metal/src/sync.rs | 11 +- third_party/rust/metal/src/texture.rs | 14 +- third_party/rust/metal/src/types.rs | 10 + .../rust/metal/src/vertexdescriptor.rs | 12 +- third_party/rust/naga/.cargo-checksum.json | 2 +- third_party/rust/naga/.cargo/config.toml | 2 + .../.github/workflows/validation-linux.yml | 14 +- .../.github/workflows/validation-macos.yml | 8 +- .../.github/workflows/validation-windows.yml | 18 +- third_party/rust/naga/CHANGELOG.md | 71 + third_party/rust/naga/Cargo.toml | 8 +- third_party/rust/naga/Makefile | 131 - third_party/rust/naga/src/back/dot/mod.rs | 10 +- .../rust/naga/src/back/glsl/features.rs | 1 + third_party/rust/naga/src/back/glsl/mod.rs | 72 +- third_party/rust/naga/src/back/hlsl/conv.rs | 24 +- third_party/rust/naga/src/back/hlsl/help.rs | 13 +- .../rust/naga/src/back/hlsl/keywords.rs | 745 ++- .../rust/naga/src/back/hlsl/storage.rs | 18 +- third_party/rust/naga/src/back/hlsl/writer.rs | 99 +- third_party/rust/naga/src/back/mod.rs | 2 +- third_party/rust/naga/src/back/msl/writer.rs | 151 +- third_party/rust/naga/src/back/spv/block.rs | 212 +- third_party/rust/naga/src/back/spv/helpers.rs | 3 +- third_party/rust/naga/src/back/spv/image.rs | 4 +- .../rust/naga/src/back/spv/instructions.rs | 8 + third_party/rust/naga/src/back/spv/mod.rs | 22 +- third_party/rust/naga/src/back/spv/ray.rs | 9 +- third_party/rust/naga/src/back/spv/writer.rs | 125 +- third_party/rust/naga/src/back/wgsl/writer.rs | 79 +- third_party/rust/naga/src/front/glsl/ast.rs | 5 +- .../rust/naga/src/front/glsl/constants.rs | 106 +- .../rust/naga/src/front/glsl/context.rs | 45 +- .../rust/naga/src/front/glsl/functions.rs | 17 +- .../rust/naga/src/front/glsl/offset.rs | 11 +- .../src/front/glsl/parser/declarations.rs | 1 - .../naga/src/front/glsl/parser/expressions.rs | 73 +- .../rust/naga/src/front/glsl/parser/types.rs | 24 +- third_party/rust/naga/src/front/spv/error.rs | 2 + .../rust/naga/src/front/spv/function.rs | 15 +- third_party/rust/naga/src/front/spv/image.rs | 1 + third_party/rust/naga/src/front/spv/mod.rs | 376 +- third_party/rust/naga/src/front/spv/null.rs | 7 +- third_party/rust/naga/src/front/wgsl/error.rs | 19 + .../naga/src/front/wgsl/lower/construction.rs | 37 +- .../rust/naga/src/front/wgsl/lower/mod.rs | 246 +- third_party/rust/naga/src/front/wgsl/mod.rs | 83 +- .../rust/naga/src/front/wgsl/parse/mod.rs | 52 +- third_party/rust/naga/src/lib.rs | 98 +- third_party/rust/naga/src/proc/index.rs | 21 +- third_party/rust/naga/src/proc/layouter.rs | 12 +- third_party/rust/naga/src/proc/mod.rs | 124 +- third_party/rust/naga/src/proc/namer.rs | 66 +- third_party/rust/naga/src/proc/terminator.rs | 1 + third_party/rust/naga/src/proc/typifier.rs | 5 + third_party/rust/naga/src/valid/analyzer.rs | 55 +- third_party/rust/naga/src/valid/compose.rs | 33 +- third_party/rust/naga/src/valid/expression.rs | 26 +- third_party/rust/naga/src/valid/function.rs | 57 +- third_party/rust/naga/src/valid/handles.rs | 52 +- third_party/rust/naga/src/valid/interface.rs | 57 +- third_party/rust/naga/src/valid/mod.rs | 47 +- third_party/rust/naga/src/valid/type.rs | 108 +- .../rust/wgpu-core/.cargo-checksum.json | 2 +- third_party/rust/wgpu-core/Cargo.toml | 2 +- .../rust/wgpu-core/src/binding_model.rs | 3 +- .../rust/wgpu-core/src/command/bind.rs | 3 +- .../rust/wgpu-core/src/command/bundle.rs | 11 +- .../rust/wgpu-core/src/command/clear.rs | 8 +- .../rust/wgpu-core/src/command/compute.rs | 50 +- .../rust/wgpu-core/src/command/memory_init.rs | 3 +- third_party/rust/wgpu-core/src/command/mod.rs | 17 +- .../rust/wgpu-core/src/command/query.rs | 6 +- .../rust/wgpu-core/src/command/render.rs | 22 +- .../rust/wgpu-core/src/command/transfer.rs | 6 +- .../rust/wgpu-core/src/device/global.rs | 2672 ++++++++ third_party/rust/wgpu-core/src/device/life.rs | 7 +- third_party/rust/wgpu-core/src/device/mod.rs | 5772 +---------------- .../rust/wgpu-core/src/device/queue.rs | 7 +- .../rust/wgpu-core/src/device/resource.rs | 3137 +++++++++ third_party/rust/wgpu-core/src/error.rs | 25 +- third_party/rust/wgpu-core/src/global.rs | 162 + third_party/rust/wgpu-core/src/hal_api.rs | 157 + third_party/rust/wgpu-core/src/hub.rs | 963 +-- third_party/rust/wgpu-core/src/id.rs | 4 +- third_party/rust/wgpu-core/src/identity.rs | 183 + third_party/rust/wgpu-core/src/instance.rs | 21 +- third_party/rust/wgpu-core/src/lib.rs | 22 +- third_party/rust/wgpu-core/src/pipeline.rs | 2 +- third_party/rust/wgpu-core/src/present.rs | 5 +- third_party/rust/wgpu-core/src/registry.rs | 200 + third_party/rust/wgpu-core/src/resource.rs | 16 +- third_party/rust/wgpu-core/src/storage.rs | 234 + .../rust/wgpu-core/src/track/buffer.rs | 29 +- .../rust/wgpu-core/src/track/metadata.rs | 10 +- third_party/rust/wgpu-core/src/track/mod.rs | 63 +- .../rust/wgpu-core/src/track/stateless.rs | 21 +- .../rust/wgpu-core/src/track/texture.rs | 41 +- third_party/rust/wgpu-core/src/validation.rs | 2 +- .../rust/wgpu-hal/.cargo-checksum.json | 2 +- third_party/rust/wgpu-hal/Cargo.toml | 22 +- .../rust/wgpu-hal/examples/halmark/main.rs | 42 +- .../rust/wgpu-hal/examples/raw-gles.rs | 1 + third_party/rust/wgpu-hal/src/dx12/adapter.rs | 47 +- third_party/rust/wgpu-hal/src/gles/adapter.rs | 8 +- third_party/rust/wgpu-hal/src/gles/egl.rs | 20 +- third_party/rust/wgpu-hal/src/gles/queue.rs | 2 +- .../rust/wgpu-hal/src/metal/command.rs | 11 +- third_party/rust/wgpu-hal/src/metal/device.rs | 4 +- third_party/rust/wgpu-hal/src/metal/mod.rs | 7 +- .../rust/wgpu-hal/src/vulkan/command.rs | 6 +- third_party/rust/wgpu-hal/src/vulkan/conv.rs | 14 + .../rust/wgpu-hal/src/vulkan/instance.rs | 168 +- third_party/rust/wgpu-hal/src/vulkan/mod.rs | 21 + .../rust/wgpu-types/.cargo-checksum.json | 2 +- third_party/rust/wgpu-types/Cargo.toml | 2 +- third_party/rust/wgpu-types/src/lib.rs | 147 +- 263 files changed, 25246 insertions(+), 12954 deletions(-) create mode 100644 third_party/rust/ash/src/extensions/ext/pipeline_properties.rs create mode 100644 third_party/rust/ash/src/extensions/ext/shader_object.rs create mode 100644 third_party/rust/ash/src/extensions/khr/performance_query.rs create mode 100644 third_party/rust/core-graphics/src/access.rs create mode 100644 third_party/rust/foreign-types-macros/.cargo-checksum.json create mode 100644 third_party/rust/foreign-types-macros/Cargo.toml create mode 100644 third_party/rust/foreign-types-macros/LICENSE-APACHE create mode 100644 third_party/rust/foreign-types-macros/LICENSE-MIT create mode 100644 third_party/rust/foreign-types-macros/src/build.rs create mode 100644 third_party/rust/foreign-types-macros/src/lib.rs create mode 100644 third_party/rust/foreign-types-macros/src/parse.rs create mode 100644 third_party/rust/foreign-types/tests/test.rs create mode 100644 third_party/rust/gpu-alloc-types/README.md create mode 100644 third_party/rust/gpu-alloc/README.md create mode 100644 third_party/rust/metal/assets/metal.svg create mode 100644 third_party/rust/metal/examples/mesh-shader/main.rs create mode 100644 third_party/rust/metal/examples/mesh-shader/shaders.metal create mode 100644 third_party/rust/metal/examples/mesh-shader/shaders.metallib create mode 100644 third_party/rust/metal/examples/raytracing/README.md create mode 100644 third_party/rust/metal/examples/raytracing/camera.rs create mode 100644 third_party/rust/metal/examples/raytracing/geometry.rs create mode 100644 third_party/rust/metal/examples/raytracing/main.rs create mode 100644 third_party/rust/metal/examples/raytracing/renderer.rs create mode 100644 third_party/rust/metal/examples/raytracing/scene.rs create mode 100644 third_party/rust/metal/examples/raytracing/screenshot.png create mode 100644 third_party/rust/metal/examples/raytracing/shaders.metal create mode 100644 third_party/rust/metal/examples/raytracing/shaders.metallib create mode 100644 third_party/rust/metal/src/accelerator_structure.rs create mode 100644 third_party/rust/metal/src/computepass.rs create mode 100644 third_party/rust/metal/src/counters.rs create mode 100644 third_party/rust/naga/.cargo/config.toml delete mode 100644 third_party/rust/naga/Makefile create mode 100644 third_party/rust/wgpu-core/src/device/global.rs create mode 100644 third_party/rust/wgpu-core/src/device/resource.rs create mode 100644 third_party/rust/wgpu-core/src/global.rs create mode 100644 third_party/rust/wgpu-core/src/hal_api.rs create mode 100644 third_party/rust/wgpu-core/src/identity.rs create mode 100644 third_party/rust/wgpu-core/src/registry.rs create mode 100644 third_party/rust/wgpu-core/src/storage.rs diff --git a/.cargo/config.in b/.cargo/config.in index 1f85a4361f54..c72c7fd558bd 100644 --- a/.cargo/config.in +++ b/.cargo/config.in @@ -30,14 +30,14 @@ git = "https://github.com/gfx-rs/d3d12-rs" rev = "b940b1d71" replace-with = "vendored-sources" -[source."git+https://github.com/gfx-rs/naga?rev=b99d58ea435090e561377949f428bce2c18451bb"] +[source."git+https://github.com/gfx-rs/naga?rev=76003dc0035d53a474d366dcdf49d2e4d12e921f"] git = "https://github.com/gfx-rs/naga" -rev = "b99d58ea435090e561377949f428bce2c18451bb" +rev = "76003dc0035d53a474d366dcdf49d2e4d12e921f" replace-with = "vendored-sources" -[source."git+https://github.com/gfx-rs/wgpu?rev=f71a1bc736fde37509262ca03e91d8f56a13aeb5"] +[source."git+https://github.com/gfx-rs/wgpu?rev=dcad7dfba92dd85c3ca21bb553a61834e01b04f5"] git = "https://github.com/gfx-rs/wgpu" -rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5" +rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5" replace-with = "vendored-sources" [source."git+https://github.com/glandium/warp?rev=4af45fae95bc98b0eba1ef0db17e1dac471bb23d"] diff --git a/Cargo.lock b/Cargo.lock index f5a6cb87bf5e..9732d97842fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "ash" -version = "0.37.2+1.3.238" +version = "0.37.3+1.3.251" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28bf19c1f0a470be5fbf7522a308a05df06610252c5bcf5143e1b23f629a9a03" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" dependencies = [ "libloading", ] @@ -831,9 +831,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "core-graphics" -version = "0.22.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +checksum = "506752f2b58723339d41d013009be97e549860785a366e2a5e75dfbd9725b48e" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -844,21 +844,20 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" dependencies = [ "bitflags 1.3.2", "core-foundation", - "foreign-types", "libc", ] [[package]] name = "core-text" -version = "19.2.0" +version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +checksum = "02083d15989d6247553e1a63753561555a72b2038bba1e4239db70602a798742" dependencies = [ "core-foundation", "core-graphics", @@ -1784,18 +1783,30 @@ dependencies = [ [[package]] name = "foreign-types" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ + "foreign-types-macros", "foreign-types-shared", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "foreign-types-macros" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" @@ -2312,21 +2323,21 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.999.999", "gpu-alloc-types", ] [[package]] name = "gpu-alloc-types" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.999.999", ] [[package]] @@ -3170,9 +3181,9 @@ dependencies = [ [[package]] name = "metal" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" +checksum = "550b24b0cd4cf923f36bae78eca457b3a10d8a6a14a9c84cb2687b527e6a84af" dependencies = [ "bitflags 1.3.2", "block", @@ -3180,6 +3191,7 @@ dependencies = [ "foreign-types", "log", "objc", + "paste", ] [[package]] @@ -3549,10 +3561,10 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664" [[package]] name = "naga" version = "0.12.0" -source = "git+https://github.com/gfx-rs/naga?rev=b99d58ea435090e561377949f428bce2c18451bb#b99d58ea435090e561377949f428bce2c18451bb" +source = "git+https://github.com/gfx-rs/naga?rev=76003dc0035d53a474d366dcdf49d2e4d12e921f#76003dc0035d53a474d366dcdf49d2e4d12e921f" dependencies = [ "bit-set", - "bitflags 1.3.2", + "bitflags 2.999.999", "codespan-reporting", "hexf-parse", "indexmap", @@ -6084,7 +6096,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.16.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=f71a1bc736fde37509262ca03e91d8f56a13aeb5#f71a1bc736fde37509262ca03e91d8f56a13aeb5" +source = "git+https://github.com/gfx-rs/wgpu?rev=dcad7dfba92dd85c3ca21bb553a61834e01b04f5#dcad7dfba92dd85c3ca21bb553a61834e01b04f5" dependencies = [ "arrayvec", "bit-vec", @@ -6107,7 +6119,7 @@ dependencies = [ [[package]] name = "wgpu-hal" version = "0.16.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=f71a1bc736fde37509262ca03e91d8f56a13aeb5#f71a1bc736fde37509262ca03e91d8f56a13aeb5" +source = "git+https://github.com/gfx-rs/wgpu?rev=dcad7dfba92dd85c3ca21bb553a61834e01b04f5#dcad7dfba92dd85c3ca21bb553a61834e01b04f5" dependencies = [ "android_system_properties", "arrayvec", @@ -6117,7 +6129,6 @@ dependencies = [ "block", "core-graphics-types", "d3d12", - "foreign-types", "gpu-alloc", "gpu-descriptor", "js-sys", @@ -6144,7 +6155,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.16.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=f71a1bc736fde37509262ca03e91d8f56a13aeb5#f71a1bc736fde37509262ca03e91d8f56a13aeb5" +source = "git+https://github.com/gfx-rs/wgpu?rev=dcad7dfba92dd85c3ca21bb553a61834e01b04f5#dcad7dfba92dd85c3ca21bb553a61834e01b04f5" dependencies = [ "bitflags 2.999.999", "js-sys", diff --git a/build/rust/bitflags/Cargo.toml b/build/rust/bitflags/Cargo.toml index 74c90b69231f..e3334b29985c 100644 --- a/build/rust/bitflags/Cargo.toml +++ b/build/rust/bitflags/Cargo.toml @@ -7,5 +7,8 @@ license = "MIT/Apache-2.0" [lib] path = "lib.rs" +[features] +serde = [] + [dependencies.bitflags] version = "1.0" diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml index 69a7eef1c058..f6b3fd637fe6 100644 --- a/gfx/webrender_bindings/Cargo.toml +++ b/gfx/webrender_bindings/Cargo.toml @@ -35,6 +35,6 @@ winapi = "0.3" [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.9" -core-graphics = "0.22" -foreign-types = "0.3.0" +core-graphics = "0.23" +foreign-types = "0.5.0" objc = "0.2" diff --git a/gfx/wgpu_bindings/Cargo.toml b/gfx/wgpu_bindings/Cargo.toml index de3cb96af9e3..0bbc968ca6f8 100644 --- a/gfx/wgpu_bindings/Cargo.toml +++ b/gfx/wgpu_bindings/Cargo.toml @@ -17,7 +17,7 @@ default = [] [dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5" +rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5" #Note: "replay" shouldn't ideally be needed, # but it allows us to serialize everything across IPC. features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"] @@ -27,32 +27,32 @@ features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"] [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5" +rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5" features = ["metal"] # We want the wgpu-core Direct3D backends on Windows. [target.'cfg(windows)'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5" +rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5" features = ["dx11", "dx12"] # We want the wgpu-core Vulkan backend on Linux and Windows. [target.'cfg(any(windows, all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5" +rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5" features = ["vulkan"] [dependencies.wgt] package = "wgpu-types" git = "https://github.com/gfx-rs/wgpu" -rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5" +rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5" [dependencies.wgh] package = "wgpu-hal" git = "https://github.com/gfx-rs/wgpu" -rev = "f71a1bc736fde37509262ca03e91d8f56a13aeb5" +rev = "dcad7dfba92dd85c3ca21bb553a61834e01b04f5" [dependencies] bincode = "1" diff --git a/gfx/wgpu_bindings/moz.yaml b/gfx/wgpu_bindings/moz.yaml index 87eadf58db93..a4bf36473b43 100644 --- a/gfx/wgpu_bindings/moz.yaml +++ b/gfx/wgpu_bindings/moz.yaml @@ -20,11 +20,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: commit f71a1bc736fde37509262ca03e91d8f56a13aeb5 + release: commit dcad7dfba92dd85c3ca21bb553a61834e01b04f5 # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: f71a1bc736fde37509262ca03e91d8f56a13aeb5 + revision: dcad7dfba92dd85c3ca21bb553a61834e01b04f5 license: ['MIT', 'Apache-2.0'] diff --git a/gfx/wgpu_bindings/src/client.rs b/gfx/wgpu_bindings/src/client.rs index b929cd397074..cb0dbcc5b45d 100644 --- a/gfx/wgpu_bindings/src/client.rs +++ b/gfx/wgpu_bindings/src/client.rs @@ -7,7 +7,7 @@ use crate::{ DropAction, ImageDataLayout, ImplicitLayout, QueueWriteAction, RawString, TextureAction, }; -use wgc::{hub::IdentityManager, id}; +use wgc::{identity::IdentityManager, id}; use wgt::{Backend, TextureFormat}; pub use wgc::command::{compute_ffi::*, render_ffi::*}; diff --git a/gfx/wgpu_bindings/src/identity.rs b/gfx/wgpu_bindings/src/identity.rs index 7d608b275b79..7a014bf9cde0 100644 --- a/gfx/wgpu_bindings/src/identity.rs +++ b/gfx/wgpu_bindings/src/identity.rs @@ -13,7 +13,7 @@ pub struct IdentityRecycler { kind: &'static str, } -impl wgc::hub::IdentityHandler +impl wgc::identity::IdentityHandler for IdentityRecycler { type Input = I; @@ -51,7 +51,7 @@ pub struct IdentityRecyclerFactory { free_surface: extern "C" fn(id::SurfaceId, FactoryParam), } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -61,7 +61,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -71,7 +71,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -81,7 +81,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecycler } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -91,7 +91,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFa } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -101,7 +101,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecycle } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -111,7 +111,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFacto } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -121,7 +121,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerF } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -131,7 +131,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFa } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -141,7 +141,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecycler } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -151,7 +151,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecycle } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -161,7 +161,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactor } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -171,7 +171,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -181,7 +181,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerF } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -191,7 +191,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -201,7 +201,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFac } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -211,7 +211,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory } } } -impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory { +impl wgc::identity::IdentityHandlerFactory for IdentityRecyclerFactory { type Filter = IdentityRecycler; fn spawn(&self) -> Self::Filter { IdentityRecycler { @@ -222,4 +222,4 @@ impl wgc::hub::IdentityHandlerFactory for IdentityRecyclerFactory } } -impl wgc::hub::GlobalIdentityHandlerFactory for IdentityRecyclerFactory {} +impl wgc::identity::GlobalIdentityHandlerFactory for IdentityRecyclerFactory {} diff --git a/gfx/wgpu_bindings/src/server.rs b/gfx/wgpu_bindings/src/server.rs index 912495d3075a..90c496a448c3 100644 --- a/gfx/wgpu_bindings/src/server.rs +++ b/gfx/wgpu_bindings/src/server.rs @@ -88,10 +88,10 @@ impl ErrorBuffer { } // hide wgc's global in private -pub struct Global(wgc::hub::Global); +pub struct Global(wgc::global::Global); impl std::ops::Deref for Global { - type Target = wgc::hub::Global; + type Target = wgc::global::Global; fn deref(&self) -> &Self::Target { &self.0 } @@ -110,7 +110,7 @@ pub extern "C" fn wgpu_server_new(factory: IdentityRecyclerFactory) -> *mut Glob ); wgc::instance::parse_backends_from_comma_list(&backends_pref) }; - let global = Global(wgc::hub::Global::new( + let global = Global(wgc::global::Global::new( "wgpu", factory, wgt::InstanceDescriptor { @@ -448,7 +448,7 @@ pub extern "C" fn wgpu_server_buffer_drop(global: &Global, self_id: id::BufferId } impl Global { - fn device_action( + fn device_action( &self, self_id: id::DeviceId, action: DeviceAction, @@ -548,7 +548,7 @@ impl Global { } } - fn texture_action( + fn texture_action( &self, self_id: id::TextureId, action: TextureAction, @@ -564,7 +564,7 @@ impl Global { } } - fn command_encoder_action( + fn command_encoder_action( &self, self_id: id::CommandEncoderId, action: CommandEncoderAction, diff --git a/gfx/wr/Cargo.lock b/gfx/wr/Cargo.lock index 53e4a68b7395..7158afc60f2b 100644 --- a/gfx/wr/Cargo.lock +++ b/gfx/wr/Cargo.lock @@ -375,7 +375,7 @@ dependencies = [ "cocoa-foundation", "core-foundation 0.9.2", "core-graphics 0.22.3", - "foreign-types", + "foreign-types 0.3.2", "libc", "objc", ] @@ -390,7 +390,7 @@ dependencies = [ "block", "core-foundation 0.9.2", "core-graphics-types", - "foreign-types", + "foreign-types 0.3.2", "libc", "objc", ] @@ -466,7 +466,7 @@ checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" dependencies = [ "bitflags", "core-foundation 0.7.0", - "foreign-types", + "foreign-types 0.3.2", "libc", ] @@ -479,19 +479,31 @@ dependencies = [ "bitflags", "core-foundation 0.9.2", "core-graphics-types", - "foreign-types", + "foreign-types 0.3.2", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "506752f2b58723339d41d013009be97e549860785a366e2a5e75dfbd9725b48e" +dependencies = [ + "bitflags", + "core-foundation 0.9.2", + "core-graphics-types", + "foreign-types 0.5.0", "libc", ] [[package]] name = "core-graphics-types" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e92f5d519093a4178296707dbaa3880eae85a5ef5386675f361a1cf25376e93c" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" dependencies = [ "bitflags", "core-foundation 0.9.2", - "foreign-types", "libc", ] @@ -503,7 +515,19 @@ checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" dependencies = [ "core-foundation 0.9.2", "core-graphics 0.22.3", - "foreign-types", + "foreign-types 0.3.2", + "libc", +] + +[[package]] +name = "core-text" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02083d15989d6247553e1a63753561555a72b2038bba1e4239db70602a798742" +dependencies = [ + "core-foundation 0.9.2", + "core-graphics 0.23.0", + "foreign-types 0.5.0", "libc", ] @@ -817,7 +841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c49d6b4c11dca1a1dd931a34a9f397e2da91abe3de4110505f3530a80e560b52" dependencies = [ "core-foundation 0.9.2", - "core-text", + "core-text 19.2.0", "libc", "servo-fontconfig", "winapi", @@ -829,7 +853,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", ] [[package]] @@ -838,6 +883,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -3227,8 +3278,8 @@ name = "wr_glyph_rasterizer" version = "0.1.0" dependencies = [ "core-foundation 0.9.2", - "core-graphics 0.22.3", - "core-text", + "core-graphics 0.23.0", + "core-text 20.0.0", "dwrote", "env_logger", "euclid", @@ -3268,7 +3319,7 @@ dependencies = [ "chrono", "clap", "core-foundation 0.9.2", - "core-graphics 0.22.3", + "core-graphics 0.23.0", "crossbeam", "dwrote", "env_logger", diff --git a/gfx/wr/servo-tidy.toml b/gfx/wr/servo-tidy.toml index 27074fe45ebe..6bcf048e399e 100644 --- a/gfx/wr/servo-tidy.toml +++ b/gfx/wr/servo-tidy.toml @@ -10,6 +10,12 @@ packages = [ "core-foundation", "core-foundation-sys", "core-graphics", + # requires a new version of font-loader, see https://github.com/matprec/rust-font-loader/pull/36 + "core-text", + # requires updating winit to v0.28 and glutin to v0.30 (to get rid of cocoa v0.24) + # AND also requires bumping the core-graphics dependency of winit (not present in v0.28) + "foreign-types", + "foreign-types-shared", "gl_generator", # Internal dependencies of glsl-lang (only used in wrench) require different versions. "hashbrown", diff --git a/gfx/wr/wr_glyph_rasterizer/Cargo.toml b/gfx/wr/wr_glyph_rasterizer/Cargo.toml index 1748c54fc47d..ad74273b8243 100644 --- a/gfx/wr/wr_glyph_rasterizer/Cargo.toml +++ b/gfx/wr/wr_glyph_rasterizer/Cargo.toml @@ -46,6 +46,6 @@ dwrote = "0.11" [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.9.2" -core-graphics = "0.22.3" -core-text = { version = "19.2", default-features = false } +core-graphics = "0.23" +core-text = { version = "20", default-features = false } objc = "0.2" diff --git a/gfx/wr/wrench/Cargo.toml b/gfx/wr/wrench/Cargo.toml index 1c434b789464..dfdb3ba57dfd 100644 --- a/gfx/wr/wrench/Cargo.toml +++ b/gfx/wr/wrench/Cargo.toml @@ -40,7 +40,7 @@ default-features = false features = ["png"] [target.'cfg(target_os = "macos")'.dependencies] -core-graphics = "0.22" +core-graphics = "0.23" core-foundation = "0.9" [features] diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index 600499af6a74..4fdaedfe56c5 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -471,6 +471,11 @@ who = "Nicolas Silva " criteria = "safe-to-deploy" delta = "0.37.1+1.3.235 -> 0.37.2+1.3.238" +[[audits.ash]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.37.2+1.3.238 -> 0.37.3+1.3.251" + [[audits.ashmem]] who = "Matthew Gregan " criteria = "safe-to-deploy" @@ -601,6 +606,11 @@ who = "Nicolas Silva " criteria = "safe-to-deploy" delta = "2.0.2 -> 2.1.0" +[[audits.bitflags]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "2.2.1 -> 2.3.2" + [[audits.block-buffer]] who = "Mike Hommey " criteria = "safe-to-deploy" @@ -720,6 +730,21 @@ who = "Mike Hommey " criteria = "safe-to-run" delta = "0.16.0 -> 0.16.2" +[[audits.core-graphics]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.22.3 -> 0.23.0" + +[[audits.core-graphics-types]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.1.1 -> 0.1.2" + +[[audits.core-text]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "19.2.0 -> 20.0.0" + [[audits.coreaudio-sys]] who = "Mike Hommey " criteria = "safe-to-deploy" @@ -1277,6 +1302,21 @@ criteria = "safe-to-deploy" version = "1.0.7" notes = "Simple hasher implementation with no unsafe code." +[[audits.foreign-types]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.3.2 -> 0.5.0" + +[[audits.foreign-types-macros]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +version = "0.2.3" + +[[audits.foreign-types-shared]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.1.1 -> 0.3.1" + [[audits.fs-err]] who = "Mike Hommey " criteria = "safe-to-deploy" @@ -1546,6 +1586,16 @@ criteria = "safe-to-deploy" delta = "0.5.4 -> 0.6.0" notes = "Mostly bug fixes and some added functionality" +[[audits.gpu-alloc]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.5.3 -> 0.6.0" + +[[audits.gpu-alloc-types]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.2.0 -> 0.3.0" + [[audits.gpu-descriptor]] who = "Mike Hommey " criteria = "safe-to-deploy" @@ -1840,6 +1890,11 @@ criteria = "safe-to-deploy" delta = "0.23.1 -> 0.24.0" notes = "This audit treats Dzmitry Malyshau (kvark) as a trusted reviewer." +[[audits.metal]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.24.0 -> 0.25.0" + [[audits.midir]] who = "Bobby Holley " criteria = "safe-to-deploy" @@ -1946,6 +2001,11 @@ who = "Nicolas Silva " criteria = "safe-to-deploy" delta = "0.11.0@git:f59668ccfaf7bdb3a7e43d84363a21c77357b2fe -> 0.12.0@git:b99d58ea435090e561377949f428bce2c18451bb" +[[audits.naga]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.12.0@git:b99d58ea435090e561377949f428bce2c18451bb -> 0.12.0@git:76003dc0035d53a474d366dcdf49d2e4d12e921f" + [[audits.net2]] who = "Mike Hommey " criteria = "safe-to-run" @@ -3533,6 +3593,11 @@ who = "Erich Gubler " criteria = "safe-to-deploy" delta = "0.16.0@git:25cb9f61e9a6be572ee42536bbe57aa5f759a700 -> 0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5" +[[audits.wgpu-core]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5" + [[audits.wgpu-hal]] who = "Dzmitry Malyshau " criteria = "safe-to-deploy" @@ -3611,6 +3676,11 @@ who = "Erich Gubler " criteria = "safe-to-deploy" delta = "0.16.0@git:25cb9f61e9a6be572ee42536bbe57aa5f759a700 -> 0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5" +[[audits.wgpu-hal]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5" + [[audits.wgpu-types]] who = "Dzmitry Malyshau " criteria = "safe-to-deploy" @@ -3689,6 +3759,11 @@ who = "Erich Gubler " criteria = "safe-to-deploy" delta = "0.16.0@git:25cb9f61e9a6be572ee42536bbe57aa5f759a700 -> 0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5" +[[audits.wgpu-types]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5" + [[audits.whatsys]] who = "Bobby Holley " criteria = "safe-to-deploy" diff --git a/third_party/rust/ash/.cargo-checksum.json b/third_party/rust/ash/.cargo-checksum.json index ecaa49b60b88..3746880a0876 100644 --- a/third_party/rust/ash/.cargo-checksum.json +++ b/third_party/rust/ash/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"f5ba364e2195938f21eec077ff01ae3977589f75e0dd9315507058d87f229cb3","LICENSE-APACHE":"0e8a410375e1ee5c75c6198b08b534fec6e5edef766cf971bab4a404542636ab","LICENSE-MIT":"c733ccf8ab25df175a63d9d844677b98e3a5ab8f8de1c1616087e6868a7f948e","README.md":"486092d206c93d24e2108dd0df17571a19c0f029306102d0970d0791364d6497","build.rs":"616f1c2f1a0dd883d57690b767691750c1762fb01ab4aeb662825ceecf869e7b","src/device.rs":"3821bad3d35753a9dcb95dfe9c59ae0f70ce55495ec05239fb523dbb1524e232","src/entry.rs":"7e0e9a0a4a71515d453761dc2c8839d5ba3ce4c9a038433279749ae4b3e795d5","src/extensions/experimental/amd.rs":"e89f7cf4d4b9335ae74391fddc85d03106b121b6d964ea8fad35593e9918f4e6","src/extensions/experimental/mod.rs":"41a5366e1c8bd0e1fa47e9cf6fddc8111ed0a6946813be4eefca81da969d1ee9","src/extensions/ext/acquire_drm_display.rs":"095af0b7336a2cc03e0f5584d994db8df1ad14f52360456407725013d33298ad","src/extensions/ext/buffer_device_address.rs":"124033d6e8f3251cf0d44e7d0d51d9ef28770d6c7d2fe283ffa98a32ba4ead55","src/extensions/ext/calibrated_timestamps.rs":"ba0ac6e38e7feb62b482ed9371c11447669d0d88b18bfc5e59ea75d5ed78691c","src/extensions/ext/debug_marker.rs":"33044f1f3f46280eb3f2564c9c8d66f5a470dbac51baeff34d2997f2c6a0fb94","src/extensions/ext/debug_report.rs":"405b179a8b155adbafabfaf9d38a5fb84e78c78dced79e72d64fb507520a85b1","src/extensions/ext/debug_utils.rs":"a496af59111353313013799b8862eacf343cf826c9901212c7838ec2fab40fe5","src/extensions/ext/descriptor_buffer.rs":"ae9c2ce265ada99b2ff99d6c2fe55f4842b9213cfaa2010ea7cf1a738e01c15d","src/extensions/ext/extended_dynamic_state.rs":"feeb16916cf2288713df1dd79545c9f484e3b115a2e93aa00e621b59b92085ff","src/extensions/ext/extended_dynamic_state2.rs":"ac30857e100ef00578ebcdd6d9d0136ebad95454965780836f15b42a88c00497","src/extensions/ext/extended_dynamic_state3.rs":"4e3b95846dff78cb9a467641324075741c2cb71d53233ec52b0727e066faae4d","src/extensions/ext/full_screen_exclusive.rs":"9572aa10253ff7c6d0f79b4ce92114ee48499d260043860db9ea268faf95756b","src/extensions/ext/headless_surface.rs":"dc0540ca8bb9be99975d8f432a062e1dcac53bb43dcd81a0450673fe9a3798cb","src/extensions/ext/image_compression_control.rs":"6f704c54ab6965058d0f9aef8eef9b6d7d713c419270494f8a7f1f560ee827a9","src/extensions/ext/image_drm_format_modifier.rs":"452d9833283dd2913de676747cc54b27df070915bfd8b31184ded4d9f299656d","src/extensions/ext/mesh_shader.rs":"c4c30eb1a8de3db5ad11b4f4f77c41c8981634e47495aee58ac07a6297e8344c","src/extensions/ext/metal_surface.rs":"3175d1d51e49e00cbdeabdc050932d547bffc4b0842a7e30049141ee99dda107","src/extensions/ext/mod.rs":"6daf2b78f4e6bd801b45cdf4213eb0acd7e313b5786c98e218e85ac2baf04676","src/extensions/ext/physical_device_drm.rs":"450fd7e6a136e5e0079836ab65f89a7a0ed90af5469abebd99afd2b14d155c55","src/extensions/ext/private_data.rs":"a92e37ea025d2a8106a2034403de4bfdc954b411a8c1c4f29d955d81fcfbd4a0","src/extensions/ext/sample_locations.rs":"fc664942394362a00eeb1086b63e4ab84df8884bb299db05ef6a14f98434bd1c","src/extensions/ext/tooling_info.rs":"8a4f6570d15e2a1cbea9a8fa8e70cf358aa76336e108bade9c46de25b65bf5cb","src/extensions/khr/acceleration_structure.rs":"935628eee2aa943286a2fe387dcd0655c8a539e52dcbce7769d0fd71b3af64f7","src/extensions/khr/android_surface.rs":"8183a1ba413b894287014b934df3888cb6d53b8f95bbe3f299b91fd481cdd2eb","src/extensions/khr/buffer_device_address.rs":"6ffb9bad123139cff26c77ea5a7a4556bb24a6d3daa47fc3378d67c016157098","src/extensions/khr/copy_commands2.rs":"58717fd89144de4fded43601ebb8997b14a67eb0d18b85f1ab739457cbaef1d0","src/extensions/khr/create_render_pass2.rs":"c4c15abbe9dff9778c2ecd25556ab88bd642facca75d7c69e4023ec157fce12c","src/extensions/khr/deferred_host_operations.rs":"facf3c32ea9b5093a0b8f5c8ca3e89d5517a6e39f5e781deffc91f3170c77443","src/extensions/khr/device_group.rs":"5a54fba7b9f1cd25aa2281eabeca226de5ba76bd1433adb76d4e5d650a7862b5","src/extensions/khr/device_group_creation.rs":"368e5139ade893b71e1a333cab54605b76f51656bb8e4936c492f80069616d84","src/extensions/khr/display.rs":"c8241e5d8d39b74ecc4766faba27efca5cbd31382d8d40ac2f2f4e54f1f8d88d","src/extensions/khr/display_swapchain.rs":"9bbf1d47989a1550a3515c6d98367aa0df67b43ea102be329a658e0f458ae1d9","src/extensions/khr/draw_indirect_count.rs":"14acfbdb21a96db1bd0bad467af341ee327d5a4a78b2727aa5c5707560b157f8","src/extensions/khr/dynamic_rendering.rs":"bc363c863ef269bf905de0a3e7414fc5f37af7da88412086b31f1065d0a1178f","src/extensions/khr/external_fence_fd.rs":"0a89e00c9560e6fc4b63d6295260bb5db79bb595232217ce1723ba0a4aa0af38","src/extensions/khr/external_fence_win32.rs":"a357d7dcea8e50f3b26f5bb2fbe0bcbdc1b94aa4b6bbc784570715bcb06a23a9","src/extensions/khr/external_memory_fd.rs":"624d0bcf61e16ee9e284d71354fc18a8141ec14b2fd8e1d5c1ed0547f0bd2fcf","src/extensions/khr/external_memory_win32.rs":"d731d4e531e55a7ba53bdec2045167cf494ca7b54267edc205be675790a579ef","src/extensions/khr/external_semaphore_fd.rs":"8254d0e50e26761e10b523e4d45c6128d304926880a02144724145fd4d412898","src/extensions/khr/external_semaphore_win32.rs":"2fcc7fb4ba50f94e60d1faeefdb0e4f6940120766143c9ce7257d7c0356b68af","src/extensions/khr/get_memory_requirements2.rs":"56edbc8cb1a335071518fdf52d1f549ab31292551cd5ec2d4168949446600468","src/extensions/khr/get_physical_device_properties2.rs":"a9ad06c559390c43100b7c6ab3a339ef7ce9c6e909d5e934e51fcfee2e18eb2f","src/extensions/khr/get_surface_capabilities2.rs":"6f2f8a0c84c4b962a681a2c02216df6967c1a91da7d6655f82c7eab3052db081","src/extensions/khr/maintenance1.rs":"e19365a3ad201712a871887346564d82a8bddfa8a7134b0f84f48396e0c428dd","src/extensions/khr/maintenance3.rs":"e4022aa249d57a47133df4ab6c6e3884a1613af78ba8d7b12bbeeeb87d0a19ee","src/extensions/khr/maintenance4.rs":"23a1a123dfa5ca32741fca6f14ea0aae358563ba043dda201283dbdd56687a06","src/extensions/khr/mod.rs":"1af17e94a6c0f8a95a60ea407f2b9657eee755d17671e2f7bdcf8eb24fa0ea4d","src/extensions/khr/pipeline_executable_properties.rs":"e643476dde846db4b96d4a1eab9f6cd59f2366dae706f61dfd5b2a58b33e5739","src/extensions/khr/present_wait.rs":"6bc0ff08748650e5aaa303287abecf9cd47328cd285763fdb120c5bc1bed72fd","src/extensions/khr/push_descriptor.rs":"531b9026b2e3377b259a93097ca4a6327951d11c0582dad29ea4b4817b0b7f95","src/extensions/khr/ray_tracing_maintenance1.rs":"281095b60144574189cd63e7d55f537abe46281c3f0c0501937c2e1dc4102fe9","src/extensions/khr/ray_tracing_pipeline.rs":"1d84bbcce85e6f6392828ace82022a713a71fe3a1f85fab6ba30368ac7088e23","src/extensions/khr/surface.rs":"fa60900890cf901a0d3fcb9f066f72917a783b73baff93bb377d8d3f77c18ea5","src/extensions/khr/swapchain.rs":"ec23290bc929b3db2a403d47148426a817b05547073f4d12950f816db0a9b520","src/extensions/khr/synchronization2.rs":"8d4e880ffdda8e9f458fc4ccf6de04b92d6314121071d711404b43236c9816e5","src/extensions/khr/timeline_semaphore.rs":"b554829512a648fd1d9ab493955e7c088c1f1f3a50b8fb933211d2b5a03e5cde","src/extensions/khr/wayland_surface.rs":"2d7b8423e5b856e9185cfef804f7fededd621f60e5aac26d93e69aee055dafd1","src/extensions/khr/win32_surface.rs":"135fa0493b77b322fa3478eba877848e9325bbf70d91f868862f637fbdeff507","src/extensions/khr/xcb_surface.rs":"c85bbce4d65f8c5ee4a11349183757e69df9331af50940f6befe6932ba3f6dc2","src/extensions/khr/xlib_surface.rs":"2175f140157e47af5096069e443799a1db373b2f6e9a0818a76a9398bc97bcea","src/extensions/mod.rs":"717bc2155a3d311ddc485dbf6313a0996e1906d15bd09be0aab776e33368eaa7","src/extensions/mvk/ios_surface.rs":"c268afccb727218f269649056a342688d9a93fa3f4f1888df7733d2d5c5030f6","src/extensions/mvk/macos_surface.rs":"1d9cdd0f818e2c209d5d11b1cbca6705351f097ef64697cb523e3f8e3b1cae93","src/extensions/mvk/mod.rs":"d03ac1a0144d1aca9ed1d0ce0c14b099f1fedb03b8108028b780a34f64de604c","src/extensions/nn/mod.rs":"b32935320aa2af18b129868d52d4042596b3c22046cd650a4e9e75c5f3973eb3","src/extensions/nn/vi_surface.rs":"27f09bf182967353ce5c0dc73ea89eab0f89ac3d5d18b9574b755cb3b6ff214b","src/extensions/nv/coverage_reduction_mode.rs":"428348e0876108b63dbbdce55218403c2481af902aba463633f9d4d62151c4c9","src/extensions/nv/device_diagnostic_checkpoints.rs":"8faca3ef4c99c5179996c8899c15489e1978d01fc7614248ac07057874d78f72","src/extensions/nv/mesh_shader.rs":"2bdbdf131db157d5e4f10beacdcc5cfdf54b4d296a0c0bf1239259ba32d4c76b","src/extensions/nv/mod.rs":"cb7e4f152f515c8a8beefcb7b2ff8a65e6d5932daf34139fb438c60f894e5fc2","src/extensions/nv/ray_tracing.rs":"a5c5faeb624542d13b0bb08e9434ae7604120a89e4e00a8430046c3cc218a9c1","src/instance.rs":"1afd01655c650480bffc1b6963e510632b92dc36733594c12aa3032415669270","src/lib.rs":"3dc222b92b417c0985e7ca5cd131f2966f02f038c578076962f028419edc05fa","src/prelude.rs":"035dbe3e825ff83b0af5b22ed428d95139ff16f65c6039419275a4a5820f499d","src/util.rs":"55eed33491cf1fa29ccf7f591aeba2c0bee2c7eae9c979124f27c800567104aa","src/vk.rs":"234a101311b07c82cca72db451ddf953e4cd385a6b7fd42fa4e8f659e8089e71","src/vk/aliases.rs":"c6d43e3073a3000e8ccaa1a131112a6129c22e699d559a53762fd7d99bf66e30","src/vk/bitflags.rs":"fa4e2337f029f3cb2c91b51a78ab48b2eeed64d07bc9d872783c06624aff5171","src/vk/const_debugs.rs":"b299897a023c200bd973addd736aa7b7110ce108d4012537679c0353d507af65","src/vk/constants.rs":"6e21377b7238d9c94174a97e6ebdc6e3401a2c32ef32e211142448eed1d972d7","src/vk/definitions.rs":"242aace0047bf09fa344771b8443c98d63fbcbdf0af6b38e120d37e2c83bafc5","src/vk/enums.rs":"4faea35666df46f2698b4eed1171dd916180959e06bdae43814f2ac8e9b6ce9b","src/vk/extensions.rs":"2d10226fb700efbf198ab158d2d8af6bb94563905023cd66cd81a1c9a7250dbc","src/vk/feature_extensions.rs":"c875cf2a7b02a8a8fa31f3bc8794ec526c0870b470e7a308b5b256402dc8125e","src/vk/features.rs":"46633698d0275ae55d4372403d76b09763e762e8db9fec0688f40d8204ce221b","src/vk/macros.rs":"5fde17e47d5a102bfc74dfd9ad024938d676950afae7fe932dc697cb95a9f5e4","src/vk/native.rs":"0e3d2c92be3f8b8b62d896136d1bcbdd8a9406f292aa912f646a6ed23fd96cb6","src/vk/platform_types.rs":"fc4143ac65aead425694fd4dd9f50a7c1aebe35e23c872050df5368c31694375","src/vk/prelude.rs":"8e1cf47901f63b64a1490011eb1572a7ce8401a1559cca6f057645bd2d85e035","tests/constant_size_arrays.rs":"fdd726fcebc3b05900a0d24a05826f4a19e99bc71f8f35bacc958a1e10de1013","tests/display.rs":"d294396bb5b2210432724cccc0a56e105bab8743e180d4ad7cc675a200c09539"},"package":"28bf19c1f0a470be5fbf7522a308a05df06610252c5bcf5143e1b23f629a9a03"} \ No newline at end of file +{"files":{"Cargo.toml":"647cc2f6d5950cd9107c10b0a3bd35787b3b34c6c6233c5dd6a2dca8004d1e2e","LICENSE-APACHE":"0e8a410375e1ee5c75c6198b08b534fec6e5edef766cf971bab4a404542636ab","LICENSE-MIT":"c733ccf8ab25df175a63d9d844677b98e3a5ab8f8de1c1616087e6868a7f948e","README.md":"5d1c540b5bb7dcdbb4fb95403b0a178b22c2dbf8fa75db56cc67626196ea2f41","build.rs":"b0109a1596448fb599af8ca0efdbaaf2dba09bbdded8f07f2b5bab885f9a0d42","src/device.rs":"092b983d74b493c7f91d1b6ef21ab72231972392b5cd03ddb0f06b7c4f2a08cc","src/entry.rs":"6b83a893d9efb33c5718868ae9039af0da0d77b673cfee68e009bb83ff6837b7","src/extensions/experimental/amd.rs":"e89f7cf4d4b9335ae74391fddc85d03106b121b6d964ea8fad35593e9918f4e6","src/extensions/experimental/mod.rs":"41a5366e1c8bd0e1fa47e9cf6fddc8111ed0a6946813be4eefca81da969d1ee9","src/extensions/ext/acquire_drm_display.rs":"095af0b7336a2cc03e0f5584d994db8df1ad14f52360456407725013d33298ad","src/extensions/ext/buffer_device_address.rs":"124033d6e8f3251cf0d44e7d0d51d9ef28770d6c7d2fe283ffa98a32ba4ead55","src/extensions/ext/calibrated_timestamps.rs":"ba0ac6e38e7feb62b482ed9371c11447669d0d88b18bfc5e59ea75d5ed78691c","src/extensions/ext/debug_marker.rs":"33044f1f3f46280eb3f2564c9c8d66f5a470dbac51baeff34d2997f2c6a0fb94","src/extensions/ext/debug_report.rs":"405b179a8b155adbafabfaf9d38a5fb84e78c78dced79e72d64fb507520a85b1","src/extensions/ext/debug_utils.rs":"a496af59111353313013799b8862eacf343cf826c9901212c7838ec2fab40fe5","src/extensions/ext/descriptor_buffer.rs":"ae9c2ce265ada99b2ff99d6c2fe55f4842b9213cfaa2010ea7cf1a738e01c15d","src/extensions/ext/extended_dynamic_state.rs":"feeb16916cf2288713df1dd79545c9f484e3b115a2e93aa00e621b59b92085ff","src/extensions/ext/extended_dynamic_state2.rs":"ac30857e100ef00578ebcdd6d9d0136ebad95454965780836f15b42a88c00497","src/extensions/ext/extended_dynamic_state3.rs":"4e3b95846dff78cb9a467641324075741c2cb71d53233ec52b0727e066faae4d","src/extensions/ext/full_screen_exclusive.rs":"6962432157b9209fae038827cf0b6fb2624fc05479c4436088de5a1c200e187b","src/extensions/ext/headless_surface.rs":"dc0540ca8bb9be99975d8f432a062e1dcac53bb43dcd81a0450673fe9a3798cb","src/extensions/ext/image_compression_control.rs":"6f704c54ab6965058d0f9aef8eef9b6d7d713c419270494f8a7f1f560ee827a9","src/extensions/ext/image_drm_format_modifier.rs":"452d9833283dd2913de676747cc54b27df070915bfd8b31184ded4d9f299656d","src/extensions/ext/mesh_shader.rs":"c4c30eb1a8de3db5ad11b4f4f77c41c8981634e47495aee58ac07a6297e8344c","src/extensions/ext/metal_surface.rs":"3175d1d51e49e00cbdeabdc050932d547bffc4b0842a7e30049141ee99dda107","src/extensions/ext/mod.rs":"9514f2a84c3677366889d3107f164cbc6af7862578b596a89f049d4e830f3ce1","src/extensions/ext/physical_device_drm.rs":"450fd7e6a136e5e0079836ab65f89a7a0ed90af5469abebd99afd2b14d155c55","src/extensions/ext/pipeline_properties.rs":"f4bbe96d185c6d87bf7084ff6219ad39faabd45fbd18164f80c708ebd41b9bde","src/extensions/ext/private_data.rs":"a92e37ea025d2a8106a2034403de4bfdc954b411a8c1c4f29d955d81fcfbd4a0","src/extensions/ext/sample_locations.rs":"fc664942394362a00eeb1086b63e4ab84df8884bb299db05ef6a14f98434bd1c","src/extensions/ext/shader_object.rs":"73b30e0a0802ea22cd7d0400214b7fbfd8f0ef4975dcfec5954228df6e40bb6a","src/extensions/ext/tooling_info.rs":"8a4f6570d15e2a1cbea9a8fa8e70cf358aa76336e108bade9c46de25b65bf5cb","src/extensions/khr/acceleration_structure.rs":"935628eee2aa943286a2fe387dcd0655c8a539e52dcbce7769d0fd71b3af64f7","src/extensions/khr/android_surface.rs":"8183a1ba413b894287014b934df3888cb6d53b8f95bbe3f299b91fd481cdd2eb","src/extensions/khr/buffer_device_address.rs":"6ffb9bad123139cff26c77ea5a7a4556bb24a6d3daa47fc3378d67c016157098","src/extensions/khr/copy_commands2.rs":"58717fd89144de4fded43601ebb8997b14a67eb0d18b85f1ab739457cbaef1d0","src/extensions/khr/create_render_pass2.rs":"c4c15abbe9dff9778c2ecd25556ab88bd642facca75d7c69e4023ec157fce12c","src/extensions/khr/deferred_host_operations.rs":"facf3c32ea9b5093a0b8f5c8ca3e89d5517a6e39f5e781deffc91f3170c77443","src/extensions/khr/device_group.rs":"2ff043e8612b71024d3ddebd8238d8e226e91fc25d87593c4299e9722c364964","src/extensions/khr/device_group_creation.rs":"bfcb60fb8621667e59cd07f691fe4f6c84f59316828f1b3b29e42fa950481906","src/extensions/khr/display.rs":"c8241e5d8d39b74ecc4766faba27efca5cbd31382d8d40ac2f2f4e54f1f8d88d","src/extensions/khr/display_swapchain.rs":"9bbf1d47989a1550a3515c6d98367aa0df67b43ea102be329a658e0f458ae1d9","src/extensions/khr/draw_indirect_count.rs":"14acfbdb21a96db1bd0bad467af341ee327d5a4a78b2727aa5c5707560b157f8","src/extensions/khr/dynamic_rendering.rs":"bc363c863ef269bf905de0a3e7414fc5f37af7da88412086b31f1065d0a1178f","src/extensions/khr/external_fence_fd.rs":"0a89e00c9560e6fc4b63d6295260bb5db79bb595232217ce1723ba0a4aa0af38","src/extensions/khr/external_fence_win32.rs":"a357d7dcea8e50f3b26f5bb2fbe0bcbdc1b94aa4b6bbc784570715bcb06a23a9","src/extensions/khr/external_memory_fd.rs":"e9f6a234aec6ca2bd74269b444e2326fedc2f346db8de87f99d4bfda7637af9e","src/extensions/khr/external_memory_win32.rs":"d731d4e531e55a7ba53bdec2045167cf494ca7b54267edc205be675790a579ef","src/extensions/khr/external_semaphore_fd.rs":"8254d0e50e26761e10b523e4d45c6128d304926880a02144724145fd4d412898","src/extensions/khr/external_semaphore_win32.rs":"2fcc7fb4ba50f94e60d1faeefdb0e4f6940120766143c9ce7257d7c0356b68af","src/extensions/khr/get_memory_requirements2.rs":"56edbc8cb1a335071518fdf52d1f549ab31292551cd5ec2d4168949446600468","src/extensions/khr/get_physical_device_properties2.rs":"a9ad06c559390c43100b7c6ab3a339ef7ce9c6e909d5e934e51fcfee2e18eb2f","src/extensions/khr/get_surface_capabilities2.rs":"6f2f8a0c84c4b962a681a2c02216df6967c1a91da7d6655f82c7eab3052db081","src/extensions/khr/maintenance1.rs":"e19365a3ad201712a871887346564d82a8bddfa8a7134b0f84f48396e0c428dd","src/extensions/khr/maintenance3.rs":"e4022aa249d57a47133df4ab6c6e3884a1613af78ba8d7b12bbeeeb87d0a19ee","src/extensions/khr/maintenance4.rs":"638a3804a3bed006c320a4d3378e61b9a13ff5ecb7cf0a8f70f40d37b6489fff","src/extensions/khr/mod.rs":"7a44056ef1c67830234f60a965859cb00e90a6c6f5d717d6092ae08111de74c8","src/extensions/khr/performance_query.rs":"8b634851f16b8021416510bfcc4224ba1214abbda2e67a2f6c553d1b9fd8b7da","src/extensions/khr/pipeline_executable_properties.rs":"e643476dde846db4b96d4a1eab9f6cd59f2366dae706f61dfd5b2a58b33e5739","src/extensions/khr/present_wait.rs":"6bc0ff08748650e5aaa303287abecf9cd47328cd285763fdb120c5bc1bed72fd","src/extensions/khr/push_descriptor.rs":"531b9026b2e3377b259a93097ca4a6327951d11c0582dad29ea4b4817b0b7f95","src/extensions/khr/ray_tracing_maintenance1.rs":"281095b60144574189cd63e7d55f537abe46281c3f0c0501937c2e1dc4102fe9","src/extensions/khr/ray_tracing_pipeline.rs":"1d84bbcce85e6f6392828ace82022a713a71fe3a1f85fab6ba30368ac7088e23","src/extensions/khr/surface.rs":"fa60900890cf901a0d3fcb9f066f72917a783b73baff93bb377d8d3f77c18ea5","src/extensions/khr/swapchain.rs":"c64ba70bf3a5ede9fc218b34fb5559b55b900479290ef3d684c2637abe13bda9","src/extensions/khr/synchronization2.rs":"8d4e880ffdda8e9f458fc4ccf6de04b92d6314121071d711404b43236c9816e5","src/extensions/khr/timeline_semaphore.rs":"b554829512a648fd1d9ab493955e7c088c1f1f3a50b8fb933211d2b5a03e5cde","src/extensions/khr/wayland_surface.rs":"2d7b8423e5b856e9185cfef804f7fededd621f60e5aac26d93e69aee055dafd1","src/extensions/khr/win32_surface.rs":"135fa0493b77b322fa3478eba877848e9325bbf70d91f868862f637fbdeff507","src/extensions/khr/xcb_surface.rs":"c85bbce4d65f8c5ee4a11349183757e69df9331af50940f6befe6932ba3f6dc2","src/extensions/khr/xlib_surface.rs":"2175f140157e47af5096069e443799a1db373b2f6e9a0818a76a9398bc97bcea","src/extensions/mod.rs":"717bc2155a3d311ddc485dbf6313a0996e1906d15bd09be0aab776e33368eaa7","src/extensions/mvk/ios_surface.rs":"c268afccb727218f269649056a342688d9a93fa3f4f1888df7733d2d5c5030f6","src/extensions/mvk/macos_surface.rs":"1d9cdd0f818e2c209d5d11b1cbca6705351f097ef64697cb523e3f8e3b1cae93","src/extensions/mvk/mod.rs":"d03ac1a0144d1aca9ed1d0ce0c14b099f1fedb03b8108028b780a34f64de604c","src/extensions/nn/mod.rs":"b32935320aa2af18b129868d52d4042596b3c22046cd650a4e9e75c5f3973eb3","src/extensions/nn/vi_surface.rs":"27f09bf182967353ce5c0dc73ea89eab0f89ac3d5d18b9574b755cb3b6ff214b","src/extensions/nv/coverage_reduction_mode.rs":"428348e0876108b63dbbdce55218403c2481af902aba463633f9d4d62151c4c9","src/extensions/nv/device_diagnostic_checkpoints.rs":"8faca3ef4c99c5179996c8899c15489e1978d01fc7614248ac07057874d78f72","src/extensions/nv/mesh_shader.rs":"2bdbdf131db157d5e4f10beacdcc5cfdf54b4d296a0c0bf1239259ba32d4c76b","src/extensions/nv/mod.rs":"cb7e4f152f515c8a8beefcb7b2ff8a65e6d5932daf34139fb438c60f894e5fc2","src/extensions/nv/ray_tracing.rs":"a5c5faeb624542d13b0bb08e9434ae7604120a89e4e00a8430046c3cc218a9c1","src/instance.rs":"c70ee7761eca4753d56e879c7551ed318b3cf0d7491dfbe577a60ca7029f056f","src/lib.rs":"3dc222b92b417c0985e7ca5cd131f2966f02f038c578076962f028419edc05fa","src/prelude.rs":"0efd876803db2edb93b34ef21645d0245f4f9476fac000f7de04ddf86f8917e6","src/util.rs":"51df166b0ca0317ea28c87eb42c23477a96a88b849ae867cb989dfc893845d08","src/vk.rs":"234a101311b07c82cca72db451ddf953e4cd385a6b7fd42fa4e8f659e8089e71","src/vk/aliases.rs":"10fd44d0d03d8c7747ab5d6cc9c3f87c4dbcf1ade2bfa86d61d408c328e03723","src/vk/bitflags.rs":"81212ebd4d0ac827abf850ee6c496cac3cf8b9c9bcb9153d16aaaacbbf01cc92","src/vk/const_debugs.rs":"fe1ed13e20854baa86f989fe055eea0863bcf919e33a942828e4df0c427e2e53","src/vk/constants.rs":"33e50507434eabae4f324803712b8211596b7078de35a89650920e7c8bf23868","src/vk/definitions.rs":"79fb0a7fc03aeb1bdc0f905bf459421d4bbd7454eaa9f3813c3a39ac21b77558","src/vk/enums.rs":"90af6f5584b4f975ff2292beb713aef31c37953437fba05503dddb44e279bada","src/vk/extensions.rs":"d5bc4ad7564e71532721bc49371b2dfff7c37204c4a50d2adc18a65cd8c977c0","src/vk/feature_extensions.rs":"c875cf2a7b02a8a8fa31f3bc8794ec526c0870b470e7a308b5b256402dc8125e","src/vk/features.rs":"008be2b5a1b9438fae2e75754c6415344e58e117062496643ef87240031c4434","src/vk/macros.rs":"5fde17e47d5a102bfc74dfd9ad024938d676950afae7fe932dc697cb95a9f5e4","src/vk/native.rs":"7ff91f6ec628ea07e67adbba18cabcb05e24c4f63eeb94056ae9e7e39b56ed2b","src/vk/platform_types.rs":"fc4143ac65aead425694fd4dd9f50a7c1aebe35e23c872050df5368c31694375","src/vk/prelude.rs":"8e1cf47901f63b64a1490011eb1572a7ce8401a1559cca6f057645bd2d85e035","tests/constant_size_arrays.rs":"fdd726fcebc3b05900a0d24a05826f4a19e99bc71f8f35bacc958a1e10de1013","tests/display.rs":"d294396bb5b2210432724cccc0a56e105bab8743e180d4ad7cc675a200c09539"},"package":"39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a"} \ No newline at end of file diff --git a/third_party/rust/ash/Cargo.toml b/third_party/rust/ash/Cargo.toml index 429cbf7b24fb..31a170a69b8d 100644 --- a/third_party/rust/ash/Cargo.toml +++ b/third_party/rust/ash/Cargo.toml @@ -10,10 +10,10 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" +edition = "2021" rust-version = "1.59.0" name = "ash" -version = "0.37.2+1.3.238" +version = "0.37.3+1.3.251" authors = [ "Maik Klein ", "Benjamin Saunders ", @@ -28,9 +28,7 @@ keywords = [ ] license = "MIT OR Apache-2.0" repository = "https://github.com/MaikKlein/ash" - -[package.metadata.release] -no-dev-version = true +resolver = "1" [package.metadata.docs.rs] all-features = true @@ -39,6 +37,9 @@ rustdoc-args = [ "docsrs", ] +[package.metadata.release] +no-dev-version = true + [dependencies.libloading] version = "0.7" optional = true diff --git a/third_party/rust/ash/README.md b/third_party/rust/ash/README.md index 12c0892ce3e8..513519c92c0f 100644 --- a/third_party/rust/ash/README.md +++ b/third_party/rust/ash/README.md @@ -8,6 +8,7 @@ A very lightweight wrapper around Vulkan [![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT) [![LICENSE](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE-APACHE) [![Join the chat at https://gitter.im/MaikKlein/ash](https://badges.gitter.im/MaikKlein/ash.svg)](https://gitter.im/MaikKlein/ash?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![MSRV](https://img.shields.io/badge/rustc-1.60.0+-ab6000.svg)](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html) ## Overview - [x] A true Vulkan API without compromises diff --git a/third_party/rust/ash/build.rs b/third_party/rust/ash/build.rs index ba6e61d4927a..7ccdbc4b6e01 100644 --- a/third_party/rust/ash/build.rs +++ b/third_party/rust/ash/build.rs @@ -13,12 +13,12 @@ fn main() { ("windows", "64") => "Lib", _ => "lib", }; - println!("cargo:rustc-link-search={}/{}", var, suffix); + println!("cargo:rustc-link-search={var}/{suffix}"); } let lib = match &*target_family { "windows" => "vulkan-1", _ => "vulkan", }; - println!("cargo:rustc-link-lib={}", lib); + println!("cargo:rustc-link-lib={lib}"); } } diff --git a/third_party/rust/ash/src/device.rs b/third_party/rust/ash/src/device.rs index 60a91ae15580..cf0fca78f2e3 100644 --- a/third_party/rust/ash/src/device.rs +++ b/third_party/rust/ash/src/device.rs @@ -465,34 +465,42 @@ impl Device { #[inline] pub unsafe fn get_device_buffer_memory_requirements( &self, - create_info: &vk::DeviceBufferMemoryRequirements, + memory_requirements: &vk::DeviceBufferMemoryRequirements, out: &mut vk::MemoryRequirements2, ) { - (self.device_fn_1_3.get_device_buffer_memory_requirements)(self.handle, create_info, out) + (self.device_fn_1_3.get_device_buffer_memory_requirements)( + self.handle, + memory_requirements, + out, + ) } /// #[inline] pub unsafe fn get_device_image_memory_requirements( &self, - create_info: &vk::DeviceImageMemoryRequirements, + memory_requirements: &vk::DeviceImageMemoryRequirements, out: &mut vk::MemoryRequirements2, ) { - (self.device_fn_1_3.get_device_image_memory_requirements)(self.handle, create_info, out) + (self.device_fn_1_3.get_device_image_memory_requirements)( + self.handle, + memory_requirements, + out, + ) } /// Retrieve the number of elements to pass to [`get_device_image_sparse_memory_requirements()`][Self::get_device_image_sparse_memory_requirements()] #[inline] pub unsafe fn get_device_image_sparse_memory_requirements_len( &self, - create_info: &vk::DeviceImageMemoryRequirements, + memory_requirements: &vk::DeviceImageMemoryRequirements, ) -> usize { let mut count = 0; (self .device_fn_1_3 .get_device_image_sparse_memory_requirements)( self.handle, - create_info, + memory_requirements, &mut count, std::ptr::null_mut(), ); @@ -506,7 +514,7 @@ impl Device { #[inline] pub unsafe fn get_device_image_sparse_memory_requirements( &self, - create_info: &vk::DeviceImageMemoryRequirements, + memory_requirements: &vk::DeviceImageMemoryRequirements, out: &mut [vk::SparseImageMemoryRequirements2], ) { let mut count = out.len() as u32; @@ -514,7 +522,7 @@ impl Device { .device_fn_1_3 .get_device_image_sparse_memory_requirements)( self.handle, - create_info, + memory_requirements, &mut count, out.as_mut_ptr(), ); @@ -846,6 +854,14 @@ impl Device { (self.device_fn_1_1.trim_command_pool)(self.handle(), command_pool, flags); } + /// + #[inline] + pub unsafe fn get_device_queue2(&self, queue_info: &vk::DeviceQueueInfo2) -> vk::Queue { + let mut queue = mem::zeroed(); + (self.device_fn_1_1.get_device_queue2)(self.handle(), queue_info, &mut queue); + queue + } + /// #[inline] pub unsafe fn create_sampler_ycbcr_conversion( @@ -1499,17 +1515,17 @@ impl Device { #[inline] pub unsafe fn allocate_descriptor_sets( &self, - create_info: &vk::DescriptorSetAllocateInfo, + allocate_info: &vk::DescriptorSetAllocateInfo, ) -> VkResult> { - let mut desc_set = Vec::with_capacity(create_info.descriptor_set_count as usize); + let mut desc_set = Vec::with_capacity(allocate_info.descriptor_set_count as usize); (self.device_fn_1_0.allocate_descriptor_sets)( self.handle(), - create_info, + allocate_info, desc_set.as_mut_ptr(), ) .result()?; - desc_set.set_len(create_info.descriptor_set_count as usize); + desc_set.set_len(allocate_info.descriptor_set_count as usize); Ok(desc_set) } @@ -1786,10 +1802,10 @@ impl Device { pub unsafe fn cmd_begin_render_pass( &self, command_buffer: vk::CommandBuffer, - create_info: &vk::RenderPassBeginInfo, + render_pass_begin: &vk::RenderPassBeginInfo, contents: vk::SubpassContents, ) { - (self.device_fn_1_0.cmd_begin_render_pass)(command_buffer, create_info, contents); + (self.device_fn_1_0.cmd_begin_render_pass)(command_buffer, render_pass_begin, contents); } /// @@ -2488,16 +2504,16 @@ impl Device { #[inline] pub unsafe fn allocate_command_buffers( &self, - create_info: &vk::CommandBufferAllocateInfo, + allocate_info: &vk::CommandBufferAllocateInfo, ) -> VkResult> { - let mut buffers = Vec::with_capacity(create_info.command_buffer_count as usize); + let mut buffers = Vec::with_capacity(allocate_info.command_buffer_count as usize); (self.device_fn_1_0.allocate_command_buffers)( self.handle(), - create_info, + allocate_info, buffers.as_mut_ptr(), ) .result()?; - buffers.set_len(create_info.command_buffer_count as usize); + buffers.set_len(allocate_info.command_buffer_count as usize); Ok(buffers) } @@ -2592,13 +2608,13 @@ impl Device { #[inline] pub unsafe fn allocate_memory( &self, - create_info: &vk::MemoryAllocateInfo, + allocate_info: &vk::MemoryAllocateInfo, allocation_callbacks: Option<&vk::AllocationCallbacks>, ) -> VkResult { let mut memory = mem::zeroed(); (self.device_fn_1_0.allocate_memory)( self.handle(), - create_info, + allocate_info, allocation_callbacks.as_raw_ptr(), &mut memory, ) diff --git a/third_party/rust/ash/src/entry.rs b/third_party/rust/ash/src/entry.rs index 67e6c9a7392a..7df62e7863f0 100644 --- a/third_party/rust/ash/src/entry.rs +++ b/third_party/rust/ash/src/entry.rs @@ -37,9 +37,15 @@ impl Entry { /// development packages installed (e.g. the Vulkan SDK, or Ubuntu's `libvulkan-dev`). /// /// # Safety + /// /// `dlopen`ing native libraries is inherently unsafe. The safety guidelines /// for [`Library::new()`] and [`Library::get()`] apply here. /// + /// No Vulkan functions loaded directly or indirectly from this [`Entry`] + /// may be called after it is [dropped][drop()]. + /// + /// # Example + /// /// ```no_run /// use ash::{vk, Entry}; /// # fn main() -> Result<(), Box> { @@ -86,6 +92,11 @@ impl Entry { /// Note that instance/device functions are still fetched via `vkGetInstanceProcAddr` and /// `vkGetDeviceProcAddr` for maximum performance. /// + /// Any Vulkan function acquired directly or indirectly from this [`Entry`] may be called after it + /// is [dropped][drop()]. + /// + /// # Example + /// /// ```no_run /// use ash::{vk, Entry}; /// # fn main() -> Result<(), Box> { @@ -116,8 +127,12 @@ impl Entry { /// Load Vulkan library at `path` /// /// # Safety + /// /// `dlopen`ing native libraries is inherently unsafe. The safety guidelines /// for [`Library::new()`] and [`Library::get()`] apply here. + /// + /// No Vulkan functions loaded directly or indirectly from this [`Entry`] + /// may be called after it is [dropped][drop()]. #[cfg(feature = "loaded")] #[cfg_attr(docsrs, doc(cfg(feature = "loaded")))] pub unsafe fn load_from(path: impl AsRef) -> Result { @@ -140,8 +155,9 @@ impl Entry { /// Load entry points based on an already-loaded [`vk::StaticFn`] /// /// # Safety - /// `static_fn` must contain valid function pointers that comply with the semantics specified by - /// Vulkan 1.0, which must remain valid for at least the lifetime of the returned [`Entry`]. + /// + /// `static_fn` must contain valid function pointers that comply with the semantics specified + /// by Vulkan 1.0, which must remain valid for at least the lifetime of the returned [`Entry`]. pub unsafe fn from_static_fn(static_fn: vk::StaticFn) -> Self { let load_fn = |name: &std::ffi::CStr| { mem::transmute((static_fn.get_instance_proc_addr)( @@ -176,6 +192,9 @@ impl Entry { } /// + /// + /// # Example + /// /// ```no_run /// # use ash::{Entry, vk}; /// # fn main() -> Result<(), Box> { @@ -217,9 +236,13 @@ impl Entry { /// /// /// # Safety - /// In order for the created [`Instance`] to be valid for the duration of its - /// usage, the [`Entry`](Self) this was called on must be dropped later than the - /// resulting [`Instance`]. + /// + /// The resulting [`Instance`] and any function-pointer objects (e.g. [`Device`][crate::Device] + /// and [extensions][crate::extensions]) loaded from it may not be used after this [`Entry`] + /// object is dropped, unless it was crated using [`Entry::linked()`]. + /// + /// [`Instance`] does _not_ implement [drop][drop()] semantics and can only be destroyed via + /// [`destroy_instance()`][Instance::destroy_instance()]. #[inline] pub unsafe fn create_instance( &self, diff --git a/third_party/rust/ash/src/extensions/ext/full_screen_exclusive.rs b/third_party/rust/ash/src/extensions/ext/full_screen_exclusive.rs index 3cb73cdaeb5c..c5118696d23f 100644 --- a/third_party/rust/ash/src/extensions/ext/full_screen_exclusive.rs +++ b/third_party/rust/ash/src/extensions/ext/full_screen_exclusive.rs @@ -1,9 +1,10 @@ use crate::prelude::*; use crate::vk; -use crate::{Device, Instance}; +use crate::{Device, Entry, Instance}; use std::ffi::CStr; use std::mem; +/// #[derive(Clone)] pub struct FullScreenExclusive { handle: vk::Device, @@ -11,6 +12,13 @@ pub struct FullScreenExclusive { } impl FullScreenExclusive { + /// # Warning + /// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called: + /// - [`Self::get_physical_device_surface_present_modes2()`] + /// + /// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the + /// above [`Instance`] function is called. This will be solved in the next breaking `ash` + /// release: . pub fn new(instance: &Instance, device: &Device) -> Self { let handle = device.handle(); let fp = vk::ExtFullScreenExclusiveFn::load(|name| unsafe { @@ -19,6 +27,19 @@ impl FullScreenExclusive { Self { handle, fp } } + /// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra + /// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be + /// loaded instead of always panicking. See also [`Self::new()`] for more details. + /// + /// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the + /// [`Instance`] function. + pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self { + let fp = vk::ExtFullScreenExclusiveFn::load(|name| unsafe { + mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) + }); + Self { handle: device, fp } + } + /// #[inline] pub unsafe fn acquire_full_screen_exclusive_mode( @@ -29,6 +50,10 @@ impl FullScreenExclusive { } /// + /// + /// # Warning + /// + /// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`]. #[inline] pub unsafe fn get_physical_device_surface_present_modes2( &self, diff --git a/third_party/rust/ash/src/extensions/ext/mod.rs b/third_party/rust/ash/src/extensions/ext/mod.rs index 26a78f77d622..8d4c5a2f240b 100644 --- a/third_party/rust/ash/src/extensions/ext/mod.rs +++ b/third_party/rust/ash/src/extensions/ext/mod.rs @@ -17,8 +17,10 @@ pub use self::image_drm_format_modifier::ImageDrmFormatModifier; pub use self::mesh_shader::MeshShader; pub use self::metal_surface::MetalSurface; pub use self::physical_device_drm::PhysicalDeviceDrm; +pub use self::pipeline_properties::PipelineProperties; pub use self::private_data::PrivateData; pub use self::sample_locations::SampleLocations; +pub use self::shader_object::ShaderObject; pub use self::tooling_info::ToolingInfo; mod acquire_drm_display; @@ -40,6 +42,8 @@ mod image_drm_format_modifier; mod mesh_shader; mod metal_surface; mod physical_device_drm; +mod pipeline_properties; mod private_data; mod sample_locations; +mod shader_object; mod tooling_info; diff --git a/third_party/rust/ash/src/extensions/ext/pipeline_properties.rs b/third_party/rust/ash/src/extensions/ext/pipeline_properties.rs new file mode 100644 index 000000000000..09b6b19e6f06 --- /dev/null +++ b/third_party/rust/ash/src/extensions/ext/pipeline_properties.rs @@ -0,0 +1,52 @@ +use crate::prelude::*; +use crate::vk; +use crate::{Device, Instance}; +use std::ffi::CStr; +use std::mem; + +/// +#[derive(Clone)] +pub struct PipelineProperties { + handle: vk::Device, + fp: vk::ExtPipelinePropertiesFn, +} + +impl PipelineProperties { + pub fn new(instance: &Instance, device: &Device) -> Self { + let handle = device.handle(); + let fp = vk::ExtPipelinePropertiesFn::load(|name| unsafe { + mem::transmute(instance.get_device_proc_addr(handle, name.as_ptr())) + }); + Self { handle, fp } + } + + /// + #[inline] + pub unsafe fn get_pipeline_properties( + &self, + pipeline_info: &vk::PipelineInfoEXT, + pipeline_properties: &mut impl vk::GetPipelinePropertiesEXTParamPipelineProperties, + ) -> VkResult<()> { + (self.fp.get_pipeline_properties_ext)( + self.handle, + pipeline_info, + <*mut _>::cast(pipeline_properties), + ) + .result() + } + + #[inline] + pub const fn name() -> &'static CStr { + vk::ExtPipelinePropertiesFn::name() + } + + #[inline] + pub fn fp(&self) -> &vk::ExtPipelinePropertiesFn { + &self.fp + } + + #[inline] + pub fn device(&self) -> vk::Device { + self.handle + } +} diff --git a/third_party/rust/ash/src/extensions/ext/shader_object.rs b/third_party/rust/ash/src/extensions/ext/shader_object.rs new file mode 100644 index 000000000000..1b5ff3a95fd2 --- /dev/null +++ b/third_party/rust/ash/src/extensions/ext/shader_object.rs @@ -0,0 +1,719 @@ +use crate::prelude::*; +use crate::vk; +use crate::RawPtr; +use crate::{Device, Instance}; +use std::ffi::CStr; +use std::mem; +use std::ptr; + +/// +#[derive(Clone)] +pub struct ShaderObject { + handle: vk::Device, + fp: vk::ExtShaderObjectFn, +} + +impl ShaderObject { + pub fn new(instance: &Instance, device: &Device) -> Self { + let handle = device.handle(); + let fp = vk::ExtShaderObjectFn::load(|name| unsafe { + mem::transmute(instance.get_device_proc_addr(handle, name.as_ptr())) + }); + Self { handle, fp } + } + + /// + #[inline] + pub unsafe fn create_shaders( + &self, + create_infos: &[vk::ShaderCreateInfoEXT], + allocator: Option<&vk::AllocationCallbacks>, + ) -> VkResult> { + let mut shaders = Vec::with_capacity(create_infos.len()); + (self.fp.create_shaders_ext)( + self.handle, + create_infos.len() as u32, + create_infos.as_ptr(), + allocator.as_raw_ptr(), + shaders.as_mut_ptr(), + ) + .result()?; + shaders.set_len(create_infos.len()); + Ok(shaders) + } + + /// + #[inline] + pub unsafe fn destroy_shader( + &self, + shader: vk::ShaderEXT, + allocator: Option<&vk::AllocationCallbacks>, + ) { + (self.fp.destroy_shader_ext)(self.handle, shader, allocator.as_raw_ptr()) + } + + /// + #[inline] + pub unsafe fn get_shader_binary_data(&self, shader: vk::ShaderEXT) -> VkResult> { + read_into_uninitialized_vector(|count, data: *mut u8| { + (self.fp.get_shader_binary_data_ext)(self.handle, shader, count, data.cast()) + }) + } + + /// + #[inline] + pub unsafe fn cmd_bind_shaders( + &self, + command_buffer: vk::CommandBuffer, + stages: &[vk::ShaderStageFlags], + shaders: &[vk::ShaderEXT], + ) { + assert_eq!(stages.len(), shaders.len()); + (self.fp.cmd_bind_shaders_ext)( + command_buffer, + stages.len() as u32, + stages.as_ptr(), + shaders.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_vertex_input( + &self, + command_buffer: vk::CommandBuffer, + vertex_binding_descriptions: &[vk::VertexInputBindingDescription2EXT], + vertex_attribute_descriptions: &[vk::VertexInputAttributeDescription2EXT], + ) { + (self.fp.cmd_set_vertex_input_ext)( + command_buffer, + vertex_binding_descriptions.len() as u32, + vertex_binding_descriptions.as_ptr(), + vertex_attribute_descriptions.len() as u32, + vertex_attribute_descriptions.as_ptr(), + ) + } + + // --- extended_dynamic_state functions --- + + /// + #[inline] + pub unsafe fn cmd_set_cull_mode( + &self, + command_buffer: vk::CommandBuffer, + cull_mode: vk::CullModeFlags, + ) { + (self.fp.cmd_set_cull_mode_ext)(command_buffer, cull_mode) + } + + /// + #[inline] + pub unsafe fn cmd_set_front_face( + &self, + command_buffer: vk::CommandBuffer, + front_face: vk::FrontFace, + ) { + (self.fp.cmd_set_front_face_ext)(command_buffer, front_face) + } + + /// + #[inline] + pub unsafe fn cmd_set_primitive_topology( + &self, + command_buffer: vk::CommandBuffer, + primitive_topology: vk::PrimitiveTopology, + ) { + (self.fp.cmd_set_primitive_topology_ext)(command_buffer, primitive_topology) + } + + /// + #[inline] + pub unsafe fn cmd_set_viewport_with_count( + &self, + command_buffer: vk::CommandBuffer, + viewports: &[vk::Viewport], + ) { + (self.fp.cmd_set_viewport_with_count_ext)( + command_buffer, + viewports.len() as u32, + viewports.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_scissor_with_count( + &self, + command_buffer: vk::CommandBuffer, + scissors: &[vk::Rect2D], + ) { + (self.fp.cmd_set_scissor_with_count_ext)( + command_buffer, + scissors.len() as u32, + scissors.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_bind_vertex_buffers2( + &self, + command_buffer: vk::CommandBuffer, + first_binding: u32, + buffers: &[vk::Buffer], + offsets: &[vk::DeviceSize], + sizes: Option<&[vk::DeviceSize]>, + strides: Option<&[vk::DeviceSize]>, + ) { + assert_eq!(offsets.len(), buffers.len()); + let p_sizes = if let Some(sizes) = sizes { + assert_eq!(sizes.len(), buffers.len()); + sizes.as_ptr() + } else { + ptr::null() + }; + let p_strides = if let Some(strides) = strides { + assert_eq!(strides.len(), buffers.len()); + strides.as_ptr() + } else { + ptr::null() + }; + (self.fp.cmd_bind_vertex_buffers2_ext)( + command_buffer, + first_binding, + buffers.len() as u32, + buffers.as_ptr(), + offsets.as_ptr(), + p_sizes, + p_strides, + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_depth_test_enable( + &self, + command_buffer: vk::CommandBuffer, + depth_test_enable: bool, + ) { + (self.fp.cmd_set_depth_test_enable_ext)(command_buffer, depth_test_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_depth_write_enable( + &self, + command_buffer: vk::CommandBuffer, + depth_write_enable: bool, + ) { + (self.fp.cmd_set_depth_write_enable_ext)(command_buffer, depth_write_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_depth_compare_op( + &self, + command_buffer: vk::CommandBuffer, + depth_compare_op: vk::CompareOp, + ) { + (self.fp.cmd_set_depth_compare_op_ext)(command_buffer, depth_compare_op) + } + + /// + #[inline] + pub unsafe fn cmd_set_depth_bounds_test_enable( + &self, + command_buffer: vk::CommandBuffer, + depth_bounds_test_enable: bool, + ) { + (self.fp.cmd_set_depth_bounds_test_enable_ext)( + command_buffer, + depth_bounds_test_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_stencil_test_enable( + &self, + command_buffer: vk::CommandBuffer, + stencil_test_enable: bool, + ) { + (self.fp.cmd_set_stencil_test_enable_ext)(command_buffer, stencil_test_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_stencil_op( + &self, + command_buffer: vk::CommandBuffer, + face_mask: vk::StencilFaceFlags, + fail_op: vk::StencilOp, + pass_op: vk::StencilOp, + depth_fail_op: vk::StencilOp, + compare_op: vk::CompareOp, + ) { + (self.fp.cmd_set_stencil_op_ext)( + command_buffer, + face_mask, + fail_op, + pass_op, + depth_fail_op, + compare_op, + ) + } + + // --- extended_dynamic_state2 functions --- + + /// + #[inline] + pub unsafe fn cmd_set_patch_control_points( + &self, + command_buffer: vk::CommandBuffer, + patch_control_points: u32, + ) { + (self.fp.cmd_set_patch_control_points_ext)(command_buffer, patch_control_points) + } + + /// + #[inline] + pub unsafe fn cmd_set_rasterizer_discard_enable( + &self, + command_buffer: vk::CommandBuffer, + rasterizer_discard_enable: bool, + ) { + (self.fp.cmd_set_rasterizer_discard_enable_ext)( + command_buffer, + rasterizer_discard_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_depth_bias_enable( + &self, + command_buffer: vk::CommandBuffer, + depth_bias_enable: bool, + ) { + (self.fp.cmd_set_depth_bias_enable_ext)(command_buffer, depth_bias_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_logic_op( + &self, + command_buffer: vk::CommandBuffer, + logic_op: vk::LogicOp, + ) { + (self.fp.cmd_set_logic_op_ext)(command_buffer, logic_op) + } + + /// + #[inline] + pub unsafe fn cmd_set_primitive_restart_enable( + &self, + command_buffer: vk::CommandBuffer, + primitive_restart_enable: bool, + ) { + (self.fp.cmd_set_primitive_restart_enable_ext)( + command_buffer, + primitive_restart_enable.into(), + ) + } + + // --- extended_dynamic_state3 functions --- + + /// + #[inline] + pub unsafe fn cmd_set_tessellation_domain_origin( + &self, + command_buffer: vk::CommandBuffer, + domain_origin: vk::TessellationDomainOrigin, + ) { + (self.fp.cmd_set_tessellation_domain_origin_ext)(command_buffer, domain_origin) + } + + /// + #[inline] + pub unsafe fn cmd_set_depth_clamp_enable( + &self, + command_buffer: vk::CommandBuffer, + depth_clamp_enable: bool, + ) { + (self.fp.cmd_set_depth_clamp_enable_ext)(command_buffer, depth_clamp_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_polygon_mode( + &self, + command_buffer: vk::CommandBuffer, + polygon_mode: vk::PolygonMode, + ) { + (self.fp.cmd_set_polygon_mode_ext)(command_buffer, polygon_mode) + } + + /// + #[inline] + pub unsafe fn cmd_set_rasterization_samples( + &self, + command_buffer: vk::CommandBuffer, + rasterization_samples: vk::SampleCountFlags, + ) { + (self.fp.cmd_set_rasterization_samples_ext)(command_buffer, rasterization_samples) + } + + /// + #[inline] + pub unsafe fn cmd_set_sample_mask( + &self, + command_buffer: vk::CommandBuffer, + samples: vk::SampleCountFlags, + sample_mask: &[vk::SampleMask], + ) { + assert!( + samples.as_raw().is_power_of_two(), + "Only one SampleCount bit must be set" + ); + assert_eq!(samples.as_raw() as usize / 32, sample_mask.len()); + (self.fp.cmd_set_sample_mask_ext)(command_buffer, samples, sample_mask.as_ptr()) + } + + /// + #[inline] + pub unsafe fn cmd_set_alpha_to_coverage_enable( + &self, + command_buffer: vk::CommandBuffer, + alpha_to_coverage_enable: bool, + ) { + (self.fp.cmd_set_alpha_to_coverage_enable_ext)( + command_buffer, + alpha_to_coverage_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_alpha_to_one_enable( + &self, + command_buffer: vk::CommandBuffer, + alpha_to_one_enable: bool, + ) { + (self.fp.cmd_set_alpha_to_one_enable_ext)(command_buffer, alpha_to_one_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_logic_op_enable( + &self, + command_buffer: vk::CommandBuffer, + logic_op_enable: bool, + ) { + (self.fp.cmd_set_logic_op_enable_ext)(command_buffer, logic_op_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_color_blend_enable( + &self, + command_buffer: vk::CommandBuffer, + first_attachment: u32, + color_blend_enables: &[vk::Bool32], + ) { + (self.fp.cmd_set_color_blend_enable_ext)( + command_buffer, + first_attachment, + color_blend_enables.len() as u32, + color_blend_enables.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_color_blend_equation( + &self, + command_buffer: vk::CommandBuffer, + first_attachment: u32, + color_blend_equations: &[vk::ColorBlendEquationEXT], + ) { + (self.fp.cmd_set_color_blend_equation_ext)( + command_buffer, + first_attachment, + color_blend_equations.len() as u32, + color_blend_equations.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_color_write_mask( + &self, + command_buffer: vk::CommandBuffer, + first_attachment: u32, + color_write_masks: &[vk::ColorComponentFlags], + ) { + (self.fp.cmd_set_color_write_mask_ext)( + command_buffer, + first_attachment, + color_write_masks.len() as u32, + color_write_masks.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_rasterization_stream( + &self, + command_buffer: vk::CommandBuffer, + rasterization_stream: u32, + ) { + (self.fp.cmd_set_rasterization_stream_ext)(command_buffer, rasterization_stream) + } + + /// + #[inline] + pub unsafe fn cmd_set_conservative_rasterization_mode( + &self, + command_buffer: vk::CommandBuffer, + conservative_rasterization_mode: vk::ConservativeRasterizationModeEXT, + ) { + (self.fp.cmd_set_conservative_rasterization_mode_ext)( + command_buffer, + conservative_rasterization_mode, + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_extra_primitive_overestimation_size( + &self, + command_buffer: vk::CommandBuffer, + extra_primitive_overestimation_size: f32, + ) { + (self.fp.cmd_set_extra_primitive_overestimation_size_ext)( + command_buffer, + extra_primitive_overestimation_size, + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_depth_clip_enable( + &self, + command_buffer: vk::CommandBuffer, + depth_clip_enable: bool, + ) { + (self.fp.cmd_set_depth_clip_enable_ext)(command_buffer, depth_clip_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_sample_locations_enable( + &self, + command_buffer: vk::CommandBuffer, + sample_locations_enable: bool, + ) { + (self.fp.cmd_set_sample_locations_enable_ext)( + command_buffer, + sample_locations_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_color_blend_advanced( + &self, + command_buffer: vk::CommandBuffer, + first_attachment: u32, + color_blend_advanced: &[vk::ColorBlendAdvancedEXT], + ) { + (self.fp.cmd_set_color_blend_advanced_ext)( + command_buffer, + first_attachment, + color_blend_advanced.len() as u32, + color_blend_advanced.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_provoking_vertex_mode( + &self, + command_buffer: vk::CommandBuffer, + provoking_vertex_mode: vk::ProvokingVertexModeEXT, + ) { + (self.fp.cmd_set_provoking_vertex_mode_ext)(command_buffer, provoking_vertex_mode) + } + + /// + #[inline] + pub unsafe fn cmd_set_line_rasterization_mode( + &self, + command_buffer: vk::CommandBuffer, + line_rasterization_mode: vk::LineRasterizationModeEXT, + ) { + (self.fp.cmd_set_line_rasterization_mode_ext)(command_buffer, line_rasterization_mode) + } + + /// + #[inline] + pub unsafe fn cmd_set_line_stipple_enable( + &self, + command_buffer: vk::CommandBuffer, + stippled_line_enable: bool, + ) { + (self.fp.cmd_set_line_stipple_enable_ext)(command_buffer, stippled_line_enable.into()) + } + + /// + #[inline] + pub unsafe fn cmd_set_depth_clip_negative_one_to_one( + &self, + command_buffer: vk::CommandBuffer, + negative_one_to_one: bool, + ) { + (self.fp.cmd_set_depth_clip_negative_one_to_one_ext)( + command_buffer, + negative_one_to_one.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_viewport_w_scaling_enable_nv( + &self, + command_buffer: vk::CommandBuffer, + viewport_w_scaling_enable: bool, + ) { + (self.fp.cmd_set_viewport_w_scaling_enable_nv)( + command_buffer, + viewport_w_scaling_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_viewport_swizzle_nv( + &self, + command_buffer: vk::CommandBuffer, + first_attachment: u32, + viewport_swizzles: &[vk::ViewportSwizzleNV], + ) { + (self.fp.cmd_set_viewport_swizzle_nv)( + command_buffer, + first_attachment, + viewport_swizzles.len() as u32, + viewport_swizzles.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_coverage_to_color_enable_nv( + &self, + command_buffer: vk::CommandBuffer, + coverage_to_color_enable: bool, + ) { + (self.fp.cmd_set_coverage_to_color_enable_nv)( + command_buffer, + coverage_to_color_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_coverage_to_color_location_nv( + &self, + command_buffer: vk::CommandBuffer, + coverage_to_color_location: u32, + ) { + (self.fp.cmd_set_coverage_to_color_location_nv)(command_buffer, coverage_to_color_location) + } + + /// + #[inline] + pub unsafe fn cmd_set_coverage_modulation_mode_nv( + &self, + command_buffer: vk::CommandBuffer, + coverage_modulation_mode: vk::CoverageModulationModeNV, + ) { + (self.fp.cmd_set_coverage_modulation_mode_nv)(command_buffer, coverage_modulation_mode) + } + + /// + #[inline] + pub unsafe fn cmd_set_coverage_modulation_table_enable_nv( + &self, + command_buffer: vk::CommandBuffer, + coverage_modulation_table_enable: bool, + ) { + (self.fp.cmd_set_coverage_modulation_table_enable_nv)( + command_buffer, + coverage_modulation_table_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_coverage_modulation_table_nv( + &self, + command_buffer: vk::CommandBuffer, + coverage_modulation_table: &[f32], + ) { + (self.fp.cmd_set_coverage_modulation_table_nv)( + command_buffer, + coverage_modulation_table.len() as u32, + coverage_modulation_table.as_ptr(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_shading_rate_image_enable_nv( + &self, + command_buffer: vk::CommandBuffer, + shading_rate_image_enable: bool, + ) { + (self.fp.cmd_set_shading_rate_image_enable_nv)( + command_buffer, + shading_rate_image_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_representative_fragment_test_enable_nv( + &self, + command_buffer: vk::CommandBuffer, + representative_fragment_test_enable: bool, + ) { + (self.fp.cmd_set_representative_fragment_test_enable_nv)( + command_buffer, + representative_fragment_test_enable.into(), + ) + } + + /// + #[inline] + pub unsafe fn cmd_set_coverage_reduction_mode_nv( + &self, + command_buffer: vk::CommandBuffer, + coverage_reduction_mode: vk::CoverageReductionModeNV, + ) { + (self.fp.cmd_set_coverage_reduction_mode_nv)(command_buffer, coverage_reduction_mode) + } + + pub const fn name() -> &'static CStr { + vk::ExtShaderObjectFn::name() + } + + #[inline] + pub fn fp(&self) -> &vk::ExtShaderObjectFn { + &self.fp + } + + #[inline] + pub fn device(&self) -> vk::Device { + self.handle + } +} diff --git a/third_party/rust/ash/src/extensions/khr/device_group.rs b/third_party/rust/ash/src/extensions/khr/device_group.rs index 356db71e4d55..6863b8356563 100644 --- a/third_party/rust/ash/src/extensions/khr/device_group.rs +++ b/third_party/rust/ash/src/extensions/khr/device_group.rs @@ -2,7 +2,7 @@ use super::Swapchain; use crate::prelude::*; use crate::vk; -use crate::{Device, Instance}; +use crate::{Device, Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -14,6 +14,13 @@ pub struct DeviceGroup { } impl DeviceGroup { + /// # Warning + /// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called: + /// - [`Self::get_physical_device_present_rectangles()`] + /// + /// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the + /// above [`Instance`] function is called. This will be solved in the next breaking `ash` + /// release: . pub fn new(instance: &Instance, device: &Device) -> Self { let handle = device.handle(); let fp = vk::KhrDeviceGroupFn::load(|name| unsafe { @@ -22,6 +29,19 @@ impl DeviceGroup { Self { handle, fp } } + /// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra + /// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be + /// loaded instead of always panicking. See also [`Self::new()`] for more details. + /// + /// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the + /// [`Instance`] function. + pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self { + let fp = vk::KhrDeviceGroupFn::load(|name| unsafe { + mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) + }); + Self { handle: device, fp } + } + /// #[inline] pub unsafe fn get_device_group_peer_memory_features( @@ -112,6 +132,10 @@ impl DeviceGroup { /// /// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html /// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html + /// + /// # Warning + /// + /// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`]. #[inline] pub unsafe fn get_physical_device_present_rectangles( &self, diff --git a/third_party/rust/ash/src/extensions/khr/device_group_creation.rs b/third_party/rust/ash/src/extensions/khr/device_group_creation.rs index 9a21a714c921..60f5f337615d 100644 --- a/third_party/rust/ash/src/extensions/khr/device_group_creation.rs +++ b/third_party/rust/ash/src/extensions/khr/device_group_creation.rs @@ -59,8 +59,14 @@ impl DeviceGroupCreation { &self.fp } + #[deprecated = "typo: this function is called `device()`, but returns an `Instance`."] #[inline] pub fn device(&self) -> vk::Instance { self.handle } + + #[inline] + pub fn instance(&self) -> vk::Instance { + self.handle + } } diff --git a/third_party/rust/ash/src/extensions/khr/external_memory_fd.rs b/third_party/rust/ash/src/extensions/khr/external_memory_fd.rs index 902349802f08..77e66c22a7d5 100644 --- a/third_party/rust/ash/src/extensions/khr/external_memory_fd.rs +++ b/third_party/rust/ash/src/extensions/khr/external_memory_fd.rs @@ -21,9 +21,9 @@ impl ExternalMemoryFd { /// #[inline] - pub unsafe fn get_memory_fd(&self, create_info: &vk::MemoryGetFdInfoKHR) -> VkResult { + pub unsafe fn get_memory_fd(&self, get_fd_info: &vk::MemoryGetFdInfoKHR) -> VkResult { let mut fd = -1; - (self.fp.get_memory_fd_khr)(self.handle, create_info, &mut fd).result_with_success(fd) + (self.fp.get_memory_fd_khr)(self.handle, get_fd_info, &mut fd).result_with_success(fd) } /// diff --git a/third_party/rust/ash/src/extensions/khr/maintenance4.rs b/third_party/rust/ash/src/extensions/khr/maintenance4.rs index 003e1a9cf23d..7ec178163611 100644 --- a/third_party/rust/ash/src/extensions/khr/maintenance4.rs +++ b/third_party/rust/ash/src/extensions/khr/maintenance4.rs @@ -22,32 +22,32 @@ impl Maintenance4 { #[inline] pub unsafe fn get_device_buffer_memory_requirements( &self, - create_info: &vk::DeviceBufferMemoryRequirementsKHR, + memory_requirements: &vk::DeviceBufferMemoryRequirementsKHR, out: &mut vk::MemoryRequirements2, ) { - (self.fp.get_device_buffer_memory_requirements_khr)(self.handle, create_info, out) + (self.fp.get_device_buffer_memory_requirements_khr)(self.handle, memory_requirements, out) } /// #[inline] pub unsafe fn get_device_image_memory_requirements( &self, - create_info: &vk::DeviceImageMemoryRequirementsKHR, + memory_requirements: &vk::DeviceImageMemoryRequirementsKHR, out: &mut vk::MemoryRequirements2, ) { - (self.fp.get_device_image_memory_requirements_khr)(self.handle, create_info, out) + (self.fp.get_device_image_memory_requirements_khr)(self.handle, memory_requirements, out) } /// Retrieve the number of elements to pass to [`get_device_image_sparse_memory_requirements()`][Self::get_device_image_sparse_memory_requirements()] #[inline] pub unsafe fn get_device_image_sparse_memory_requirements_len( &self, - create_info: &vk::DeviceImageMemoryRequirementsKHR, + memory_requirements: &vk::DeviceImageMemoryRequirementsKHR, ) -> usize { let mut count = 0; (self.fp.get_device_image_sparse_memory_requirements_khr)( self.handle, - create_info, + memory_requirements, &mut count, std::ptr::null_mut(), ); @@ -61,13 +61,13 @@ impl Maintenance4 { #[inline] pub unsafe fn get_device_image_sparse_memory_requirements( &self, - create_info: &vk::DeviceImageMemoryRequirementsKHR, + memory_requirements: &vk::DeviceImageMemoryRequirementsKHR, out: &mut [vk::SparseImageMemoryRequirements2], ) { let mut count = out.len() as u32; (self.fp.get_device_image_sparse_memory_requirements_khr)( self.handle, - create_info, + memory_requirements, &mut count, out.as_mut_ptr(), ); diff --git a/third_party/rust/ash/src/extensions/khr/mod.rs b/third_party/rust/ash/src/extensions/khr/mod.rs index ea809b43da88..ff84d0dbfe22 100644 --- a/third_party/rust/ash/src/extensions/khr/mod.rs +++ b/third_party/rust/ash/src/extensions/khr/mod.rs @@ -22,6 +22,7 @@ pub use self::get_surface_capabilities2::GetSurfaceCapabilities2; pub use self::maintenance1::Maintenance1; pub use self::maintenance3::Maintenance3; pub use self::maintenance4::Maintenance4; +pub use self::performance_query::PerformanceQuery; pub use self::pipeline_executable_properties::PipelineExecutableProperties; pub use self::present_wait::PresentWait; pub use self::push_descriptor::PushDescriptor; @@ -60,6 +61,7 @@ mod get_surface_capabilities2; mod maintenance1; mod maintenance3; mod maintenance4; +mod performance_query; mod pipeline_executable_properties; mod present_wait; mod push_descriptor; diff --git a/third_party/rust/ash/src/extensions/khr/performance_query.rs b/third_party/rust/ash/src/extensions/khr/performance_query.rs new file mode 100644 index 000000000000..6910b5a1bb69 --- /dev/null +++ b/third_party/rust/ash/src/extensions/khr/performance_query.rs @@ -0,0 +1,121 @@ +use crate::prelude::*; +use crate::vk; +use crate::{Entry, Instance}; +use std::ffi::CStr; +use std::mem; +use std::ptr; + +/// +#[derive(Clone)] +pub struct PerformanceQuery { + handle: vk::Instance, + fp: vk::KhrPerformanceQueryFn, +} + +impl PerformanceQuery { + pub fn new(entry: &Entry, instance: &Instance) -> Self { + let handle = instance.handle(); + let fp = vk::KhrPerformanceQueryFn::load(|name| unsafe { + mem::transmute(entry.get_instance_proc_addr(handle, name.as_ptr())) + }); + Self { handle, fp } + } + + /// Retrieve the number of elements to pass to [`enumerate_physical_device_queue_family_performance_query_counters()`][Self::enumerate_physical_device_queue_family_performance_query_counters()] + #[inline] + pub unsafe fn enumerate_physical_device_queue_family_performance_query_counters_len( + &self, + physical_device: vk::PhysicalDevice, + queue_family_index: u32, + ) -> VkResult { + let mut count = 0; + (self + .fp + .enumerate_physical_device_queue_family_performance_query_counters_khr)( + physical_device, + queue_family_index, + &mut count, + ptr::null_mut(), + ptr::null_mut(), + ) + .result_with_success(count as usize) + } + + /// + /// + /// Call [`enumerate_physical_device_queue_family_performance_query_counters_len()`][Self::enumerate_physical_device_queue_family_performance_query_counters_len()] to query the number of elements to pass to `out_counters` and `out_counter_descriptions`. + /// Be sure to [`Default::default()`]-initialize these elements and optionally set their `p_next` pointer. + #[inline] + pub unsafe fn enumerate_physical_device_queue_family_performance_query_counters( + &self, + physical_device: vk::PhysicalDevice, + queue_family_index: u32, + out_counters: &mut [vk::PerformanceCounterKHR], + out_counter_descriptions: &mut [vk::PerformanceCounterDescriptionKHR], + ) -> VkResult<()> { + assert_eq!(out_counters.len(), out_counter_descriptions.len()); + let mut count = out_counters.len() as u32; + (self + .fp + .enumerate_physical_device_queue_family_performance_query_counters_khr)( + physical_device, + queue_family_index, + &mut count, + out_counters.as_mut_ptr(), + out_counter_descriptions.as_mut_ptr(), + ) + .result()?; + assert_eq!(count as usize, out_counters.len()); + assert_eq!(count as usize, out_counter_descriptions.len()); + Ok(()) + } + + /// + #[inline] + pub unsafe fn get_physical_device_queue_family_performance_query_passes( + &self, + physical_device: vk::PhysicalDevice, + performance_query_create_info: &vk::QueryPoolPerformanceCreateInfoKHR, + ) -> u32 { + let mut num_passes = 0; + (self + .fp + .get_physical_device_queue_family_performance_query_passes_khr)( + physical_device, + performance_query_create_info, + &mut num_passes, + ); + num_passes + } + + /// + #[inline] + pub unsafe fn acquire_profiling_lock( + &self, + device: vk::Device, + info: &vk::AcquireProfilingLockInfoKHR, + ) -> VkResult<()> { + (self.fp.acquire_profiling_lock_khr)(device, info).result() + } + + /// + #[inline] + pub unsafe fn release_profiling_lock(&self, device: vk::Device) { + (self.fp.release_profiling_lock_khr)(device) + } + + #[inline] + pub const fn name() -> &'static CStr { + vk::KhrPerformanceQueryFn::name() + } + + #[inline] + pub fn fp(&self) -> &vk::KhrPerformanceQueryFn { + &self.fp + } + + #[inline] + pub fn instance(&self) -> vk::Instance { + self.handle + } +} diff --git a/third_party/rust/ash/src/extensions/khr/swapchain.rs b/third_party/rust/ash/src/extensions/khr/swapchain.rs index 8f57729de7c6..ee608efd8289 100755 --- a/third_party/rust/ash/src/extensions/khr/swapchain.rs +++ b/third_party/rust/ash/src/extensions/khr/swapchain.rs @@ -3,10 +3,11 @@ use super::DeviceGroup; use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{Device, Instance}; +use crate::{Device, Entry, Instance}; use std::ffi::CStr; use std::mem; +/// #[derive(Clone)] pub struct Swapchain { handle: vk::Device, @@ -14,6 +15,13 @@ pub struct Swapchain { } impl Swapchain { + /// # Warning + /// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called: + /// - [`Self::get_physical_device_present_rectangles()`] + /// + /// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the + /// above [`Instance`] function is called. This will be solved in the next breaking `ash` + /// release: . pub fn new(instance: &Instance, device: &Device) -> Self { let handle = device.handle(); let fp = vk::KhrSwapchainFn::load(|name| unsafe { @@ -22,6 +30,19 @@ impl Swapchain { Self { handle, fp } } + /// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra + /// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be + /// loaded instead of always panicking. See also [`Self::new()`] for more details. + /// + /// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the + /// [`Instance`] function. + pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self { + let fp = vk::KhrSwapchainFn::load(|name| unsafe { + mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) + }); + Self { handle: device, fp } + } + /// #[inline] pub unsafe fn create_swapchain( @@ -153,6 +174,10 @@ impl Swapchain { /// /// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html /// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html + /// + /// # Warning + /// + /// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`]. #[inline] pub unsafe fn get_physical_device_present_rectangles( &self, diff --git a/third_party/rust/ash/src/instance.rs b/third_party/rust/ash/src/instance.rs index 8e3bd1a8b9b4..da3ef99e1422 100644 --- a/third_party/rust/ash/src/instance.rs +++ b/third_party/rust/ash/src/instance.rs @@ -1,3 +1,5 @@ +#[cfg(doc)] +use super::Entry; use crate::device::Device; use crate::prelude::*; use crate::vk; @@ -335,9 +337,17 @@ impl Instance { /// /// /// # Safety - /// In order for the created [`Device`] to be valid for the duration of its - /// usage, the [`Instance`] this was called on must be dropped later than the - /// resulting [`Device`]. + /// + /// There is a [parent/child relation] between [`Instance`] and the resulting [`Device`]. The + /// application must not [destroy][Instance::destroy_instance()] the parent [`Instance`] object + /// before first [destroying][Device::destroy_device()] the returned [`Device`] child object. + /// [`Device`] does _not_ implement [drop][drop()] semantics and can only be destroyed via + /// [`destroy_device()`][Device::destroy_device()]. + /// + /// See the [`Entry::create_instance()`] documentation for more destruction ordering rules on + /// [`Instance`]. + /// + /// [parent/child relation]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#fundamentals-objectmodel-lifetime #[inline] pub unsafe fn create_device( &self, diff --git a/third_party/rust/ash/src/prelude.rs b/third_party/rust/ash/src/prelude.rs index 321c3aadddb1..e43480326037 100644 --- a/third_party/rust/ash/src/prelude.rs +++ b/third_party/rust/ash/src/prelude.rs @@ -26,13 +26,12 @@ impl vk::Result { } } -/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, -/// ensuring all available data has been read into the vector. +/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, ensuring all +/// available data has been read into the vector. /// -/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available -/// items may change between calls; [`vk::Result::INCOMPLETE`] is returned when the count -/// increased (and the vector is not large enough after querying the initial size), -/// requiring Ash to try again. +/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available items may +/// change between calls; [`vk::Result::INCOMPLETE`] is returned when the count increased (and the +/// vector is not large enough after querying the initial size), requiring Ash to try again. /// /// [`vkEnumerateInstanceExtensionProperties`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceExtensionProperties.html pub(crate) unsafe fn read_into_uninitialized_vector, T>( @@ -56,18 +55,17 @@ where } } -/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, -/// ensuring all available data has been read into the vector. +/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, ensuring all +/// available data has been read into the vector. /// -/// Items in the target vector are [`default()`][`Default::default()`]-initialized which -/// is required for [`vk::BaseOutStructure`]-like structs where [`vk::BaseOutStructure::s_type`] -/// needs to be a valid type and [`vk::BaseOutStructure::p_next`] a valid or -/// [`null`][`std::ptr::null_mut()`] pointer. +/// Items in the target vector are [`default()`][Default::default()]-initialized which is required +/// for [`vk::BaseOutStructure`]-like structs where [`vk::BaseOutStructure::s_type`] needs to be a +/// valid type and [`vk::BaseOutStructure::p_next`] a valid or [`null`][std::ptr::null_mut()] +/// pointer. /// -/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available -/// items may change between calls; [`vk::Result::INCOMPLETE`] is returned when the count -/// increased (and the vector is not large enough after querying the initial size), -/// requiring Ash to try again. +/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available items may +/// change between calls; [`vk::Result::INCOMPLETE`] is returned when the count increased (and the +/// vector is not large enough after querying the initial size), requiring Ash to try again. /// /// [`vkEnumerateInstanceExtensionProperties`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceExtensionProperties.html pub(crate) unsafe fn read_into_defaulted_vector< @@ -116,7 +114,7 @@ pub(crate) fn debug_flags + Copy>( if !first { f.write_str(" | ")?; } - write!(f, "{:b}", accum)?; + write!(f, "{accum:b}")?; } Ok(()) } diff --git a/third_party/rust/ash/src/util.rs b/third_party/rust/ash/src/util.rs index 119fab9c65d1..9827617ef0c0 100644 --- a/third_party/rust/ash/src/util.rs +++ b/third_party/rust/ash/src/util.rs @@ -104,7 +104,9 @@ impl<'a, T: Copy + 'a> Iterator for AlignIter<'a, T> { /// let words = ash::util::read_spv(&mut std::io::Cursor::new(&SPIRV[..])).unwrap(); /// ``` pub fn read_spv(x: &mut R) -> io::Result> { + // TODO use stream_len() once it is stabilized and remove the subsequent rewind() call let size = x.seek(io::SeekFrom::End(0))?; + x.rewind()?; if size % 4 != 0 { return Err(io::Error::new( io::ErrorKind::InvalidData, @@ -119,7 +121,6 @@ pub fn read_spv(x: &mut R) -> io::Result> { // Zero-initialize the result to prevent read_exact from possibly // reading uninitialized memory. let mut result = vec![0u32; words]; - x.seek(io::SeekFrom::Start(0))?; x.read_exact(unsafe { slice::from_raw_parts_mut(result.as_mut_ptr().cast::(), words * 4) })?; diff --git a/third_party/rust/ash/src/vk/aliases.rs b/third_party/rust/ash/src/vk/aliases.rs index 1e5d20fe2350..7eb57b749150 100644 --- a/third_party/rust/ash/src/vk/aliases.rs +++ b/third_party/rust/ash/src/vk/aliases.rs @@ -200,6 +200,8 @@ pub type PhysicalDeviceSubgroupSizeControlPropertiesEXT = PhysicalDeviceSubgroupSizeControlProperties; pub type PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT = PipelineShaderStageRequiredSubgroupSizeCreateInfo; +pub type ShaderRequiredSubgroupSizeCreateInfoEXT = + PipelineShaderStageRequiredSubgroupSizeCreateInfo; pub type MemoryOpaqueCaptureAddressAllocateInfoKHR = MemoryOpaqueCaptureAddressAllocateInfo; pub type DeviceMemoryOpaqueCaptureAddressInfoKHR = DeviceMemoryOpaqueCaptureAddressInfo; pub type PhysicalDevicePipelineCreationCacheControlFeaturesEXT = diff --git a/third_party/rust/ash/src/vk/bitflags.rs b/third_party/rust/ash/src/vk/bitflags.rs index 66699d721410..b3a5af920586 100644 --- a/third_party/rust/ash/src/vk/bitflags.rs +++ b/third_party/rust/ash/src/vk/bitflags.rs @@ -1280,13 +1280,23 @@ impl VideoEncodeCapabilityFlagsKHR { } #[repr(transparent)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[doc = ""] +pub struct VideoEncodeFeedbackFlagsKHR(pub(crate) Flags); +vk_bitflags_wrapped!(VideoEncodeFeedbackFlagsKHR, Flags); +impl VideoEncodeFeedbackFlagsKHR { + pub const BITSTREAM_BUFFER_OFFSET: Self = Self(0b1); + pub const BITSTREAM_BYTES_WRITTEN: Self = Self(0b10); +} +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[doc = ""] pub struct VideoEncodeRateControlModeFlagsKHR(pub(crate) Flags); vk_bitflags_wrapped!(VideoEncodeRateControlModeFlagsKHR, Flags); impl VideoEncodeRateControlModeFlagsKHR { - pub const NONE: Self = Self(0); - pub const CBR: Self = Self(1); - pub const VBR: Self = Self(2); + pub const DEFAULT: Self = Self(0); + pub const DISABLED: Self = Self(0b1); + pub const CBR: Self = Self(0b10); + pub const VBR: Self = Self(0b100); } #[repr(transparent)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -1319,26 +1329,7 @@ impl VideoEncodeH264CapabilityFlagsEXT { pub const ROW_UNALIGNED_SLICE: Self = Self(0b100_0000_0000_0000_0000_0000); pub const DIFFERENT_SLICE_TYPE: Self = Self(0b1000_0000_0000_0000_0000_0000); pub const B_FRAME_IN_L1_LIST: Self = Self(0b1_0000_0000_0000_0000_0000_0000); -} -#[repr(transparent)] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[doc = ""] -pub struct VideoEncodeH264InputModeFlagsEXT(pub(crate) Flags); -vk_bitflags_wrapped!(VideoEncodeH264InputModeFlagsEXT, Flags); -impl VideoEncodeH264InputModeFlagsEXT { - pub const FRAME: Self = Self(0b1); - pub const SLICE: Self = Self(0b10); - pub const NON_VCL: Self = Self(0b100); -} -#[repr(transparent)] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[doc = ""] -pub struct VideoEncodeH264OutputModeFlagsEXT(pub(crate) Flags); -vk_bitflags_wrapped!(VideoEncodeH264OutputModeFlagsEXT, Flags); -impl VideoEncodeH264OutputModeFlagsEXT { - pub const FRAME: Self = Self(0b1); - pub const SLICE: Self = Self(0b10); - pub const NON_VCL: Self = Self(0b100); + pub const DIFFERENT_REFERENCE_FINAL_LISTS: Self = Self(0b10_0000_0000_0000_0000_0000_0000); } #[repr(transparent)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -1474,26 +1465,7 @@ impl VideoEncodeH265CapabilityFlagsEXT { pub const DEPENDENT_SLICE_SEGMENT: Self = Self(0b1000_0000_0000_0000_0000_0000); pub const DIFFERENT_SLICE_TYPE: Self = Self(0b1_0000_0000_0000_0000_0000_0000); pub const B_FRAME_IN_L1_LIST: Self = Self(0b10_0000_0000_0000_0000_0000_0000); -} -#[repr(transparent)] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[doc = ""] -pub struct VideoEncodeH265InputModeFlagsEXT(pub(crate) Flags); -vk_bitflags_wrapped!(VideoEncodeH265InputModeFlagsEXT, Flags); -impl VideoEncodeH265InputModeFlagsEXT { - pub const FRAME: Self = Self(0b1); - pub const SLICE_SEGMENT: Self = Self(0b10); - pub const NON_VCL: Self = Self(0b100); -} -#[repr(transparent)] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[doc = ""] -pub struct VideoEncodeH265OutputModeFlagsEXT(pub(crate) Flags); -vk_bitflags_wrapped!(VideoEncodeH265OutputModeFlagsEXT, Flags); -impl VideoEncodeH265OutputModeFlagsEXT { - pub const FRAME: Self = Self(0b1); - pub const SLICE_SEGMENT: Self = Self(0b10); - pub const NON_VCL: Self = Self(0b100); + pub const DIFFERENT_REFERENCE_FINAL_LISTS: Self = Self(0b100_0000_0000_0000_0000_0000_0000); } #[repr(transparent)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -1641,3 +1613,11 @@ vk_bitflags_wrapped!(MicromapCreateFlagsEXT, Flags); impl MicromapCreateFlagsEXT { pub const DEVICE_ADDRESS_CAPTURE_REPLAY: Self = Self(0b1); } +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[doc = ""] +pub struct ShaderCreateFlagsEXT(pub(crate) Flags); +vk_bitflags_wrapped!(ShaderCreateFlagsEXT, Flags); +impl ShaderCreateFlagsEXT { + pub const LINK_STAGE: Self = Self(0b1); +} diff --git a/third_party/rust/ash/src/vk/const_debugs.rs b/third_party/rust/ash/src/vk/const_debugs.rs index 6508306e3020..04ba6415d336 100644 --- a/third_party/rust/ash/src/vk/const_debugs.rs +++ b/third_party/rust/ash/src/vk/const_debugs.rs @@ -318,11 +318,15 @@ impl fmt::Debug for AccessFlags2 { ), (AccessFlags2::MICROMAP_READ_EXT.0, "MICROMAP_READ_EXT"), (AccessFlags2::MICROMAP_WRITE_EXT.0, "MICROMAP_WRITE_EXT"), + (AccessFlags2::RESERVED_49_ARM.0, "RESERVED_49_ARM"), + (AccessFlags2::RESERVED_50_ARM.0, "RESERVED_50_ARM"), (AccessFlags2::OPTICAL_FLOW_READ_NV.0, "OPTICAL_FLOW_READ_NV"), ( AccessFlags2::OPTICAL_FLOW_WRITE_NV.0, "OPTICAL_FLOW_WRITE_NV", ), + (AccessFlags2::RESERVED_47_EXT.0, "RESERVED_47_EXT"), + (AccessFlags2::RESERVED_48_EXT.0, "RESERVED_48_EXT"), ]; debug_flags(f, KNOWN, self.0) } @@ -515,6 +519,7 @@ impl fmt::Debug for BufferCreateFlags { BufferCreateFlags::DESCRIPTOR_BUFFER_CAPTURE_REPLAY_EXT.0, "DESCRIPTOR_BUFFER_CAPTURE_REPLAY_EXT", ), + (BufferCreateFlags::RESERVED_6_KHR.0, "RESERVED_6_KHR"), (BufferCreateFlags::PROTECTED.0, "PROTECTED"), ( BufferCreateFlags::DEVICE_ADDRESS_CAPTURE_REPLAY.0, @@ -655,12 +660,12 @@ impl fmt::Debug for BuildAccelerationStructureFlagsKHR { "ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT", ), ( - BuildAccelerationStructureFlagsKHR::RESERVED_9_NV.0, - "RESERVED_9_NV", + BuildAccelerationStructureFlagsKHR::ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV.0, + "ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV", ), ( - BuildAccelerationStructureFlagsKHR::RESERVED_10_NV.0, - "RESERVED_10_NV", + BuildAccelerationStructureFlagsKHR::ALLOW_DATA_ACCESS.0, + "ALLOW_DATA_ACCESS", ), ]; debug_flags(f, KNOWN, self.0) @@ -1204,6 +1209,10 @@ impl fmt::Debug for DescriptorSetLayoutCreateFlags { DescriptorSetLayoutCreateFlags::HOST_ONLY_POOL_EXT.0, "HOST_ONLY_POOL_EXT", ), + ( + DescriptorSetLayoutCreateFlags::RESERVED_6_EXT.0, + "RESERVED_6_EXT", + ), ( DescriptorSetLayoutCreateFlags::UPDATE_AFTER_BIND_POOL.0, "UPDATE_AFTER_BIND_POOL", @@ -1444,6 +1453,21 @@ impl fmt::Debug for DiscardRectangleModeEXT { } } } +impl fmt::Debug for DisplacementMicromapFormatNV { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let name = match *self { + Self::TYPE_64_TRIANGLES_64_BYTES => Some("TYPE_64_TRIANGLES_64_BYTES"), + Self::TYPE_256_TRIANGLES_128_BYTES => Some("TYPE_256_TRIANGLES_128_BYTES"), + Self::TYPE_1024_TRIANGLES_128_BYTES => Some("TYPE_1024_TRIANGLES_128_BYTES"), + _ => None, + }; + if let Some(x) = name { + f.write_str(x) + } else { + self.0.fmt(f) + } + } +} impl fmt::Debug for DisplayEventTypeEXT { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let name = match *self { @@ -1525,6 +1549,7 @@ impl fmt::Debug for DriverId { Self::MESA_VENUS => Some("MESA_VENUS"), Self::MESA_DOZEN => Some("MESA_DOZEN"), Self::MESA_NVK => Some("MESA_NVK"), + Self::IMAGINATION_OPEN_SOURCE_MESA => Some("IMAGINATION_OPEN_SOURCE_MESA"), _ => None, }; if let Some(x) = name { @@ -1548,12 +1573,15 @@ impl fmt::Debug for DynamicState { Self::STENCIL_REFERENCE => Some("STENCIL_REFERENCE"), Self::VIEWPORT_W_SCALING_NV => Some("VIEWPORT_W_SCALING_NV"), Self::DISCARD_RECTANGLE_EXT => Some("DISCARD_RECTANGLE_EXT"), + Self::DISCARD_RECTANGLE_ENABLE_EXT => Some("DISCARD_RECTANGLE_ENABLE_EXT"), + Self::DISCARD_RECTANGLE_MODE_EXT => Some("DISCARD_RECTANGLE_MODE_EXT"), Self::SAMPLE_LOCATIONS_EXT => Some("SAMPLE_LOCATIONS_EXT"), Self::RAY_TRACING_PIPELINE_STACK_SIZE_KHR => { Some("RAY_TRACING_PIPELINE_STACK_SIZE_KHR") } Self::VIEWPORT_SHADING_RATE_PALETTE_NV => Some("VIEWPORT_SHADING_RATE_PALETTE_NV"), Self::VIEWPORT_COARSE_SAMPLE_ORDER_NV => Some("VIEWPORT_COARSE_SAMPLE_ORDER_NV"), + Self::EXCLUSIVE_SCISSOR_ENABLE_NV => Some("EXCLUSIVE_SCISSOR_ENABLE_NV"), Self::EXCLUSIVE_SCISSOR_NV => Some("EXCLUSIVE_SCISSOR_NV"), Self::FRAGMENT_SHADING_RATE_KHR => Some("FRAGMENT_SHADING_RATE_KHR"), Self::LINE_STIPPLE_EXT => Some("LINE_STIPPLE_EXT"), @@ -1600,6 +1628,9 @@ impl fmt::Debug for DynamicState { Some("REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV") } Self::COVERAGE_REDUCTION_MODE_NV => Some("COVERAGE_REDUCTION_MODE_NV"), + Self::ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT => { + Some("ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT") + } Self::CULL_MODE => Some("CULL_MODE"), Self::FRONT_FACE => Some("FRONT_FACE"), Self::PRIMITIVE_TOPOLOGY => Some("PRIMITIVE_TOPOLOGY"), @@ -1680,14 +1711,6 @@ impl fmt::Debug for ExternalFenceHandleTypeFlags { "OPAQUE_WIN32_KMT", ), (ExternalFenceHandleTypeFlags::SYNC_FD.0, "SYNC_FD"), - ( - ExternalFenceHandleTypeFlags::RESERVED_4_NV.0, - "RESERVED_4_NV", - ), - ( - ExternalFenceHandleTypeFlags::RESERVED_5_NV.0, - "RESERVED_5_NV", - ), ]; debug_flags(f, KNOWN, self.0) } @@ -1765,8 +1788,8 @@ impl fmt::Debug for ExternalMemoryHandleTypeFlags { "RDMA_ADDRESS_NV", ), ( - ExternalMemoryHandleTypeFlags::RESERVED_13_NV.0, - "RESERVED_13_NV", + ExternalMemoryHandleTypeFlags::TYPE_530_QNX.0, + "TYPE_530_QNX", ), ]; debug_flags(f, KNOWN, self.0) @@ -1825,10 +1848,6 @@ impl fmt::Debug for ExternalSemaphoreHandleTypeFlags { ExternalSemaphoreHandleTypeFlags::ZIRCON_EVENT_FUCHSIA.0, "ZIRCON_EVENT_FUCHSIA", ), - ( - ExternalSemaphoreHandleTypeFlags::RESERVED_5_NV.0, - "RESERVED_5_NV", - ), ]; debug_flags(f, KNOWN, self.0) } @@ -2190,7 +2209,7 @@ impl fmt::Debug for FormatFeatureFlags { } impl fmt::Debug for FormatFeatureFlags2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - const KNOWN : & [(Flags64 , & str)] = & [(FormatFeatureFlags2 :: SAMPLED_IMAGE . 0 , "SAMPLED_IMAGE") , (FormatFeatureFlags2 :: STORAGE_IMAGE . 0 , "STORAGE_IMAGE") , (FormatFeatureFlags2 :: STORAGE_IMAGE_ATOMIC . 0 , "STORAGE_IMAGE_ATOMIC") , (FormatFeatureFlags2 :: UNIFORM_TEXEL_BUFFER . 0 , "UNIFORM_TEXEL_BUFFER") , (FormatFeatureFlags2 :: STORAGE_TEXEL_BUFFER . 0 , "STORAGE_TEXEL_BUFFER") , (FormatFeatureFlags2 :: STORAGE_TEXEL_BUFFER_ATOMIC . 0 , "STORAGE_TEXEL_BUFFER_ATOMIC") , (FormatFeatureFlags2 :: VERTEX_BUFFER . 0 , "VERTEX_BUFFER") , (FormatFeatureFlags2 :: COLOR_ATTACHMENT . 0 , "COLOR_ATTACHMENT") , (FormatFeatureFlags2 :: COLOR_ATTACHMENT_BLEND . 0 , "COLOR_ATTACHMENT_BLEND") , (FormatFeatureFlags2 :: DEPTH_STENCIL_ATTACHMENT . 0 , "DEPTH_STENCIL_ATTACHMENT") , (FormatFeatureFlags2 :: BLIT_SRC . 0 , "BLIT_SRC") , (FormatFeatureFlags2 :: BLIT_DST . 0 , "BLIT_DST") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_LINEAR . 0 , "SAMPLED_IMAGE_FILTER_LINEAR") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_CUBIC . 0 , "SAMPLED_IMAGE_FILTER_CUBIC") , (FormatFeatureFlags2 :: TRANSFER_SRC . 0 , "TRANSFER_SRC") , (FormatFeatureFlags2 :: TRANSFER_DST . 0 , "TRANSFER_DST") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_MINMAX . 0 , "SAMPLED_IMAGE_FILTER_MINMAX") , (FormatFeatureFlags2 :: MIDPOINT_CHROMA_SAMPLES . 0 , "MIDPOINT_CHROMA_SAMPLES") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE") , (FormatFeatureFlags2 :: DISJOINT . 0 , "DISJOINT") , (FormatFeatureFlags2 :: COSITED_CHROMA_SAMPLES . 0 , "COSITED_CHROMA_SAMPLES") , (FormatFeatureFlags2 :: STORAGE_READ_WITHOUT_FORMAT . 0 , "STORAGE_READ_WITHOUT_FORMAT") , (FormatFeatureFlags2 :: STORAGE_WRITE_WITHOUT_FORMAT . 0 , "STORAGE_WRITE_WITHOUT_FORMAT") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_DEPTH_COMPARISON . 0 , "SAMPLED_IMAGE_DEPTH_COMPARISON") , (FormatFeatureFlags2 :: VIDEO_DECODE_OUTPUT_KHR . 0 , "VIDEO_DECODE_OUTPUT_KHR") , (FormatFeatureFlags2 :: VIDEO_DECODE_DPB_KHR . 0 , "VIDEO_DECODE_DPB_KHR") , (FormatFeatureFlags2 :: ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR . 0 , "ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR") , (FormatFeatureFlags2 :: FRAGMENT_DENSITY_MAP_EXT . 0 , "FRAGMENT_DENSITY_MAP_EXT") , (FormatFeatureFlags2 :: FRAGMENT_SHADING_RATE_ATTACHMENT_KHR . 0 , "FRAGMENT_SHADING_RATE_ATTACHMENT_KHR") , (FormatFeatureFlags2 :: RESERVED_44_EXT . 0 , "RESERVED_44_EXT") , (FormatFeatureFlags2 :: RESERVED_45_EXT . 0 , "RESERVED_45_EXT") , (FormatFeatureFlags2 :: VIDEO_ENCODE_INPUT_KHR . 0 , "VIDEO_ENCODE_INPUT_KHR") , (FormatFeatureFlags2 :: VIDEO_ENCODE_DPB_KHR . 0 , "VIDEO_ENCODE_DPB_KHR") , (FormatFeatureFlags2 :: LINEAR_COLOR_ATTACHMENT_NV . 0 , "LINEAR_COLOR_ATTACHMENT_NV") , (FormatFeatureFlags2 :: WEIGHT_IMAGE_QCOM . 0 , "WEIGHT_IMAGE_QCOM") , (FormatFeatureFlags2 :: WEIGHT_SAMPLED_IMAGE_QCOM . 0 , "WEIGHT_SAMPLED_IMAGE_QCOM") , (FormatFeatureFlags2 :: BLOCK_MATCHING_QCOM . 0 , "BLOCK_MATCHING_QCOM") , (FormatFeatureFlags2 :: BOX_FILTER_SAMPLED_QCOM . 0 , "BOX_FILTER_SAMPLED_QCOM") , (FormatFeatureFlags2 :: RESERVED_39_EXT . 0 , "RESERVED_39_EXT") , (FormatFeatureFlags2 :: OPTICAL_FLOW_IMAGE_NV . 0 , "OPTICAL_FLOW_IMAGE_NV") , (FormatFeatureFlags2 :: OPTICAL_FLOW_VECTOR_NV . 0 , "OPTICAL_FLOW_VECTOR_NV") , (FormatFeatureFlags2 :: OPTICAL_FLOW_COST_NV . 0 , "OPTICAL_FLOW_COST_NV")] ; + const KNOWN : & [(Flags64 , & str)] = & [(FormatFeatureFlags2 :: SAMPLED_IMAGE . 0 , "SAMPLED_IMAGE") , (FormatFeatureFlags2 :: STORAGE_IMAGE . 0 , "STORAGE_IMAGE") , (FormatFeatureFlags2 :: STORAGE_IMAGE_ATOMIC . 0 , "STORAGE_IMAGE_ATOMIC") , (FormatFeatureFlags2 :: UNIFORM_TEXEL_BUFFER . 0 , "UNIFORM_TEXEL_BUFFER") , (FormatFeatureFlags2 :: STORAGE_TEXEL_BUFFER . 0 , "STORAGE_TEXEL_BUFFER") , (FormatFeatureFlags2 :: STORAGE_TEXEL_BUFFER_ATOMIC . 0 , "STORAGE_TEXEL_BUFFER_ATOMIC") , (FormatFeatureFlags2 :: VERTEX_BUFFER . 0 , "VERTEX_BUFFER") , (FormatFeatureFlags2 :: COLOR_ATTACHMENT . 0 , "COLOR_ATTACHMENT") , (FormatFeatureFlags2 :: COLOR_ATTACHMENT_BLEND . 0 , "COLOR_ATTACHMENT_BLEND") , (FormatFeatureFlags2 :: DEPTH_STENCIL_ATTACHMENT . 0 , "DEPTH_STENCIL_ATTACHMENT") , (FormatFeatureFlags2 :: BLIT_SRC . 0 , "BLIT_SRC") , (FormatFeatureFlags2 :: BLIT_DST . 0 , "BLIT_DST") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_LINEAR . 0 , "SAMPLED_IMAGE_FILTER_LINEAR") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_CUBIC . 0 , "SAMPLED_IMAGE_FILTER_CUBIC") , (FormatFeatureFlags2 :: TRANSFER_SRC . 0 , "TRANSFER_SRC") , (FormatFeatureFlags2 :: TRANSFER_DST . 0 , "TRANSFER_DST") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_FILTER_MINMAX . 0 , "SAMPLED_IMAGE_FILTER_MINMAX") , (FormatFeatureFlags2 :: MIDPOINT_CHROMA_SAMPLES . 0 , "MIDPOINT_CHROMA_SAMPLES") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE . 0 , "SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE") , (FormatFeatureFlags2 :: DISJOINT . 0 , "DISJOINT") , (FormatFeatureFlags2 :: COSITED_CHROMA_SAMPLES . 0 , "COSITED_CHROMA_SAMPLES") , (FormatFeatureFlags2 :: STORAGE_READ_WITHOUT_FORMAT . 0 , "STORAGE_READ_WITHOUT_FORMAT") , (FormatFeatureFlags2 :: STORAGE_WRITE_WITHOUT_FORMAT . 0 , "STORAGE_WRITE_WITHOUT_FORMAT") , (FormatFeatureFlags2 :: SAMPLED_IMAGE_DEPTH_COMPARISON . 0 , "SAMPLED_IMAGE_DEPTH_COMPARISON") , (FormatFeatureFlags2 :: VIDEO_DECODE_OUTPUT_KHR . 0 , "VIDEO_DECODE_OUTPUT_KHR") , (FormatFeatureFlags2 :: VIDEO_DECODE_DPB_KHR . 0 , "VIDEO_DECODE_DPB_KHR") , (FormatFeatureFlags2 :: ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR . 0 , "ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR") , (FormatFeatureFlags2 :: FRAGMENT_DENSITY_MAP_EXT . 0 , "FRAGMENT_DENSITY_MAP_EXT") , (FormatFeatureFlags2 :: FRAGMENT_SHADING_RATE_ATTACHMENT_KHR . 0 , "FRAGMENT_SHADING_RATE_ATTACHMENT_KHR") , (FormatFeatureFlags2 :: RESERVED_44_EXT . 0 , "RESERVED_44_EXT") , (FormatFeatureFlags2 :: RESERVED_45_EXT . 0 , "RESERVED_45_EXT") , (FormatFeatureFlags2 :: RESERVED_46_EXT . 0 , "RESERVED_46_EXT") , (FormatFeatureFlags2 :: VIDEO_ENCODE_INPUT_KHR . 0 , "VIDEO_ENCODE_INPUT_KHR") , (FormatFeatureFlags2 :: VIDEO_ENCODE_DPB_KHR . 0 , "VIDEO_ENCODE_DPB_KHR") , (FormatFeatureFlags2 :: LINEAR_COLOR_ATTACHMENT_NV . 0 , "LINEAR_COLOR_ATTACHMENT_NV") , (FormatFeatureFlags2 :: WEIGHT_IMAGE_QCOM . 0 , "WEIGHT_IMAGE_QCOM") , (FormatFeatureFlags2 :: WEIGHT_SAMPLED_IMAGE_QCOM . 0 , "WEIGHT_SAMPLED_IMAGE_QCOM") , (FormatFeatureFlags2 :: BLOCK_MATCHING_QCOM . 0 , "BLOCK_MATCHING_QCOM") , (FormatFeatureFlags2 :: BOX_FILTER_SAMPLED_QCOM . 0 , "BOX_FILTER_SAMPLED_QCOM") , (FormatFeatureFlags2 :: RESERVED_39_EXT . 0 , "RESERVED_39_EXT") , (FormatFeatureFlags2 :: OPTICAL_FLOW_IMAGE_NV . 0 , "OPTICAL_FLOW_IMAGE_NV") , (FormatFeatureFlags2 :: OPTICAL_FLOW_VECTOR_NV . 0 , "OPTICAL_FLOW_VECTOR_NV") , (FormatFeatureFlags2 :: OPTICAL_FLOW_COST_NV . 0 , "OPTICAL_FLOW_COST_NV")] ; debug_flags(f, KNOWN, self.0) } } @@ -2546,6 +2565,7 @@ impl fmt::Debug for ImageCreateFlags { ImageCreateFlags::FRAGMENT_DENSITY_MAP_OFFSET_QCOM.0, "FRAGMENT_DENSITY_MAP_OFFSET_QCOM", ), + (ImageCreateFlags::RESERVED_20_KHR.0, "RESERVED_20_KHR"), (ImageCreateFlags::ALIAS.0, "ALIAS"), ( ImageCreateFlags::SPLIT_INSTANCE_BIND_REGIONS.0, @@ -2721,6 +2741,7 @@ impl fmt::Debug for ImageUsageFlags { ImageUsageFlags::SAMPLE_BLOCK_MATCH_QCOM.0, "SAMPLE_BLOCK_MATCH_QCOM", ), + (ImageUsageFlags::RESERVED_23_EXT.0, "RESERVED_23_EXT"), ]; debug_flags(f, KNOWN, self.0) } @@ -2740,7 +2761,6 @@ impl fmt::Debug for ImageViewCreateFlags { ImageViewCreateFlags::FRAGMENT_DENSITY_MAP_DEFERRED_EXT.0, "FRAGMENT_DENSITY_MAP_DEFERRED_EXT", ), - (ImageViewCreateFlags::RESERVED_3_EXT.0, "RESERVED_3_EXT"), ]; debug_flags(f, KNOWN, self.0) } @@ -2925,7 +2945,6 @@ impl fmt::Debug for MemoryHeapFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { const KNOWN: &[(Flags, &str)] = &[ (MemoryHeapFlags::DEVICE_LOCAL.0, "DEVICE_LOCAL"), - (MemoryHeapFlags::RESERVED_2_KHR.0, "RESERVED_2_KHR"), (MemoryHeapFlags::MULTI_INSTANCE.0, "MULTI_INSTANCE"), ]; debug_flags(f, KNOWN, self.0) @@ -2974,6 +2993,12 @@ impl fmt::Debug for MemoryPropertyFlags { debug_flags(f, KNOWN, self.0) } } +impl fmt::Debug for MemoryUnmapFlagsKHR { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + const KNOWN: &[(Flags, &str)] = &[]; + debug_flags(f, KNOWN, self.0) + } +} impl fmt::Debug for MetalSurfaceCreateFlagsEXT { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { const KNOWN: &[(Flags, &str)] = &[]; @@ -2993,6 +3018,7 @@ impl fmt::Debug for MicromapTypeEXT { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let name = match *self { Self::OPACITY_MICROMAP => Some("OPACITY_MICROMAP"), + Self::DISPLACEMENT_MICROMAP_NV => Some("DISPLACEMENT_MICROMAP_NV"), _ => None, }; if let Some(x) = name { @@ -3307,14 +3333,10 @@ impl fmt::Debug for PipelineBindPoint { } impl fmt::Debug for PipelineCacheCreateFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - const KNOWN: &[(Flags, &str)] = &[ - (PipelineCacheCreateFlags::RESERVED_1_EXT.0, "RESERVED_1_EXT"), - (PipelineCacheCreateFlags::RESERVED_2_KHR.0, "RESERVED_2_KHR"), - ( - PipelineCacheCreateFlags::EXTERNALLY_SYNCHRONIZED.0, - "EXTERNALLY_SYNCHRONIZED", - ), - ]; + const KNOWN: &[(Flags, &str)] = &[( + PipelineCacheCreateFlags::EXTERNALLY_SYNCHRONIZED.0, + "EXTERNALLY_SYNCHRONIZED", + )]; debug_flags(f, KNOWN, self.0) } } @@ -3454,7 +3476,10 @@ impl fmt::Debug for PipelineCreateFlags { PipelineCreateFlags::RAY_TRACING_OPACITY_MICROMAP_EXT.0, "RAY_TRACING_OPACITY_MICROMAP_EXT", ), - (PipelineCreateFlags::RESERVED_28_NV.0, "RESERVED_28_NV"), + ( + PipelineCreateFlags::RAY_TRACING_DISPLACEMENT_MICROMAP_NV.0, + "RAY_TRACING_DISPLACEMENT_MICROMAP_NV", + ), ( PipelineCreateFlags::NO_PROTECTED_ACCESS_EXT.0, "NO_PROTECTED_ACCESS_EXT", @@ -3800,10 +3825,12 @@ impl fmt::Debug for PipelineStageFlags2 { "MICROMAP_BUILD_EXT", ), ( - PipelineStageFlags2::RESEVED_41_HUAWEI.0, - "RESEVED_41_HUAWEI", + PipelineStageFlags2::CLUSTER_CULLING_SHADER_HUAWEI.0, + "CLUSTER_CULLING_SHADER_HUAWEI", ), + (PipelineStageFlags2::RESERVED_43_ARM.0, "RESERVED_43_ARM"), (PipelineStageFlags2::OPTICAL_FLOW_NV.0, "OPTICAL_FLOW_NV"), + (PipelineStageFlags2::RESERVED_42_EXT.0, "RESERVED_42_EXT"), ]; debug_flags(f, KNOWN, self.0) } @@ -3928,7 +3955,8 @@ impl fmt::Debug for PrimitiveTopology { } impl fmt::Debug for PrivateDataSlotCreateFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - const KNOWN: &[(Flags, &str)] = &[]; + const KNOWN: &[(Flags, &str)] = + &[(PrivateDataSlotCreateFlags::RESERVED_0_NV.0, "RESERVED_0_NV")]; debug_flags(f, KNOWN, self.0) } } @@ -4007,6 +4035,10 @@ impl fmt::Debug for QueryPipelineStatisticFlags { QueryPipelineStatisticFlags::MESH_SHADER_INVOCATIONS_EXT.0, "MESH_SHADER_INVOCATIONS_EXT", ), + ( + QueryPipelineStatisticFlags::CLUSTER_CULLING_SHADER_INVOCATIONS_HUAWEI.0, + "CLUSTER_CULLING_SHADER_INVOCATIONS_HUAWEI", + ), ]; debug_flags(f, KNOWN, self.0) } @@ -4076,9 +4108,7 @@ impl fmt::Debug for QueryType { Some("ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV") } Self::PERFORMANCE_QUERY_INTEL => Some("PERFORMANCE_QUERY_INTEL"), - Self::VIDEO_ENCODESTREAM_BUFFER_RANGE_KHR => { - Some("VIDEO_ENCODESTREAM_BUFFER_RANGE_KHR") - } + Self::VIDEO_ENCODE_FEEDBACK_KHR => Some("VIDEO_ENCODE_FEEDBACK_KHR"), Self::MESH_PRIMITIVES_GENERATED_EXT => Some("MESH_PRIMITIVES_GENERATED_EXT"), Self::PRIMITIVES_GENERATED_EXT => Some("PRIMITIVES_GENERATED_EXT"), Self::ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR => { @@ -4107,7 +4137,9 @@ impl fmt::Debug for QueueFlags { (QueueFlags::RESERVED_9_EXT.0, "RESERVED_9_EXT"), (QueueFlags::VIDEO_ENCODE_KHR.0, "VIDEO_ENCODE_KHR"), (QueueFlags::RESERVED_7_QCOM.0, "RESERVED_7_QCOM"), + (QueueFlags::RESERVED_11_ARM.0, "RESERVED_11_ARM"), (QueueFlags::OPTICAL_FLOW_NV.0, "OPTICAL_FLOW_NV"), + (QueueFlags::RESERVED_10_EXT.0, "RESERVED_10_EXT"), (QueueFlags::PROTECTED.0, "PROTECTED"), ]; debug_flags(f, KNOWN, self.0) @@ -4206,6 +4238,10 @@ impl fmt::Debug for ResolveModeFlags { (ResolveModeFlags::AVERAGE.0, "AVERAGE"), (ResolveModeFlags::MIN.0, "MIN"), (ResolveModeFlags::MAX.0, "MAX"), + ( + ResolveModeFlags::EXTENSION_469_FLAG_0.0, + "EXTENSION_469_FLAG_0", + ), ]; debug_flags(f, KNOWN, self.0) } @@ -4379,12 +4415,52 @@ impl fmt::Debug for SemaphoreWaitFlags { debug_flags(f, KNOWN, self.0) } } +impl fmt::Debug for ShaderCodeTypeEXT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let name = match *self { + Self::BINARY => Some("BINARY"), + Self::SPIRV => Some("SPIRV"), + _ => None, + }; + if let Some(x) = name { + f.write_str(x) + } else { + self.0.fmt(f) + } + } +} impl fmt::Debug for ShaderCorePropertiesFlagsAMD { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { const KNOWN: &[(Flags, &str)] = &[]; debug_flags(f, KNOWN, self.0) } } +impl fmt::Debug for ShaderCreateFlagsEXT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + const KNOWN: &[(Flags, &str)] = &[ + (ShaderCreateFlagsEXT::LINK_STAGE.0, "LINK_STAGE"), + ( + ShaderCreateFlagsEXT::ALLOW_VARYING_SUBGROUP_SIZE.0, + "ALLOW_VARYING_SUBGROUP_SIZE", + ), + ( + ShaderCreateFlagsEXT::REQUIRE_FULL_SUBGROUPS.0, + "REQUIRE_FULL_SUBGROUPS", + ), + (ShaderCreateFlagsEXT::NO_TASK_SHADER.0, "NO_TASK_SHADER"), + (ShaderCreateFlagsEXT::DISPATCH_BASE.0, "DISPATCH_BASE"), + ( + ShaderCreateFlagsEXT::FRAGMENT_SHADING_RATE_ATTACHMENT.0, + "FRAGMENT_SHADING_RATE_ATTACHMENT", + ), + ( + ShaderCreateFlagsEXT::FRAGMENT_DENSITY_MAP_ATTACHMENT.0, + "FRAGMENT_DENSITY_MAP_ATTACHMENT", + ), + ]; + debug_flags(f, KNOWN, self.0) + } +} impl fmt::Debug for ShaderFloatControlsIndependence { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let name = match *self { @@ -4466,10 +4542,10 @@ impl fmt::Debug for ShaderStageFlags { ShaderStageFlags::SUBPASS_SHADING_HUAWEI.0, "SUBPASS_SHADING_HUAWEI", ), - (ShaderStageFlags::RESERVED_19_HUAWEI.0, "RESERVED_19_HUAWEI"), - (ShaderStageFlags::EXT_483_RESERVE_15.0, "EXT_483_RESERVE_15"), - (ShaderStageFlags::EXT_483_RESERVE_16.0, "EXT_483_RESERVE_16"), - (ShaderStageFlags::EXT_483_RESERVE_17.0, "EXT_483_RESERVE_17"), + ( + ShaderStageFlags::CLUSTER_CULLING_HUAWEI.0, + "CLUSTER_CULLING_HUAWEI", + ), ]; debug_flags(f, KNOWN, self.0) } @@ -4745,9 +4821,6 @@ impl fmt::Debug for StructureType { Self::VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT => { Some("VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT") } - Self::VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT => { - Some("VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT") - } Self::VIDEO_ENCODE_H264_PROFILE_INFO_EXT => Some("VIDEO_ENCODE_H264_PROFILE_INFO_EXT"), Self::VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT => { Some("VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT") @@ -4755,9 +4828,6 @@ impl fmt::Debug for StructureType { Self::VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT => { Some("VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT") } - Self::VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT => { - Some("VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT") - } Self::VIDEO_ENCODE_H265_CAPABILITIES_EXT => Some("VIDEO_ENCODE_H265_CAPABILITIES_EXT"), Self::VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT => { Some("VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT") @@ -4774,13 +4844,7 @@ impl fmt::Debug for StructureType { Self::VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT => { Some("VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT") } - Self::VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT => { - Some("VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT") - } Self::VIDEO_ENCODE_H265_PROFILE_INFO_EXT => Some("VIDEO_ENCODE_H265_PROFILE_INFO_EXT"), - Self::VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT => { - Some("VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT") - } Self::VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT => { Some("VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT") } @@ -5374,6 +5438,8 @@ impl fmt::Debug for StructureType { Self::PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR => { Some("PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR") } + Self::MEMORY_MAP_INFO_KHR => Some("MEMORY_MAP_INFO_KHR"), + Self::MEMORY_UNMAP_INFO_KHR => Some("MEMORY_UNMAP_INFO_KHR"), Self::PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT => { Some("PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT") } @@ -5476,6 +5542,9 @@ impl fmt::Debug for StructureType { } Self::VIDEO_ENCODE_CAPABILITIES_KHR => Some("VIDEO_ENCODE_CAPABILITIES_KHR"), Self::VIDEO_ENCODE_USAGE_INFO_KHR => Some("VIDEO_ENCODE_USAGE_INFO_KHR"), + Self::QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR => { + Some("QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR") + } Self::PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV => { Some("PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV") } @@ -5483,6 +5552,7 @@ impl fmt::Debug for StructureType { Some("DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV") } Self::RESERVED_QCOM => Some("RESERVED_QCOM"), + Self::QUERY_LOW_LATENCY_SUPPORT_NV => Some("QUERY_LOW_LATENCY_SUPPORT_NV"), Self::EXPORT_METAL_OBJECT_CREATE_INFO_EXT => { Some("EXPORT_METAL_OBJECT_CREATE_INFO_EXT") } @@ -5736,6 +5806,12 @@ impl fmt::Debug for StructureType { Self::PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT => { Some("PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT") } + Self::PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT => { + Some("PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT") + } + Self::PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT => { + Some("PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT") + } Self::MICROMAP_BUILD_INFO_EXT => Some("MICROMAP_BUILD_INFO_EXT"), Self::MICROMAP_VERSION_INFO_EXT => Some("MICROMAP_VERSION_INFO_EXT"), Self::COPY_MICROMAP_INFO_EXT => Some("COPY_MICROMAP_INFO_EXT"), @@ -5752,6 +5828,21 @@ impl fmt::Debug for StructureType { Self::ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT => { Some("ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT") } + Self::PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV => { + Some("PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV") + } + Self::PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV => { + Some("PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV") + } + Self::ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV => { + Some("ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV") + } + Self::PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI => { + Some("PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI") + } + Self::PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI => { + Some("PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI") + } Self::PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT => { Some("PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT") } @@ -5761,6 +5852,13 @@ impl fmt::Debug for StructureType { Self::PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT => { Some("PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT") } + Self::PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM => { + Some("PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM") + } + Self::PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT => { + Some("PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT") + } + Self::IMAGE_VIEW_SLICED_CREATE_INFO_EXT => Some("IMAGE_VIEW_SLICED_CREATE_INFO_EXT"), Self::PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE => { Some("PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE") } @@ -5866,6 +5964,16 @@ impl fmt::Debug for StructureType { Self::PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT => { Some("PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT") } + Self::PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR => { + Some("PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR") + } + Self::PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT => { + Some("PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT") + } + Self::PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT => { + Some("PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT") + } + Self::SHADER_CREATE_INFO_EXT => Some("SHADER_CREATE_INFO_EXT"), Self::PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM => { Some("PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM") } @@ -5895,6 +6003,21 @@ impl fmt::Debug for StructureType { Self::PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM => { Some("PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM") } + Self::PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT => { + Some("PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT") + } + Self::PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT => { + Some("PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT") + } + Self::PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM => { + Some("PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM") + } + Self::MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM => { + Some("MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM") + } + Self::PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT => { + Some("PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT") + } Self::PHYSICAL_DEVICE_SUBGROUP_PROPERTIES => { Some("PHYSICAL_DEVICE_SUBGROUP_PROPERTIES") } @@ -6550,6 +6673,7 @@ impl fmt::Debug for VendorId { Self::CODEPLAY => Some("CODEPLAY"), Self::MESA => Some("MESA"), Self::POCL => Some("POCL"), + Self::MOBILEYE => Some("MOBILEYE"), _ => None, }; if let Some(x) = name { @@ -6728,6 +6852,21 @@ impl fmt::Debug for VideoEncodeContentFlagsKHR { debug_flags(f, KNOWN, self.0) } } +impl fmt::Debug for VideoEncodeFeedbackFlagsKHR { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + const KNOWN: &[(Flags, &str)] = &[ + ( + VideoEncodeFeedbackFlagsKHR::BITSTREAM_BUFFER_OFFSET.0, + "BITSTREAM_BUFFER_OFFSET", + ), + ( + VideoEncodeFeedbackFlagsKHR::BITSTREAM_BYTES_WRITTEN.0, + "BITSTREAM_BYTES_WRITTEN", + ), + ]; + debug_flags(f, KNOWN, self.0) + } +} impl fmt::Debug for VideoEncodeFlagsKHR { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { const KNOWN: &[(Flags, &str)] = &[]; @@ -6831,26 +6970,10 @@ impl fmt::Debug for VideoEncodeH264CapabilityFlagsEXT { VideoEncodeH264CapabilityFlagsEXT::B_FRAME_IN_L1_LIST.0, "B_FRAME_IN_L1_LIST", ), - ]; - debug_flags(f, KNOWN, self.0) - } -} -impl fmt::Debug for VideoEncodeH264InputModeFlagsEXT { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - const KNOWN: &[(Flags, &str)] = &[ - (VideoEncodeH264InputModeFlagsEXT::FRAME.0, "FRAME"), - (VideoEncodeH264InputModeFlagsEXT::SLICE.0, "SLICE"), - (VideoEncodeH264InputModeFlagsEXT::NON_VCL.0, "NON_VCL"), - ]; - debug_flags(f, KNOWN, self.0) - } -} -impl fmt::Debug for VideoEncodeH264OutputModeFlagsEXT { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - const KNOWN: &[(Flags, &str)] = &[ - (VideoEncodeH264OutputModeFlagsEXT::FRAME.0, "FRAME"), - (VideoEncodeH264OutputModeFlagsEXT::SLICE.0, "SLICE"), - (VideoEncodeH264OutputModeFlagsEXT::NON_VCL.0, "NON_VCL"), + ( + VideoEncodeH264CapabilityFlagsEXT::DIFFERENT_REFERENCE_FINAL_LISTS.0, + "DIFFERENT_REFERENCE_FINAL_LISTS", + ), ]; debug_flags(f, KNOWN, self.0) } @@ -6977,6 +7100,10 @@ impl fmt::Debug for VideoEncodeH265CapabilityFlagsEXT { VideoEncodeH265CapabilityFlagsEXT::B_FRAME_IN_L1_LIST.0, "B_FRAME_IN_L1_LIST", ), + ( + VideoEncodeH265CapabilityFlagsEXT::DIFFERENT_REFERENCE_FINAL_LISTS.0, + "DIFFERENT_REFERENCE_FINAL_LISTS", + ), ]; debug_flags(f, KNOWN, self.0) } @@ -6991,32 +7118,6 @@ impl fmt::Debug for VideoEncodeH265CtbSizeFlagsEXT { debug_flags(f, KNOWN, self.0) } } -impl fmt::Debug for VideoEncodeH265InputModeFlagsEXT { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - const KNOWN: &[(Flags, &str)] = &[ - (VideoEncodeH265InputModeFlagsEXT::FRAME.0, "FRAME"), - ( - VideoEncodeH265InputModeFlagsEXT::SLICE_SEGMENT.0, - "SLICE_SEGMENT", - ), - (VideoEncodeH265InputModeFlagsEXT::NON_VCL.0, "NON_VCL"), - ]; - debug_flags(f, KNOWN, self.0) - } -} -impl fmt::Debug for VideoEncodeH265OutputModeFlagsEXT { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - const KNOWN: &[(Flags, &str)] = &[ - (VideoEncodeH265OutputModeFlagsEXT::FRAME.0, "FRAME"), - ( - VideoEncodeH265OutputModeFlagsEXT::SLICE_SEGMENT.0, - "SLICE_SEGMENT", - ), - (VideoEncodeH265OutputModeFlagsEXT::NON_VCL.0, "NON_VCL"), - ]; - debug_flags(f, KNOWN, self.0) - } -} impl fmt::Debug for VideoEncodeH265RateControlStructureEXT { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let name = match *self { @@ -7064,7 +7165,8 @@ impl fmt::Debug for VideoEncodeRateControlFlagsKHR { impl fmt::Debug for VideoEncodeRateControlModeFlagsKHR { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { const KNOWN: &[(Flags, &str)] = &[ - (VideoEncodeRateControlModeFlagsKHR::NONE.0, "NONE"), + (VideoEncodeRateControlModeFlagsKHR::DEFAULT.0, "DEFAULT"), + (VideoEncodeRateControlModeFlagsKHR::DISABLED.0, "DISABLED"), (VideoEncodeRateControlModeFlagsKHR::CBR.0, "CBR"), (VideoEncodeRateControlModeFlagsKHR::VBR.0, "VBR"), ]; diff --git a/third_party/rust/ash/src/vk/constants.rs b/third_party/rust/ash/src/vk/constants.rs index 78da55ec713a..384e28a20a83 100644 --- a/third_party/rust/ash/src/vk/constants.rs +++ b/third_party/rust/ash/src/vk/constants.rs @@ -10,6 +10,7 @@ pub const MAX_MEMORY_HEAPS: usize = 16; pub const LOD_CLAMP_NONE: f32 = 1000.00; pub const REMAINING_MIP_LEVELS: u32 = !0; pub const REMAINING_ARRAY_LAYERS: u32 = !0; +pub const REMAINING_3D_SLICES_EXT: u32 = !0; pub const WHOLE_SIZE: u64 = !0; pub const ATTACHMENT_UNUSED: u32 = !0; pub const TRUE: Bool32 = 1; diff --git a/third_party/rust/ash/src/vk/definitions.rs b/third_party/rust/ash/src/vk/definitions.rs index c73770b05e82..6961285b2204 100644 --- a/third_party/rust/ash/src/vk/definitions.rs +++ b/third_party/rust/ash/src/vk/definitions.rs @@ -56,7 +56,8 @@ pub const API_VERSION_1_1: u32 = make_api_version(0, 1, 1, 0); pub const API_VERSION_1_2: u32 = make_api_version(0, 1, 2, 0); #[doc = ""] pub const API_VERSION_1_3: u32 = make_api_version(0, 1, 3, 0); -pub const HEADER_VERSION: u32 = 238u32; +#[doc = ""] +pub const HEADER_VERSION: u32 = 251; #[doc = ""] pub const HEADER_VERSION_COMPLETE: u32 = make_api_version(0, 1, 3, HEADER_VERSION); #[doc = ""] @@ -326,6 +327,11 @@ vk_bitflags_wrapped!(VideoEncodeFlagsKHR, Flags); #[doc = ""] pub struct VideoEncodeRateControlFlagsKHR(pub(crate) Flags); vk_bitflags_wrapped!(VideoEncodeRateControlFlagsKHR, Flags); +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[doc = ""] +pub struct MemoryUnmapFlagsKHR(pub(crate) Flags); +vk_bitflags_wrapped!(MemoryUnmapFlagsKHR, Flags); define_handle!( Instance, INSTANCE, @@ -426,6 +432,12 @@ handle_nondispatchable ! (CuModuleNVX , CU_MODULE_NVX , doc = "" +); handle_nondispatchable!( DisplayKHR, DISPLAY_KHR, @@ -1600,7 +1612,9 @@ pub struct DeviceCreateInfo { pub flags: DeviceCreateFlags, pub queue_create_info_count: u32, pub p_queue_create_infos: *const DeviceQueueCreateInfo, + #[deprecated = "functionality described by this member no longer operates"] pub enabled_layer_count: u32, + #[deprecated = "functionality described by this member no longer operates"] pub pp_enabled_layer_names: *const *const c_char, pub enabled_extension_count: u32, pub pp_enabled_extension_names: *const *const c_char, @@ -1609,6 +1623,7 @@ pub struct DeviceCreateInfo { impl ::std::default::Default for DeviceCreateInfo { #[inline] fn default() -> Self { + #[allow(deprecated)] Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), @@ -1664,6 +1679,8 @@ impl<'a> DeviceCreateInfoBuilder<'a> { self } #[inline] + #[deprecated = "functionality described by this member no longer operates"] + #[allow(deprecated)] pub fn enabled_layer_names(mut self, enabled_layer_names: &'a [*const c_char]) -> Self { self.inner.enabled_layer_count = enabled_layer_names.len() as _; self.inner.pp_enabled_layer_names = enabled_layer_names.as_ptr(); @@ -10267,6 +10284,11 @@ impl<'a> FramebufferCreateInfoBuilder<'a> { self } #[inline] + pub fn attachment_count(mut self, attachment_count: u32) -> Self { + self.inner.attachment_count = attachment_count; + self + } + #[inline] pub fn attachments(mut self, attachments: &'a [ImageView]) -> Self { self.inner.attachment_count = attachments.len() as _; self.inner.p_attachments = attachments.as_ptr(); @@ -23884,6 +23906,74 @@ impl<'a> ImageViewUsageCreateInfoBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] +#[doc = ""] +pub struct ImageViewSlicedCreateInfoEXT { + pub s_type: StructureType, + pub p_next: *const c_void, + pub slice_offset: u32, + pub slice_count: u32, +} +impl ::std::default::Default for ImageViewSlicedCreateInfoEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null(), + slice_offset: u32::default(), + slice_count: u32::default(), + } + } +} +unsafe impl TaggedStructure for ImageViewSlicedCreateInfoEXT { + const STRUCTURE_TYPE: StructureType = StructureType::IMAGE_VIEW_SLICED_CREATE_INFO_EXT; +} +impl ImageViewSlicedCreateInfoEXT { + pub fn builder<'a>() -> ImageViewSlicedCreateInfoEXTBuilder<'a> { + ImageViewSlicedCreateInfoEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct ImageViewSlicedCreateInfoEXTBuilder<'a> { + inner: ImageViewSlicedCreateInfoEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsImageViewCreateInfo for ImageViewSlicedCreateInfoEXTBuilder<'_> {} +unsafe impl ExtendsImageViewCreateInfo for ImageViewSlicedCreateInfoEXT {} +impl<'a> ::std::ops::Deref for ImageViewSlicedCreateInfoEXTBuilder<'a> { + type Target = ImageViewSlicedCreateInfoEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for ImageViewSlicedCreateInfoEXTBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> ImageViewSlicedCreateInfoEXTBuilder<'a> { + #[inline] + pub fn slice_offset(mut self, slice_offset: u32) -> Self { + self.inner.slice_offset = slice_offset; + self + } + #[inline] + pub fn slice_count(mut self, slice_count: u32) -> Self { + self.inner.slice_count = slice_count; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> ImageViewSlicedCreateInfoEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] #[doc = ""] pub struct PipelineTessellationDomainOriginStateCreateInfo { pub s_type: StructureType, @@ -44433,6 +44523,11 @@ unsafe impl ExtendsPipelineShaderStageCreateInfo for PipelineShaderStageRequiredSubgroupSizeCreateInfo { } +unsafe impl ExtendsShaderCreateInfoEXT + for PipelineShaderStageRequiredSubgroupSizeCreateInfoBuilder<'_> +{ +} +unsafe impl ExtendsShaderCreateInfoEXT for PipelineShaderStageRequiredSubgroupSizeCreateInfo {} impl<'a> ::std::ops::Deref for PipelineShaderStageRequiredSubgroupSizeCreateInfoBuilder<'a> { type Target = PipelineShaderStageRequiredSubgroupSizeCreateInfo; fn deref(&self) -> &Self::Target { @@ -44598,6 +44693,98 @@ impl<'a> PhysicalDeviceSubpassShadingPropertiesHUAWEIBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceClusterCullingShaderPropertiesHUAWEI { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub max_work_group_count: [u32; 3], + pub max_work_group_size: [u32; 3], + pub max_output_cluster_count: u32, + pub indirect_buffer_offset_alignment: DeviceSize, +} +impl ::std::default::Default for PhysicalDeviceClusterCullingShaderPropertiesHUAWEI { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + max_work_group_count: unsafe { ::std::mem::zeroed() }, + max_work_group_size: unsafe { ::std::mem::zeroed() }, + max_output_cluster_count: u32::default(), + indirect_buffer_offset_alignment: DeviceSize::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceClusterCullingShaderPropertiesHUAWEI { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI; +} +impl PhysicalDeviceClusterCullingShaderPropertiesHUAWEI { + pub fn builder<'a>() -> PhysicalDeviceClusterCullingShaderPropertiesHUAWEIBuilder<'a> { + PhysicalDeviceClusterCullingShaderPropertiesHUAWEIBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceClusterCullingShaderPropertiesHUAWEIBuilder<'a> { + inner: PhysicalDeviceClusterCullingShaderPropertiesHUAWEI, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceProperties2 + for PhysicalDeviceClusterCullingShaderPropertiesHUAWEIBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceProperties2 + for PhysicalDeviceClusterCullingShaderPropertiesHUAWEI +{ +} +impl<'a> ::std::ops::Deref for PhysicalDeviceClusterCullingShaderPropertiesHUAWEIBuilder<'a> { + type Target = PhysicalDeviceClusterCullingShaderPropertiesHUAWEI; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceClusterCullingShaderPropertiesHUAWEIBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceClusterCullingShaderPropertiesHUAWEIBuilder<'a> { + #[inline] + pub fn max_work_group_count(mut self, max_work_group_count: [u32; 3]) -> Self { + self.inner.max_work_group_count = max_work_group_count; + self + } + #[inline] + pub fn max_work_group_size(mut self, max_work_group_size: [u32; 3]) -> Self { + self.inner.max_work_group_size = max_work_group_size; + self + } + #[inline] + pub fn max_output_cluster_count(mut self, max_output_cluster_count: u32) -> Self { + self.inner.max_output_cluster_count = max_output_cluster_count; + self + } + #[inline] + pub fn indirect_buffer_offset_alignment( + mut self, + indirect_buffer_offset_alignment: DeviceSize, + ) -> Self { + self.inner.indirect_buffer_offset_alignment = indirect_buffer_offset_alignment; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceClusterCullingShaderPropertiesHUAWEI { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] #[doc = ""] pub struct MemoryOpaqueCaptureAddressAllocateInfo { pub s_type: StructureType, @@ -51237,6 +51424,86 @@ impl<'a> PhysicalDeviceSubpassShadingFeaturesHUAWEIBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceClusterCullingShaderFeaturesHUAWEI { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub clusterculling_shader: Bool32, + pub multiview_cluster_culling_shader: Bool32, +} +impl ::std::default::Default for PhysicalDeviceClusterCullingShaderFeaturesHUAWEI { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + clusterculling_shader: Bool32::default(), + multiview_cluster_culling_shader: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceClusterCullingShaderFeaturesHUAWEI { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI; +} +impl PhysicalDeviceClusterCullingShaderFeaturesHUAWEI { + pub fn builder<'a>() -> PhysicalDeviceClusterCullingShaderFeaturesHUAWEIBuilder<'a> { + PhysicalDeviceClusterCullingShaderFeaturesHUAWEIBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceClusterCullingShaderFeaturesHUAWEIBuilder<'a> { + inner: PhysicalDeviceClusterCullingShaderFeaturesHUAWEI, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceClusterCullingShaderFeaturesHUAWEIBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceFeatures2 for PhysicalDeviceClusterCullingShaderFeaturesHUAWEI {} +unsafe impl ExtendsDeviceCreateInfo + for PhysicalDeviceClusterCullingShaderFeaturesHUAWEIBuilder<'_> +{ +} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceClusterCullingShaderFeaturesHUAWEI {} +impl<'a> ::std::ops::Deref for PhysicalDeviceClusterCullingShaderFeaturesHUAWEIBuilder<'a> { + type Target = PhysicalDeviceClusterCullingShaderFeaturesHUAWEI; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceClusterCullingShaderFeaturesHUAWEIBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceClusterCullingShaderFeaturesHUAWEIBuilder<'a> { + #[inline] + pub fn clusterculling_shader(mut self, clusterculling_shader: bool) -> Self { + self.inner.clusterculling_shader = clusterculling_shader.into(); + self + } + #[inline] + pub fn multiview_cluster_culling_shader( + mut self, + multiview_cluster_culling_shader: bool, + ) -> Self { + self.inner.multiview_cluster_culling_shader = multiview_cluster_culling_shader.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceClusterCullingShaderFeaturesHUAWEI { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] #[doc = ""] pub struct BufferCopy2 { pub s_type: StructureType, @@ -53276,6 +53543,157 @@ impl<'a> PhysicalDeviceImage2DViewOf3DFeaturesEXTBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceImageSlicedViewOf3DFeaturesEXT { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub image_sliced_view_of3_d: Bool32, +} +impl ::std::default::Default for PhysicalDeviceImageSlicedViewOf3DFeaturesEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + image_sliced_view_of3_d: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceImageSlicedViewOf3DFeaturesEXT { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT; +} +impl PhysicalDeviceImageSlicedViewOf3DFeaturesEXT { + pub fn builder<'a>() -> PhysicalDeviceImageSlicedViewOf3DFeaturesEXTBuilder<'a> { + PhysicalDeviceImageSlicedViewOf3DFeaturesEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceImageSlicedViewOf3DFeaturesEXTBuilder<'a> { + inner: PhysicalDeviceImageSlicedViewOf3DFeaturesEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceImageSlicedViewOf3DFeaturesEXTBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceFeatures2 for PhysicalDeviceImageSlicedViewOf3DFeaturesEXT {} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceImageSlicedViewOf3DFeaturesEXTBuilder<'_> {} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceImageSlicedViewOf3DFeaturesEXT {} +impl<'a> ::std::ops::Deref for PhysicalDeviceImageSlicedViewOf3DFeaturesEXTBuilder<'a> { + type Target = PhysicalDeviceImageSlicedViewOf3DFeaturesEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceImageSlicedViewOf3DFeaturesEXTBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceImageSlicedViewOf3DFeaturesEXTBuilder<'a> { + #[inline] + pub fn image_sliced_view_of3_d(mut self, image_sliced_view_of3_d: bool) -> Self { + self.inner.image_sliced_view_of3_d = image_sliced_view_of3_d.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceImageSlicedViewOf3DFeaturesEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub attachment_feedback_loop_dynamic_state: Bool32, +} +impl ::std::default::Default for PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + attachment_feedback_loop_dynamic_state: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT; +} +impl PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { + pub fn builder<'a>() -> PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXTBuilder<'a> { + PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXTBuilder<'a> { + inner: PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXTBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT +{ +} +unsafe impl ExtendsDeviceCreateInfo + for PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXTBuilder<'_> +{ +} +unsafe impl ExtendsDeviceCreateInfo + for PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT +{ +} +impl<'a> ::std::ops::Deref + for PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXTBuilder<'a> +{ + type Target = PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut + for PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXTBuilder<'a> +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXTBuilder<'a> { + #[inline] + pub fn attachment_feedback_loop_dynamic_state( + mut self, + attachment_feedback_loop_dynamic_state: bool, + ) -> Self { + self.inner.attachment_feedback_loop_dynamic_state = + attachment_feedback_loop_dynamic_state.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] #[doc = ""] pub struct PhysicalDeviceMutableDescriptorTypeFeaturesEXT { pub s_type: StructureType, @@ -57267,7 +57685,7 @@ impl<'a> VideoDecodeH265SessionParametersCreateInfoKHRBuilder<'a> { pub struct VideoDecodeH265PictureInfoKHR { pub s_type: StructureType, pub p_next: *const c_void, - pub p_std_picture_info: *mut StdVideoDecodeH265PictureInfo, + pub p_std_picture_info: *const StdVideoDecodeH265PictureInfo, pub slice_segment_count: u32, pub p_slice_segment_offsets: *const u32, } @@ -57277,7 +57695,7 @@ impl ::std::default::Default for VideoDecodeH265PictureInfoKHR { Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), - p_std_picture_info: ::std::ptr::null_mut(), + p_std_picture_info: ::std::ptr::null(), slice_segment_count: u32::default(), p_slice_segment_offsets: ::std::ptr::null(), } @@ -57314,10 +57732,7 @@ impl<'a> ::std::ops::DerefMut for VideoDecodeH265PictureInfoKHRBuilder<'a> { } impl<'a> VideoDecodeH265PictureInfoKHRBuilder<'a> { #[inline] - pub fn std_picture_info( - mut self, - std_picture_info: &'a mut StdVideoDecodeH265PictureInfo, - ) -> Self { + pub fn std_picture_info(mut self, std_picture_info: &'a StdVideoDecodeH265PictureInfo) -> Self { self.inner.p_std_picture_info = std_picture_info; self } @@ -57989,9 +58404,9 @@ pub struct VideoEncodeInfoKHR { pub p_next: *const c_void, pub flags: VideoEncodeFlagsKHR, pub quality_level: u32, - pub dst_bitstream_buffer: Buffer, - pub dst_bitstream_buffer_offset: DeviceSize, - pub dst_bitstream_buffer_max_range: DeviceSize, + pub dst_buffer: Buffer, + pub dst_buffer_offset: DeviceSize, + pub dst_buffer_range: DeviceSize, pub src_picture_resource: VideoPictureResourceInfoKHR, pub p_setup_reference_slot: *const VideoReferenceSlotInfoKHR, pub reference_slot_count: u32, @@ -58006,9 +58421,9 @@ impl ::std::default::Default for VideoEncodeInfoKHR { p_next: ::std::ptr::null(), flags: VideoEncodeFlagsKHR::default(), quality_level: u32::default(), - dst_bitstream_buffer: Buffer::default(), - dst_bitstream_buffer_offset: DeviceSize::default(), - dst_bitstream_buffer_max_range: DeviceSize::default(), + dst_buffer: Buffer::default(), + dst_buffer_offset: DeviceSize::default(), + dst_buffer_range: DeviceSize::default(), src_picture_resource: VideoPictureResourceInfoKHR::default(), p_setup_reference_slot: ::std::ptr::null(), reference_slot_count: u32::default(), @@ -58057,21 +58472,18 @@ impl<'a> VideoEncodeInfoKHRBuilder<'a> { self } #[inline] - pub fn dst_bitstream_buffer(mut self, dst_bitstream_buffer: Buffer) -> Self { - self.inner.dst_bitstream_buffer = dst_bitstream_buffer; + pub fn dst_buffer(mut self, dst_buffer: Buffer) -> Self { + self.inner.dst_buffer = dst_buffer; self } #[inline] - pub fn dst_bitstream_buffer_offset(mut self, dst_bitstream_buffer_offset: DeviceSize) -> Self { - self.inner.dst_bitstream_buffer_offset = dst_bitstream_buffer_offset; + pub fn dst_buffer_offset(mut self, dst_buffer_offset: DeviceSize) -> Self { + self.inner.dst_buffer_offset = dst_buffer_offset; self } #[inline] - pub fn dst_bitstream_buffer_max_range( - mut self, - dst_bitstream_buffer_max_range: DeviceSize, - ) -> Self { - self.inner.dst_bitstream_buffer_max_range = dst_bitstream_buffer_max_range; + pub fn dst_buffer_range(mut self, dst_buffer_range: DeviceSize) -> Self { + self.inner.dst_buffer_range = dst_buffer_range; self } #[inline] @@ -58128,14 +58540,79 @@ impl<'a> VideoEncodeInfoKHRBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] +#[doc = ""] +pub struct QueryPoolVideoEncodeFeedbackCreateInfoKHR { + pub s_type: StructureType, + pub p_next: *const c_void, + pub encode_feedback_flags: VideoEncodeFeedbackFlagsKHR, +} +impl ::std::default::Default for QueryPoolVideoEncodeFeedbackCreateInfoKHR { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null(), + encode_feedback_flags: VideoEncodeFeedbackFlagsKHR::default(), + } + } +} +unsafe impl TaggedStructure for QueryPoolVideoEncodeFeedbackCreateInfoKHR { + const STRUCTURE_TYPE: StructureType = + StructureType::QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR; +} +impl QueryPoolVideoEncodeFeedbackCreateInfoKHR { + pub fn builder<'a>() -> QueryPoolVideoEncodeFeedbackCreateInfoKHRBuilder<'a> { + QueryPoolVideoEncodeFeedbackCreateInfoKHRBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct QueryPoolVideoEncodeFeedbackCreateInfoKHRBuilder<'a> { + inner: QueryPoolVideoEncodeFeedbackCreateInfoKHR, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsQueryPoolCreateInfo for QueryPoolVideoEncodeFeedbackCreateInfoKHRBuilder<'_> {} +unsafe impl ExtendsQueryPoolCreateInfo for QueryPoolVideoEncodeFeedbackCreateInfoKHR {} +impl<'a> ::std::ops::Deref for QueryPoolVideoEncodeFeedbackCreateInfoKHRBuilder<'a> { + type Target = QueryPoolVideoEncodeFeedbackCreateInfoKHR; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for QueryPoolVideoEncodeFeedbackCreateInfoKHRBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> QueryPoolVideoEncodeFeedbackCreateInfoKHRBuilder<'a> { + #[inline] + pub fn encode_feedback_flags( + mut self, + encode_feedback_flags: VideoEncodeFeedbackFlagsKHR, + ) -> Self { + self.inner.encode_feedback_flags = encode_feedback_flags; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> QueryPoolVideoEncodeFeedbackCreateInfoKHR { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] #[doc = ""] pub struct VideoEncodeRateControlInfoKHR { pub s_type: StructureType, pub p_next: *const c_void, pub flags: VideoEncodeRateControlFlagsKHR, pub rate_control_mode: VideoEncodeRateControlModeFlagsKHR, - pub layer_count: u8, - pub p_layer_configs: *const VideoEncodeRateControlLayerInfoKHR, + pub layer_count: u32, + pub p_layers: *const VideoEncodeRateControlLayerInfoKHR, } impl ::std::default::Default for VideoEncodeRateControlInfoKHR { #[inline] @@ -58145,8 +58622,8 @@ impl ::std::default::Default for VideoEncodeRateControlInfoKHR { p_next: ::std::ptr::null(), flags: VideoEncodeRateControlFlagsKHR::default(), rate_control_mode: VideoEncodeRateControlModeFlagsKHR::default(), - layer_count: u8::default(), - p_layer_configs: ::std::ptr::null(), + layer_count: u32::default(), + p_layers: ::std::ptr::null(), } } } @@ -58194,12 +58671,9 @@ impl<'a> VideoEncodeRateControlInfoKHRBuilder<'a> { self } #[inline] - pub fn layer_configs( - mut self, - layer_configs: &'a [VideoEncodeRateControlLayerInfoKHR], - ) -> Self { - self.inner.layer_count = layer_configs.len() as _; - self.inner.p_layer_configs = layer_configs.as_ptr(); + pub fn layers(mut self, layers: &'a [VideoEncodeRateControlLayerInfoKHR]) -> Self { + self.inner.layer_count = layers.len() as _; + self.inner.p_layers = layers.as_ptr(); self } #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] @@ -58216,8 +58690,8 @@ impl<'a> VideoEncodeRateControlInfoKHRBuilder<'a> { pub struct VideoEncodeRateControlLayerInfoKHR { pub s_type: StructureType, pub p_next: *const c_void, - pub average_bitrate: u32, - pub max_bitrate: u32, + pub average_bitrate: u64, + pub max_bitrate: u64, pub frame_rate_numerator: u32, pub frame_rate_denominator: u32, pub virtual_buffer_size_in_ms: u32, @@ -58229,8 +58703,8 @@ impl ::std::default::Default for VideoEncodeRateControlLayerInfoKHR { Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), - average_bitrate: u32::default(), - max_bitrate: u32::default(), + average_bitrate: u64::default(), + max_bitrate: u64::default(), frame_rate_numerator: u32::default(), frame_rate_denominator: u32::default(), virtual_buffer_size_in_ms: u32::default(), @@ -58270,12 +58744,12 @@ impl<'a> ::std::ops::DerefMut for VideoEncodeRateControlLayerInfoKHRBuilder<'a> } impl<'a> VideoEncodeRateControlLayerInfoKHRBuilder<'a> { #[inline] - pub fn average_bitrate(mut self, average_bitrate: u32) -> Self { + pub fn average_bitrate(mut self, average_bitrate: u64) -> Self { self.inner.average_bitrate = average_bitrate; self } #[inline] - pub fn max_bitrate(mut self, max_bitrate: u32) -> Self { + pub fn max_bitrate(mut self, max_bitrate: u64) -> Self { self.inner.max_bitrate = max_bitrate; self } @@ -58335,9 +58809,10 @@ pub struct VideoEncodeCapabilitiesKHR { pub p_next: *mut c_void, pub flags: VideoEncodeCapabilityFlagsKHR, pub rate_control_modes: VideoEncodeRateControlModeFlagsKHR, - pub rate_control_layer_count: u8, - pub quality_level_count: u8, + pub max_rate_control_layers: u32, + pub max_quality_levels: u32, pub input_image_data_fill_alignment: Extent2D, + pub supported_encode_feedback_flags: VideoEncodeFeedbackFlagsKHR, } impl ::std::default::Default for VideoEncodeCapabilitiesKHR { #[inline] @@ -58347,9 +58822,10 @@ impl ::std::default::Default for VideoEncodeCapabilitiesKHR { p_next: ::std::ptr::null_mut(), flags: VideoEncodeCapabilityFlagsKHR::default(), rate_control_modes: VideoEncodeRateControlModeFlagsKHR::default(), - rate_control_layer_count: u8::default(), - quality_level_count: u8::default(), + max_rate_control_layers: u32::default(), + max_quality_levels: u32::default(), input_image_data_fill_alignment: Extent2D::default(), + supported_encode_feedback_flags: VideoEncodeFeedbackFlagsKHR::default(), } } } @@ -58397,13 +58873,13 @@ impl<'a> VideoEncodeCapabilitiesKHRBuilder<'a> { self } #[inline] - pub fn rate_control_layer_count(mut self, rate_control_layer_count: u8) -> Self { - self.inner.rate_control_layer_count = rate_control_layer_count; + pub fn max_rate_control_layers(mut self, max_rate_control_layers: u32) -> Self { + self.inner.max_rate_control_layers = max_rate_control_layers; self } #[inline] - pub fn quality_level_count(mut self, quality_level_count: u8) -> Self { - self.inner.quality_level_count = quality_level_count; + pub fn max_quality_levels(mut self, max_quality_levels: u32) -> Self { + self.inner.max_quality_levels = max_quality_levels; self } #[inline] @@ -58414,6 +58890,14 @@ impl<'a> VideoEncodeCapabilitiesKHRBuilder<'a> { self.inner.input_image_data_fill_alignment = input_image_data_fill_alignment; self } + #[inline] + pub fn supported_encode_feedback_flags( + mut self, + supported_encode_feedback_flags: VideoEncodeFeedbackFlagsKHR, + ) -> Self { + self.inner.supported_encode_feedback_flags = supported_encode_feedback_flags; + self + } #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] #[doc = r" so references to builders can be passed directly to Vulkan functions."] @@ -58429,11 +58913,9 @@ pub struct VideoEncodeH264CapabilitiesEXT { pub s_type: StructureType, pub p_next: *mut c_void, pub flags: VideoEncodeH264CapabilityFlagsEXT, - pub input_mode_flags: VideoEncodeH264InputModeFlagsEXT, - pub output_mode_flags: VideoEncodeH264OutputModeFlagsEXT, - pub max_p_picture_l0_reference_count: u8, - pub max_b_picture_l0_reference_count: u8, - pub max_l1_reference_count: u8, + pub max_p_picture_l0_reference_count: u32, + pub max_b_picture_l0_reference_count: u32, + pub max_l1_reference_count: u32, pub motion_vectors_over_pic_boundaries_flag: Bool32, pub max_bytes_per_pic_denom: u32, pub max_bits_per_mb_denom: u32, @@ -58447,11 +58929,9 @@ impl ::std::default::Default for VideoEncodeH264CapabilitiesEXT { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null_mut(), flags: VideoEncodeH264CapabilityFlagsEXT::default(), - input_mode_flags: VideoEncodeH264InputModeFlagsEXT::default(), - output_mode_flags: VideoEncodeH264OutputModeFlagsEXT::default(), - max_p_picture_l0_reference_count: u8::default(), - max_b_picture_l0_reference_count: u8::default(), - max_l1_reference_count: u8::default(), + max_p_picture_l0_reference_count: u32::default(), + max_b_picture_l0_reference_count: u32::default(), + max_l1_reference_count: u32::default(), motion_vectors_over_pic_boundaries_flag: Bool32::default(), max_bytes_per_pic_denom: u32::default(), max_bits_per_mb_denom: u32::default(), @@ -58496,22 +58976,9 @@ impl<'a> VideoEncodeH264CapabilitiesEXTBuilder<'a> { self } #[inline] - pub fn input_mode_flags(mut self, input_mode_flags: VideoEncodeH264InputModeFlagsEXT) -> Self { - self.inner.input_mode_flags = input_mode_flags; - self - } - #[inline] - pub fn output_mode_flags( - mut self, - output_mode_flags: VideoEncodeH264OutputModeFlagsEXT, - ) -> Self { - self.inner.output_mode_flags = output_mode_flags; - self - } - #[inline] pub fn max_p_picture_l0_reference_count( mut self, - max_p_picture_l0_reference_count: u8, + max_p_picture_l0_reference_count: u32, ) -> Self { self.inner.max_p_picture_l0_reference_count = max_p_picture_l0_reference_count; self @@ -58519,13 +58986,13 @@ impl<'a> VideoEncodeH264CapabilitiesEXTBuilder<'a> { #[inline] pub fn max_b_picture_l0_reference_count( mut self, - max_b_picture_l0_reference_count: u8, + max_b_picture_l0_reference_count: u32, ) -> Self { self.inner.max_b_picture_l0_reference_count = max_b_picture_l0_reference_count; self } #[inline] - pub fn max_l1_reference_count(mut self, max_l1_reference_count: u8) -> Self { + pub fn max_l1_reference_count(mut self, max_l1_reference_count: u32) -> Self { self.inner.max_l1_reference_count = max_l1_reference_count; self } @@ -58738,7 +59205,6 @@ impl<'a> VideoEncodeH264SessionParametersCreateInfoEXTBuilder<'a> { pub struct VideoEncodeH264DpbSlotInfoEXT { pub s_type: StructureType, pub p_next: *const c_void, - pub slot_index: i8, pub p_std_reference_info: *const StdVideoEncodeH264ReferenceInfo, } impl ::std::default::Default for VideoEncodeH264DpbSlotInfoEXT { @@ -58747,7 +59213,6 @@ impl ::std::default::Default for VideoEncodeH264DpbSlotInfoEXT { Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), - slot_index: i8::default(), p_std_reference_info: ::std::ptr::null(), } } @@ -58768,6 +59233,8 @@ pub struct VideoEncodeH264DpbSlotInfoEXTBuilder<'a> { inner: VideoEncodeH264DpbSlotInfoEXT, marker: ::std::marker::PhantomData<&'a ()>, } +unsafe impl ExtendsVideoReferenceSlotInfoKHR for VideoEncodeH264DpbSlotInfoEXTBuilder<'_> {} +unsafe impl ExtendsVideoReferenceSlotInfoKHR for VideoEncodeH264DpbSlotInfoEXT {} impl<'a> ::std::ops::Deref for VideoEncodeH264DpbSlotInfoEXTBuilder<'a> { type Target = VideoEncodeH264DpbSlotInfoEXT; fn deref(&self) -> &Self::Target { @@ -58780,11 +59247,6 @@ impl<'a> ::std::ops::DerefMut for VideoEncodeH264DpbSlotInfoEXTBuilder<'a> { } } impl<'a> VideoEncodeH264DpbSlotInfoEXTBuilder<'a> { - #[inline] - pub fn slot_index(mut self, slot_index: i8) -> Self { - self.inner.slot_index = slot_index; - self - } #[inline] pub fn std_reference_info( mut self, @@ -58807,10 +59269,10 @@ impl<'a> VideoEncodeH264DpbSlotInfoEXTBuilder<'a> { pub struct VideoEncodeH264VclFrameInfoEXT { pub s_type: StructureType, pub p_next: *const c_void, - pub p_reference_final_lists: *const VideoEncodeH264ReferenceListsInfoEXT, + pub p_std_reference_final_lists: *const StdVideoEncodeH264ReferenceListsInfo, pub nalu_slice_entry_count: u32, pub p_nalu_slice_entries: *const VideoEncodeH264NaluSliceInfoEXT, - pub p_current_picture_info: *const StdVideoEncodeH264PictureInfo, + pub p_std_picture_info: *const StdVideoEncodeH264PictureInfo, } impl ::std::default::Default for VideoEncodeH264VclFrameInfoEXT { #[inline] @@ -58818,10 +59280,10 @@ impl ::std::default::Default for VideoEncodeH264VclFrameInfoEXT { Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), - p_reference_final_lists: ::std::ptr::null(), + p_std_reference_final_lists: ::std::ptr::null(), nalu_slice_entry_count: u32::default(), p_nalu_slice_entries: ::std::ptr::null(), - p_current_picture_info: ::std::ptr::null(), + p_std_picture_info: ::std::ptr::null(), } } } @@ -58856,11 +59318,11 @@ impl<'a> ::std::ops::DerefMut for VideoEncodeH264VclFrameInfoEXTBuilder<'a> { } impl<'a> VideoEncodeH264VclFrameInfoEXTBuilder<'a> { #[inline] - pub fn reference_final_lists( + pub fn std_reference_final_lists( mut self, - reference_final_lists: &'a VideoEncodeH264ReferenceListsInfoEXT, + std_reference_final_lists: &'a StdVideoEncodeH264ReferenceListsInfo, ) -> Self { - self.inner.p_reference_final_lists = reference_final_lists; + self.inner.p_std_reference_final_lists = std_reference_final_lists; self } #[inline] @@ -58873,11 +59335,8 @@ impl<'a> VideoEncodeH264VclFrameInfoEXTBuilder<'a> { self } #[inline] - pub fn current_picture_info( - mut self, - current_picture_info: &'a StdVideoEncodeH264PictureInfo, - ) -> Self { - self.inner.p_current_picture_info = current_picture_info; + pub fn std_picture_info(mut self, std_picture_info: &'a StdVideoEncodeH264PictureInfo) -> Self { + self.inner.p_std_picture_info = std_picture_info; self } #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] @@ -58890,173 +59349,6 @@ impl<'a> VideoEncodeH264VclFrameInfoEXTBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] -#[doc = ""] -pub struct VideoEncodeH264ReferenceListsInfoEXT { - pub s_type: StructureType, - pub p_next: *const c_void, - pub reference_list0_entry_count: u8, - pub p_reference_list0_entries: *const VideoEncodeH264DpbSlotInfoEXT, - pub reference_list1_entry_count: u8, - pub p_reference_list1_entries: *const VideoEncodeH264DpbSlotInfoEXT, - pub p_mem_mgmt_ctrl_operations: *const StdVideoEncodeH264RefMemMgmtCtrlOperations, -} -impl ::std::default::Default for VideoEncodeH264ReferenceListsInfoEXT { - #[inline] - fn default() -> Self { - Self { - s_type: Self::STRUCTURE_TYPE, - p_next: ::std::ptr::null(), - reference_list0_entry_count: u8::default(), - p_reference_list0_entries: ::std::ptr::null(), - reference_list1_entry_count: u8::default(), - p_reference_list1_entries: ::std::ptr::null(), - p_mem_mgmt_ctrl_operations: ::std::ptr::null(), - } - } -} -unsafe impl TaggedStructure for VideoEncodeH264ReferenceListsInfoEXT { - const STRUCTURE_TYPE: StructureType = StructureType::VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT; -} -impl VideoEncodeH264ReferenceListsInfoEXT { - pub fn builder<'a>() -> VideoEncodeH264ReferenceListsInfoEXTBuilder<'a> { - VideoEncodeH264ReferenceListsInfoEXTBuilder { - inner: Self::default(), - marker: ::std::marker::PhantomData, - } - } -} -#[repr(transparent)] -pub struct VideoEncodeH264ReferenceListsInfoEXTBuilder<'a> { - inner: VideoEncodeH264ReferenceListsInfoEXT, - marker: ::std::marker::PhantomData<&'a ()>, -} -impl<'a> ::std::ops::Deref for VideoEncodeH264ReferenceListsInfoEXTBuilder<'a> { - type Target = VideoEncodeH264ReferenceListsInfoEXT; - fn deref(&self) -> &Self::Target { - &self.inner - } -} -impl<'a> ::std::ops::DerefMut for VideoEncodeH264ReferenceListsInfoEXTBuilder<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} -impl<'a> VideoEncodeH264ReferenceListsInfoEXTBuilder<'a> { - #[inline] - pub fn reference_list0_entries( - mut self, - reference_list0_entries: &'a [VideoEncodeH264DpbSlotInfoEXT], - ) -> Self { - self.inner.reference_list0_entry_count = reference_list0_entries.len() as _; - self.inner.p_reference_list0_entries = reference_list0_entries.as_ptr(); - self - } - #[inline] - pub fn reference_list1_entries( - mut self, - reference_list1_entries: &'a [VideoEncodeH264DpbSlotInfoEXT], - ) -> Self { - self.inner.reference_list1_entry_count = reference_list1_entries.len() as _; - self.inner.p_reference_list1_entries = reference_list1_entries.as_ptr(); - self - } - #[inline] - pub fn mem_mgmt_ctrl_operations( - mut self, - mem_mgmt_ctrl_operations: &'a StdVideoEncodeH264RefMemMgmtCtrlOperations, - ) -> Self { - self.inner.p_mem_mgmt_ctrl_operations = mem_mgmt_ctrl_operations; - self - } - #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] - #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] - #[doc = r" so references to builders can be passed directly to Vulkan functions."] - pub fn build(self) -> VideoEncodeH264ReferenceListsInfoEXT { - self.inner - } -} -#[repr(C)] -#[cfg_attr(feature = "debug", derive(Debug))] -#[derive(Copy, Clone)] -#[doc = ""] -pub struct VideoEncodeH264EmitPictureParametersInfoEXT { - pub s_type: StructureType, - pub p_next: *const c_void, - pub sps_id: u8, - pub emit_sps_enable: Bool32, - pub pps_id_entry_count: u32, - pub pps_id_entries: *const u8, -} -impl ::std::default::Default for VideoEncodeH264EmitPictureParametersInfoEXT { - #[inline] - fn default() -> Self { - Self { - s_type: Self::STRUCTURE_TYPE, - p_next: ::std::ptr::null(), - sps_id: u8::default(), - emit_sps_enable: Bool32::default(), - pps_id_entry_count: u32::default(), - pps_id_entries: ::std::ptr::null(), - } - } -} -unsafe impl TaggedStructure for VideoEncodeH264EmitPictureParametersInfoEXT { - const STRUCTURE_TYPE: StructureType = - StructureType::VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT; -} -impl VideoEncodeH264EmitPictureParametersInfoEXT { - pub fn builder<'a>() -> VideoEncodeH264EmitPictureParametersInfoEXTBuilder<'a> { - VideoEncodeH264EmitPictureParametersInfoEXTBuilder { - inner: Self::default(), - marker: ::std::marker::PhantomData, - } - } -} -#[repr(transparent)] -pub struct VideoEncodeH264EmitPictureParametersInfoEXTBuilder<'a> { - inner: VideoEncodeH264EmitPictureParametersInfoEXT, - marker: ::std::marker::PhantomData<&'a ()>, -} -unsafe impl ExtendsVideoEncodeInfoKHR for VideoEncodeH264EmitPictureParametersInfoEXTBuilder<'_> {} -unsafe impl ExtendsVideoEncodeInfoKHR for VideoEncodeH264EmitPictureParametersInfoEXT {} -impl<'a> ::std::ops::Deref for VideoEncodeH264EmitPictureParametersInfoEXTBuilder<'a> { - type Target = VideoEncodeH264EmitPictureParametersInfoEXT; - fn deref(&self) -> &Self::Target { - &self.inner - } -} -impl<'a> ::std::ops::DerefMut for VideoEncodeH264EmitPictureParametersInfoEXTBuilder<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} -impl<'a> VideoEncodeH264EmitPictureParametersInfoEXTBuilder<'a> { - #[inline] - pub fn sps_id(mut self, sps_id: u8) -> Self { - self.inner.sps_id = sps_id; - self - } - #[inline] - pub fn emit_sps_enable(mut self, emit_sps_enable: bool) -> Self { - self.inner.emit_sps_enable = emit_sps_enable.into(); - self - } - #[inline] - pub fn pps_id_entries(mut self, pps_id_entries: &'a [u8]) -> Self { - self.inner.pps_id_entry_count = pps_id_entries.len() as _; - self.inner.pps_id_entries = pps_id_entries.as_ptr(); - self - } - #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] - #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] - #[doc = r" so references to builders can be passed directly to Vulkan functions."] - pub fn build(self) -> VideoEncodeH264EmitPictureParametersInfoEXT { - self.inner - } -} -#[repr(C)] -#[cfg_attr(feature = "debug", derive(Debug))] -#[derive(Copy, Clone)] #[doc = ""] pub struct VideoEncodeH264ProfileInfoEXT { pub s_type: StructureType, @@ -59125,8 +59417,8 @@ pub struct VideoEncodeH264NaluSliceInfoEXT { pub s_type: StructureType, pub p_next: *const c_void, pub mb_count: u32, - pub p_reference_final_lists: *const VideoEncodeH264ReferenceListsInfoEXT, - pub p_slice_header_std: *const StdVideoEncodeH264SliceHeader, + pub p_std_reference_final_lists: *const StdVideoEncodeH264ReferenceListsInfo, + pub p_std_slice_header: *const StdVideoEncodeH264SliceHeader, } impl ::std::default::Default for VideoEncodeH264NaluSliceInfoEXT { #[inline] @@ -59135,8 +59427,8 @@ impl ::std::default::Default for VideoEncodeH264NaluSliceInfoEXT { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), mb_count: u32::default(), - p_reference_final_lists: ::std::ptr::null(), - p_slice_header_std: ::std::ptr::null(), + p_std_reference_final_lists: ::std::ptr::null(), + p_std_slice_header: ::std::ptr::null(), } } } @@ -59174,16 +59466,16 @@ impl<'a> VideoEncodeH264NaluSliceInfoEXTBuilder<'a> { self } #[inline] - pub fn reference_final_lists( + pub fn std_reference_final_lists( mut self, - reference_final_lists: &'a VideoEncodeH264ReferenceListsInfoEXT, + std_reference_final_lists: &'a StdVideoEncodeH264ReferenceListsInfo, ) -> Self { - self.inner.p_reference_final_lists = reference_final_lists; + self.inner.p_std_reference_final_lists = std_reference_final_lists; self } #[inline] - pub fn slice_header_std(mut self, slice_header_std: &'a StdVideoEncodeH264SliceHeader) -> Self { - self.inner.p_slice_header_std = slice_header_std; + pub fn std_slice_header(mut self, std_slice_header: &'a StdVideoEncodeH264SliceHeader) -> Self { + self.inner.p_std_slice_header = std_slice_header; self } #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] @@ -59204,7 +59496,7 @@ pub struct VideoEncodeH264RateControlInfoEXT { pub idr_period: u32, pub consecutive_b_frame_count: u32, pub rate_control_structure: VideoEncodeH264RateControlStructureEXT, - pub temporal_layer_count: u8, + pub temporal_layer_count: u32, } impl ::std::default::Default for VideoEncodeH264RateControlInfoEXT { #[inline] @@ -59216,7 +59508,7 @@ impl ::std::default::Default for VideoEncodeH264RateControlInfoEXT { idr_period: u32::default(), consecutive_b_frame_count: u32::default(), rate_control_structure: VideoEncodeH264RateControlStructureEXT::default(), - temporal_layer_count: u8::default(), + temporal_layer_count: u32::default(), } } } @@ -59274,7 +59566,7 @@ impl<'a> VideoEncodeH264RateControlInfoEXTBuilder<'a> { self } #[inline] - pub fn temporal_layer_count(mut self, temporal_layer_count: u8) -> Self { + pub fn temporal_layer_count(mut self, temporal_layer_count: u32) -> Self { self.inner.temporal_layer_count = temporal_layer_count; self } @@ -59404,7 +59696,7 @@ impl<'a> VideoEncodeH264FrameSizeEXTBuilder<'a> { pub struct VideoEncodeH264RateControlLayerInfoEXT { pub s_type: StructureType, pub p_next: *const c_void, - pub temporal_layer_id: u8, + pub temporal_layer_id: u32, pub use_initial_rc_qp: Bool32, pub initial_rc_qp: VideoEncodeH264QpEXT, pub use_min_qp: Bool32, @@ -59420,7 +59712,7 @@ impl ::std::default::Default for VideoEncodeH264RateControlLayerInfoEXT { Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), - temporal_layer_id: u8::default(), + temporal_layer_id: u32::default(), use_initial_rc_qp: Bool32::default(), initial_rc_qp: VideoEncodeH264QpEXT::default(), use_min_qp: Bool32::default(), @@ -59469,7 +59761,7 @@ impl<'a> ::std::ops::DerefMut for VideoEncodeH264RateControlLayerInfoEXTBuilder< } impl<'a> VideoEncodeH264RateControlLayerInfoEXTBuilder<'a> { #[inline] - pub fn temporal_layer_id(mut self, temporal_layer_id: u8) -> Self { + pub fn temporal_layer_id(mut self, temporal_layer_id: u32) -> Self { self.inner.temporal_layer_id = temporal_layer_id; self } @@ -59528,25 +59820,23 @@ pub struct VideoEncodeH265CapabilitiesEXT { pub s_type: StructureType, pub p_next: *mut c_void, pub flags: VideoEncodeH265CapabilityFlagsEXT, - pub input_mode_flags: VideoEncodeH265InputModeFlagsEXT, - pub output_mode_flags: VideoEncodeH265OutputModeFlagsEXT, pub ctb_sizes: VideoEncodeH265CtbSizeFlagsEXT, pub transform_block_sizes: VideoEncodeH265TransformBlockSizeFlagsEXT, - pub max_p_picture_l0_reference_count: u8, - pub max_b_picture_l0_reference_count: u8, - pub max_l1_reference_count: u8, - pub max_sub_layers_count: u8, - pub min_log2_min_luma_coding_block_size_minus3: u8, - pub max_log2_min_luma_coding_block_size_minus3: u8, - pub min_log2_min_luma_transform_block_size_minus2: u8, - pub max_log2_min_luma_transform_block_size_minus2: u8, - pub min_max_transform_hierarchy_depth_inter: u8, - pub max_max_transform_hierarchy_depth_inter: u8, - pub min_max_transform_hierarchy_depth_intra: u8, - pub max_max_transform_hierarchy_depth_intra: u8, - pub max_diff_cu_qp_delta_depth: u8, - pub min_max_num_merge_cand: u8, - pub max_max_num_merge_cand: u8, + pub max_p_picture_l0_reference_count: u32, + pub max_b_picture_l0_reference_count: u32, + pub max_l1_reference_count: u32, + pub max_sub_layers_count: u32, + pub min_log2_min_luma_coding_block_size_minus3: u32, + pub max_log2_min_luma_coding_block_size_minus3: u32, + pub min_log2_min_luma_transform_block_size_minus2: u32, + pub max_log2_min_luma_transform_block_size_minus2: u32, + pub min_max_transform_hierarchy_depth_inter: u32, + pub max_max_transform_hierarchy_depth_inter: u32, + pub min_max_transform_hierarchy_depth_intra: u32, + pub max_max_transform_hierarchy_depth_intra: u32, + pub max_diff_cu_qp_delta_depth: u32, + pub min_max_num_merge_cand: u32, + pub max_max_num_merge_cand: u32, } impl ::std::default::Default for VideoEncodeH265CapabilitiesEXT { #[inline] @@ -59555,25 +59845,23 @@ impl ::std::default::Default for VideoEncodeH265CapabilitiesEXT { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null_mut(), flags: VideoEncodeH265CapabilityFlagsEXT::default(), - input_mode_flags: VideoEncodeH265InputModeFlagsEXT::default(), - output_mode_flags: VideoEncodeH265OutputModeFlagsEXT::default(), ctb_sizes: VideoEncodeH265CtbSizeFlagsEXT::default(), transform_block_sizes: VideoEncodeH265TransformBlockSizeFlagsEXT::default(), - max_p_picture_l0_reference_count: u8::default(), - max_b_picture_l0_reference_count: u8::default(), - max_l1_reference_count: u8::default(), - max_sub_layers_count: u8::default(), - min_log2_min_luma_coding_block_size_minus3: u8::default(), - max_log2_min_luma_coding_block_size_minus3: u8::default(), - min_log2_min_luma_transform_block_size_minus2: u8::default(), - max_log2_min_luma_transform_block_size_minus2: u8::default(), - min_max_transform_hierarchy_depth_inter: u8::default(), - max_max_transform_hierarchy_depth_inter: u8::default(), - min_max_transform_hierarchy_depth_intra: u8::default(), - max_max_transform_hierarchy_depth_intra: u8::default(), - max_diff_cu_qp_delta_depth: u8::default(), - min_max_num_merge_cand: u8::default(), - max_max_num_merge_cand: u8::default(), + max_p_picture_l0_reference_count: u32::default(), + max_b_picture_l0_reference_count: u32::default(), + max_l1_reference_count: u32::default(), + max_sub_layers_count: u32::default(), + min_log2_min_luma_coding_block_size_minus3: u32::default(), + max_log2_min_luma_coding_block_size_minus3: u32::default(), + min_log2_min_luma_transform_block_size_minus2: u32::default(), + max_log2_min_luma_transform_block_size_minus2: u32::default(), + min_max_transform_hierarchy_depth_inter: u32::default(), + max_max_transform_hierarchy_depth_inter: u32::default(), + min_max_transform_hierarchy_depth_intra: u32::default(), + max_max_transform_hierarchy_depth_intra: u32::default(), + max_diff_cu_qp_delta_depth: u32::default(), + min_max_num_merge_cand: u32::default(), + max_max_num_merge_cand: u32::default(), } } } @@ -59613,19 +59901,6 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { self } #[inline] - pub fn input_mode_flags(mut self, input_mode_flags: VideoEncodeH265InputModeFlagsEXT) -> Self { - self.inner.input_mode_flags = input_mode_flags; - self - } - #[inline] - pub fn output_mode_flags( - mut self, - output_mode_flags: VideoEncodeH265OutputModeFlagsEXT, - ) -> Self { - self.inner.output_mode_flags = output_mode_flags; - self - } - #[inline] pub fn ctb_sizes(mut self, ctb_sizes: VideoEncodeH265CtbSizeFlagsEXT) -> Self { self.inner.ctb_sizes = ctb_sizes; self @@ -59641,7 +59916,7 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn max_p_picture_l0_reference_count( mut self, - max_p_picture_l0_reference_count: u8, + max_p_picture_l0_reference_count: u32, ) -> Self { self.inner.max_p_picture_l0_reference_count = max_p_picture_l0_reference_count; self @@ -59649,25 +59924,25 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn max_b_picture_l0_reference_count( mut self, - max_b_picture_l0_reference_count: u8, + max_b_picture_l0_reference_count: u32, ) -> Self { self.inner.max_b_picture_l0_reference_count = max_b_picture_l0_reference_count; self } #[inline] - pub fn max_l1_reference_count(mut self, max_l1_reference_count: u8) -> Self { + pub fn max_l1_reference_count(mut self, max_l1_reference_count: u32) -> Self { self.inner.max_l1_reference_count = max_l1_reference_count; self } #[inline] - pub fn max_sub_layers_count(mut self, max_sub_layers_count: u8) -> Self { + pub fn max_sub_layers_count(mut self, max_sub_layers_count: u32) -> Self { self.inner.max_sub_layers_count = max_sub_layers_count; self } #[inline] pub fn min_log2_min_luma_coding_block_size_minus3( mut self, - min_log2_min_luma_coding_block_size_minus3: u8, + min_log2_min_luma_coding_block_size_minus3: u32, ) -> Self { self.inner.min_log2_min_luma_coding_block_size_minus3 = min_log2_min_luma_coding_block_size_minus3; @@ -59676,7 +59951,7 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn max_log2_min_luma_coding_block_size_minus3( mut self, - max_log2_min_luma_coding_block_size_minus3: u8, + max_log2_min_luma_coding_block_size_minus3: u32, ) -> Self { self.inner.max_log2_min_luma_coding_block_size_minus3 = max_log2_min_luma_coding_block_size_minus3; @@ -59685,7 +59960,7 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn min_log2_min_luma_transform_block_size_minus2( mut self, - min_log2_min_luma_transform_block_size_minus2: u8, + min_log2_min_luma_transform_block_size_minus2: u32, ) -> Self { self.inner.min_log2_min_luma_transform_block_size_minus2 = min_log2_min_luma_transform_block_size_minus2; @@ -59694,7 +59969,7 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn max_log2_min_luma_transform_block_size_minus2( mut self, - max_log2_min_luma_transform_block_size_minus2: u8, + max_log2_min_luma_transform_block_size_minus2: u32, ) -> Self { self.inner.max_log2_min_luma_transform_block_size_minus2 = max_log2_min_luma_transform_block_size_minus2; @@ -59703,7 +59978,7 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn min_max_transform_hierarchy_depth_inter( mut self, - min_max_transform_hierarchy_depth_inter: u8, + min_max_transform_hierarchy_depth_inter: u32, ) -> Self { self.inner.min_max_transform_hierarchy_depth_inter = min_max_transform_hierarchy_depth_inter; @@ -59712,7 +59987,7 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn max_max_transform_hierarchy_depth_inter( mut self, - max_max_transform_hierarchy_depth_inter: u8, + max_max_transform_hierarchy_depth_inter: u32, ) -> Self { self.inner.max_max_transform_hierarchy_depth_inter = max_max_transform_hierarchy_depth_inter; @@ -59721,7 +59996,7 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn min_max_transform_hierarchy_depth_intra( mut self, - min_max_transform_hierarchy_depth_intra: u8, + min_max_transform_hierarchy_depth_intra: u32, ) -> Self { self.inner.min_max_transform_hierarchy_depth_intra = min_max_transform_hierarchy_depth_intra; @@ -59730,24 +60005,24 @@ impl<'a> VideoEncodeH265CapabilitiesEXTBuilder<'a> { #[inline] pub fn max_max_transform_hierarchy_depth_intra( mut self, - max_max_transform_hierarchy_depth_intra: u8, + max_max_transform_hierarchy_depth_intra: u32, ) -> Self { self.inner.max_max_transform_hierarchy_depth_intra = max_max_transform_hierarchy_depth_intra; self } #[inline] - pub fn max_diff_cu_qp_delta_depth(mut self, max_diff_cu_qp_delta_depth: u8) -> Self { + pub fn max_diff_cu_qp_delta_depth(mut self, max_diff_cu_qp_delta_depth: u32) -> Self { self.inner.max_diff_cu_qp_delta_depth = max_diff_cu_qp_delta_depth; self } #[inline] - pub fn min_max_num_merge_cand(mut self, min_max_num_merge_cand: u8) -> Self { + pub fn min_max_num_merge_cand(mut self, min_max_num_merge_cand: u32) -> Self { self.inner.min_max_num_merge_cand = min_max_num_merge_cand; self } #[inline] - pub fn max_max_num_merge_cand(mut self, max_max_num_merge_cand: u8) -> Self { + pub fn max_max_num_merge_cand(mut self, max_max_num_merge_cand: u32) -> Self { self.inner.max_max_num_merge_cand = max_max_num_merge_cand; self } @@ -59948,10 +60223,10 @@ impl<'a> VideoEncodeH265SessionParametersCreateInfoEXTBuilder<'a> { pub struct VideoEncodeH265VclFrameInfoEXT { pub s_type: StructureType, pub p_next: *const c_void, - pub p_reference_final_lists: *const VideoEncodeH265ReferenceListsInfoEXT, + pub p_std_reference_final_lists: *const StdVideoEncodeH265ReferenceListsInfo, pub nalu_slice_segment_entry_count: u32, pub p_nalu_slice_segment_entries: *const VideoEncodeH265NaluSliceSegmentInfoEXT, - pub p_current_picture_info: *const StdVideoEncodeH265PictureInfo, + pub p_std_picture_info: *const StdVideoEncodeH265PictureInfo, } impl ::std::default::Default for VideoEncodeH265VclFrameInfoEXT { #[inline] @@ -59959,10 +60234,10 @@ impl ::std::default::Default for VideoEncodeH265VclFrameInfoEXT { Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), - p_reference_final_lists: ::std::ptr::null(), + p_std_reference_final_lists: ::std::ptr::null(), nalu_slice_segment_entry_count: u32::default(), p_nalu_slice_segment_entries: ::std::ptr::null(), - p_current_picture_info: ::std::ptr::null(), + p_std_picture_info: ::std::ptr::null(), } } } @@ -59997,11 +60272,11 @@ impl<'a> ::std::ops::DerefMut for VideoEncodeH265VclFrameInfoEXTBuilder<'a> { } impl<'a> VideoEncodeH265VclFrameInfoEXTBuilder<'a> { #[inline] - pub fn reference_final_lists( + pub fn std_reference_final_lists( mut self, - reference_final_lists: &'a VideoEncodeH265ReferenceListsInfoEXT, + std_reference_final_lists: &'a StdVideoEncodeH265ReferenceListsInfo, ) -> Self { - self.inner.p_reference_final_lists = reference_final_lists; + self.inner.p_std_reference_final_lists = std_reference_final_lists; self } #[inline] @@ -60014,11 +60289,8 @@ impl<'a> VideoEncodeH265VclFrameInfoEXTBuilder<'a> { self } #[inline] - pub fn current_picture_info( - mut self, - current_picture_info: &'a StdVideoEncodeH265PictureInfo, - ) -> Self { - self.inner.p_current_picture_info = current_picture_info; + pub fn std_picture_info(mut self, std_picture_info: &'a StdVideoEncodeH265PictureInfo) -> Self { + self.inner.p_std_picture_info = std_picture_info; self } #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] @@ -60031,106 +60303,13 @@ impl<'a> VideoEncodeH265VclFrameInfoEXTBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] -#[doc = ""] -pub struct VideoEncodeH265EmitPictureParametersInfoEXT { - pub s_type: StructureType, - pub p_next: *const c_void, - pub vps_id: u8, - pub sps_id: u8, - pub emit_vps_enable: Bool32, - pub emit_sps_enable: Bool32, - pub pps_id_entry_count: u32, - pub pps_id_entries: *const u8, -} -impl ::std::default::Default for VideoEncodeH265EmitPictureParametersInfoEXT { - #[inline] - fn default() -> Self { - Self { - s_type: Self::STRUCTURE_TYPE, - p_next: ::std::ptr::null(), - vps_id: u8::default(), - sps_id: u8::default(), - emit_vps_enable: Bool32::default(), - emit_sps_enable: Bool32::default(), - pps_id_entry_count: u32::default(), - pps_id_entries: ::std::ptr::null(), - } - } -} -unsafe impl TaggedStructure for VideoEncodeH265EmitPictureParametersInfoEXT { - const STRUCTURE_TYPE: StructureType = - StructureType::VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT; -} -impl VideoEncodeH265EmitPictureParametersInfoEXT { - pub fn builder<'a>() -> VideoEncodeH265EmitPictureParametersInfoEXTBuilder<'a> { - VideoEncodeH265EmitPictureParametersInfoEXTBuilder { - inner: Self::default(), - marker: ::std::marker::PhantomData, - } - } -} -#[repr(transparent)] -pub struct VideoEncodeH265EmitPictureParametersInfoEXTBuilder<'a> { - inner: VideoEncodeH265EmitPictureParametersInfoEXT, - marker: ::std::marker::PhantomData<&'a ()>, -} -unsafe impl ExtendsVideoEncodeInfoKHR for VideoEncodeH265EmitPictureParametersInfoEXTBuilder<'_> {} -unsafe impl ExtendsVideoEncodeInfoKHR for VideoEncodeH265EmitPictureParametersInfoEXT {} -impl<'a> ::std::ops::Deref for VideoEncodeH265EmitPictureParametersInfoEXTBuilder<'a> { - type Target = VideoEncodeH265EmitPictureParametersInfoEXT; - fn deref(&self) -> &Self::Target { - &self.inner - } -} -impl<'a> ::std::ops::DerefMut for VideoEncodeH265EmitPictureParametersInfoEXTBuilder<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} -impl<'a> VideoEncodeH265EmitPictureParametersInfoEXTBuilder<'a> { - #[inline] - pub fn vps_id(mut self, vps_id: u8) -> Self { - self.inner.vps_id = vps_id; - self - } - #[inline] - pub fn sps_id(mut self, sps_id: u8) -> Self { - self.inner.sps_id = sps_id; - self - } - #[inline] - pub fn emit_vps_enable(mut self, emit_vps_enable: bool) -> Self { - self.inner.emit_vps_enable = emit_vps_enable.into(); - self - } - #[inline] - pub fn emit_sps_enable(mut self, emit_sps_enable: bool) -> Self { - self.inner.emit_sps_enable = emit_sps_enable.into(); - self - } - #[inline] - pub fn pps_id_entries(mut self, pps_id_entries: &'a [u8]) -> Self { - self.inner.pps_id_entry_count = pps_id_entries.len() as _; - self.inner.pps_id_entries = pps_id_entries.as_ptr(); - self - } - #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] - #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] - #[doc = r" so references to builders can be passed directly to Vulkan functions."] - pub fn build(self) -> VideoEncodeH265EmitPictureParametersInfoEXT { - self.inner - } -} -#[repr(C)] -#[cfg_attr(feature = "debug", derive(Debug))] -#[derive(Copy, Clone)] #[doc = ""] pub struct VideoEncodeH265NaluSliceSegmentInfoEXT { pub s_type: StructureType, pub p_next: *const c_void, pub ctb_count: u32, - pub p_reference_final_lists: *const VideoEncodeH265ReferenceListsInfoEXT, - pub p_slice_segment_header_std: *const StdVideoEncodeH265SliceSegmentHeader, + pub p_std_reference_final_lists: *const StdVideoEncodeH265ReferenceListsInfo, + pub p_std_slice_segment_header: *const StdVideoEncodeH265SliceSegmentHeader, } impl ::std::default::Default for VideoEncodeH265NaluSliceSegmentInfoEXT { #[inline] @@ -60139,8 +60318,8 @@ impl ::std::default::Default for VideoEncodeH265NaluSliceSegmentInfoEXT { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), ctb_count: u32::default(), - p_reference_final_lists: ::std::ptr::null(), - p_slice_segment_header_std: ::std::ptr::null(), + p_std_reference_final_lists: ::std::ptr::null(), + p_std_slice_segment_header: ::std::ptr::null(), } } } @@ -60179,19 +60358,19 @@ impl<'a> VideoEncodeH265NaluSliceSegmentInfoEXTBuilder<'a> { self } #[inline] - pub fn reference_final_lists( + pub fn std_reference_final_lists( mut self, - reference_final_lists: &'a VideoEncodeH265ReferenceListsInfoEXT, + std_reference_final_lists: &'a StdVideoEncodeH265ReferenceListsInfo, ) -> Self { - self.inner.p_reference_final_lists = reference_final_lists; + self.inner.p_std_reference_final_lists = std_reference_final_lists; self } #[inline] - pub fn slice_segment_header_std( + pub fn std_slice_segment_header( mut self, - slice_segment_header_std: &'a StdVideoEncodeH265SliceSegmentHeader, + std_slice_segment_header: &'a StdVideoEncodeH265SliceSegmentHeader, ) -> Self { - self.inner.p_slice_segment_header_std = slice_segment_header_std; + self.inner.p_std_slice_segment_header = std_slice_segment_header; self } #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] @@ -60212,7 +60391,7 @@ pub struct VideoEncodeH265RateControlInfoEXT { pub idr_period: u32, pub consecutive_b_frame_count: u32, pub rate_control_structure: VideoEncodeH265RateControlStructureEXT, - pub sub_layer_count: u8, + pub sub_layer_count: u32, } impl ::std::default::Default for VideoEncodeH265RateControlInfoEXT { #[inline] @@ -60224,7 +60403,7 @@ impl ::std::default::Default for VideoEncodeH265RateControlInfoEXT { idr_period: u32::default(), consecutive_b_frame_count: u32::default(), rate_control_structure: VideoEncodeH265RateControlStructureEXT::default(), - sub_layer_count: u8::default(), + sub_layer_count: u32::default(), } } } @@ -60282,7 +60461,7 @@ impl<'a> VideoEncodeH265RateControlInfoEXTBuilder<'a> { self } #[inline] - pub fn sub_layer_count(mut self, sub_layer_count: u8) -> Self { + pub fn sub_layer_count(mut self, sub_layer_count: u32) -> Self { self.inner.sub_layer_count = sub_layer_count; self } @@ -60412,7 +60591,7 @@ impl<'a> VideoEncodeH265FrameSizeEXTBuilder<'a> { pub struct VideoEncodeH265RateControlLayerInfoEXT { pub s_type: StructureType, pub p_next: *const c_void, - pub temporal_id: u8, + pub temporal_id: u32, pub use_initial_rc_qp: Bool32, pub initial_rc_qp: VideoEncodeH265QpEXT, pub use_min_qp: Bool32, @@ -60428,7 +60607,7 @@ impl ::std::default::Default for VideoEncodeH265RateControlLayerInfoEXT { Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), - temporal_id: u8::default(), + temporal_id: u32::default(), use_initial_rc_qp: Bool32::default(), initial_rc_qp: VideoEncodeH265QpEXT::default(), use_min_qp: Bool32::default(), @@ -60477,7 +60656,7 @@ impl<'a> ::std::ops::DerefMut for VideoEncodeH265RateControlLayerInfoEXTBuilder< } impl<'a> VideoEncodeH265RateControlLayerInfoEXTBuilder<'a> { #[inline] - pub fn temporal_id(mut self, temporal_id: u8) -> Self { + pub fn temporal_id(mut self, temporal_id: u32) -> Self { self.inner.temporal_id = temporal_id; self } @@ -60598,7 +60777,6 @@ impl<'a> VideoEncodeH265ProfileInfoEXTBuilder<'a> { pub struct VideoEncodeH265DpbSlotInfoEXT { pub s_type: StructureType, pub p_next: *const c_void, - pub slot_index: i8, pub p_std_reference_info: *const StdVideoEncodeH265ReferenceInfo, } impl ::std::default::Default for VideoEncodeH265DpbSlotInfoEXT { @@ -60607,7 +60785,6 @@ impl ::std::default::Default for VideoEncodeH265DpbSlotInfoEXT { Self { s_type: Self::STRUCTURE_TYPE, p_next: ::std::ptr::null(), - slot_index: i8::default(), p_std_reference_info: ::std::ptr::null(), } } @@ -60628,6 +60805,8 @@ pub struct VideoEncodeH265DpbSlotInfoEXTBuilder<'a> { inner: VideoEncodeH265DpbSlotInfoEXT, marker: ::std::marker::PhantomData<&'a ()>, } +unsafe impl ExtendsVideoReferenceSlotInfoKHR for VideoEncodeH265DpbSlotInfoEXTBuilder<'_> {} +unsafe impl ExtendsVideoReferenceSlotInfoKHR for VideoEncodeH265DpbSlotInfoEXT {} impl<'a> ::std::ops::Deref for VideoEncodeH265DpbSlotInfoEXTBuilder<'a> { type Target = VideoEncodeH265DpbSlotInfoEXT; fn deref(&self) -> &Self::Target { @@ -60640,11 +60819,6 @@ impl<'a> ::std::ops::DerefMut for VideoEncodeH265DpbSlotInfoEXTBuilder<'a> { } } impl<'a> VideoEncodeH265DpbSlotInfoEXTBuilder<'a> { - #[inline] - pub fn slot_index(mut self, slot_index: i8) -> Self { - self.inner.slot_index = slot_index; - self - } #[inline] pub fn std_reference_info( mut self, @@ -60663,94 +60837,6 @@ impl<'a> VideoEncodeH265DpbSlotInfoEXTBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] -#[doc = ""] -pub struct VideoEncodeH265ReferenceListsInfoEXT { - pub s_type: StructureType, - pub p_next: *const c_void, - pub reference_list0_entry_count: u8, - pub p_reference_list0_entries: *const VideoEncodeH265DpbSlotInfoEXT, - pub reference_list1_entry_count: u8, - pub p_reference_list1_entries: *const VideoEncodeH265DpbSlotInfoEXT, - pub p_reference_modifications: *const StdVideoEncodeH265ReferenceModifications, -} -impl ::std::default::Default for VideoEncodeH265ReferenceListsInfoEXT { - #[inline] - fn default() -> Self { - Self { - s_type: Self::STRUCTURE_TYPE, - p_next: ::std::ptr::null(), - reference_list0_entry_count: u8::default(), - p_reference_list0_entries: ::std::ptr::null(), - reference_list1_entry_count: u8::default(), - p_reference_list1_entries: ::std::ptr::null(), - p_reference_modifications: ::std::ptr::null(), - } - } -} -unsafe impl TaggedStructure for VideoEncodeH265ReferenceListsInfoEXT { - const STRUCTURE_TYPE: StructureType = StructureType::VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT; -} -impl VideoEncodeH265ReferenceListsInfoEXT { - pub fn builder<'a>() -> VideoEncodeH265ReferenceListsInfoEXTBuilder<'a> { - VideoEncodeH265ReferenceListsInfoEXTBuilder { - inner: Self::default(), - marker: ::std::marker::PhantomData, - } - } -} -#[repr(transparent)] -pub struct VideoEncodeH265ReferenceListsInfoEXTBuilder<'a> { - inner: VideoEncodeH265ReferenceListsInfoEXT, - marker: ::std::marker::PhantomData<&'a ()>, -} -impl<'a> ::std::ops::Deref for VideoEncodeH265ReferenceListsInfoEXTBuilder<'a> { - type Target = VideoEncodeH265ReferenceListsInfoEXT; - fn deref(&self) -> &Self::Target { - &self.inner - } -} -impl<'a> ::std::ops::DerefMut for VideoEncodeH265ReferenceListsInfoEXTBuilder<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} -impl<'a> VideoEncodeH265ReferenceListsInfoEXTBuilder<'a> { - #[inline] - pub fn reference_list0_entries( - mut self, - reference_list0_entries: &'a [VideoEncodeH265DpbSlotInfoEXT], - ) -> Self { - self.inner.reference_list0_entry_count = reference_list0_entries.len() as _; - self.inner.p_reference_list0_entries = reference_list0_entries.as_ptr(); - self - } - #[inline] - pub fn reference_list1_entries( - mut self, - reference_list1_entries: &'a [VideoEncodeH265DpbSlotInfoEXT], - ) -> Self { - self.inner.reference_list1_entry_count = reference_list1_entries.len() as _; - self.inner.p_reference_list1_entries = reference_list1_entries.as_ptr(); - self - } - #[inline] - pub fn reference_modifications( - mut self, - reference_modifications: &'a StdVideoEncodeH265ReferenceModifications, - ) -> Self { - self.inner.p_reference_modifications = reference_modifications; - self - } - #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] - #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] - #[doc = r" so references to builders can be passed directly to Vulkan functions."] - pub fn build(self) -> VideoEncodeH265ReferenceListsInfoEXT { - self.inner - } -} -#[repr(C)] -#[cfg_attr(feature = "debug", derive(Debug))] -#[derive(Copy, Clone)] #[doc = ""] pub struct PhysicalDeviceInheritedViewportScissorFeaturesNV { pub s_type: StructureType, @@ -68736,6 +68822,370 @@ impl<'a> AccelerationStructureTrianglesOpacityMicromapEXTBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceDisplacementMicromapFeaturesNV { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub displacement_micromap: Bool32, +} +impl ::std::default::Default for PhysicalDeviceDisplacementMicromapFeaturesNV { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + displacement_micromap: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceDisplacementMicromapFeaturesNV { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV; +} +impl PhysicalDeviceDisplacementMicromapFeaturesNV { + pub fn builder<'a>() -> PhysicalDeviceDisplacementMicromapFeaturesNVBuilder<'a> { + PhysicalDeviceDisplacementMicromapFeaturesNVBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceDisplacementMicromapFeaturesNVBuilder<'a> { + inner: PhysicalDeviceDisplacementMicromapFeaturesNV, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceDisplacementMicromapFeaturesNVBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceFeatures2 for PhysicalDeviceDisplacementMicromapFeaturesNV {} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceDisplacementMicromapFeaturesNVBuilder<'_> {} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceDisplacementMicromapFeaturesNV {} +impl<'a> ::std::ops::Deref for PhysicalDeviceDisplacementMicromapFeaturesNVBuilder<'a> { + type Target = PhysicalDeviceDisplacementMicromapFeaturesNV; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceDisplacementMicromapFeaturesNVBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceDisplacementMicromapFeaturesNVBuilder<'a> { + #[inline] + pub fn displacement_micromap(mut self, displacement_micromap: bool) -> Self { + self.inner.displacement_micromap = displacement_micromap.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceDisplacementMicromapFeaturesNV { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceDisplacementMicromapPropertiesNV { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub max_displacement_micromap_subdivision_level: u32, +} +impl ::std::default::Default for PhysicalDeviceDisplacementMicromapPropertiesNV { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + max_displacement_micromap_subdivision_level: u32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceDisplacementMicromapPropertiesNV { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV; +} +impl PhysicalDeviceDisplacementMicromapPropertiesNV { + pub fn builder<'a>() -> PhysicalDeviceDisplacementMicromapPropertiesNVBuilder<'a> { + PhysicalDeviceDisplacementMicromapPropertiesNVBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceDisplacementMicromapPropertiesNVBuilder<'a> { + inner: PhysicalDeviceDisplacementMicromapPropertiesNV, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceProperties2 + for PhysicalDeviceDisplacementMicromapPropertiesNVBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceProperties2 for PhysicalDeviceDisplacementMicromapPropertiesNV {} +impl<'a> ::std::ops::Deref for PhysicalDeviceDisplacementMicromapPropertiesNVBuilder<'a> { + type Target = PhysicalDeviceDisplacementMicromapPropertiesNV; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceDisplacementMicromapPropertiesNVBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceDisplacementMicromapPropertiesNVBuilder<'a> { + #[inline] + pub fn max_displacement_micromap_subdivision_level( + mut self, + max_displacement_micromap_subdivision_level: u32, + ) -> Self { + self.inner.max_displacement_micromap_subdivision_level = + max_displacement_micromap_subdivision_level; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceDisplacementMicromapPropertiesNV { + self.inner + } +} +#[repr(C)] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct AccelerationStructureTrianglesDisplacementMicromapNV { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub displacement_bias_and_scale_format: Format, + pub displacement_vector_format: Format, + pub displacement_bias_and_scale_buffer: DeviceOrHostAddressConstKHR, + pub displacement_bias_and_scale_stride: DeviceSize, + pub displacement_vector_buffer: DeviceOrHostAddressConstKHR, + pub displacement_vector_stride: DeviceSize, + pub displaced_micromap_primitive_flags: DeviceOrHostAddressConstKHR, + pub displaced_micromap_primitive_flags_stride: DeviceSize, + pub index_type: IndexType, + pub index_buffer: DeviceOrHostAddressConstKHR, + pub index_stride: DeviceSize, + pub base_triangle: u32, + pub usage_counts_count: u32, + pub p_usage_counts: *const MicromapUsageEXT, + pub pp_usage_counts: *const *const MicromapUsageEXT, + pub micromap: MicromapEXT, +} +#[cfg(feature = "debug")] +impl fmt::Debug for AccelerationStructureTrianglesDisplacementMicromapNV { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("AccelerationStructureTrianglesDisplacementMicromapNV") + .field("s_type", &self.s_type) + .field("p_next", &self.p_next) + .field( + "displacement_bias_and_scale_format", + &self.displacement_bias_and_scale_format, + ) + .field( + "displacement_vector_format", + &self.displacement_vector_format, + ) + .field("displacement_bias_and_scale_buffer", &"union") + .field( + "displacement_bias_and_scale_stride", + &self.displacement_bias_and_scale_stride, + ) + .field("displacement_vector_buffer", &"union") + .field( + "displacement_vector_stride", + &self.displacement_vector_stride, + ) + .field("displaced_micromap_primitive_flags", &"union") + .field( + "displaced_micromap_primitive_flags_stride", + &self.displaced_micromap_primitive_flags_stride, + ) + .field("index_type", &self.index_type) + .field("index_buffer", &"union") + .field("index_stride", &self.index_stride) + .field("base_triangle", &self.base_triangle) + .field("usage_counts_count", &self.usage_counts_count) + .field("p_usage_counts", &self.p_usage_counts) + .field("pp_usage_counts", &self.pp_usage_counts) + .field("micromap", &self.micromap) + .finish() + } +} +impl ::std::default::Default for AccelerationStructureTrianglesDisplacementMicromapNV { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + displacement_bias_and_scale_format: Format::default(), + displacement_vector_format: Format::default(), + displacement_bias_and_scale_buffer: DeviceOrHostAddressConstKHR::default(), + displacement_bias_and_scale_stride: DeviceSize::default(), + displacement_vector_buffer: DeviceOrHostAddressConstKHR::default(), + displacement_vector_stride: DeviceSize::default(), + displaced_micromap_primitive_flags: DeviceOrHostAddressConstKHR::default(), + displaced_micromap_primitive_flags_stride: DeviceSize::default(), + index_type: IndexType::default(), + index_buffer: DeviceOrHostAddressConstKHR::default(), + index_stride: DeviceSize::default(), + base_triangle: u32::default(), + usage_counts_count: u32::default(), + p_usage_counts: ::std::ptr::null(), + pp_usage_counts: ::std::ptr::null(), + micromap: MicromapEXT::default(), + } + } +} +unsafe impl TaggedStructure for AccelerationStructureTrianglesDisplacementMicromapNV { + const STRUCTURE_TYPE: StructureType = + StructureType::ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV; +} +impl AccelerationStructureTrianglesDisplacementMicromapNV { + pub fn builder<'a>() -> AccelerationStructureTrianglesDisplacementMicromapNVBuilder<'a> { + AccelerationStructureTrianglesDisplacementMicromapNVBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct AccelerationStructureTrianglesDisplacementMicromapNVBuilder<'a> { + inner: AccelerationStructureTrianglesDisplacementMicromapNV, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsAccelerationStructureGeometryTrianglesDataKHR + for AccelerationStructureTrianglesDisplacementMicromapNVBuilder<'_> +{ +} +unsafe impl ExtendsAccelerationStructureGeometryTrianglesDataKHR + for AccelerationStructureTrianglesDisplacementMicromapNV +{ +} +impl<'a> ::std::ops::Deref for AccelerationStructureTrianglesDisplacementMicromapNVBuilder<'a> { + type Target = AccelerationStructureTrianglesDisplacementMicromapNV; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for AccelerationStructureTrianglesDisplacementMicromapNVBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> AccelerationStructureTrianglesDisplacementMicromapNVBuilder<'a> { + #[inline] + pub fn displacement_bias_and_scale_format( + mut self, + displacement_bias_and_scale_format: Format, + ) -> Self { + self.inner.displacement_bias_and_scale_format = displacement_bias_and_scale_format; + self + } + #[inline] + pub fn displacement_vector_format(mut self, displacement_vector_format: Format) -> Self { + self.inner.displacement_vector_format = displacement_vector_format; + self + } + #[inline] + pub fn displacement_bias_and_scale_buffer( + mut self, + displacement_bias_and_scale_buffer: DeviceOrHostAddressConstKHR, + ) -> Self { + self.inner.displacement_bias_and_scale_buffer = displacement_bias_and_scale_buffer; + self + } + #[inline] + pub fn displacement_bias_and_scale_stride( + mut self, + displacement_bias_and_scale_stride: DeviceSize, + ) -> Self { + self.inner.displacement_bias_and_scale_stride = displacement_bias_and_scale_stride; + self + } + #[inline] + pub fn displacement_vector_buffer( + mut self, + displacement_vector_buffer: DeviceOrHostAddressConstKHR, + ) -> Self { + self.inner.displacement_vector_buffer = displacement_vector_buffer; + self + } + #[inline] + pub fn displacement_vector_stride(mut self, displacement_vector_stride: DeviceSize) -> Self { + self.inner.displacement_vector_stride = displacement_vector_stride; + self + } + #[inline] + pub fn displaced_micromap_primitive_flags( + mut self, + displaced_micromap_primitive_flags: DeviceOrHostAddressConstKHR, + ) -> Self { + self.inner.displaced_micromap_primitive_flags = displaced_micromap_primitive_flags; + self + } + #[inline] + pub fn displaced_micromap_primitive_flags_stride( + mut self, + displaced_micromap_primitive_flags_stride: DeviceSize, + ) -> Self { + self.inner.displaced_micromap_primitive_flags_stride = + displaced_micromap_primitive_flags_stride; + self + } + #[inline] + pub fn index_type(mut self, index_type: IndexType) -> Self { + self.inner.index_type = index_type; + self + } + #[inline] + pub fn index_buffer(mut self, index_buffer: DeviceOrHostAddressConstKHR) -> Self { + self.inner.index_buffer = index_buffer; + self + } + #[inline] + pub fn index_stride(mut self, index_stride: DeviceSize) -> Self { + self.inner.index_stride = index_stride; + self + } + #[inline] + pub fn base_triangle(mut self, base_triangle: u32) -> Self { + self.inner.base_triangle = base_triangle; + self + } + #[inline] + pub fn usage_counts(mut self, usage_counts: &'a [MicromapUsageEXT]) -> Self { + self.inner.usage_counts_count = usage_counts.len() as _; + self.inner.p_usage_counts = usage_counts.as_ptr(); + self + } + #[inline] + pub fn usage_counts_ptrs(mut self, usage_counts_ptrs: &'a [&'a MicromapUsageEXT]) -> Self { + self.inner.usage_counts_count = usage_counts_ptrs.len() as _; + self.inner.pp_usage_counts = usage_counts_ptrs.as_ptr().cast(); + self + } + #[inline] + pub fn micromap(mut self, micromap: MicromapEXT) -> Self { + self.inner.micromap = micromap; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> AccelerationStructureTrianglesDisplacementMicromapNV { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] #[doc = ""] pub struct PipelinePropertiesIdentifierEXT { pub s_type: StructureType, @@ -71870,6 +72320,8 @@ pub struct DeviceFaultVendorBinaryHeaderVersionOneEXT { pub application_name_offset: u32, pub application_version: u32, pub engine_name_offset: u32, + pub engine_version: u32, + pub api_version: u32, } impl ::std::default::Default for DeviceFaultVendorBinaryHeaderVersionOneEXT { #[inline] @@ -71884,6 +72336,8 @@ impl ::std::default::Default for DeviceFaultVendorBinaryHeaderVersionOneEXT { application_name_offset: u32::default(), application_version: u32::default(), engine_name_offset: u32::default(), + engine_version: u32::default(), + api_version: u32::default(), } } } @@ -71960,6 +72414,16 @@ impl<'a> DeviceFaultVendorBinaryHeaderVersionOneEXTBuilder<'a> { self.inner.engine_name_offset = engine_name_offset; self } + #[inline] + pub fn engine_version(mut self, engine_version: u32) -> Self { + self.inner.engine_version = engine_version; + self + } + #[inline] + pub fn api_version(mut self, api_version: u32) -> Self { + self.inner.api_version = api_version; + self + } #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] #[doc = r" so references to builders can be passed directly to Vulkan functions."] @@ -71969,6 +72433,79 @@ impl<'a> DeviceFaultVendorBinaryHeaderVersionOneEXTBuilder<'a> { } #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub pipeline_library_group_handles: Bool32, +} +impl ::std::default::Default for PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + pipeline_library_group_handles: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT; +} +impl PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { + pub fn builder<'a>() -> PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXTBuilder<'a> { + PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXTBuilder<'a> { + inner: PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXTBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT +{ +} +unsafe impl ExtendsDeviceCreateInfo + for PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXTBuilder<'_> +{ +} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT {} +impl<'a> ::std::ops::Deref for PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXTBuilder<'a> { + type Target = PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXTBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXTBuilder<'a> { + #[inline] + pub fn pipeline_library_group_handles(mut self, pipeline_library_group_handles: bool) -> Self { + self.inner.pipeline_library_group_handles = pipeline_library_group_handles.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone, Default)] #[doc = ""] pub struct DecompressMemoryRegionNV { @@ -72187,6 +72724,87 @@ impl<'a> PhysicalDeviceShaderCoreBuiltinsFeaturesARMBuilder<'a> { #[repr(C)] #[cfg_attr(feature = "debug", derive(Debug))] #[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub dynamic_rendering_unused_attachments: Bool32, +} +impl ::std::default::Default for PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + dynamic_rendering_unused_attachments: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT; +} +impl PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { + pub fn builder<'a>() -> PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXTBuilder<'a> { + PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXTBuilder<'a> { + inner: PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXTBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT +{ +} +unsafe impl ExtendsDeviceCreateInfo + for PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXTBuilder<'_> +{ +} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT {} +impl<'a> ::std::ops::Deref + for PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXTBuilder<'a> +{ + type Target = PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut + for PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXTBuilder<'a> +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXTBuilder<'a> { + #[inline] + pub fn dynamic_rendering_unused_attachments( + mut self, + dynamic_rendering_unused_attachments: bool, + ) -> Self { + self.inner.dynamic_rendering_unused_attachments = + dynamic_rendering_unused_attachments.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] #[doc = ""] pub struct SurfacePresentModeEXT { pub s_type: StructureType, @@ -72480,7 +73098,7 @@ impl<'a> PhysicalDeviceSwapchainMaintenance1FeaturesEXTBuilder<'a> { #[doc = ""] pub struct SwapchainPresentFenceInfoEXT { pub s_type: StructureType, - pub p_next: *mut c_void, + pub p_next: *const c_void, pub swapchain_count: u32, pub p_fences: *const Fence, } @@ -72489,7 +73107,7 @@ impl ::std::default::Default for SwapchainPresentFenceInfoEXT { fn default() -> Self { Self { s_type: Self::STRUCTURE_TYPE, - p_next: ::std::ptr::null_mut(), + p_next: ::std::ptr::null(), swapchain_count: u32::default(), p_fences: ::std::ptr::null(), } @@ -72544,7 +73162,7 @@ impl<'a> SwapchainPresentFenceInfoEXTBuilder<'a> { #[doc = ""] pub struct SwapchainPresentModesCreateInfoEXT { pub s_type: StructureType, - pub p_next: *mut c_void, + pub p_next: *const c_void, pub present_mode_count: u32, pub p_present_modes: *const PresentModeKHR, } @@ -72553,7 +73171,7 @@ impl ::std::default::Default for SwapchainPresentModesCreateInfoEXT { fn default() -> Self { Self { s_type: Self::STRUCTURE_TYPE, - p_next: ::std::ptr::null_mut(), + p_next: ::std::ptr::null(), present_mode_count: u32::default(), p_present_modes: ::std::ptr::null(), } @@ -72608,7 +73226,7 @@ impl<'a> SwapchainPresentModesCreateInfoEXTBuilder<'a> { #[doc = ""] pub struct SwapchainPresentModeInfoEXT { pub s_type: StructureType, - pub p_next: *mut c_void, + pub p_next: *const c_void, pub swapchain_count: u32, pub p_present_modes: *const PresentModeKHR, } @@ -72617,7 +73235,7 @@ impl ::std::default::Default for SwapchainPresentModeInfoEXT { fn default() -> Self { Self { s_type: Self::STRUCTURE_TYPE, - p_next: ::std::ptr::null_mut(), + p_next: ::std::ptr::null(), swapchain_count: u32::default(), p_present_modes: ::std::ptr::null(), } @@ -73176,3 +73794,955 @@ impl<'a> PhysicalDeviceMultiviewPerViewViewportsFeaturesQCOMBuilder<'a> { self.inner } } +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceRayTracingPositionFetchFeaturesKHR { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub ray_tracing_position_fetch: Bool32, +} +impl ::std::default::Default for PhysicalDeviceRayTracingPositionFetchFeaturesKHR { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + ray_tracing_position_fetch: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceRayTracingPositionFetchFeaturesKHR { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR; +} +impl PhysicalDeviceRayTracingPositionFetchFeaturesKHR { + pub fn builder<'a>() -> PhysicalDeviceRayTracingPositionFetchFeaturesKHRBuilder<'a> { + PhysicalDeviceRayTracingPositionFetchFeaturesKHRBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceRayTracingPositionFetchFeaturesKHRBuilder<'a> { + inner: PhysicalDeviceRayTracingPositionFetchFeaturesKHR, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceRayTracingPositionFetchFeaturesKHRBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceFeatures2 for PhysicalDeviceRayTracingPositionFetchFeaturesKHR {} +unsafe impl ExtendsDeviceCreateInfo + for PhysicalDeviceRayTracingPositionFetchFeaturesKHRBuilder<'_> +{ +} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceRayTracingPositionFetchFeaturesKHR {} +impl<'a> ::std::ops::Deref for PhysicalDeviceRayTracingPositionFetchFeaturesKHRBuilder<'a> { + type Target = PhysicalDeviceRayTracingPositionFetchFeaturesKHR; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceRayTracingPositionFetchFeaturesKHRBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceRayTracingPositionFetchFeaturesKHRBuilder<'a> { + #[inline] + pub fn ray_tracing_position_fetch(mut self, ray_tracing_position_fetch: bool) -> Self { + self.inner.ray_tracing_position_fetch = ray_tracing_position_fetch.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceRayTracingPositionFetchFeaturesKHR { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceShaderCorePropertiesARM { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub pixel_rate: u32, + pub texel_rate: u32, + pub fma_rate: u32, +} +impl ::std::default::Default for PhysicalDeviceShaderCorePropertiesARM { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + pixel_rate: u32::default(), + texel_rate: u32::default(), + fma_rate: u32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceShaderCorePropertiesARM { + const STRUCTURE_TYPE: StructureType = StructureType::PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM; +} +impl PhysicalDeviceShaderCorePropertiesARM { + pub fn builder<'a>() -> PhysicalDeviceShaderCorePropertiesARMBuilder<'a> { + PhysicalDeviceShaderCorePropertiesARMBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceShaderCorePropertiesARMBuilder<'a> { + inner: PhysicalDeviceShaderCorePropertiesARM, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceProperties2 for PhysicalDeviceShaderCorePropertiesARMBuilder<'_> {} +unsafe impl ExtendsPhysicalDeviceProperties2 for PhysicalDeviceShaderCorePropertiesARM {} +impl<'a> ::std::ops::Deref for PhysicalDeviceShaderCorePropertiesARMBuilder<'a> { + type Target = PhysicalDeviceShaderCorePropertiesARM; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceShaderCorePropertiesARMBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceShaderCorePropertiesARMBuilder<'a> { + #[inline] + pub fn pixel_rate(mut self, pixel_rate: u32) -> Self { + self.inner.pixel_rate = pixel_rate; + self + } + #[inline] + pub fn texel_rate(mut self, texel_rate: u32) -> Self { + self.inner.texel_rate = texel_rate; + self + } + #[inline] + pub fn fma_rate(mut self, fma_rate: u32) -> Self { + self.inner.fma_rate = fma_rate; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceShaderCorePropertiesARM { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub multiview_per_view_render_areas: Bool32, +} +impl ::std::default::Default for PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + multiview_per_view_render_areas: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM; +} +impl PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { + pub fn builder<'a>() -> PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOMBuilder<'a> { + PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOMBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOMBuilder<'a> { + inner: PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOMBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceFeatures2 + for PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM +{ +} +unsafe impl ExtendsDeviceCreateInfo + for PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOMBuilder<'_> +{ +} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM {} +impl<'a> ::std::ops::Deref for PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOMBuilder<'a> { + type Target = PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOMBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOMBuilder<'a> { + #[inline] + pub fn multiview_per_view_render_areas( + mut self, + multiview_per_view_render_areas: bool, + ) -> Self { + self.inner.multiview_per_view_render_areas = multiview_per_view_render_areas.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { + pub s_type: StructureType, + pub p_next: *const c_void, + pub per_view_render_area_count: u32, + pub p_per_view_render_areas: *const Rect2D, +} +impl ::std::default::Default for MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null(), + per_view_render_area_count: u32::default(), + p_per_view_render_areas: ::std::ptr::null(), + } + } +} +unsafe impl TaggedStructure for MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { + const STRUCTURE_TYPE: StructureType = + StructureType::MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM; +} +impl MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { + pub fn builder<'a>() -> MultiviewPerViewRenderAreasRenderPassBeginInfoQCOMBuilder<'a> { + MultiviewPerViewRenderAreasRenderPassBeginInfoQCOMBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct MultiviewPerViewRenderAreasRenderPassBeginInfoQCOMBuilder<'a> { + inner: MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsRenderPassBeginInfo + for MultiviewPerViewRenderAreasRenderPassBeginInfoQCOMBuilder<'_> +{ +} +unsafe impl ExtendsRenderPassBeginInfo for MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM {} +unsafe impl ExtendsRenderingInfo for MultiviewPerViewRenderAreasRenderPassBeginInfoQCOMBuilder<'_> {} +unsafe impl ExtendsRenderingInfo for MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM {} +impl<'a> ::std::ops::Deref for MultiviewPerViewRenderAreasRenderPassBeginInfoQCOMBuilder<'a> { + type Target = MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for MultiviewPerViewRenderAreasRenderPassBeginInfoQCOMBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> MultiviewPerViewRenderAreasRenderPassBeginInfoQCOMBuilder<'a> { + #[inline] + pub fn per_view_render_areas(mut self, per_view_render_areas: &'a [Rect2D]) -> Self { + self.inner.per_view_render_area_count = per_view_render_areas.len() as _; + self.inner.p_per_view_render_areas = per_view_render_areas.as_ptr(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct QueryLowLatencySupportNV { + pub s_type: StructureType, + pub p_next: *const c_void, + pub p_queried_low_latency_data: *mut c_void, +} +impl ::std::default::Default for QueryLowLatencySupportNV { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null(), + p_queried_low_latency_data: ::std::ptr::null_mut(), + } + } +} +unsafe impl TaggedStructure for QueryLowLatencySupportNV { + const STRUCTURE_TYPE: StructureType = StructureType::QUERY_LOW_LATENCY_SUPPORT_NV; +} +impl QueryLowLatencySupportNV { + pub fn builder<'a>() -> QueryLowLatencySupportNVBuilder<'a> { + QueryLowLatencySupportNVBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct QueryLowLatencySupportNVBuilder<'a> { + inner: QueryLowLatencySupportNV, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsSemaphoreCreateInfo for QueryLowLatencySupportNVBuilder<'_> {} +unsafe impl ExtendsSemaphoreCreateInfo for QueryLowLatencySupportNV {} +impl<'a> ::std::ops::Deref for QueryLowLatencySupportNVBuilder<'a> { + type Target = QueryLowLatencySupportNV; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for QueryLowLatencySupportNVBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> QueryLowLatencySupportNVBuilder<'a> { + #[inline] + pub fn queried_low_latency_data(mut self, queried_low_latency_data: *mut c_void) -> Self { + self.inner.p_queried_low_latency_data = queried_low_latency_data; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> QueryLowLatencySupportNV { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct MemoryMapInfoKHR { + pub s_type: StructureType, + pub p_next: *const c_void, + pub flags: MemoryMapFlags, + pub memory: DeviceMemory, + pub offset: DeviceSize, + pub size: DeviceSize, +} +impl ::std::default::Default for MemoryMapInfoKHR { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null(), + flags: MemoryMapFlags::default(), + memory: DeviceMemory::default(), + offset: DeviceSize::default(), + size: DeviceSize::default(), + } + } +} +unsafe impl TaggedStructure for MemoryMapInfoKHR { + const STRUCTURE_TYPE: StructureType = StructureType::MEMORY_MAP_INFO_KHR; +} +impl MemoryMapInfoKHR { + pub fn builder<'a>() -> MemoryMapInfoKHRBuilder<'a> { + MemoryMapInfoKHRBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct MemoryMapInfoKHRBuilder<'a> { + inner: MemoryMapInfoKHR, + marker: ::std::marker::PhantomData<&'a ()>, +} +impl<'a> ::std::ops::Deref for MemoryMapInfoKHRBuilder<'a> { + type Target = MemoryMapInfoKHR; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for MemoryMapInfoKHRBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> MemoryMapInfoKHRBuilder<'a> { + #[inline] + pub fn flags(mut self, flags: MemoryMapFlags) -> Self { + self.inner.flags = flags; + self + } + #[inline] + pub fn memory(mut self, memory: DeviceMemory) -> Self { + self.inner.memory = memory; + self + } + #[inline] + pub fn offset(mut self, offset: DeviceSize) -> Self { + self.inner.offset = offset; + self + } + #[inline] + pub fn size(mut self, size: DeviceSize) -> Self { + self.inner.size = size; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> MemoryMapInfoKHR { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct MemoryUnmapInfoKHR { + pub s_type: StructureType, + pub p_next: *const c_void, + pub flags: MemoryUnmapFlagsKHR, + pub memory: DeviceMemory, +} +impl ::std::default::Default for MemoryUnmapInfoKHR { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null(), + flags: MemoryUnmapFlagsKHR::default(), + memory: DeviceMemory::default(), + } + } +} +unsafe impl TaggedStructure for MemoryUnmapInfoKHR { + const STRUCTURE_TYPE: StructureType = StructureType::MEMORY_UNMAP_INFO_KHR; +} +impl MemoryUnmapInfoKHR { + pub fn builder<'a>() -> MemoryUnmapInfoKHRBuilder<'a> { + MemoryUnmapInfoKHRBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct MemoryUnmapInfoKHRBuilder<'a> { + inner: MemoryUnmapInfoKHR, + marker: ::std::marker::PhantomData<&'a ()>, +} +impl<'a> ::std::ops::Deref for MemoryUnmapInfoKHRBuilder<'a> { + type Target = MemoryUnmapInfoKHR; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for MemoryUnmapInfoKHRBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> MemoryUnmapInfoKHRBuilder<'a> { + #[inline] + pub fn flags(mut self, flags: MemoryUnmapFlagsKHR) -> Self { + self.inner.flags = flags; + self + } + #[inline] + pub fn memory(mut self, memory: DeviceMemory) -> Self { + self.inner.memory = memory; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> MemoryUnmapInfoKHR { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceShaderObjectFeaturesEXT { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub shader_object: Bool32, +} +impl ::std::default::Default for PhysicalDeviceShaderObjectFeaturesEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + shader_object: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceShaderObjectFeaturesEXT { + const STRUCTURE_TYPE: StructureType = StructureType::PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT; +} +impl PhysicalDeviceShaderObjectFeaturesEXT { + pub fn builder<'a>() -> PhysicalDeviceShaderObjectFeaturesEXTBuilder<'a> { + PhysicalDeviceShaderObjectFeaturesEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceShaderObjectFeaturesEXTBuilder<'a> { + inner: PhysicalDeviceShaderObjectFeaturesEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 for PhysicalDeviceShaderObjectFeaturesEXTBuilder<'_> {} +unsafe impl ExtendsPhysicalDeviceFeatures2 for PhysicalDeviceShaderObjectFeaturesEXT {} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceShaderObjectFeaturesEXTBuilder<'_> {} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceShaderObjectFeaturesEXT {} +impl<'a> ::std::ops::Deref for PhysicalDeviceShaderObjectFeaturesEXTBuilder<'a> { + type Target = PhysicalDeviceShaderObjectFeaturesEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceShaderObjectFeaturesEXTBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceShaderObjectFeaturesEXTBuilder<'a> { + #[inline] + pub fn shader_object(mut self, shader_object: bool) -> Self { + self.inner.shader_object = shader_object.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceShaderObjectFeaturesEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceShaderObjectPropertiesEXT { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub shader_binary_uuid: [u8; UUID_SIZE], + pub shader_binary_version: u32, +} +impl ::std::default::Default for PhysicalDeviceShaderObjectPropertiesEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + shader_binary_uuid: unsafe { ::std::mem::zeroed() }, + shader_binary_version: u32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceShaderObjectPropertiesEXT { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT; +} +impl PhysicalDeviceShaderObjectPropertiesEXT { + pub fn builder<'a>() -> PhysicalDeviceShaderObjectPropertiesEXTBuilder<'a> { + PhysicalDeviceShaderObjectPropertiesEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceShaderObjectPropertiesEXTBuilder<'a> { + inner: PhysicalDeviceShaderObjectPropertiesEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceProperties2 + for PhysicalDeviceShaderObjectPropertiesEXTBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceProperties2 for PhysicalDeviceShaderObjectPropertiesEXT {} +impl<'a> ::std::ops::Deref for PhysicalDeviceShaderObjectPropertiesEXTBuilder<'a> { + type Target = PhysicalDeviceShaderObjectPropertiesEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceShaderObjectPropertiesEXTBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceShaderObjectPropertiesEXTBuilder<'a> { + #[inline] + pub fn shader_binary_uuid(mut self, shader_binary_uuid: [u8; UUID_SIZE]) -> Self { + self.inner.shader_binary_uuid = shader_binary_uuid; + self + } + #[inline] + pub fn shader_binary_version(mut self, shader_binary_version: u32) -> Self { + self.inner.shader_binary_version = shader_binary_version; + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceShaderObjectPropertiesEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct ShaderCreateInfoEXT { + pub s_type: StructureType, + pub p_next: *const c_void, + pub flags: ShaderCreateFlagsEXT, + pub stage: ShaderStageFlags, + pub next_stage: ShaderStageFlags, + pub code_type: ShaderCodeTypeEXT, + pub code_size: usize, + pub p_code: *const c_void, + pub p_name: *const c_char, + pub set_layout_count: u32, + pub p_set_layouts: *const DescriptorSetLayout, + pub push_constant_range_count: u32, + pub p_push_constant_ranges: *const PushConstantRange, + pub p_specialization_info: *const SpecializationInfo, +} +impl ::std::default::Default for ShaderCreateInfoEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null(), + flags: ShaderCreateFlagsEXT::default(), + stage: ShaderStageFlags::default(), + next_stage: ShaderStageFlags::default(), + code_type: ShaderCodeTypeEXT::default(), + code_size: usize::default(), + p_code: ::std::ptr::null(), + p_name: ::std::ptr::null(), + set_layout_count: u32::default(), + p_set_layouts: ::std::ptr::null(), + push_constant_range_count: u32::default(), + p_push_constant_ranges: ::std::ptr::null(), + p_specialization_info: ::std::ptr::null(), + } + } +} +unsafe impl TaggedStructure for ShaderCreateInfoEXT { + const STRUCTURE_TYPE: StructureType = StructureType::SHADER_CREATE_INFO_EXT; +} +impl ShaderCreateInfoEXT { + pub fn builder<'a>() -> ShaderCreateInfoEXTBuilder<'a> { + ShaderCreateInfoEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct ShaderCreateInfoEXTBuilder<'a> { + inner: ShaderCreateInfoEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +pub unsafe trait ExtendsShaderCreateInfoEXT {} +impl<'a> ::std::ops::Deref for ShaderCreateInfoEXTBuilder<'a> { + type Target = ShaderCreateInfoEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for ShaderCreateInfoEXTBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> ShaderCreateInfoEXTBuilder<'a> { + #[inline] + pub fn flags(mut self, flags: ShaderCreateFlagsEXT) -> Self { + self.inner.flags = flags; + self + } + #[inline] + pub fn stage(mut self, stage: ShaderStageFlags) -> Self { + self.inner.stage = stage; + self + } + #[inline] + pub fn next_stage(mut self, next_stage: ShaderStageFlags) -> Self { + self.inner.next_stage = next_stage; + self + } + #[inline] + pub fn code_type(mut self, code_type: ShaderCodeTypeEXT) -> Self { + self.inner.code_type = code_type; + self + } + #[inline] + pub fn code(mut self, code: &'a [u8]) -> Self { + self.inner.code_size = code.len(); + self.inner.p_code = code.as_ptr().cast(); + self + } + #[inline] + pub fn name(mut self, name: &'a ::std::ffi::CStr) -> Self { + self.inner.p_name = name.as_ptr(); + self + } + #[inline] + pub fn set_layouts(mut self, set_layouts: &'a [DescriptorSetLayout]) -> Self { + self.inner.set_layout_count = set_layouts.len() as _; + self.inner.p_set_layouts = set_layouts.as_ptr(); + self + } + #[inline] + pub fn push_constant_ranges(mut self, push_constant_ranges: &'a [PushConstantRange]) -> Self { + self.inner.push_constant_range_count = push_constant_ranges.len() as _; + self.inner.p_push_constant_ranges = push_constant_ranges.as_ptr(); + self + } + #[inline] + pub fn specialization_info(mut self, specialization_info: &'a SpecializationInfo) -> Self { + self.inner.p_specialization_info = specialization_info; + self + } + #[doc = r" Prepends the given extension struct between the root and the first pointer. This"] + #[doc = r" method only exists on structs that can be passed to a function directly. Only"] + #[doc = r" valid extension structs can be pushed into the chain."] + #[doc = r" If the chain looks like `A -> B -> C`, and you call `builder.push_next(&mut D)`, then the"] + #[doc = r" chain will look like `A -> D -> B -> C`."] + pub fn push_next(mut self, next: &'a mut T) -> Self { + unsafe { + let next_ptr = <*const T>::cast(next); + let last_next = ptr_chain_iter(next).last().unwrap(); + (*last_next).p_next = self.inner.p_next as _; + self.inner.p_next = next_ptr; + } + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> ShaderCreateInfoEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceShaderTileImageFeaturesEXT { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub shader_tile_image_color_read_access: Bool32, + pub shader_tile_image_depth_read_access: Bool32, + pub shader_tile_image_stencil_read_access: Bool32, +} +impl ::std::default::Default for PhysicalDeviceShaderTileImageFeaturesEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + shader_tile_image_color_read_access: Bool32::default(), + shader_tile_image_depth_read_access: Bool32::default(), + shader_tile_image_stencil_read_access: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceShaderTileImageFeaturesEXT { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT; +} +impl PhysicalDeviceShaderTileImageFeaturesEXT { + pub fn builder<'a>() -> PhysicalDeviceShaderTileImageFeaturesEXTBuilder<'a> { + PhysicalDeviceShaderTileImageFeaturesEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceShaderTileImageFeaturesEXTBuilder<'a> { + inner: PhysicalDeviceShaderTileImageFeaturesEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceFeatures2 for PhysicalDeviceShaderTileImageFeaturesEXTBuilder<'_> {} +unsafe impl ExtendsPhysicalDeviceFeatures2 for PhysicalDeviceShaderTileImageFeaturesEXT {} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceShaderTileImageFeaturesEXTBuilder<'_> {} +unsafe impl ExtendsDeviceCreateInfo for PhysicalDeviceShaderTileImageFeaturesEXT {} +impl<'a> ::std::ops::Deref for PhysicalDeviceShaderTileImageFeaturesEXTBuilder<'a> { + type Target = PhysicalDeviceShaderTileImageFeaturesEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceShaderTileImageFeaturesEXTBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceShaderTileImageFeaturesEXTBuilder<'a> { + #[inline] + pub fn shader_tile_image_color_read_access( + mut self, + shader_tile_image_color_read_access: bool, + ) -> Self { + self.inner.shader_tile_image_color_read_access = shader_tile_image_color_read_access.into(); + self + } + #[inline] + pub fn shader_tile_image_depth_read_access( + mut self, + shader_tile_image_depth_read_access: bool, + ) -> Self { + self.inner.shader_tile_image_depth_read_access = shader_tile_image_depth_read_access.into(); + self + } + #[inline] + pub fn shader_tile_image_stencil_read_access( + mut self, + shader_tile_image_stencil_read_access: bool, + ) -> Self { + self.inner.shader_tile_image_stencil_read_access = + shader_tile_image_stencil_read_access.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceShaderTileImageFeaturesEXT { + self.inner + } +} +#[repr(C)] +#[cfg_attr(feature = "debug", derive(Debug))] +#[derive(Copy, Clone)] +#[doc = ""] +pub struct PhysicalDeviceShaderTileImagePropertiesEXT { + pub s_type: StructureType, + pub p_next: *mut c_void, + pub shader_tile_image_coherent_read_accelerated: Bool32, + pub shader_tile_image_read_sample_from_pixel_rate_invocation: Bool32, + pub shader_tile_image_read_from_helper_invocation: Bool32, +} +impl ::std::default::Default for PhysicalDeviceShaderTileImagePropertiesEXT { + #[inline] + fn default() -> Self { + Self { + s_type: Self::STRUCTURE_TYPE, + p_next: ::std::ptr::null_mut(), + shader_tile_image_coherent_read_accelerated: Bool32::default(), + shader_tile_image_read_sample_from_pixel_rate_invocation: Bool32::default(), + shader_tile_image_read_from_helper_invocation: Bool32::default(), + } + } +} +unsafe impl TaggedStructure for PhysicalDeviceShaderTileImagePropertiesEXT { + const STRUCTURE_TYPE: StructureType = + StructureType::PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT; +} +impl PhysicalDeviceShaderTileImagePropertiesEXT { + pub fn builder<'a>() -> PhysicalDeviceShaderTileImagePropertiesEXTBuilder<'a> { + PhysicalDeviceShaderTileImagePropertiesEXTBuilder { + inner: Self::default(), + marker: ::std::marker::PhantomData, + } + } +} +#[repr(transparent)] +pub struct PhysicalDeviceShaderTileImagePropertiesEXTBuilder<'a> { + inner: PhysicalDeviceShaderTileImagePropertiesEXT, + marker: ::std::marker::PhantomData<&'a ()>, +} +unsafe impl ExtendsPhysicalDeviceProperties2 + for PhysicalDeviceShaderTileImagePropertiesEXTBuilder<'_> +{ +} +unsafe impl ExtendsPhysicalDeviceProperties2 for PhysicalDeviceShaderTileImagePropertiesEXT {} +impl<'a> ::std::ops::Deref for PhysicalDeviceShaderTileImagePropertiesEXTBuilder<'a> { + type Target = PhysicalDeviceShaderTileImagePropertiesEXT; + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl<'a> ::std::ops::DerefMut for PhysicalDeviceShaderTileImagePropertiesEXTBuilder<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} +impl<'a> PhysicalDeviceShaderTileImagePropertiesEXTBuilder<'a> { + #[inline] + pub fn shader_tile_image_coherent_read_accelerated( + mut self, + shader_tile_image_coherent_read_accelerated: bool, + ) -> Self { + self.inner.shader_tile_image_coherent_read_accelerated = + shader_tile_image_coherent_read_accelerated.into(); + self + } + #[inline] + pub fn shader_tile_image_read_sample_from_pixel_rate_invocation( + mut self, + shader_tile_image_read_sample_from_pixel_rate_invocation: bool, + ) -> Self { + self.inner + .shader_tile_image_read_sample_from_pixel_rate_invocation = + shader_tile_image_read_sample_from_pixel_rate_invocation.into(); + self + } + #[inline] + pub fn shader_tile_image_read_from_helper_invocation( + mut self, + shader_tile_image_read_from_helper_invocation: bool, + ) -> Self { + self.inner.shader_tile_image_read_from_helper_invocation = + shader_tile_image_read_from_helper_invocation.into(); + self + } + #[doc = r" Calling build will **discard** all the lifetime information. Only call this if"] + #[doc = r" necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,"] + #[doc = r" so references to builders can be passed directly to Vulkan functions."] + pub fn build(self) -> PhysicalDeviceShaderTileImagePropertiesEXT { + self.inner + } +} diff --git a/third_party/rust/ash/src/vk/enums.rs b/third_party/rust/ash/src/vk/enums.rs index a27a55b40c5e..6201209715f2 100644 --- a/third_party/rust/ash/src/vk/enums.rs +++ b/third_party/rust/ash/src/vk/enums.rs @@ -1744,6 +1744,8 @@ impl VendorId { pub const MESA: Self = Self(0x1_0005); #[doc = "PoCL vendor ID"] pub const POCL: Self = Self(0x1_0006); + #[doc = "Mobileye vendor ID"] + pub const MOBILEYE: Self = Self(0x1_0007); } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[repr(transparent)] @@ -1808,6 +1810,8 @@ impl DriverId { pub const MESA_DOZEN: Self = Self(23); #[doc = "Mesa open source project"] pub const MESA_NVK: Self = Self(24); + #[doc = "Imagination Technologies"] + pub const IMAGINATION_OPEN_SOURCE_MESA: Self = Self(25); } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[repr(transparent)] @@ -2780,6 +2784,43 @@ impl DeviceFaultVendorBinaryHeaderVersionEXT { impl DeviceFaultVendorBinaryHeaderVersionEXT { pub const ONE: Self = Self(1); } +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +#[doc = ""] +pub struct DisplacementMicromapFormatNV(pub(crate) i32); +impl DisplacementMicromapFormatNV { + #[inline] + pub const fn from_raw(x: i32) -> Self { + Self(x) + } + #[inline] + pub const fn as_raw(self) -> i32 { + self.0 + } +} +impl DisplacementMicromapFormatNV { + pub const TYPE_64_TRIANGLES_64_BYTES: Self = Self(1); + pub const TYPE_256_TRIANGLES_128_BYTES: Self = Self(2); + pub const TYPE_1024_TRIANGLES_128_BYTES: Self = Self(3); +} +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +#[doc = ""] +pub struct ShaderCodeTypeEXT(pub(crate) i32); +impl ShaderCodeTypeEXT { + #[inline] + pub const fn from_raw(x: i32) -> Self { + Self(x) + } + #[inline] + pub const fn as_raw(self) -> i32 { + self.0 + } +} +impl ShaderCodeTypeEXT { + pub const BINARY: Self = Self(0); + pub const SPIRV: Self = Self(1); +} impl fmt::Debug for ObjectType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let name = match *self { @@ -2828,6 +2869,7 @@ impl fmt::Debug for ObjectType { Self::BUFFER_COLLECTION_FUCHSIA => Some("BUFFER_COLLECTION_FUCHSIA"), Self::MICROMAP_EXT => Some("MICROMAP_EXT"), Self::OPTICAL_FLOW_SESSION_NV => Some("OPTICAL_FLOW_SESSION_NV"), + Self::SHADER_EXT => Some("SHADER_EXT"), Self::SAMPLER_YCBCR_CONVERSION => Some("SAMPLER_YCBCR_CONVERSION"), Self::DESCRIPTOR_UPDATE_TEMPLATE => Some("DESCRIPTOR_UPDATE_TEMPLATE"), Self::PRIVATE_DATA_SLOT => Some("PRIVATE_DATA_SLOT"), @@ -2898,7 +2940,13 @@ impl fmt::Debug for Result { Self::THREAD_DONE_KHR => Some("THREAD_DONE_KHR"), Self::OPERATION_DEFERRED_KHR => Some("OPERATION_DEFERRED_KHR"), Self::OPERATION_NOT_DEFERRED_KHR => Some("OPERATION_NOT_DEFERRED_KHR"), + Self::ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR => { + Some("ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR") + } Self::ERROR_COMPRESSION_EXHAUSTED_EXT => Some("ERROR_COMPRESSION_EXHAUSTED_EXT"), + Self::ERROR_INCOMPATIBLE_SHADER_BINARY_EXT => { + Some("ERROR_INCOMPATIBLE_SHADER_BINARY_EXT") + } Self::ERROR_OUT_OF_POOL_MEMORY => Some("ERROR_OUT_OF_POOL_MEMORY"), Self::ERROR_INVALID_EXTERNAL_HANDLE => Some("ERROR_INVALID_EXTERNAL_HANDLE"), Self::ERROR_FRAGMENTATION => Some("ERROR_FRAGMENTATION"), diff --git a/third_party/rust/ash/src/vk/extensions.rs b/third_party/rust/ash/src/vk/extensions.rs index cf4936d9955b..47ccd9b677d1 100644 --- a/third_party/rust/ash/src/vk/extensions.rs +++ b/third_party/rust/ash/src/vk/extensions.rs @@ -1538,7 +1538,7 @@ impl KhrSamplerMirrorClampToEdgeFn { impl SamplerAddressMode { #[doc = "Note that this defines what was previously a core enum, and so uses the 'value' attribute rather than 'offset', and does not have a suffix. This is a special case, and should not be repeated"] pub const MIRROR_CLAMP_TO_EDGE: Self = Self(4); - #[deprecated = "Alias introduced for consistency with extension suffixing rules"] + #[deprecated = "Introduced for consistency with extension suffixing rules"] pub const MIRROR_CLAMP_TO_EDGE_KHR: Self = Self::MIRROR_CLAMP_TO_EDGE; } impl ImgFilterCubicFn { @@ -3096,7 +3096,7 @@ impl ExtVideoEncodeH264Fn { pub const fn name() -> &'static ::std::ffi::CStr { unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_video_encode_h264\0") } } - pub const SPEC_VERSION: u32 = 9u32; + pub const SPEC_VERSION: u32 = 10u32; } #[derive(Clone)] pub struct ExtVideoEncodeH264Fn {} @@ -3118,11 +3118,9 @@ impl StructureType { pub const VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT: Self = Self(1_000_038_003); pub const VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT: Self = Self(1_000_038_004); pub const VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT: Self = Self(1_000_038_005); - pub const VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT: Self = Self(1_000_038_006); pub const VIDEO_ENCODE_H264_PROFILE_INFO_EXT: Self = Self(1_000_038_007); pub const VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT: Self = Self(1_000_038_008); pub const VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT: Self = Self(1_000_038_009); - pub const VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT: Self = Self(1_000_038_010); } #[doc = "Generated from 'VK_EXT_video_encode_h264'"] impl VideoCodecOperationFlagsKHR { @@ -3133,7 +3131,7 @@ impl ExtVideoEncodeH265Fn { pub const fn name() -> &'static ::std::ffi::CStr { unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_video_encode_h265\0") } } - pub const SPEC_VERSION: u32 = 9u32; + pub const SPEC_VERSION: u32 = 10u32; } #[derive(Clone)] pub struct ExtVideoEncodeH265Fn {} @@ -3155,9 +3153,7 @@ impl StructureType { pub const VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT: Self = Self(1_000_039_003); pub const VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT: Self = Self(1_000_039_004); pub const VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT: Self = Self(1_000_039_005); - pub const VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT: Self = Self(1_000_039_006); pub const VIDEO_ENCODE_H265_PROFILE_INFO_EXT: Self = Self(1_000_039_007); - pub const VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT: Self = Self(1_000_039_008); pub const VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT: Self = Self(1_000_039_009); pub const VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT: Self = Self(1_000_039_010); } @@ -3545,25 +3541,6 @@ impl ImageCreateFlags { impl StructureType { pub const PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV: Self = Self(1_000_050_000); } -impl NvExtension52Fn { - #[inline] - pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_extension_52\0") } - } - pub const SPEC_VERSION: u32 = 0u32; -} -#[derive(Clone)] -pub struct NvExtension52Fn {} -unsafe impl Send for NvExtension52Fn {} -unsafe impl Sync for NvExtension52Fn {} -impl NvExtension52Fn { - pub fn load(mut _f: F) -> Self - where - F: FnMut(&::std::ffi::CStr) -> *const c_void, - { - Self {} - } -} impl NvExtension53Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -6094,6 +6071,25 @@ impl GoogleDisplayTimingFn { impl StructureType { pub const PRESENT_TIMES_INFO_GOOGLE: Self = Self(1_000_092_000); } +impl ReservedDoNotUse94Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_RESERVED_do_not_use_94\0") } + } + pub const SPEC_VERSION: u32 = 1u32; +} +#[derive(Clone)] +pub struct ReservedDoNotUse94Fn {} +unsafe impl Send for ReservedDoNotUse94Fn {} +unsafe impl Sync for ReservedDoNotUse94Fn {} +impl ReservedDoNotUse94Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} impl NvSampleMaskOverrideCoverageFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -6218,7 +6214,7 @@ impl ExtDiscardRectanglesFn { pub const fn name() -> &'static ::std::ffi::CStr { unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_discard_rectangles\0") } } - pub const SPEC_VERSION: u32 = 1u32; + pub const SPEC_VERSION: u32 = 2u32; } #[allow(non_camel_case_types)] pub type PFN_vkCmdSetDiscardRectangleEXT = unsafe extern "system" fn( @@ -6227,9 +6223,19 @@ pub type PFN_vkCmdSetDiscardRectangleEXT = unsafe extern "system" fn( discard_rectangle_count: u32, p_discard_rectangles: *const Rect2D, ); +#[allow(non_camel_case_types)] +pub type PFN_vkCmdSetDiscardRectangleEnableEXT = + unsafe extern "system" fn(command_buffer: CommandBuffer, discard_rectangle_enable: Bool32); +#[allow(non_camel_case_types)] +pub type PFN_vkCmdSetDiscardRectangleModeEXT = unsafe extern "system" fn( + command_buffer: CommandBuffer, + discard_rectangle_mode: DiscardRectangleModeEXT, +); #[derive(Clone)] pub struct ExtDiscardRectanglesFn { pub cmd_set_discard_rectangle_ext: PFN_vkCmdSetDiscardRectangleEXT, + pub cmd_set_discard_rectangle_enable_ext: PFN_vkCmdSetDiscardRectangleEnableEXT, + pub cmd_set_discard_rectangle_mode_ext: PFN_vkCmdSetDiscardRectangleModeEXT, } unsafe impl Send for ExtDiscardRectanglesFn {} unsafe impl Sync for ExtDiscardRectanglesFn {} @@ -6261,12 +6267,54 @@ impl ExtDiscardRectanglesFn { ::std::mem::transmute(val) } }, + cmd_set_discard_rectangle_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_discard_rectangle_enable_ext( + _command_buffer: CommandBuffer, + _discard_rectangle_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_discard_rectangle_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDiscardRectangleEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_discard_rectangle_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_discard_rectangle_mode_ext: unsafe { + unsafe extern "system" fn cmd_set_discard_rectangle_mode_ext( + _command_buffer: CommandBuffer, + _discard_rectangle_mode: DiscardRectangleModeEXT, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_discard_rectangle_mode_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDiscardRectangleModeEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_discard_rectangle_mode_ext + } else { + ::std::mem::transmute(val) + } + }, } } } #[doc = "Generated from 'VK_EXT_discard_rectangles'"] impl DynamicState { pub const DISCARD_RECTANGLE_EXT: Self = Self(1_000_099_000); + pub const DISCARD_RECTANGLE_ENABLE_EXT: Self = Self(1_000_099_001); + pub const DISCARD_RECTANGLE_MODE_EXT: Self = Self(1_000_099_002); } #[doc = "Generated from 'VK_EXT_discard_rectangles'"] impl StructureType { @@ -6361,6 +6409,10 @@ impl NvExtension104Fn { Self {} } } +#[doc = "Generated from 'VK_NV_extension_104'"] +impl PrivateDataSlotCreateFlags { + pub const RESERVED_0_NV: Self = Self(0b1); +} impl ExtSwapchainColorspaceFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -8468,6 +8520,25 @@ impl KhrRelaxedBlockLayoutFn { Self {} } } +impl ReservedDoNotUse146Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_RESERVED_do_not_use_146\0") } + } + pub const SPEC_VERSION: u32 = 1u32; +} +#[derive(Clone)] +pub struct ReservedDoNotUse146Fn {} +unsafe impl Send for ReservedDoNotUse146Fn {} +unsafe impl Sync for ReservedDoNotUse146Fn {} +impl ReservedDoNotUse146Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} impl KhrGetMemoryRequirements2Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -11884,29 +11955,6 @@ impl GoogleExtension195Fn { Self {} } } -impl GoogleExtension196Fn { - #[inline] - pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_GOOGLE_extension_196\0") } - } - pub const SPEC_VERSION: u32 = 0u32; -} -#[derive(Clone)] -pub struct GoogleExtension196Fn {} -unsafe impl Send for GoogleExtension196Fn {} -unsafe impl Sync for GoogleExtension196Fn {} -impl GoogleExtension196Fn { - pub fn load(mut _f: F) -> Self - where - F: FnMut(&::std::ffi::CStr) -> *const c_void, - { - Self {} - } -} -#[doc = "Generated from 'VK_GOOGLE_extension_196'"] -impl PipelineCacheCreateFlags { - pub const RESERVED_1_EXT: Self = Self(0b10); -} impl KhrDriverPropertiesFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -12272,9 +12320,16 @@ impl NvScissorExclusiveFn { pub const fn name() -> &'static ::std::ffi::CStr { unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_scissor_exclusive\0") } } - pub const SPEC_VERSION: u32 = 1u32; + pub const SPEC_VERSION: u32 = 2u32; } #[allow(non_camel_case_types)] +pub type PFN_vkCmdSetExclusiveScissorEnableNV = unsafe extern "system" fn( + command_buffer: CommandBuffer, + first_exclusive_scissor: u32, + exclusive_scissor_count: u32, + p_exclusive_scissor_enables: *const Bool32, +); +#[allow(non_camel_case_types)] pub type PFN_vkCmdSetExclusiveScissorNV = unsafe extern "system" fn( command_buffer: CommandBuffer, first_exclusive_scissor: u32, @@ -12283,6 +12338,7 @@ pub type PFN_vkCmdSetExclusiveScissorNV = unsafe extern "system" fn( ); #[derive(Clone)] pub struct NvScissorExclusiveFn { + pub cmd_set_exclusive_scissor_enable_nv: PFN_vkCmdSetExclusiveScissorEnableNV, pub cmd_set_exclusive_scissor_nv: PFN_vkCmdSetExclusiveScissorNV, } unsafe impl Send for NvScissorExclusiveFn {} @@ -12293,6 +12349,28 @@ impl NvScissorExclusiveFn { F: FnMut(&::std::ffi::CStr) -> *const c_void, { Self { + cmd_set_exclusive_scissor_enable_nv: unsafe { + unsafe extern "system" fn cmd_set_exclusive_scissor_enable_nv( + _command_buffer: CommandBuffer, + _first_exclusive_scissor: u32, + _exclusive_scissor_count: u32, + _p_exclusive_scissor_enables: *const Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_exclusive_scissor_enable_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetExclusiveScissorEnableNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_exclusive_scissor_enable_nv + } else { + ::std::mem::transmute(val) + } + }, cmd_set_exclusive_scissor_nv: unsafe { unsafe extern "system" fn cmd_set_exclusive_scissor_nv( _command_buffer: CommandBuffer, @@ -12320,6 +12398,7 @@ impl NvScissorExclusiveFn { } #[doc = "Generated from 'VK_NV_scissor_exclusive'"] impl DynamicState { + pub const EXCLUSIVE_SCISSOR_ENABLE_NV: Self = Self(1_000_205_000); pub const EXCLUSIVE_SCISSOR_NV: Self = Self(1_000_205_001); } #[doc = "Generated from 'VK_NV_scissor_exclusive'"] @@ -13331,7 +13410,7 @@ pub type PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR = unsafe extern "system" pub type PFN_vkCmdSetFragmentShadingRateKHR = unsafe extern "system" fn( command_buffer: CommandBuffer, p_fragment_size: *const Extent2D, - combiner_ops: *const [FragmentShadingRateCombinerOpKHR; 2], + combiner_ops: *const [FragmentShadingRateCombinerOpKHR; 2usize], ); #[derive(Clone)] pub struct KhrFragmentShadingRateFn { @@ -13372,7 +13451,7 @@ impl KhrFragmentShadingRateFn { unsafe extern "system" fn cmd_set_fragment_shading_rate_khr( _command_buffer: CommandBuffer, _p_fragment_size: *const Extent2D, - _combiner_ops: *const [FragmentShadingRateCombinerOpKHR; 2], + _combiner_ops: *const [FragmentShadingRateCombinerOpKHR; 2usize], ) { panic!(concat!( "Unable to load ", @@ -15534,28 +15613,84 @@ impl IntelExtension271Fn { } } #[doc = "Generated from 'VK_INTEL_extension_271'"] +impl FormatFeatureFlags2 { + pub const RESERVED_46_EXT: Self = + Self(0b100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); +} +#[doc = "Generated from 'VK_INTEL_extension_271'"] impl ImageUsageFlags { pub const RESERVED_22_EXT: Self = Self(0b100_0000_0000_0000_0000_0000); } -impl IntelExtension272Fn { +impl KhrMapMemory2Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_INTEL_extension_272\0") } + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_map_memory2\0") } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } +#[allow(non_camel_case_types)] +pub type PFN_vkMapMemory2KHR = unsafe extern "system" fn( + device: Device, + p_memory_map_info: *const MemoryMapInfoKHR, + pp_data: *mut *mut c_void, +) -> Result; +#[allow(non_camel_case_types)] +pub type PFN_vkUnmapMemory2KHR = unsafe extern "system" fn( + device: Device, + p_memory_unmap_info: *const MemoryUnmapInfoKHR, +) -> Result; #[derive(Clone)] -pub struct IntelExtension272Fn {} -unsafe impl Send for IntelExtension272Fn {} -unsafe impl Sync for IntelExtension272Fn {} -impl IntelExtension272Fn { +pub struct KhrMapMemory2Fn { + pub map_memory2_khr: PFN_vkMapMemory2KHR, + pub unmap_memory2_khr: PFN_vkUnmapMemory2KHR, +} +unsafe impl Send for KhrMapMemory2Fn {} +unsafe impl Sync for KhrMapMemory2Fn {} +impl KhrMapMemory2Fn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, { - Self {} + Self { + map_memory2_khr: unsafe { + unsafe extern "system" fn map_memory2_khr( + _device: Device, + _p_memory_map_info: *const MemoryMapInfoKHR, + _pp_data: *mut *mut c_void, + ) -> Result { + panic!(concat!("Unable to load ", stringify!(map_memory2_khr))) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkMapMemory2KHR\0"); + let val = _f(cname); + if val.is_null() { + map_memory2_khr + } else { + ::std::mem::transmute(val) + } + }, + unmap_memory2_khr: unsafe { + unsafe extern "system" fn unmap_memory2_khr( + _device: Device, + _p_memory_unmap_info: *const MemoryUnmapInfoKHR, + ) -> Result { + panic!(concat!("Unable to load ", stringify!(unmap_memory2_khr))) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkUnmapMemory2KHR\0"); + let val = _f(cname); + if val.is_null() { + unmap_memory2_khr + } else { + ::std::mem::transmute(val) + } + }, + } } } +#[doc = "Generated from 'VK_KHR_map_memory2'"] +impl StructureType { + pub const MEMORY_MAP_INFO_KHR: Self = Self(1_000_271_000); + pub const MEMORY_UNMAP_INFO_KHR: Self = Self(1_000_271_001); +} impl IntelExtension273Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -16656,21 +16791,12 @@ impl KhrExtension299Fn { Self {} } } -#[doc = "Generated from 'VK_KHR_extension_299'"] -impl MemoryHeapFlags { - pub const RESERVED_2_KHR: Self = Self(0b100); -} -#[doc = "Generated from 'VK_KHR_extension_299'"] -impl PipelineCacheCreateFlags { - pub const RESERVED_1_KHR: Self = Self::RESERVED_1_EXT; - pub const RESERVED_2_KHR: Self = Self(0b100); -} impl KhrVideoEncodeQueueFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_video_encode_queue\0") } } - pub const SPEC_VERSION: u32 = 7u32; + pub const SPEC_VERSION: u32 = 8u32; } #[allow(non_camel_case_types)] pub type PFN_vkCmdEncodeVideoKHR = unsafe extern "system" fn( @@ -16747,19 +16873,24 @@ impl PipelineStageFlags2 { } #[doc = "Generated from 'VK_KHR_video_encode_queue'"] impl QueryType { - pub const VIDEO_ENCODESTREAM_BUFFER_RANGE_KHR: Self = Self(1_000_299_000); + pub const VIDEO_ENCODE_FEEDBACK_KHR: Self = Self(1_000_299_000); } #[doc = "Generated from 'VK_KHR_video_encode_queue'"] impl QueueFlags { pub const VIDEO_ENCODE_KHR: Self = Self(0b100_0000); } #[doc = "Generated from 'VK_KHR_video_encode_queue'"] +impl Result { + pub const ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR: Self = Self(-1_000_299_000); +} +#[doc = "Generated from 'VK_KHR_video_encode_queue'"] impl StructureType { pub const VIDEO_ENCODE_INFO_KHR: Self = Self(1_000_299_000); pub const VIDEO_ENCODE_RATE_CONTROL_INFO_KHR: Self = Self(1_000_299_001); pub const VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR: Self = Self(1_000_299_002); pub const VIDEO_ENCODE_CAPABILITIES_KHR: Self = Self(1_000_299_003); pub const VIDEO_ENCODE_USAGE_INFO_KHR: Self = Self(1_000_299_004); + pub const QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR: Self = Self(1_000_299_005); } #[doc = "Generated from 'VK_KHR_video_encode_queue'"] impl VideoCodingControlFlagsKHR { @@ -16931,25 +17062,6 @@ impl NvExtension308Fn { Self {} } } -impl KhrExtension309Fn { - #[inline] - pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_309\0") } - } - pub const SPEC_VERSION: u32 = 0u32; -} -#[derive(Clone)] -pub struct KhrExtension309Fn {} -unsafe impl Send for KhrExtension309Fn {} -unsafe impl Sync for KhrExtension309Fn {} -impl KhrExtension309Fn { - pub fn load(mut _f: F) -> Self - where - F: FnMut(&::std::ffi::CStr) -> *const c_void, - { - Self {} - } -} impl QcomExtension310Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -16973,18 +17085,18 @@ impl QcomExtension310Fn { impl StructureType { pub const RESERVED_QCOM: Self = Self(1_000_309_000); } -impl NvExtension311Fn { +impl NvLowLatencyFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_extension_311\0") } + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_low_latency\0") } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } #[derive(Clone)] -pub struct NvExtension311Fn {} -unsafe impl Send for NvExtension311Fn {} -unsafe impl Sync for NvExtension311Fn {} -impl NvExtension311Fn { +pub struct NvLowLatencyFn {} +unsafe impl Send for NvLowLatencyFn {} +unsafe impl Sync for NvLowLatencyFn {} +impl NvLowLatencyFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, @@ -16992,6 +17104,10 @@ impl NvExtension311Fn { Self {} } } +#[doc = "Generated from 'VK_NV_low_latency'"] +impl StructureType { + pub const QUERY_LOW_LATENCY_SUPPORT_NV: Self = Self(1_000_310_000); +} impl ExtMetalObjectsFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -18058,7 +18174,7 @@ impl NvFragmentShadingRateEnumsFn { pub type PFN_vkCmdSetFragmentShadingRateEnumNV = unsafe extern "system" fn( command_buffer: CommandBuffer, shading_rate: FragmentShadingRateNV, - combiner_ops: *const [FragmentShadingRateCombinerOpKHR; 2], + combiner_ops: *const [FragmentShadingRateCombinerOpKHR; 2usize], ); #[derive(Clone)] pub struct NvFragmentShadingRateEnumsFn { @@ -18076,7 +18192,7 @@ impl NvFragmentShadingRateEnumsFn { unsafe extern "system" fn cmd_set_fragment_shading_rate_enum_nv( _command_buffer: CommandBuffer, _shading_rate: FragmentShadingRateNV, - _combiner_ops: *const [FragmentShadingRateCombinerOpKHR; 2], + _combiner_ops: *const [FragmentShadingRateCombinerOpKHR; 2usize], ) { panic!(concat!( "Unable to load ", @@ -18808,7 +18924,7 @@ impl ExtDeviceFaultFn { pub const fn name() -> &'static ::std::ffi::CStr { unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_device_fault\0") } } - pub const SPEC_VERSION: u32 = 1u32; + pub const SPEC_VERSION: u32 = 2u32; } #[allow(non_camel_case_types)] pub type PFN_vkGetDeviceFaultInfoEXT = unsafe extern "system" fn( @@ -20122,6 +20238,10 @@ impl ExtPipelinePropertiesFn { pub const SPEC_VERSION: u32 = 1u32; } #[allow(non_camel_case_types)] +#[doc = "Implemented for all types that can be passed as argument to `pipeline_properties` in [`PFN_vkGetPipelinePropertiesEXT`]"] +pub unsafe trait GetPipelinePropertiesEXTParamPipelineProperties {} +unsafe impl GetPipelinePropertiesEXTParamPipelineProperties for PipelinePropertiesIdentifierEXT {} +#[allow(non_camel_case_types)] pub type PFN_vkGetPipelinePropertiesEXT = unsafe extern "system" fn( device: Device, p_pipeline_info: *const PipelineInfoEXT, @@ -20169,57 +20289,6 @@ impl StructureType { pub const PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT: Self = Self(1_000_372_001); pub const PIPELINE_INFO_EXT: Self = Self::PIPELINE_INFO_KHR; } -impl NvExtension374Fn { - #[inline] - pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_extension_374\0") } - } - pub const SPEC_VERSION: u32 = 0u32; -} -#[derive(Clone)] -pub struct NvExtension374Fn {} -unsafe impl Send for NvExtension374Fn {} -unsafe impl Sync for NvExtension374Fn {} -impl NvExtension374Fn { - pub fn load(mut _f: F) -> Self - where - F: FnMut(&::std::ffi::CStr) -> *const c_void, - { - Self {} - } -} -#[doc = "Generated from 'VK_NV_extension_374'"] -impl ExternalFenceHandleTypeFlags { - pub const RESERVED_4_NV: Self = Self(0b1_0000); - pub const RESERVED_5_NV: Self = Self(0b10_0000); -} -#[doc = "Generated from 'VK_NV_extension_374'"] -impl ExternalSemaphoreHandleTypeFlags { - pub const RESERVED_5_NV: Self = Self(0b10_0000); -} -impl NvExtension375Fn { - #[inline] - pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_extension_375\0") } - } - pub const SPEC_VERSION: u32 = 0u32; -} -#[derive(Clone)] -pub struct NvExtension375Fn {} -unsafe impl Send for NvExtension375Fn {} -unsafe impl Sync for NvExtension375Fn {} -impl NvExtension375Fn { - pub fn load(mut _f: F) -> Self - where - F: FnMut(&::std::ffi::CStr) -> *const c_void, - { - Self {} - } -} -#[doc = "Generated from 'VK_NV_extension_375'"] -impl ExternalMemoryHandleTypeFlags { - pub const RESERVED_13_NV: Self = Self(0b10_0000_0000_0000); -} impl ExtExtension376Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -21012,18 +21081,18 @@ impl KhrPortabilityEnumerationFn { impl InstanceCreateFlags { pub const ENUMERATE_PORTABILITY_KHR: Self = Self(0b1); } -impl KhrExtension396Fn { +impl ExtShaderTileImageFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_396\0") } + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_shader_tile_image\0") } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } #[derive(Clone)] -pub struct KhrExtension396Fn {} -unsafe impl Send for KhrExtension396Fn {} -unsafe impl Sync for KhrExtension396Fn {} -impl KhrExtension396Fn { +pub struct ExtShaderTileImageFn {} +unsafe impl Send for ExtShaderTileImageFn {} +unsafe impl Sync for ExtShaderTileImageFn {} +impl ExtShaderTileImageFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, @@ -21031,6 +21100,11 @@ impl KhrExtension396Fn { Self {} } } +#[doc = "Generated from 'VK_EXT_shader_tile_image'"] +impl StructureType { + pub const PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT: Self = Self(1_000_395_000); + pub const PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT: Self = Self(1_000_395_001); +} impl ExtOpacityMicromapFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -21488,18 +21562,18 @@ impl StructureType { pub const MICROMAP_BUILD_SIZES_INFO_EXT: Self = Self(1_000_396_008); pub const ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT: Self = Self(1_000_396_009); } -impl NvExtension398Fn { +impl NvDisplacementMicromapFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_extension_398\0") } + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_displacement_micromap\0") } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } #[derive(Clone)] -pub struct NvExtension398Fn {} -unsafe impl Send for NvExtension398Fn {} -unsafe impl Sync for NvExtension398Fn {} -impl NvExtension398Fn { +pub struct NvDisplacementMicromapFn {} +unsafe impl Send for NvDisplacementMicromapFn {} +unsafe impl Sync for NvDisplacementMicromapFn {} +impl NvDisplacementMicromapFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, @@ -21507,14 +21581,24 @@ impl NvExtension398Fn { Self {} } } -#[doc = "Generated from 'VK_NV_extension_398'"] +#[doc = "Generated from 'VK_NV_displacement_micromap'"] impl BuildAccelerationStructureFlagsKHR { - pub const RESERVED_9_NV: Self = Self(0b10_0000_0000); - pub const RESERVED_10_NV: Self = Self(0b100_0000_0000); + pub const ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV: Self = Self(0b10_0000_0000); } -#[doc = "Generated from 'VK_NV_extension_398'"] +#[doc = "Generated from 'VK_NV_displacement_micromap'"] +impl MicromapTypeEXT { + pub const DISPLACEMENT_MICROMAP_NV: Self = Self(1_000_397_000); +} +#[doc = "Generated from 'VK_NV_displacement_micromap'"] impl PipelineCreateFlags { - pub const RESERVED_28_NV: Self = Self(0b1_0000_0000_0000_0000_0000_0000_0000); + pub const RAY_TRACING_DISPLACEMENT_MICROMAP_NV: Self = + Self(0b1_0000_0000_0000_0000_0000_0000_0000); +} +#[doc = "Generated from 'VK_NV_displacement_micromap'"] +impl StructureType { + pub const PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV: Self = Self(1_000_397_000); + pub const PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV: Self = Self(1_000_397_001); + pub const ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV: Self = Self(1_000_397_002); } impl JuiceExtension399Fn { #[inline] @@ -21638,33 +21722,100 @@ impl FbExtension404Fn { Self {} } } -impl HuaweiExtension405Fn { +impl HuaweiClusterCullingShaderFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_HUAWEI_extension_405\0") } + unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_HUAWEI_cluster_culling_shader\0") + } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 2u32; } +#[allow(non_camel_case_types)] +pub type PFN_vkCmdDrawClusterHUAWEI = unsafe extern "system" fn( + command_buffer: CommandBuffer, + group_count_x: u32, + group_count_y: u32, + group_count_z: u32, +); +#[allow(non_camel_case_types)] +pub type PFN_vkCmdDrawClusterIndirectHUAWEI = + unsafe extern "system" fn(command_buffer: CommandBuffer, buffer: Buffer, offset: DeviceSize); #[derive(Clone)] -pub struct HuaweiExtension405Fn {} -unsafe impl Send for HuaweiExtension405Fn {} -unsafe impl Sync for HuaweiExtension405Fn {} -impl HuaweiExtension405Fn { +pub struct HuaweiClusterCullingShaderFn { + pub cmd_draw_cluster_huawei: PFN_vkCmdDrawClusterHUAWEI, + pub cmd_draw_cluster_indirect_huawei: PFN_vkCmdDrawClusterIndirectHUAWEI, +} +unsafe impl Send for HuaweiClusterCullingShaderFn {} +unsafe impl Sync for HuaweiClusterCullingShaderFn {} +impl HuaweiClusterCullingShaderFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, { - Self {} + Self { + cmd_draw_cluster_huawei: unsafe { + unsafe extern "system" fn cmd_draw_cluster_huawei( + _command_buffer: CommandBuffer, + _group_count_x: u32, + _group_count_y: u32, + _group_count_z: u32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_draw_cluster_huawei) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdDrawClusterHUAWEI\0"); + let val = _f(cname); + if val.is_null() { + cmd_draw_cluster_huawei + } else { + ::std::mem::transmute(val) + } + }, + cmd_draw_cluster_indirect_huawei: unsafe { + unsafe extern "system" fn cmd_draw_cluster_indirect_huawei( + _command_buffer: CommandBuffer, + _buffer: Buffer, + _offset: DeviceSize, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_draw_cluster_indirect_huawei) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdDrawClusterIndirectHUAWEI\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_draw_cluster_indirect_huawei + } else { + ::std::mem::transmute(val) + } + }, + } } } -#[doc = "Generated from 'VK_HUAWEI_extension_405'"] +#[doc = "Generated from 'VK_HUAWEI_cluster_culling_shader'"] impl PipelineStageFlags2 { - pub const RESEVED_41_HUAWEI: Self = + pub const CLUSTER_CULLING_SHADER_HUAWEI: Self = Self(0b10_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); } -#[doc = "Generated from 'VK_HUAWEI_extension_405'"] +#[doc = "Generated from 'VK_HUAWEI_cluster_culling_shader'"] +impl QueryPipelineStatisticFlags { + pub const CLUSTER_CULLING_SHADER_INVOCATIONS_HUAWEI: Self = Self(0b10_0000_0000_0000); +} +#[doc = "Generated from 'VK_HUAWEI_cluster_culling_shader'"] impl ShaderStageFlags { - pub const RESERVED_19_HUAWEI: Self = Self(0b1000_0000_0000_0000_0000); + pub const CLUSTER_CULLING_HUAWEI: Self = Self(0b1000_0000_0000_0000_0000); +} +#[doc = "Generated from 'VK_HUAWEI_cluster_culling_shader'"] +impl StructureType { + pub const PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI: Self = Self(1_000_404_000); + pub const PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI: Self = Self(1_000_404_001); } impl HuaweiExtension406Fn { #[inline] @@ -21998,18 +22149,20 @@ impl HuaweiExtension415Fn { Self {} } } -impl ArmExtension416Fn { +impl ArmShaderCorePropertiesFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_ARM_extension_416\0") } + unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_ARM_shader_core_properties\0") + } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } #[derive(Clone)] -pub struct ArmExtension416Fn {} -unsafe impl Send for ArmExtension416Fn {} -unsafe impl Sync for ArmExtension416Fn {} -impl ArmExtension416Fn { +pub struct ArmShaderCorePropertiesFn {} +unsafe impl Send for ArmShaderCorePropertiesFn {} +unsafe impl Sync for ArmShaderCorePropertiesFn {} +impl ArmShaderCorePropertiesFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, @@ -22017,6 +22170,10 @@ impl ArmExtension416Fn { Self {} } } +#[doc = "Generated from 'VK_ARM_shader_core_properties'"] +impl StructureType { + pub const PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM: Self = Self(1_000_415_000); +} impl KhrExtension417Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -22055,18 +22212,20 @@ impl ArmExtension418Fn { Self {} } } -impl ExtExtension419Fn { +impl ExtImageSlicedViewOf3dFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_419\0") } + unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_image_sliced_view_of_3d\0") + } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } #[derive(Clone)] -pub struct ExtExtension419Fn {} -unsafe impl Send for ExtExtension419Fn {} -unsafe impl Sync for ExtExtension419Fn {} -impl ExtExtension419Fn { +pub struct ExtImageSlicedViewOf3dFn {} +unsafe impl Send for ExtImageSlicedViewOf3dFn {} +unsafe impl Sync for ExtImageSlicedViewOf3dFn {} +impl ExtImageSlicedViewOf3dFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, @@ -22074,9 +22233,10 @@ impl ExtExtension419Fn { Self {} } } -#[doc = "Generated from 'VK_EXT_extension_419'"] -impl ImageViewCreateFlags { - pub const RESERVED_3_EXT: Self = Self(0b1000); +#[doc = "Generated from 'VK_EXT_image_sliced_view_of_3d'"] +impl StructureType { + pub const PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT: Self = Self(1_000_418_000); + pub const IMAGE_VIEW_SLICED_CREATE_INFO_EXT: Self = Self(1_000_418_001); } impl ExtExtension420Fn { #[inline] @@ -22633,25 +22793,6 @@ impl KhrExtension435Fn { Self {} } } -impl NvExtension436Fn { - #[inline] - pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_extension_436\0") } - } - pub const SPEC_VERSION: u32 = 0u32; -} -#[derive(Clone)] -pub struct NvExtension436Fn {} -unsafe impl Send for NvExtension436Fn {} -unsafe impl Sync for NvExtension436Fn {} -impl NvExtension436Fn { - pub fn load(mut _f: F) -> Self - where - F: FnMut(&::std::ffi::CStr) -> *const c_void, - { - Self {} - } -} impl ExtExtension437Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -23025,6 +23166,22 @@ impl ArmExtension453Fn { Self {} } } +#[doc = "Generated from 'VK_ARM_extension_453'"] +impl AccessFlags2 { + pub const RESERVED_49_ARM: Self = + Self(0b10_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); + pub const RESERVED_50_ARM: Self = + Self(0b100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); +} +#[doc = "Generated from 'VK_ARM_extension_453'"] +impl PipelineStageFlags2 { + pub const RESERVED_43_ARM: Self = + Self(0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); +} +#[doc = "Generated from 'VK_ARM_extension_453'"] +impl QueueFlags { + pub const RESERVED_11_ARM: Self = Self(0b1000_0000_0000); +} impl GoogleExtension454Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -24039,6 +24196,10 @@ impl ExtExtension461Fn { impl FormatFeatureFlags2 { pub const RESERVED_39_EXT: Self = Self(0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000); } +#[doc = "Generated from 'VK_EXT_extension_461'"] +impl ImageUsageFlags { + pub const RESERVED_23_EXT: Self = Self(0b1000_0000_0000_0000_0000_0000); +} impl ExtExtension462Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -24497,6 +24658,10 @@ impl AndroidExtension469Fn { Self {} } } +#[doc = "Generated from 'VK_ANDROID_extension_469'"] +impl ResolveModeFlags { + pub const EXTENSION_469_FLAG_0: Self = Self(0b1_0000); +} impl AmdExtension470Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -24725,18 +24890,20 @@ impl ExtExtension481Fn { Self {} } } -impl ExtExtension482Fn { +impl KhrRayTracingPositionFetchFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_482\0") } + unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_ray_tracing_position_fetch\0") + } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } #[derive(Clone)] -pub struct ExtExtension482Fn {} -unsafe impl Send for ExtExtension482Fn {} -unsafe impl Sync for ExtExtension482Fn {} -impl ExtExtension482Fn { +pub struct KhrRayTracingPositionFetchFn {} +unsafe impl Send for KhrRayTracingPositionFetchFn {} +unsafe impl Sync for KhrRayTracingPositionFetchFn {} +impl KhrRayTracingPositionFetchFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, @@ -24744,30 +24911,1212 @@ impl ExtExtension482Fn { Self {} } } -impl ExtExtension483Fn { +#[doc = "Generated from 'VK_KHR_ray_tracing_position_fetch'"] +impl BuildAccelerationStructureFlagsKHR { + pub const ALLOW_DATA_ACCESS: Self = Self(0b1000_0000_0000); +} +#[doc = "Generated from 'VK_KHR_ray_tracing_position_fetch'"] +impl StructureType { + pub const PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR: Self = Self(1_000_481_000); +} +impl ExtShaderObjectFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_483\0") } + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_shader_object\0") } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } +#[allow(non_camel_case_types)] +pub type PFN_vkCreateShadersEXT = unsafe extern "system" fn( + device: Device, + create_info_count: u32, + p_create_infos: *const ShaderCreateInfoEXT, + p_allocator: *const AllocationCallbacks, + p_shaders: *mut ShaderEXT, +) -> Result; +#[allow(non_camel_case_types)] +pub type PFN_vkDestroyShaderEXT = unsafe extern "system" fn( + device: Device, + shader: ShaderEXT, + p_allocator: *const AllocationCallbacks, +); +#[allow(non_camel_case_types)] +pub type PFN_vkGetShaderBinaryDataEXT = unsafe extern "system" fn( + device: Device, + shader: ShaderEXT, + p_data_size: *mut usize, + p_data: *mut c_void, +) -> Result; +#[allow(non_camel_case_types)] +pub type PFN_vkCmdBindShadersEXT = unsafe extern "system" fn( + command_buffer: CommandBuffer, + stage_count: u32, + p_stages: *const ShaderStageFlags, + p_shaders: *const ShaderEXT, +); #[derive(Clone)] -pub struct ExtExtension483Fn {} -unsafe impl Send for ExtExtension483Fn {} -unsafe impl Sync for ExtExtension483Fn {} -impl ExtExtension483Fn { +pub struct ExtShaderObjectFn { + pub create_shaders_ext: PFN_vkCreateShadersEXT, + pub destroy_shader_ext: PFN_vkDestroyShaderEXT, + pub get_shader_binary_data_ext: PFN_vkGetShaderBinaryDataEXT, + pub cmd_bind_shaders_ext: PFN_vkCmdBindShadersEXT, + pub cmd_set_cull_mode_ext: crate::vk::PFN_vkCmdSetCullMode, + pub cmd_set_front_face_ext: crate::vk::PFN_vkCmdSetFrontFace, + pub cmd_set_primitive_topology_ext: crate::vk::PFN_vkCmdSetPrimitiveTopology, + pub cmd_set_viewport_with_count_ext: crate::vk::PFN_vkCmdSetViewportWithCount, + pub cmd_set_scissor_with_count_ext: crate::vk::PFN_vkCmdSetScissorWithCount, + pub cmd_bind_vertex_buffers2_ext: crate::vk::PFN_vkCmdBindVertexBuffers2, + pub cmd_set_depth_test_enable_ext: crate::vk::PFN_vkCmdSetDepthTestEnable, + pub cmd_set_depth_write_enable_ext: crate::vk::PFN_vkCmdSetDepthWriteEnable, + pub cmd_set_depth_compare_op_ext: crate::vk::PFN_vkCmdSetDepthCompareOp, + pub cmd_set_depth_bounds_test_enable_ext: crate::vk::PFN_vkCmdSetDepthBoundsTestEnable, + pub cmd_set_stencil_test_enable_ext: crate::vk::PFN_vkCmdSetStencilTestEnable, + pub cmd_set_stencil_op_ext: crate::vk::PFN_vkCmdSetStencilOp, + pub cmd_set_vertex_input_ext: crate::vk::PFN_vkCmdSetVertexInputEXT, + pub cmd_set_patch_control_points_ext: crate::vk::PFN_vkCmdSetPatchControlPointsEXT, + pub cmd_set_rasterizer_discard_enable_ext: crate::vk::PFN_vkCmdSetRasterizerDiscardEnable, + pub cmd_set_depth_bias_enable_ext: crate::vk::PFN_vkCmdSetDepthBiasEnable, + pub cmd_set_logic_op_ext: crate::vk::PFN_vkCmdSetLogicOpEXT, + pub cmd_set_primitive_restart_enable_ext: crate::vk::PFN_vkCmdSetPrimitiveRestartEnable, + pub cmd_set_tessellation_domain_origin_ext: crate::vk::PFN_vkCmdSetTessellationDomainOriginEXT, + pub cmd_set_depth_clamp_enable_ext: crate::vk::PFN_vkCmdSetDepthClampEnableEXT, + pub cmd_set_polygon_mode_ext: crate::vk::PFN_vkCmdSetPolygonModeEXT, + pub cmd_set_rasterization_samples_ext: crate::vk::PFN_vkCmdSetRasterizationSamplesEXT, + pub cmd_set_sample_mask_ext: crate::vk::PFN_vkCmdSetSampleMaskEXT, + pub cmd_set_alpha_to_coverage_enable_ext: crate::vk::PFN_vkCmdSetAlphaToCoverageEnableEXT, + pub cmd_set_alpha_to_one_enable_ext: crate::vk::PFN_vkCmdSetAlphaToOneEnableEXT, + pub cmd_set_logic_op_enable_ext: crate::vk::PFN_vkCmdSetLogicOpEnableEXT, + pub cmd_set_color_blend_enable_ext: crate::vk::PFN_vkCmdSetColorBlendEnableEXT, + pub cmd_set_color_blend_equation_ext: crate::vk::PFN_vkCmdSetColorBlendEquationEXT, + pub cmd_set_color_write_mask_ext: crate::vk::PFN_vkCmdSetColorWriteMaskEXT, + pub cmd_set_rasterization_stream_ext: crate::vk::PFN_vkCmdSetRasterizationStreamEXT, + pub cmd_set_conservative_rasterization_mode_ext: + crate::vk::PFN_vkCmdSetConservativeRasterizationModeEXT, + pub cmd_set_extra_primitive_overestimation_size_ext: + crate::vk::PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT, + pub cmd_set_depth_clip_enable_ext: crate::vk::PFN_vkCmdSetDepthClipEnableEXT, + pub cmd_set_sample_locations_enable_ext: crate::vk::PFN_vkCmdSetSampleLocationsEnableEXT, + pub cmd_set_color_blend_advanced_ext: crate::vk::PFN_vkCmdSetColorBlendAdvancedEXT, + pub cmd_set_provoking_vertex_mode_ext: crate::vk::PFN_vkCmdSetProvokingVertexModeEXT, + pub cmd_set_line_rasterization_mode_ext: crate::vk::PFN_vkCmdSetLineRasterizationModeEXT, + pub cmd_set_line_stipple_enable_ext: crate::vk::PFN_vkCmdSetLineStippleEnableEXT, + pub cmd_set_depth_clip_negative_one_to_one_ext: + crate::vk::PFN_vkCmdSetDepthClipNegativeOneToOneEXT, + pub cmd_set_viewport_w_scaling_enable_nv: crate::vk::PFN_vkCmdSetViewportWScalingEnableNV, + pub cmd_set_viewport_swizzle_nv: crate::vk::PFN_vkCmdSetViewportSwizzleNV, + pub cmd_set_coverage_to_color_enable_nv: crate::vk::PFN_vkCmdSetCoverageToColorEnableNV, + pub cmd_set_coverage_to_color_location_nv: crate::vk::PFN_vkCmdSetCoverageToColorLocationNV, + pub cmd_set_coverage_modulation_mode_nv: crate::vk::PFN_vkCmdSetCoverageModulationModeNV, + pub cmd_set_coverage_modulation_table_enable_nv: + crate::vk::PFN_vkCmdSetCoverageModulationTableEnableNV, + pub cmd_set_coverage_modulation_table_nv: crate::vk::PFN_vkCmdSetCoverageModulationTableNV, + pub cmd_set_shading_rate_image_enable_nv: crate::vk::PFN_vkCmdSetShadingRateImageEnableNV, + pub cmd_set_representative_fragment_test_enable_nv: + crate::vk::PFN_vkCmdSetRepresentativeFragmentTestEnableNV, + pub cmd_set_coverage_reduction_mode_nv: crate::vk::PFN_vkCmdSetCoverageReductionModeNV, +} +unsafe impl Send for ExtShaderObjectFn {} +unsafe impl Sync for ExtShaderObjectFn {} +impl ExtShaderObjectFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, { - Self {} + Self { + create_shaders_ext: unsafe { + unsafe extern "system" fn create_shaders_ext( + _device: Device, + _create_info_count: u32, + _p_create_infos: *const ShaderCreateInfoEXT, + _p_allocator: *const AllocationCallbacks, + _p_shaders: *mut ShaderEXT, + ) -> Result { + panic!(concat!("Unable to load ", stringify!(create_shaders_ext))) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCreateShadersEXT\0"); + let val = _f(cname); + if val.is_null() { + create_shaders_ext + } else { + ::std::mem::transmute(val) + } + }, + destroy_shader_ext: unsafe { + unsafe extern "system" fn destroy_shader_ext( + _device: Device, + _shader: ShaderEXT, + _p_allocator: *const AllocationCallbacks, + ) { + panic!(concat!("Unable to load ", stringify!(destroy_shader_ext))) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkDestroyShaderEXT\0"); + let val = _f(cname); + if val.is_null() { + destroy_shader_ext + } else { + ::std::mem::transmute(val) + } + }, + get_shader_binary_data_ext: unsafe { + unsafe extern "system" fn get_shader_binary_data_ext( + _device: Device, + _shader: ShaderEXT, + _p_data_size: *mut usize, + _p_data: *mut c_void, + ) -> Result { + panic!(concat!( + "Unable to load ", + stringify!(get_shader_binary_data_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkGetShaderBinaryDataEXT\0"); + let val = _f(cname); + if val.is_null() { + get_shader_binary_data_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_bind_shaders_ext: unsafe { + unsafe extern "system" fn cmd_bind_shaders_ext( + _command_buffer: CommandBuffer, + _stage_count: u32, + _p_stages: *const ShaderStageFlags, + _p_shaders: *const ShaderEXT, + ) { + panic!(concat!("Unable to load ", stringify!(cmd_bind_shaders_ext))) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdBindShadersEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_bind_shaders_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_cull_mode_ext: unsafe { + unsafe extern "system" fn cmd_set_cull_mode_ext( + _command_buffer: CommandBuffer, + _cull_mode: CullModeFlags, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_cull_mode_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetCullModeEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_cull_mode_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_front_face_ext: unsafe { + unsafe extern "system" fn cmd_set_front_face_ext( + _command_buffer: CommandBuffer, + _front_face: FrontFace, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_front_face_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetFrontFaceEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_front_face_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_primitive_topology_ext: unsafe { + unsafe extern "system" fn cmd_set_primitive_topology_ext( + _command_buffer: CommandBuffer, + _primitive_topology: PrimitiveTopology, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_primitive_topology_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetPrimitiveTopologyEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_primitive_topology_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_viewport_with_count_ext: unsafe { + unsafe extern "system" fn cmd_set_viewport_with_count_ext( + _command_buffer: CommandBuffer, + _viewport_count: u32, + _p_viewports: *const Viewport, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_viewport_with_count_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetViewportWithCountEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_viewport_with_count_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_scissor_with_count_ext: unsafe { + unsafe extern "system" fn cmd_set_scissor_with_count_ext( + _command_buffer: CommandBuffer, + _scissor_count: u32, + _p_scissors: *const Rect2D, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_scissor_with_count_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetScissorWithCountEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_scissor_with_count_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_bind_vertex_buffers2_ext: unsafe { + unsafe extern "system" fn cmd_bind_vertex_buffers2_ext( + _command_buffer: CommandBuffer, + _first_binding: u32, + _binding_count: u32, + _p_buffers: *const Buffer, + _p_offsets: *const DeviceSize, + _p_sizes: *const DeviceSize, + _p_strides: *const DeviceSize, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_bind_vertex_buffers2_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdBindVertexBuffers2EXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_bind_vertex_buffers2_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_depth_test_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_depth_test_enable_ext( + _command_buffer: CommandBuffer, + _depth_test_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_depth_test_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDepthTestEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_depth_test_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_depth_write_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_depth_write_enable_ext( + _command_buffer: CommandBuffer, + _depth_write_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_depth_write_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDepthWriteEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_depth_write_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_depth_compare_op_ext: unsafe { + unsafe extern "system" fn cmd_set_depth_compare_op_ext( + _command_buffer: CommandBuffer, + _depth_compare_op: CompareOp, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_depth_compare_op_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetDepthCompareOpEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_depth_compare_op_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_depth_bounds_test_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_depth_bounds_test_enable_ext( + _command_buffer: CommandBuffer, + _depth_bounds_test_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_depth_bounds_test_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDepthBoundsTestEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_depth_bounds_test_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_stencil_test_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_stencil_test_enable_ext( + _command_buffer: CommandBuffer, + _stencil_test_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_stencil_test_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetStencilTestEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_stencil_test_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_stencil_op_ext: unsafe { + unsafe extern "system" fn cmd_set_stencil_op_ext( + _command_buffer: CommandBuffer, + _face_mask: StencilFaceFlags, + _fail_op: StencilOp, + _pass_op: StencilOp, + _depth_fail_op: StencilOp, + _compare_op: CompareOp, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_stencil_op_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetStencilOpEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_stencil_op_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_vertex_input_ext: unsafe { + unsafe extern "system" fn cmd_set_vertex_input_ext( + _command_buffer: CommandBuffer, + _vertex_binding_description_count: u32, + _p_vertex_binding_descriptions: *const VertexInputBindingDescription2EXT, + _vertex_attribute_description_count: u32, + _p_vertex_attribute_descriptions: *const VertexInputAttributeDescription2EXT, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_vertex_input_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetVertexInputEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_vertex_input_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_patch_control_points_ext: unsafe { + unsafe extern "system" fn cmd_set_patch_control_points_ext( + _command_buffer: CommandBuffer, + _patch_control_points: u32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_patch_control_points_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetPatchControlPointsEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_patch_control_points_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_rasterizer_discard_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_rasterizer_discard_enable_ext( + _command_buffer: CommandBuffer, + _rasterizer_discard_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_rasterizer_discard_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetRasterizerDiscardEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_rasterizer_discard_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_depth_bias_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_depth_bias_enable_ext( + _command_buffer: CommandBuffer, + _depth_bias_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_depth_bias_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDepthBiasEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_depth_bias_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_logic_op_ext: unsafe { + unsafe extern "system" fn cmd_set_logic_op_ext( + _command_buffer: CommandBuffer, + _logic_op: LogicOp, + ) { + panic!(concat!("Unable to load ", stringify!(cmd_set_logic_op_ext))) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetLogicOpEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_logic_op_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_primitive_restart_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_primitive_restart_enable_ext( + _command_buffer: CommandBuffer, + _primitive_restart_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_primitive_restart_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetPrimitiveRestartEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_primitive_restart_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_tessellation_domain_origin_ext: unsafe { + unsafe extern "system" fn cmd_set_tessellation_domain_origin_ext( + _command_buffer: CommandBuffer, + _domain_origin: TessellationDomainOrigin, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_tessellation_domain_origin_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetTessellationDomainOriginEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_tessellation_domain_origin_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_depth_clamp_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_depth_clamp_enable_ext( + _command_buffer: CommandBuffer, + _depth_clamp_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_depth_clamp_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDepthClampEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_depth_clamp_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_polygon_mode_ext: unsafe { + unsafe extern "system" fn cmd_set_polygon_mode_ext( + _command_buffer: CommandBuffer, + _polygon_mode: PolygonMode, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_polygon_mode_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetPolygonModeEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_polygon_mode_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_rasterization_samples_ext: unsafe { + unsafe extern "system" fn cmd_set_rasterization_samples_ext( + _command_buffer: CommandBuffer, + _rasterization_samples: SampleCountFlags, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_rasterization_samples_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetRasterizationSamplesEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_rasterization_samples_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_sample_mask_ext: unsafe { + unsafe extern "system" fn cmd_set_sample_mask_ext( + _command_buffer: CommandBuffer, + _samples: SampleCountFlags, + _p_sample_mask: *const SampleMask, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_sample_mask_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetSampleMaskEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_sample_mask_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_alpha_to_coverage_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_alpha_to_coverage_enable_ext( + _command_buffer: CommandBuffer, + _alpha_to_coverage_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_alpha_to_coverage_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetAlphaToCoverageEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_alpha_to_coverage_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_alpha_to_one_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_alpha_to_one_enable_ext( + _command_buffer: CommandBuffer, + _alpha_to_one_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_alpha_to_one_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetAlphaToOneEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_alpha_to_one_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_logic_op_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_logic_op_enable_ext( + _command_buffer: CommandBuffer, + _logic_op_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_logic_op_enable_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetLogicOpEnableEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_logic_op_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_color_blend_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_color_blend_enable_ext( + _command_buffer: CommandBuffer, + _first_attachment: u32, + _attachment_count: u32, + _p_color_blend_enables: *const Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_color_blend_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetColorBlendEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_color_blend_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_color_blend_equation_ext: unsafe { + unsafe extern "system" fn cmd_set_color_blend_equation_ext( + _command_buffer: CommandBuffer, + _first_attachment: u32, + _attachment_count: u32, + _p_color_blend_equations: *const ColorBlendEquationEXT, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_color_blend_equation_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetColorBlendEquationEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_color_blend_equation_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_color_write_mask_ext: unsafe { + unsafe extern "system" fn cmd_set_color_write_mask_ext( + _command_buffer: CommandBuffer, + _first_attachment: u32, + _attachment_count: u32, + _p_color_write_masks: *const ColorComponentFlags, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_color_write_mask_ext) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetColorWriteMaskEXT\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_color_write_mask_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_rasterization_stream_ext: unsafe { + unsafe extern "system" fn cmd_set_rasterization_stream_ext( + _command_buffer: CommandBuffer, + _rasterization_stream: u32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_rasterization_stream_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetRasterizationStreamEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_rasterization_stream_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_conservative_rasterization_mode_ext: unsafe { + unsafe extern "system" fn cmd_set_conservative_rasterization_mode_ext( + _command_buffer: CommandBuffer, + _conservative_rasterization_mode: ConservativeRasterizationModeEXT, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_conservative_rasterization_mode_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetConservativeRasterizationModeEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_conservative_rasterization_mode_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_extra_primitive_overestimation_size_ext: unsafe { + unsafe extern "system" fn cmd_set_extra_primitive_overestimation_size_ext( + _command_buffer: CommandBuffer, + _extra_primitive_overestimation_size: f32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_extra_primitive_overestimation_size_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetExtraPrimitiveOverestimationSizeEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_extra_primitive_overestimation_size_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_depth_clip_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_depth_clip_enable_ext( + _command_buffer: CommandBuffer, + _depth_clip_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_depth_clip_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDepthClipEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_depth_clip_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_sample_locations_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_sample_locations_enable_ext( + _command_buffer: CommandBuffer, + _sample_locations_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_sample_locations_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetSampleLocationsEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_sample_locations_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_color_blend_advanced_ext: unsafe { + unsafe extern "system" fn cmd_set_color_blend_advanced_ext( + _command_buffer: CommandBuffer, + _first_attachment: u32, + _attachment_count: u32, + _p_color_blend_advanced: *const ColorBlendAdvancedEXT, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_color_blend_advanced_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetColorBlendAdvancedEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_color_blend_advanced_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_provoking_vertex_mode_ext: unsafe { + unsafe extern "system" fn cmd_set_provoking_vertex_mode_ext( + _command_buffer: CommandBuffer, + _provoking_vertex_mode: ProvokingVertexModeEXT, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_provoking_vertex_mode_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetProvokingVertexModeEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_provoking_vertex_mode_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_line_rasterization_mode_ext: unsafe { + unsafe extern "system" fn cmd_set_line_rasterization_mode_ext( + _command_buffer: CommandBuffer, + _line_rasterization_mode: LineRasterizationModeEXT, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_line_rasterization_mode_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetLineRasterizationModeEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_line_rasterization_mode_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_line_stipple_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_line_stipple_enable_ext( + _command_buffer: CommandBuffer, + _stippled_line_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_line_stipple_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetLineStippleEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_line_stipple_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_depth_clip_negative_one_to_one_ext: unsafe { + unsafe extern "system" fn cmd_set_depth_clip_negative_one_to_one_ext( + _command_buffer: CommandBuffer, + _negative_one_to_one: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_depth_clip_negative_one_to_one_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetDepthClipNegativeOneToOneEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_depth_clip_negative_one_to_one_ext + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_viewport_w_scaling_enable_nv: unsafe { + unsafe extern "system" fn cmd_set_viewport_w_scaling_enable_nv( + _command_buffer: CommandBuffer, + _viewport_w_scaling_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_viewport_w_scaling_enable_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetViewportWScalingEnableNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_viewport_w_scaling_enable_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_viewport_swizzle_nv: unsafe { + unsafe extern "system" fn cmd_set_viewport_swizzle_nv( + _command_buffer: CommandBuffer, + _first_viewport: u32, + _viewport_count: u32, + _p_viewport_swizzles: *const ViewportSwizzleNV, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_viewport_swizzle_nv) + )) + } + let cname = + ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"vkCmdSetViewportSwizzleNV\0"); + let val = _f(cname); + if val.is_null() { + cmd_set_viewport_swizzle_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_coverage_to_color_enable_nv: unsafe { + unsafe extern "system" fn cmd_set_coverage_to_color_enable_nv( + _command_buffer: CommandBuffer, + _coverage_to_color_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_coverage_to_color_enable_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetCoverageToColorEnableNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_coverage_to_color_enable_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_coverage_to_color_location_nv: unsafe { + unsafe extern "system" fn cmd_set_coverage_to_color_location_nv( + _command_buffer: CommandBuffer, + _coverage_to_color_location: u32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_coverage_to_color_location_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetCoverageToColorLocationNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_coverage_to_color_location_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_coverage_modulation_mode_nv: unsafe { + unsafe extern "system" fn cmd_set_coverage_modulation_mode_nv( + _command_buffer: CommandBuffer, + _coverage_modulation_mode: CoverageModulationModeNV, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_coverage_modulation_mode_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetCoverageModulationModeNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_coverage_modulation_mode_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_coverage_modulation_table_enable_nv: unsafe { + unsafe extern "system" fn cmd_set_coverage_modulation_table_enable_nv( + _command_buffer: CommandBuffer, + _coverage_modulation_table_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_coverage_modulation_table_enable_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetCoverageModulationTableEnableNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_coverage_modulation_table_enable_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_coverage_modulation_table_nv: unsafe { + unsafe extern "system" fn cmd_set_coverage_modulation_table_nv( + _command_buffer: CommandBuffer, + _coverage_modulation_table_count: u32, + _p_coverage_modulation_table: *const f32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_coverage_modulation_table_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetCoverageModulationTableNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_coverage_modulation_table_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_shading_rate_image_enable_nv: unsafe { + unsafe extern "system" fn cmd_set_shading_rate_image_enable_nv( + _command_buffer: CommandBuffer, + _shading_rate_image_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_shading_rate_image_enable_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetShadingRateImageEnableNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_shading_rate_image_enable_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_representative_fragment_test_enable_nv: unsafe { + unsafe extern "system" fn cmd_set_representative_fragment_test_enable_nv( + _command_buffer: CommandBuffer, + _representative_fragment_test_enable: Bool32, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_representative_fragment_test_enable_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetRepresentativeFragmentTestEnableNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_representative_fragment_test_enable_nv + } else { + ::std::mem::transmute(val) + } + }, + cmd_set_coverage_reduction_mode_nv: unsafe { + unsafe extern "system" fn cmd_set_coverage_reduction_mode_nv( + _command_buffer: CommandBuffer, + _coverage_reduction_mode: CoverageReductionModeNV, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_coverage_reduction_mode_nv) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetCoverageReductionModeNV\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_coverage_reduction_mode_nv + } else { + ::std::mem::transmute(val) + } + }, + } } } -#[doc = "Generated from 'VK_EXT_extension_483'"] -impl ShaderStageFlags { - pub const EXT_483_RESERVE_15: Self = Self(0b1000_0000_0000_0000); - pub const EXT_483_RESERVE_16: Self = Self(0b1_0000_0000_0000_0000); - pub const EXT_483_RESERVE_17: Self = Self(0b10_0000_0000_0000_0000); +#[doc = "Generated from 'VK_EXT_shader_object'"] +impl ObjectType { + pub const SHADER_EXT: Self = Self(1_000_482_000); +} +#[doc = "Generated from 'VK_EXT_shader_object'"] +impl Result { + pub const ERROR_INCOMPATIBLE_SHADER_BINARY_EXT: Self = Self(1_000_482_000); +} +#[doc = "Generated from 'VK_EXT_shader_object'"] +impl ShaderCreateFlagsEXT { + pub const ALLOW_VARYING_SUBGROUP_SIZE: Self = Self(0b10); + pub const REQUIRE_FULL_SUBGROUPS: Self = Self(0b100); + pub const NO_TASK_SHADER: Self = Self(0b1000); + pub const DISPATCH_BASE: Self = Self(0b1_0000); + pub const FRAGMENT_SHADING_RATE_ATTACHMENT: Self = Self(0b10_0000); + pub const FRAGMENT_DENSITY_MAP_ATTACHMENT: Self = Self(0b100_0000); +} +#[doc = "Generated from 'VK_EXT_shader_object'"] +impl StructureType { + pub const PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT: Self = Self(1_000_482_000); + pub const PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT: Self = Self(1_000_482_001); + pub const SHADER_CREATE_INFO_EXT: Self = Self(1_000_482_002); + pub const SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT: Self = + Self::PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO; } impl ExtExtension484Fn { #[inline] @@ -24962,25 +26311,6 @@ impl StructureType { pub const PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM: Self = Self(1_000_488_000); } -impl NvExtension490Fn { - #[inline] - pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_NV_extension_490\0") } - } - pub const SPEC_VERSION: u32 = 0u32; -} -#[derive(Clone)] -pub struct NvExtension490Fn {} -unsafe impl Send for NvExtension490Fn {} -unsafe impl Sync for NvExtension490Fn {} -impl NvExtension490Fn { - pub fn load(mut _f: F) -> Self - where - F: FnMut(&::std::ffi::CStr) -> *const c_void, - { - Self {} - } -} impl NvRayTracingInvocationReorderFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -25168,18 +26498,22 @@ impl StructureType { pub const PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM: Self = Self(1_000_497_000); pub const PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM: Self = Self(1_000_497_001); } -impl ExtExtension499Fn { +impl ExtPipelineLibraryGroupHandlesFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_499\0") } + unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"VK_EXT_pipeline_library_group_handles\0", + ) + } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } #[derive(Clone)] -pub struct ExtExtension499Fn {} -unsafe impl Send for ExtExtension499Fn {} -unsafe impl Sync for ExtExtension499Fn {} -impl ExtExtension499Fn { +pub struct ExtPipelineLibraryGroupHandlesFn {} +unsafe impl Send for ExtPipelineLibraryGroupHandlesFn {} +unsafe impl Sync for ExtPipelineLibraryGroupHandlesFn {} +impl ExtPipelineLibraryGroupHandlesFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, @@ -25187,18 +26521,27 @@ impl ExtExtension499Fn { Self {} } } -impl ExtExtension500Fn { +#[doc = "Generated from 'VK_EXT_pipeline_library_group_handles'"] +impl StructureType { + pub const PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT: Self = + Self(1_000_498_000); +} +impl ExtDynamicRenderingUnusedAttachmentsFn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { - unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_500\0") } + unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"VK_EXT_dynamic_rendering_unused_attachments\0", + ) + } } - pub const SPEC_VERSION: u32 = 0u32; + pub const SPEC_VERSION: u32 = 1u32; } #[derive(Clone)] -pub struct ExtExtension500Fn {} -unsafe impl Send for ExtExtension500Fn {} -unsafe impl Sync for ExtExtension500Fn {} -impl ExtExtension500Fn { +pub struct ExtDynamicRenderingUnusedAttachmentsFn {} +unsafe impl Send for ExtDynamicRenderingUnusedAttachmentsFn {} +unsafe impl Sync for ExtDynamicRenderingUnusedAttachmentsFn {} +impl ExtDynamicRenderingUnusedAttachmentsFn { pub fn load(mut _f: F) -> Self where F: FnMut(&::std::ffi::CStr) -> *const c_void, @@ -25206,6 +26549,11 @@ impl ExtExtension500Fn { Self {} } } +#[doc = "Generated from 'VK_EXT_dynamic_rendering_unused_attachments'"] +impl StructureType { + pub const PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT: Self = + Self(1_000_499_000); +} impl ExtExtension501Fn { #[inline] pub const fn name() -> &'static ::std::ffi::CStr { @@ -25320,3 +26668,578 @@ impl NvExtension506Fn { Self {} } } +impl KhrExtension507Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_507\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct KhrExtension507Fn {} +unsafe impl Send for KhrExtension507Fn {} +unsafe impl Sync for KhrExtension507Fn {} +impl KhrExtension507Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl ExtExtension508Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_508\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension508Fn {} +unsafe impl Send for ExtExtension508Fn {} +unsafe impl Sync for ExtExtension508Fn {} +impl ExtExtension508Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +#[doc = "Generated from 'VK_EXT_extension_508'"] +impl AccessFlags2 { + pub const RESERVED_47_EXT: Self = + Self(0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); + pub const RESERVED_48_EXT: Self = + Self(0b1_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); +} +#[doc = "Generated from 'VK_EXT_extension_508'"] +impl PipelineStageFlags2 { + pub const RESERVED_42_EXT: Self = Self(0b100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); +} +#[doc = "Generated from 'VK_EXT_extension_508'"] +impl QueueFlags { + pub const RESERVED_10_EXT: Self = Self(0b100_0000_0000); +} +impl ExtExtension509Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_509\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension509Fn {} +unsafe impl Send for ExtExtension509Fn {} +unsafe impl Sync for ExtExtension509Fn {} +impl ExtExtension509Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl MesaExtension510Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_MESA_extension_510\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct MesaExtension510Fn {} +unsafe impl Send for MesaExtension510Fn {} +unsafe impl Sync for MesaExtension510Fn {} +impl MesaExtension510Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl QcomMultiviewPerViewRenderAreasFn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"VK_QCOM_multiview_per_view_render_areas\0", + ) + } + } + pub const SPEC_VERSION: u32 = 1u32; +} +#[derive(Clone)] +pub struct QcomMultiviewPerViewRenderAreasFn {} +unsafe impl Send for QcomMultiviewPerViewRenderAreasFn {} +unsafe impl Sync for QcomMultiviewPerViewRenderAreasFn {} +impl QcomMultiviewPerViewRenderAreasFn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +#[doc = "Generated from 'VK_QCOM_multiview_per_view_render_areas'"] +impl StructureType { + pub const PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM: Self = + Self(1_000_510_000); + pub const MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM: Self = + Self(1_000_510_001); +} +impl ExtExtension512Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_512\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension512Fn {} +unsafe impl Send for ExtExtension512Fn {} +unsafe impl Sync for ExtExtension512Fn {} +impl ExtExtension512Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl KhrExtension513Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_513\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct KhrExtension513Fn {} +unsafe impl Send for KhrExtension513Fn {} +unsafe impl Sync for KhrExtension513Fn {} +impl KhrExtension513Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl KhrExtension514Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_514\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct KhrExtension514Fn {} +unsafe impl Send for KhrExtension514Fn {} +unsafe impl Sync for KhrExtension514Fn {} +impl KhrExtension514Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl KhrExtension515Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_515\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct KhrExtension515Fn {} +unsafe impl Send for KhrExtension515Fn {} +unsafe impl Sync for KhrExtension515Fn {} +impl KhrExtension515Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl KhrExtension516Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_516\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct KhrExtension516Fn {} +unsafe impl Send for KhrExtension516Fn {} +unsafe impl Sync for KhrExtension516Fn {} +impl KhrExtension516Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +#[doc = "Generated from 'VK_KHR_extension_516'"] +impl BufferCreateFlags { + pub const RESERVED_6_KHR: Self = Self(0b100_0000); +} +#[doc = "Generated from 'VK_KHR_extension_516'"] +impl ImageCreateFlags { + pub const RESERVED_20_KHR: Self = Self(0b1_0000_0000_0000_0000_0000); +} +impl ExtExtension517Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_517\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension517Fn {} +unsafe impl Send for ExtExtension517Fn {} +unsafe impl Sync for ExtExtension517Fn {} +impl ExtExtension517Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +#[doc = "Generated from 'VK_EXT_extension_517'"] +impl DescriptorSetLayoutCreateFlags { + pub const RESERVED_6_EXT: Self = Self(0b100_0000); +} +impl MesaExtension518Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_MESA_extension_518\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct MesaExtension518Fn {} +unsafe impl Send for MesaExtension518Fn {} +unsafe impl Sync for MesaExtension518Fn {} +impl MesaExtension518Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl QcomExtension519Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_QCOM_extension_519\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct QcomExtension519Fn {} +unsafe impl Send for QcomExtension519Fn {} +unsafe impl Sync for QcomExtension519Fn {} +impl QcomExtension519Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl QcomExtension520Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_QCOM_extension_520\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct QcomExtension520Fn {} +unsafe impl Send for QcomExtension520Fn {} +unsafe impl Sync for QcomExtension520Fn {} +impl QcomExtension520Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl QcomExtension521Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_QCOM_extension_521\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct QcomExtension521Fn {} +unsafe impl Send for QcomExtension521Fn {} +unsafe impl Sync for QcomExtension521Fn {} +impl QcomExtension521Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl QcomExtension522Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_QCOM_extension_522\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct QcomExtension522Fn {} +unsafe impl Send for QcomExtension522Fn {} +unsafe impl Sync for QcomExtension522Fn {} +impl QcomExtension522Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl ExtExtension523Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_523\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension523Fn {} +unsafe impl Send for ExtExtension523Fn {} +unsafe impl Sync for ExtExtension523Fn {} +impl ExtExtension523Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl ExtExtension524Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_524\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension524Fn {} +unsafe impl Send for ExtExtension524Fn {} +unsafe impl Sync for ExtExtension524Fn {} +impl ExtExtension524Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl ExtAttachmentFeedbackLoopDynamicStateFn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { + ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"VK_EXT_attachment_feedback_loop_dynamic_state\0", + ) + } + } + pub const SPEC_VERSION: u32 = 1u32; +} +#[allow(non_camel_case_types)] +pub type PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT = + unsafe extern "system" fn(command_buffer: CommandBuffer, aspect_mask: ImageAspectFlags); +#[derive(Clone)] +pub struct ExtAttachmentFeedbackLoopDynamicStateFn { + pub cmd_set_attachment_feedback_loop_enable_ext: PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT, +} +unsafe impl Send for ExtAttachmentFeedbackLoopDynamicStateFn {} +unsafe impl Sync for ExtAttachmentFeedbackLoopDynamicStateFn {} +impl ExtAttachmentFeedbackLoopDynamicStateFn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self { + cmd_set_attachment_feedback_loop_enable_ext: unsafe { + unsafe extern "system" fn cmd_set_attachment_feedback_loop_enable_ext( + _command_buffer: CommandBuffer, + _aspect_mask: ImageAspectFlags, + ) { + panic!(concat!( + "Unable to load ", + stringify!(cmd_set_attachment_feedback_loop_enable_ext) + )) + } + let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked( + b"vkCmdSetAttachmentFeedbackLoopEnableEXT\0", + ); + let val = _f(cname); + if val.is_null() { + cmd_set_attachment_feedback_loop_enable_ext + } else { + ::std::mem::transmute(val) + } + }, + } + } +} +#[doc = "Generated from 'VK_EXT_attachment_feedback_loop_dynamic_state'"] +impl DynamicState { + pub const ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT: Self = Self(1_000_524_000); +} +#[doc = "Generated from 'VK_EXT_attachment_feedback_loop_dynamic_state'"] +impl StructureType { + pub const PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT: Self = + Self(1_000_524_000); +} +impl ExtExtension526Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_526\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension526Fn {} +unsafe impl Send for ExtExtension526Fn {} +unsafe impl Sync for ExtExtension526Fn {} +impl ExtExtension526Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl ExtExtension527Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_527\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension527Fn {} +unsafe impl Send for ExtExtension527Fn {} +unsafe impl Sync for ExtExtension527Fn {} +impl ExtExtension527Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl ExtExtension528Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_EXT_extension_528\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct ExtExtension528Fn {} +unsafe impl Send for ExtExtension528Fn {} +unsafe impl Sync for ExtExtension528Fn {} +impl ExtExtension528Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl KhrExtension529Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_529\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct KhrExtension529Fn {} +unsafe impl Send for KhrExtension529Fn {} +unsafe impl Sync for KhrExtension529Fn {} +impl KhrExtension529Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl QnxExtension530Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_QNX_extension_530\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct QnxExtension530Fn {} +unsafe impl Send for QnxExtension530Fn {} +unsafe impl Sync for QnxExtension530Fn {} +impl QnxExtension530Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +#[doc = "Generated from 'VK_QNX_extension_530'"] +impl ExternalMemoryHandleTypeFlags { + pub const TYPE_530_QNX: Self = Self(0b100_0000_0000_0000); +} +impl MsftExtension531Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_MSFT_extension_531\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct MsftExtension531Fn {} +unsafe impl Send for MsftExtension531Fn {} +unsafe impl Sync for MsftExtension531Fn {} +impl MsftExtension531Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} +impl KhrExtension532Fn { + #[inline] + pub const fn name() -> &'static ::std::ffi::CStr { + unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"VK_KHR_extension_532\0") } + } + pub const SPEC_VERSION: u32 = 0u32; +} +#[derive(Clone)] +pub struct KhrExtension532Fn {} +unsafe impl Send for KhrExtension532Fn {} +unsafe impl Sync for KhrExtension532Fn {} +impl KhrExtension532Fn { + pub fn load(mut _f: F) -> Self + where + F: FnMut(&::std::ffi::CStr) -> *const c_void, + { + Self {} + } +} diff --git a/third_party/rust/ash/src/vk/features.rs b/third_party/rust/ash/src/vk/features.rs index 4a52e377eff7..f7ddc8e6be48 100644 --- a/third_party/rust/ash/src/vk/features.rs +++ b/third_party/rust/ash/src/vk/features.rs @@ -999,7 +999,7 @@ pub type PFN_vkCmdSetDepthBias = unsafe extern "system" fn( ); #[allow(non_camel_case_types)] pub type PFN_vkCmdSetBlendConstants = - unsafe extern "system" fn(command_buffer: CommandBuffer, blend_constants: *const [f32; 4]); + unsafe extern "system" fn(command_buffer: CommandBuffer, blend_constants: *const [f32; 4usize]); #[allow(non_camel_case_types)] pub type PFN_vkCmdSetDepthBounds = unsafe extern "system" fn( command_buffer: CommandBuffer, @@ -2876,7 +2876,7 @@ impl DeviceFnV1_0 { cmd_set_blend_constants: unsafe { unsafe extern "system" fn cmd_set_blend_constants( _command_buffer: CommandBuffer, - _blend_constants: *const [f32; 4], + _blend_constants: *const [f32; 4usize], ) { panic!(concat!( "Unable to load ", diff --git a/third_party/rust/ash/src/vk/native.rs b/third_party/rust/ash/src/vk/native.rs index 02edfba5c8c5..03e0ad526104 100644 --- a/third_party/rust/ash/src/vk/native.rs +++ b/third_party/rust/ash/src/vk/native.rs @@ -1,4 +1,4 @@ -/* automatically generated by rust-bindgen 0.61.0 */ +/* automatically generated by rust-bindgen 0.64.0 */ #[repr(C)] #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] @@ -7050,42 +7050,48 @@ impl StdVideoEncodeH264ReferenceInfoFlags { #[repr(C)] #[repr(align(4))] #[derive(Debug, Copy, Clone)] -pub struct StdVideoEncodeH264RefMgmtFlags { +pub struct StdVideoEncodeH264ReferenceListsInfoFlags { pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: [u8; 3usize], } #[test] -fn bindgen_test_layout_StdVideoEncodeH264RefMgmtFlags() { +fn bindgen_test_layout_StdVideoEncodeH264ReferenceListsInfoFlags() { assert_eq!( - ::std::mem::size_of::(), + ::std::mem::size_of::(), 4usize, - concat!("Size of: ", stringify!(StdVideoEncodeH264RefMgmtFlags)) + concat!( + "Size of: ", + stringify!(StdVideoEncodeH264ReferenceListsInfoFlags) + ) ); assert_eq!( - ::std::mem::align_of::(), + ::std::mem::align_of::(), 4usize, - concat!("Alignment of ", stringify!(StdVideoEncodeH264RefMgmtFlags)) + concat!( + "Alignment of ", + stringify!(StdVideoEncodeH264ReferenceListsInfoFlags) + ) ); } -impl StdVideoEncodeH264RefMgmtFlags { +impl StdVideoEncodeH264ReferenceListsInfoFlags { #[inline] - pub fn ref_pic_list_modification_l0_flag(&self) -> u32 { + pub fn ref_pic_list_modification_flag_l0(&self) -> u32 { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } } #[inline] - pub fn set_ref_pic_list_modification_l0_flag(&mut self, val: u32) { + pub fn set_ref_pic_list_modification_flag_l0(&mut self, val: u32) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] - pub fn ref_pic_list_modification_l1_flag(&self) -> u32 { + pub fn ref_pic_list_modification_flag_l1(&self) -> u32 { unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } } #[inline] - pub fn set_ref_pic_list_modification_l1_flag(&mut self, val: u32) { + pub fn set_ref_pic_list_modification_flag_l1(&mut self, val: u32) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(1usize, 1u8, val as u64) @@ -7093,19 +7099,19 @@ impl StdVideoEncodeH264RefMgmtFlags { } #[inline] pub fn new_bitfield_1( - ref_pic_list_modification_l0_flag: u32, - ref_pic_list_modification_l1_flag: u32, + ref_pic_list_modification_flag_l0: u32, + ref_pic_list_modification_flag_l1: u32, ) -> __BindgenBitfieldUnit<[u8; 1usize]> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { - let ref_pic_list_modification_l0_flag: u32 = - unsafe { ::std::mem::transmute(ref_pic_list_modification_l0_flag) }; - ref_pic_list_modification_l0_flag as u64 + let ref_pic_list_modification_flag_l0: u32 = + unsafe { ::std::mem::transmute(ref_pic_list_modification_flag_l0) }; + ref_pic_list_modification_flag_l0 as u64 }); __bindgen_bitfield_unit.set(1usize, 1u8, { - let ref_pic_list_modification_l1_flag: u32 = - unsafe { ::std::mem::transmute(ref_pic_list_modification_l1_flag) }; - ref_pic_list_modification_l1_flag as u64 + let ref_pic_list_modification_flag_l1: u32 = + unsafe { ::std::mem::transmute(ref_pic_list_modification_flag_l1) }; + ref_pic_list_modification_flag_l1 as u64 }); __bindgen_bitfield_unit } @@ -7255,34 +7261,39 @@ fn bindgen_test_layout_StdVideoEncodeH264RefPicMarkingEntry() { } #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct StdVideoEncodeH264RefMemMgmtCtrlOperations { - pub flags: StdVideoEncodeH264RefMgmtFlags, +pub struct StdVideoEncodeH264ReferenceListsInfo { + pub flags: StdVideoEncodeH264ReferenceListsInfoFlags, + pub refPicList0EntryCount: u8, + pub refPicList1EntryCount: u8, pub refList0ModOpCount: u8, - pub pRefList0ModOperations: *const StdVideoEncodeH264RefListModEntry, pub refList1ModOpCount: u8, - pub pRefList1ModOperations: *const StdVideoEncodeH264RefListModEntry, pub refPicMarkingOpCount: u8, + pub reserved1: [u8; 7usize], + pub pRefPicList0Entries: *const u8, + pub pRefPicList1Entries: *const u8, + pub pRefList0ModOperations: *const StdVideoEncodeH264RefListModEntry, + pub pRefList1ModOperations: *const StdVideoEncodeH264RefListModEntry, pub pRefPicMarkingOperations: *const StdVideoEncodeH264RefPicMarkingEntry, } #[test] -fn bindgen_test_layout_StdVideoEncodeH264RefMemMgmtCtrlOperations() { - const UNINIT: ::std::mem::MaybeUninit = +fn bindgen_test_layout_StdVideoEncodeH264ReferenceListsInfo() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( - ::std::mem::size_of::(), - 48usize, + ::std::mem::size_of::(), + 56usize, concat!( "Size of: ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations) + stringify!(StdVideoEncodeH264ReferenceListsInfo) ) ); assert_eq!( - ::std::mem::align_of::(), + ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations) + stringify!(StdVideoEncodeH264ReferenceListsInfo) ) ); assert_eq!( @@ -7290,67 +7301,117 @@ fn bindgen_test_layout_StdVideoEncodeH264RefMemMgmtCtrlOperations() { 0usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations), + stringify!(StdVideoEncodeH264ReferenceListsInfo), "::", stringify!(flags) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).refList0ModOpCount) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).refPicList0EntryCount) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations), + stringify!(StdVideoEncodeH264ReferenceListsInfo), + "::", + stringify!(refPicList0EntryCount) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).refPicList1EntryCount) as usize - ptr as usize }, + 5usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264ReferenceListsInfo), + "::", + stringify!(refPicList1EntryCount) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).refList0ModOpCount) as usize - ptr as usize }, + 6usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264ReferenceListsInfo), "::", stringify!(refList0ModOpCount) ) ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pRefList0ModOperations) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations), - "::", - stringify!(pRefList0ModOperations) - ) - ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).refList1ModOpCount) as usize - ptr as usize }, - 16usize, + 7usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations), + stringify!(StdVideoEncodeH264ReferenceListsInfo), "::", stringify!(refList1ModOpCount) ) ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pRefList1ModOperations) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations), - "::", - stringify!(pRefList1ModOperations) - ) - ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).refPicMarkingOpCount) as usize - ptr as usize }, - 32usize, + 8usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations), + stringify!(StdVideoEncodeH264ReferenceListsInfo), "::", stringify!(refPicMarkingOpCount) ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pRefPicMarkingOperations) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).reserved1) as usize - ptr as usize }, + 9usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264ReferenceListsInfo), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).pRefPicList0Entries) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264ReferenceListsInfo), + "::", + stringify!(pRefPicList0Entries) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).pRefPicList1Entries) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264ReferenceListsInfo), + "::", + stringify!(pRefPicList1Entries) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).pRefList0ModOperations) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264ReferenceListsInfo), + "::", + stringify!(pRefList0ModOperations) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).pRefList1ModOperations) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH264RefMemMgmtCtrlOperations), + stringify!(StdVideoEncodeH264ReferenceListsInfo), + "::", + stringify!(pRefList1ModOperations) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).pRefPicMarkingOperations) as usize - ptr as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264ReferenceListsInfo), "::", stringify!(pRefPicMarkingOperations) ) @@ -7362,6 +7423,7 @@ pub struct StdVideoEncodeH264PictureInfo { pub flags: StdVideoEncodeH264PictureInfoFlags, pub seq_parameter_set_id: u8, pub pic_parameter_set_id: u8, + pub reserved1: u16, pub pictureType: StdVideoH264PictureType, pub frame_num: u32, pub PicOrderCnt: i32, @@ -7411,6 +7473,16 @@ fn bindgen_test_layout_StdVideoEncodeH264PictureInfo() { stringify!(pic_parameter_set_id) ) ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).reserved1) as usize - ptr as usize }, + 6usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264PictureInfo), + "::", + stringify!(reserved1) + ) + ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pictureType) as usize - ptr as usize }, 8usize, @@ -7446,6 +7518,7 @@ fn bindgen_test_layout_StdVideoEncodeH264PictureInfo() { #[derive(Debug, Copy, Clone)] pub struct StdVideoEncodeH264ReferenceInfo { pub flags: StdVideoEncodeH264ReferenceInfoFlags, + pub pictureType: StdVideoH264PictureType, pub FrameNum: u32, pub PicOrderCnt: i32, pub long_term_pic_num: u16, @@ -7458,7 +7531,7 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() { let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), - 16usize, + 20usize, concat!("Size of: ", stringify!(StdVideoEncodeH264ReferenceInfo)) ); assert_eq!( @@ -7477,8 +7550,18 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).FrameNum) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).pictureType) as usize - ptr as usize }, 4usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264ReferenceInfo), + "::", + stringify!(pictureType) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).FrameNum) as usize - ptr as usize }, + 8usize, concat!( "Offset of field: ", stringify!(StdVideoEncodeH264ReferenceInfo), @@ -7488,7 +7571,7 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() { ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).PicOrderCnt) as usize - ptr as usize }, - 8usize, + 12usize, concat!( "Offset of field: ", stringify!(StdVideoEncodeH264ReferenceInfo), @@ -7498,7 +7581,7 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() { ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).long_term_pic_num) as usize - ptr as usize }, - 12usize, + 16usize, concat!( "Offset of field: ", stringify!(StdVideoEncodeH264ReferenceInfo), @@ -7508,7 +7591,7 @@ fn bindgen_test_layout_StdVideoEncodeH264ReferenceInfo() { ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).long_term_frame_idx) as usize - ptr as usize }, - 14usize, + 18usize, concat!( "Offset of field: ", stringify!(StdVideoEncodeH264ReferenceInfo), @@ -7530,6 +7613,8 @@ pub struct StdVideoEncodeH264SliceHeader { pub disable_deblocking_filter_idc: StdVideoH264DisableDeblockingFilterIdc, pub slice_alpha_c0_offset_div2: i8, pub slice_beta_offset_div2: i8, + pub reserved1: u16, + pub reserved2: u32, pub pWeightTable: *const StdVideoEncodeH264WeightTable, } #[test] @@ -7653,6 +7738,26 @@ fn bindgen_test_layout_StdVideoEncodeH264SliceHeader() { stringify!(slice_beta_offset_div2) ) ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).reserved1) as usize - ptr as usize }, + 26usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264SliceHeader), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).reserved2) as usize - ptr as usize }, + 28usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH264SliceHeader), + "::", + stringify!(reserved2) + ) + ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pWeightTable) as usize - ptr as usize }, 32usize, @@ -8511,31 +8616,31 @@ fn bindgen_test_layout_StdVideoEncodeH265SliceSegmentHeader() { #[repr(C)] #[repr(align(4))] #[derive(Debug, Copy, Clone)] -pub struct StdVideoEncodeH265ReferenceModificationFlags { +pub struct StdVideoEncodeH265ReferenceListsInfoFlags { pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: [u8; 3usize], } #[test] -fn bindgen_test_layout_StdVideoEncodeH265ReferenceModificationFlags() { +fn bindgen_test_layout_StdVideoEncodeH265ReferenceListsInfoFlags() { assert_eq!( - ::std::mem::size_of::(), + ::std::mem::size_of::(), 4usize, concat!( "Size of: ", - stringify!(StdVideoEncodeH265ReferenceModificationFlags) + stringify!(StdVideoEncodeH265ReferenceListsInfoFlags) ) ); assert_eq!( - ::std::mem::align_of::(), + ::std::mem::align_of::(), 4usize, concat!( "Alignment of ", - stringify!(StdVideoEncodeH265ReferenceModificationFlags) + stringify!(StdVideoEncodeH265ReferenceListsInfoFlags) ) ); } -impl StdVideoEncodeH265ReferenceModificationFlags { +impl StdVideoEncodeH265ReferenceListsInfoFlags { #[inline] pub fn ref_pic_list_modification_flag_l0(&self) -> u32 { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } @@ -8579,32 +8684,35 @@ impl StdVideoEncodeH265ReferenceModificationFlags { } #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct StdVideoEncodeH265ReferenceModifications { - pub flags: StdVideoEncodeH265ReferenceModificationFlags, - pub referenceList0ModificationsCount: u8, - pub pReferenceList0Modifications: *const u8, - pub referenceList1ModificationsCount: u8, - pub pReferenceList1Modifications: *const u8, +pub struct StdVideoEncodeH265ReferenceListsInfo { + pub flags: StdVideoEncodeH265ReferenceListsInfoFlags, + pub num_ref_idx_l0_active_minus1: u8, + pub num_ref_idx_l1_active_minus1: u8, + pub reserved1: u16, + pub pRefPicList0Entries: *const u8, + pub pRefPicList1Entries: *const u8, + pub pRefList0Modifications: *const u8, + pub pRefList1Modifications: *const u8, } #[test] -fn bindgen_test_layout_StdVideoEncodeH265ReferenceModifications() { - const UNINIT: ::std::mem::MaybeUninit = +fn bindgen_test_layout_StdVideoEncodeH265ReferenceListsInfo() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( - ::std::mem::size_of::(), - 32usize, + ::std::mem::size_of::(), + 40usize, concat!( "Size of: ", - stringify!(StdVideoEncodeH265ReferenceModifications) + stringify!(StdVideoEncodeH265ReferenceListsInfo) ) ); assert_eq!( - ::std::mem::align_of::(), + ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", - stringify!(StdVideoEncodeH265ReferenceModifications) + stringify!(StdVideoEncodeH265ReferenceListsInfo) ) ); assert_eq!( @@ -8612,57 +8720,83 @@ fn bindgen_test_layout_StdVideoEncodeH265ReferenceModifications() { 0usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH265ReferenceModifications), + stringify!(StdVideoEncodeH265ReferenceListsInfo), "::", stringify!(flags) ) ); assert_eq!( unsafe { - ::std::ptr::addr_of!((*ptr).referenceList0ModificationsCount) as usize - ptr as usize + ::std::ptr::addr_of!((*ptr).num_ref_idx_l0_active_minus1) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH265ReferenceModifications), + stringify!(StdVideoEncodeH265ReferenceListsInfo), "::", - stringify!(referenceList0ModificationsCount) + stringify!(num_ref_idx_l0_active_minus1) ) ); assert_eq!( unsafe { - ::std::ptr::addr_of!((*ptr).pReferenceList0Modifications) as usize - ptr as usize + ::std::ptr::addr_of!((*ptr).num_ref_idx_l1_active_minus1) as usize - ptr as usize }, + 5usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH265ReferenceListsInfo), + "::", + stringify!(num_ref_idx_l1_active_minus1) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).reserved1) as usize - ptr as usize }, + 6usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH265ReferenceListsInfo), + "::", + stringify!(reserved1) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).pRefPicList0Entries) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH265ReferenceModifications), + stringify!(StdVideoEncodeH265ReferenceListsInfo), "::", - stringify!(pReferenceList0Modifications) + stringify!(pRefPicList0Entries) ) ); assert_eq!( - unsafe { - ::std::ptr::addr_of!((*ptr).referenceList1ModificationsCount) as usize - ptr as usize - }, + unsafe { ::std::ptr::addr_of!((*ptr).pRefPicList1Entries) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH265ReferenceModifications), + stringify!(StdVideoEncodeH265ReferenceListsInfo), "::", - stringify!(referenceList1ModificationsCount) + stringify!(pRefPicList1Entries) ) ); assert_eq!( - unsafe { - ::std::ptr::addr_of!((*ptr).pReferenceList1Modifications) as usize - ptr as usize - }, + unsafe { ::std::ptr::addr_of!((*ptr).pRefList0Modifications) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", - stringify!(StdVideoEncodeH265ReferenceModifications), + stringify!(StdVideoEncodeH265ReferenceListsInfo), "::", - stringify!(pReferenceList1Modifications) + stringify!(pRefList0Modifications) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).pRefList1Modifications) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH265ReferenceListsInfo), + "::", + stringify!(pRefList1Modifications) ) ); } @@ -8786,8 +8920,8 @@ pub struct StdVideoEncodeH265PictureInfo { pub sps_video_parameter_set_id: u8, pub pps_seq_parameter_set_id: u8, pub pps_pic_parameter_set_id: u8, - pub PicOrderCntVal: i32, pub TemporalId: u8, + pub PicOrderCntVal: i32, } #[test] fn bindgen_test_layout_StdVideoEncodeH265PictureInfo() { @@ -8796,7 +8930,7 @@ fn bindgen_test_layout_StdVideoEncodeH265PictureInfo() { let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), - 20usize, + 16usize, concat!("Size of: ", stringify!(StdVideoEncodeH265PictureInfo)) ); assert_eq!( @@ -8854,6 +8988,16 @@ fn bindgen_test_layout_StdVideoEncodeH265PictureInfo() { stringify!(pps_pic_parameter_set_id) ) ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).TemporalId) as usize - ptr as usize }, + 11usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH265PictureInfo), + "::", + stringify!(TemporalId) + ) + ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).PicOrderCntVal) as usize - ptr as usize }, 12usize, @@ -8864,16 +9008,6 @@ fn bindgen_test_layout_StdVideoEncodeH265PictureInfo() { stringify!(PicOrderCntVal) ) ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).TemporalId) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(StdVideoEncodeH265PictureInfo), - "::", - stringify!(TemporalId) - ) - ); } #[repr(C)] #[repr(align(4))] @@ -8947,6 +9081,7 @@ impl StdVideoEncodeH265ReferenceInfoFlags { #[derive(Debug, Copy, Clone)] pub struct StdVideoEncodeH265ReferenceInfo { pub flags: StdVideoEncodeH265ReferenceInfoFlags, + pub PictureType: StdVideoH265PictureType, pub PicOrderCntVal: i32, pub TemporalId: u8, } @@ -8957,7 +9092,7 @@ fn bindgen_test_layout_StdVideoEncodeH265ReferenceInfo() { let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), - 12usize, + 16usize, concat!("Size of: ", stringify!(StdVideoEncodeH265ReferenceInfo)) ); assert_eq!( @@ -8976,8 +9111,18 @@ fn bindgen_test_layout_StdVideoEncodeH265ReferenceInfo() { ) ); assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).PicOrderCntVal) as usize - ptr as usize }, + unsafe { ::std::ptr::addr_of!((*ptr).PictureType) as usize - ptr as usize }, 4usize, + concat!( + "Offset of field: ", + stringify!(StdVideoEncodeH265ReferenceInfo), + "::", + stringify!(PictureType) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).PicOrderCntVal) as usize - ptr as usize }, + 8usize, concat!( "Offset of field: ", stringify!(StdVideoEncodeH265ReferenceInfo), @@ -8987,7 +9132,7 @@ fn bindgen_test_layout_StdVideoEncodeH265ReferenceInfo() { ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).TemporalId) as usize - ptr as usize }, - 8usize, + 12usize, concat!( "Offset of field: ", stringify!(StdVideoEncodeH265ReferenceInfo), diff --git a/third_party/rust/core-graphics-types/.cargo-checksum.json b/third_party/rust/core-graphics-types/.cargo-checksum.json index 31da816670f6..cc00991ad20d 100644 --- a/third_party/rust/core-graphics-types/.cargo-checksum.json +++ b/third_party/rust/core-graphics-types/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"e2e38d84cf514ad088ebc1909123ef4f707db6855528f938eb57d1e06c5a23ef","src/base.rs":"3764010f0c416db49be8a9e191fffb6848e8287edbdd5b12972613e301720ded","src/geometry.rs":"b94e50a16b8540dc6f37bfe4b1549ac68974cd6ba6c0bbd9209559f8a46d86eb","src/lib.rs":"31700ac9508fd32005bafd1c12a86a6803d198e9b1a71166a7391e642c091cd1"},"package":"3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"} \ No newline at end of file +{"files":{"Cargo.toml":"cac07dfd7a2fcbb169a0c471a8a139ade8da91f92b7fbc198f3f2185d9c94d16","src/base.rs":"561db031cc746eab35a10fe72e10c314615b11e13cd48366fcdb2223196308a7","src/geometry.rs":"4ed03b07a4c5ba0f090689d31ef6eab8ec5b8f6eb7fb4e04fdf65e5ad8cd70ea","src/lib.rs":"31700ac9508fd32005bafd1c12a86a6803d198e9b1a71166a7391e642c091cd1"},"package":"2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33"} \ No newline at end of file diff --git a/third_party/rust/core-graphics-types/Cargo.toml b/third_party/rust/core-graphics-types/Cargo.toml index fbc4836458dc..365717dfb42f 100644 --- a/third_party/rust/core-graphics-types/Cargo.toml +++ b/third_party/rust/core-graphics-types/Cargo.toml @@ -3,31 +3,29 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] name = "core-graphics-types" -version = "0.1.1" +version = "0.1.2" authors = ["The Servo Project Developers"] description = "Bindings for some fundamental Core Graphics types" homepage = "https://github.com/servo/core-foundation-rs" -license = "MIT / Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/servo/core-foundation-rs" + [package.metadata.docs.rs] default-target = "x86_64-apple-darwin" + [dependencies.bitflags] version = "1.0" [dependencies.core-foundation] version = "0.9" -[dependencies.foreign-types] -version = "0.3.0" - [dependencies.libc] version = "0.2" diff --git a/third_party/rust/core-graphics-types/src/base.rs b/third_party/rust/core-graphics-types/src/base.rs index d5efc3b62e13..03a85f155910 100644 --- a/third_party/rust/core-graphics-types/src/base.rs +++ b/third_party/rust/core-graphics-types/src/base.rs @@ -26,7 +26,18 @@ pub type CGFloat = libc::c_double; #[cfg(not(target_pointer_width = "64"))] pub type CGFloat = libc::c_float; -pub type CGError = libc::int32_t; +pub type CGError = i32; pub type CGGlyph = libc::c_ushort; +pub const kCGErrorSuccess: CGError = 0; +pub const kCGErrorFailure: CGError = 1000; +pub const kCGErrorIllegalArgument: CGError = 1001; +pub const kCGErrorInvalidConnection: CGError = 1002; +pub const kCGErrorInvalidContext: CGError = 1003; +pub const kCGErrorCannotComplete: CGError = 1004; +pub const kCGErrorNotImplemented: CGError = 1006; +pub const kCGErrorRangeCheck: CGError = 1007; +pub const kCGErrorTypeCheck: CGError = 1008; +pub const kCGErrorInvalidOperation: CGError = 1010; +pub const kCGErrorNoneAvailable: CGError = 1011; diff --git a/third_party/rust/core-graphics-types/src/geometry.rs b/third_party/rust/core-graphics-types/src/geometry.rs index 906c605ec640..586075270c9f 100644 --- a/third_party/rust/core-graphics-types/src/geometry.rs +++ b/third_party/rust/core-graphics-types/src/geometry.rs @@ -138,6 +138,11 @@ impl CGRect { ffi::CGRectApplyAffineTransform(*self, *t) } } + + #[inline] + pub fn contains(&self, point: &CGPoint) -> bool { + unsafe { ffi::CGRectContainsPoint(*self,*point) == 1 } + } } #[repr(C)] @@ -190,6 +195,8 @@ mod ffi { pub fn CGPointApplyAffineTransform(point: CGPoint, t: CGAffineTransform) -> CGPoint; pub fn CGRectApplyAffineTransform(rect: CGRect, t: CGAffineTransform) -> CGRect; pub fn CGSizeApplyAffineTransform(size: CGSize, t: CGAffineTransform) -> CGSize; + + pub fn CGRectContainsPoint(rect:CGRect, point: CGPoint) -> boolean_t; } } diff --git a/third_party/rust/core-graphics/.cargo-checksum.json b/third_party/rust/core-graphics/.cargo-checksum.json index 9dafee4db221..37468e19bb8a 100644 --- a/third_party/rust/core-graphics/.cargo-checksum.json +++ b/third_party/rust/core-graphics/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"453b079ac8a6df8842e7e8a37222318c500f68e1605db7adbdf87337830df593","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"6745c3c38183d2eda9b1fa265fb0a95018db5c110cbabc00b32327d951bbe2ea","src/base.rs":"838683ff67253f4aff1d4b4177531210ca73d4e61f05c5d96a8f196b2a88c787","src/color.rs":"4c8ec4ab828cbc1b2a1538a34a51f5b380927f2f1daf187dff6f732f57a43656","src/color_space.rs":"b3d7ee8a21703c789160867cb8eb2188bd1daa193e3d030f21adb6f1a6f872de","src/context.rs":"8bda7f9ecb5be768b09a29cc3b0a4f329f55d2a2ab74030d121610283862d833","src/data_provider.rs":"b25201fdea43ea1a019c68aa5e997725d04d0824a238354ddc9f2dd8a6835cc4","src/display.rs":"9db5e5440fd302849b13b48393cab4db95447df8d5057c4534a9d8be948ca480","src/event.rs":"17c601ca0b8a0d806fc576cc6cee63a784deaf4246793cf6ce3abcb562de15c5","src/event_source.rs":"d55a4f5b5e62789325028febc51bbf54c74b15ab1a4e70c6ad749a2f9753e081","src/font.rs":"2a7ac5024f17550dd2b6eb97f6971559f930c163eac3a6625d6d55703fd5e96e","src/geometry.rs":"8e12dc89835406bfa514de8fb58f5fd435724d1ddb97dc3a70392efbcf1c42ed","src/gradient.rs":"8ee8661706f36914d08e903840c4f07414b38ba40ea4a482d34b900ac6ac7cf9","src/image.rs":"a5a5df8c0f310455f038eeb16688015f481688cb417f8e8f424a4c1d2a1cdd57","src/lib.rs":"78264571227db6fc9194cb90d64beaff1738a501f88b5da55eb17ae42592d26f","src/path.rs":"c429afeaed999b02ac00f89a867b5fc64f1e223039079a4e0529306b734ff117","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"3077395beb77193530b713aa681cb61f7b86fa79e4e4060133b6d61cf9f47e09","src/window.rs":"2f6c3dc958ae2c0c9e2fc5033300b96e60ed0abee9823ea1f03797d64df0911a"},"package":"2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"} \ No newline at end of file +{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"a0088b6d4f15d2f3abbd411834b84eaa7179b374133fb57b8d3d2048149cc494","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"6745c3c38183d2eda9b1fa265fb0a95018db5c110cbabc00b32327d951bbe2ea","src/access.rs":"919937f8fe61966543c602e30d5d59d61e0b7313bb6b33c25aa600ec5e43345e","src/base.rs":"838683ff67253f4aff1d4b4177531210ca73d4e61f05c5d96a8f196b2a88c787","src/color.rs":"4c8ec4ab828cbc1b2a1538a34a51f5b380927f2f1daf187dff6f732f57a43656","src/color_space.rs":"6a0be06bb7ecdf9d20c461912359d22e0ffd7151c6977a8d9b3b0efdd7929442","src/context.rs":"93d543bd2b77ee6b3132b4378b1652576354fae9bb675cde63e0347d81fec334","src/data_provider.rs":"88e1cdd75c35cff44150f0aac75de6ac715acbf4328abef1b2f191b54401c650","src/display.rs":"391f24669ad1ad5dcd6d15b5e418b6b07731186d3c18d94c8c0935ab348fb3b9","src/event.rs":"7c2ce02fa67cd4613745709563846b57b12fdde105a65d16d29f7a300e9c0f7b","src/event_source.rs":"a81f8bbd41bf4c4e3e91d6a6eab31356728fbf08787aca899ed03259808dfe4a","src/font.rs":"43cad7dfcc49f5f2de408146c6e38843b2d0092b3f5880fbf80e43e18b100f25","src/geometry.rs":"8e12dc89835406bfa514de8fb58f5fd435724d1ddb97dc3a70392efbcf1c42ed","src/gradient.rs":"dd957f14b77d448fa1e51c2e67849364062aa1d5bd60405f060f9a094c628061","src/image.rs":"72076f34a805b1d2336e425cc29d2ec3583046b847e9284ef7413f7eca2acb9a","src/lib.rs":"ca6aabcc5f307a9b15cd3e531d7fb9f54bdf58d9717d38e007e4facf1ca8c9a4","src/path.rs":"9389719ee257d86f50075b294b1b9df8fb3fc93b3442deee868e188489613a2d","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"3077395beb77193530b713aa681cb61f7b86fa79e4e4060133b6d61cf9f47e09","src/window.rs":"2f6c3dc958ae2c0c9e2fc5033300b96e60ed0abee9823ea1f03797d64df0911a"},"package":"506752f2b58723339d41d013009be97e549860785a366e2a5e75dfbd9725b48e"} \ No newline at end of file diff --git a/third_party/rust/core-graphics/Cargo.toml b/third_party/rust/core-graphics/Cargo.toml index b3871d54f4cc..645a88a6b9c0 100644 --- a/third_party/rust/core-graphics/Cargo.toml +++ b/third_party/rust/core-graphics/Cargo.toml @@ -3,23 +3,25 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] name = "core-graphics" -version = "0.22.3" +version = "0.23.0" authors = ["The Servo Project Developers"] description = "Bindings to Core Graphics for macOS" -homepage = "https://github.com/servo/core-graphics-rs" -license = "MIT / Apache-2.0" +homepage = "https://github.com/servo/core-foundation-rs" +readme = "README.md" +license = "MIT OR Apache-2.0" repository = "https://github.com/servo/core-foundation-rs" + [package.metadata.docs.rs] default-target = "x86_64-apple-darwin" + [dependencies.bitflags] version = "1.0" @@ -30,7 +32,7 @@ version = "0.9" version = "0.1" [dependencies.foreign-types] -version = "0.3.0" +version = "0.5.0" [dependencies.libc] version = "0.2" diff --git a/third_party/rust/core-graphics/src/access.rs b/third_party/rust/core-graphics/src/access.rs new file mode 100644 index 000000000000..4e852c85ae84 --- /dev/null +++ b/third_party/rust/core-graphics/src/access.rs @@ -0,0 +1,26 @@ +pub use base::boolean_t; + +#[derive(Default)] +pub struct ScreenCaptureAccess; + +impl ScreenCaptureAccess { + /// If current app not in list, will open window. + /// Return the same result as preflight. + #[inline] + pub fn request(&self) -> bool { + unsafe { CGRequestScreenCaptureAccess() == 1 } + } + + /// Return true if has access + #[inline] + pub fn preflight(&self) -> bool { + unsafe { CGPreflightScreenCaptureAccess() == 1 } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern "C" { + // Screen Capture Access + fn CGRequestScreenCaptureAccess() -> boolean_t; + fn CGPreflightScreenCaptureAccess() -> boolean_t; +} diff --git a/third_party/rust/core-graphics/src/color_space.rs b/third_party/rust/core-graphics/src/color_space.rs index 9eef09c30b19..2b29635756b0 100644 --- a/third_party/rust/core-graphics/src/color_space.rs +++ b/third_party/rust/core-graphics/src/color_space.rs @@ -13,11 +13,11 @@ use foreign_types::ForeignType; foreign_type! { #[doc(hidden)] - type CType = ::sys::CGColorSpace; - fn drop = |p| CFRelease(p as *mut _); - fn clone = |p| CFRetain(p as *const _) as *mut _; - pub struct CGColorSpace; - pub struct CGColorSpaceRef; + pub unsafe type CGColorSpace { + type CType = ::sys::CGColorSpace; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + } } impl CGColorSpace { @@ -53,13 +53,61 @@ impl CGColorSpace { #[link(name = "CoreGraphics", kind = "framework")] extern { + /// The Display P3 color space, created by Apple. + pub static kCGColorSpaceDisplayP3: CFStringRef; + /// The Display P3 color space, using the HLG transfer function. + pub static kCGColorSpaceDisplayP3_HLG: CFStringRef; + /// The Display P3 color space with a linear transfer function + /// and extended-range values. + pub static kCGColorSpaceExtendedLinearDisplayP3: CFStringRef; + /// The standard Red Green Blue (sRGB) color space. pub static kCGColorSpaceSRGB: CFStringRef; - pub static kCGColorSpaceAdobeRGB1998: CFStringRef; - pub static kCGColorSpaceGenericGray: CFStringRef; - pub static kCGColorSpaceGenericRGB: CFStringRef; - pub static kCGColorSpaceGenericCMYK: CFStringRef; - pub static kCGColorSpaceGenericRGBLinear: CFStringRef; + /// The sRGB color space with a linear transfer function. + pub static kCGColorSpaceLinearSRGB: CFStringRef; + /// The extended sRGB color space. + pub static kCGColorSpaceExtendedSRGB: CFStringRef; + /// The sRGB color space with a linear transfer function and + /// extended-range values. + pub static kCGColorSpaceExtendedLinearSRGB: CFStringRef; + /// The generic gray color space that has an exponential transfer + /// function with a power of 2.2. pub static kCGColorSpaceGenericGrayGamma2_2: CFStringRef; + /// The gray color space using a linear transfer function. + pub static kCGColorSpaceLinearGray: CFStringRef; + /// The extended gray color space. + pub static kCGColorSpaceExtendedGray: CFStringRef; + /// The extended gray color space with a linear transfer function. + pub static kCGColorSpaceExtendedLinearGray: CFStringRef; + /// The generic RGB color space with a linear transfer function. + pub static kCGColorSpaceGenericRGBLinear: CFStringRef; + /// The generic CMYK color space. + pub static kCGColorSpaceGenericCMYK: CFStringRef; + /// The XYZ color space, as defined by the CIE 1931 standard. + pub static kCGColorSpaceGenericXYZ: CFStringRef; + /// The generic LAB color space. + pub static kCGColorSpaceGenericLab: CFStringRef; + /// The ACEScg color space. + pub static kCGColorSpaceACESCGLinear: CFStringRef; + /// The Adobe RGB (1998) color space. + pub static kCGColorSpaceAdobeRGB1998: CFStringRef; + /// The DCI P3 color space, which is the digital cinema standard. + pub static kCGColorSpaceDCIP3: CFStringRef; + /// The recommendation of the International Telecommunication Union + /// (ITU) Radiocommunication sector for the BT.709 color space. + pub static kCGColorSpaceITUR_709: CFStringRef; + /// The Reference Output Medium Metric (ROMM) RGB color space. + pub static kCGColorSpaceROMMRGB: CFStringRef; + /// The recommendation of the International Telecommunication Union + /// (ITU) Radiocommunication sector for the BT.2020 color space. + pub static kCGColorSpaceITUR_2020: CFStringRef; + /// The recommendation of the International Telecommunication Union + /// (ITU) Radiocommunication sector for the BT.2020 color space, with + /// a linear transfer function and extended range values. + pub static kCGColorSpaceExtendedLinearITUR_2020: CFStringRef; + /// The name of the generic RGB color space. + pub static kCGColorSpaceGenericRGB: CFStringRef; + /// The name of the generic gray color space. + pub static kCGColorSpaceGenericGray: CFStringRef; fn CGColorSpaceCreateDeviceRGB() -> ::sys::CGColorSpaceRef; fn CGColorSpaceCreateDeviceGray() -> ::sys::CGColorSpaceRef; diff --git a/third_party/rust/core-graphics/src/context.rs b/third_party/rust/core-graphics/src/context.rs index 4efc0f70a371..aca5fb74d52d 100644 --- a/third_party/rust/core-graphics/src/context.rs +++ b/third_party/rust/core-graphics/src/context.rs @@ -109,11 +109,11 @@ pub enum CGInterpolationQuality { foreign_type! { #[doc(hidden)] - type CType = ::sys::CGContext; - fn drop = |cs| CGContextRelease(cs); - fn clone = |p| CGContextRetain(p); - pub struct CGContext; - pub struct CGContextRef; + pub unsafe type CGContext { + type CType = ::sys::CGContext; + fn drop = |cs| CGContextRelease(cs); + fn clone = |p| CGContextRetain(p); + } } impl CGContext { @@ -389,6 +389,12 @@ impl CGContextRef { } } + pub fn reset_clip(&self) { + unsafe { + CGContextResetClip(self.as_ptr()); + } + } + pub fn draw_path(&self, mode: CGPathDrawingMode) { unsafe { CGContextDrawPath(self.as_ptr(), mode); @@ -612,6 +618,12 @@ impl CGContextRef { CGContextSetShadowWithColor(self.as_ptr(), offset, blur, color.as_concrete_TypeRef()); } } + + pub fn set_alpha(&self, alpha: CGFloat) { + unsafe { + CGContextSetAlpha(self.as_ptr(), alpha); + } + } } #[test] @@ -708,6 +720,7 @@ extern { fn CGContextEOFillPath(c: ::sys::CGContextRef); fn CGContextClip(c: ::sys::CGContextRef); fn CGContextEOClip(c: ::sys::CGContextRef); + fn CGContextResetClip(c: ::sys::CGContextRef); fn CGContextStrokePath(c: ::sys::CGContextRef); fn CGContextSetRGBFillColor(context: ::sys::CGContextRef, red: CGFloat, @@ -771,5 +784,7 @@ extern { fn CGContextSetShadow(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat); fn CGContextSetShadowWithColor(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat, color: ::sys::CGColorRef); + + fn CGContextSetAlpha(c: ::sys::CGContextRef, alpha: CGFloat); } diff --git a/third_party/rust/core-graphics/src/data_provider.rs b/third_party/rust/core-graphics/src/data_provider.rs index e8bb0a024188..38d515e397ff 100644 --- a/third_party/rust/core-graphics/src/data_provider.rs +++ b/third_party/rust/core-graphics/src/data_provider.rs @@ -32,11 +32,11 @@ pub type CGDataProviderGetBytesAtPositionCallback = Option Option { + unsafe { + let image_ref = CGDisplayCreateImageForRect(self.id, bounds); + if !image_ref.is_null() { + Some(CGImage::from_ptr(image_ref)) + } else { + None + } + } + } + /// Returns a composite image based on a dynamically generated list of /// windows. #[inline] @@ -604,7 +629,7 @@ impl CGDisplayMode { 16 } else if pixel_encoding.eq_ignore_ascii_case(IO8BitIndexedPixels) { 8 - }else{ + } else { 0 } } @@ -621,6 +646,7 @@ extern "C" { pub static kCGDisplayShowDuplicateLowResolutionModes: CFStringRef; + pub fn CGDisplayModeRetain(mode: ::sys::CGDisplayModeRef); pub fn CGDisplayModeRelease(mode: ::sys::CGDisplayModeRef); pub fn CGMainDisplayID() -> CGDirectDisplayID; @@ -657,7 +683,17 @@ extern "C" { pub fn CGDisplayPixelsWide(display: CGDirectDisplayID) -> libc::size_t; pub fn CGDisplayBounds(display: CGDirectDisplayID) -> CGRect; pub fn CGDisplayCreateImage(display: CGDirectDisplayID) -> ::sys::CGImageRef; + pub fn CGDisplayCreateImageForRect( + display: CGDirectDisplayID, + rect: CGRect, + ) -> ::sys::CGImageRef; + // Capturing and Releasing Displays + pub fn CGDisplayCapture(display: CGDirectDisplayID) -> CGError; + pub fn CGDisplayRelease(display: CGDirectDisplayID) -> CGError; + pub fn CGShieldingWindowLevel() -> CGWindowLevel; + + // Configuring Displays pub fn CGBeginDisplayConfiguration(config: *mut CGDisplayConfigRef) -> CGError; pub fn CGCancelDisplayConfiguration(config: CGDisplayConfigRef) -> CGError; pub fn CGCompleteDisplayConfiguration( @@ -681,6 +717,7 @@ extern "C" { x: i32, y: i32, ) -> CGError; + pub fn CGRestorePermanentDisplayConfiguration(); pub fn CGDisplayCopyDisplayMode(display: CGDirectDisplayID) -> ::sys::CGDisplayModeRef; pub fn CGDisplayModeGetHeight(mode: ::sys::CGDisplayModeRef) -> libc::size_t; @@ -696,6 +733,11 @@ extern "C" { display: CGDirectDisplayID, options: CFDictionaryRef, ) -> CFArrayRef; + pub fn CGDisplaySetDisplayMode( + display: CGDirectDisplayID, + mode: ::sys::CGDisplayModeRef, + options: CFDictionaryRef, + ) -> CGError; // mouse stuff pub fn CGDisplayHideCursor(display: CGDirectDisplayID) -> CGError; @@ -704,6 +746,32 @@ extern "C" { pub fn CGWarpMouseCursorPosition(point: CGPoint) -> CGError; pub fn CGAssociateMouseAndMouseCursorPosition(connected: boolean_t) -> CGError; + // Display Fade Effects + pub fn CGConfigureDisplayFadeEffect( + config: CGDisplayConfigRef, + fadeOutSeconds: CGDisplayFadeInterval, + fadeInSeconds: CGDisplayFadeInterval, + fadeRed: f32, + fadeGreen: f32, + fadeBlue: f32, + ) -> CGError; + pub fn CGAcquireDisplayFadeReservation( + seconds: CGDisplayReservationInterval, + token: *mut CGDisplayFadeReservationToken, + ) -> CGError; + pub fn CGDisplayFade( + token: CGDisplayFadeReservationToken, + duration: CGDisplayFadeInterval, + startBlend: CGDisplayBlendFraction, + endBlend: CGDisplayBlendFraction, + redBlend: f32, + greenBlend: f32, + blueBlend: f32, + synchronous: boolean_t, + ) -> CGError; + // CGDisplayFadeOperationInProgress + pub fn CGReleaseDisplayFadeReservation(token: CGDisplayFadeReservationToken) -> CGError; + // Window Services Reference pub fn CGWindowListCopyWindowInfo( option: CGWindowListOption, diff --git a/third_party/rust/core-graphics/src/event.rs b/third_party/rust/core-graphics/src/event.rs index 8cf9c6262e90..3f2d8c143d2c 100644 --- a/third_party/rust/core-graphics/src/event.rs +++ b/third_party/rust/core-graphics/src/event.rs @@ -505,7 +505,7 @@ impl<'tap_life> CGEventTap<'tap_life> { callback_ref: Box::from_raw(cbr), }) } else { - Box::from_raw(cbr); + let _ = Box::from_raw(cbr); Err(()) } } @@ -518,11 +518,11 @@ impl<'tap_life> CGEventTap<'tap_life> { foreign_type! { #[doc(hidden)] - type CType = ::sys::CGEvent; - fn drop = |p| CFRelease(p as *mut _); - fn clone = |p| CFRetain(p as *const _) as *mut _; - pub struct CGEvent; - pub struct CGEventRef; + pub unsafe type CGEvent { + type CType = ::sys::CGEvent; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + } } impl CGEvent { @@ -607,12 +607,16 @@ impl CGEvent { } } - pub fn location(&self) -> CGPoint { + pub fn post_from_tap(&self, tap_proxy: CGEventTapProxy) { unsafe { - CGEventGetLocation(self.as_ptr()) + CGEventTapPostEvent(tap_proxy, self.as_ptr()); } } + pub fn location(&self) -> CGPoint { + unsafe { CGEventGetLocation(self.as_ptr()) } + } + #[cfg(feature = "elcapitan")] pub fn post_to_pid(&self, pid: libc::pid_t) { unsafe { @@ -734,6 +738,8 @@ extern { /// taps. fn CGEventPost(tapLocation: CGEventTapLocation, event: ::sys::CGEventRef); + fn CGEventTapPostEvent(tapProxy: CGEventTapProxy, event: ::sys::CGEventRef); + #[cfg(feature = "elcapitan")] /// Post an event to a specified process ID fn CGEventPostToPid(pid: libc::pid_t, event: ::sys::CGEventRef); diff --git a/third_party/rust/core-graphics/src/event_source.rs b/third_party/rust/core-graphics/src/event_source.rs index ce13f5a91cfd..6db64a2dca15 100644 --- a/third_party/rust/core-graphics/src/event_source.rs +++ b/third_party/rust/core-graphics/src/event_source.rs @@ -12,11 +12,11 @@ pub enum CGEventSourceStateID { foreign_type! { #[doc(hidden)] - type CType = ::sys::CGEventSource; - fn drop = |p| CFRelease(p as *mut _); - fn clone = |p| CFRetain(p as *const _) as *mut _; - pub struct CGEventSource; - pub struct CGEventSourceRef; + pub unsafe type CGEventSource { + type CType = ::sys::CGEventSource; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + } } impl CGEventSource { diff --git a/third_party/rust/core-graphics/src/font.rs b/third_party/rust/core-graphics/src/font.rs index adf7a1493284..739b8ddf3291 100644 --- a/third_party/rust/core-graphics/src/font.rs +++ b/third_party/rust/core-graphics/src/font.rs @@ -15,6 +15,7 @@ use core_foundation::string::{CFString, CFStringRef}; use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; use data_provider::CGDataProvider; use geometry::CGRect; +use std::ptr::NonNull; use foreign_types::ForeignType; @@ -24,16 +25,13 @@ pub use core_graphics_types::base::CGGlyph; foreign_type! { #[doc(hidden)] - type CType = ::sys::CGFont; - fn drop = |p| CFRelease(p as *mut _); - fn clone = |p| CFRetain(p as *const _) as *mut _; - pub struct CGFont; - pub struct CGFontRef; + pub unsafe type CGFont: Send + Sync { + type CType = ::sys::CGFont; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + } } -unsafe impl Send for CGFont {} -unsafe impl Sync for CGFont {} - impl CGFont { pub fn type_id() -> CFTypeID { unsafe { @@ -44,10 +42,9 @@ impl CGFont { pub fn from_data_provider(provider: CGDataProvider) -> Result { unsafe { let font_ref = CGFontCreateWithDataProvider(provider.as_ptr()); - if !font_ref.is_null() { - Ok(CGFont::from_ptr(font_ref)) - } else { - Err(()) + match NonNull::new(font_ref) { + Some(font_ref) => Ok(CGFont(font_ref)), + None => Err(()), } } } @@ -55,10 +52,9 @@ impl CGFont { pub fn from_name(name: &CFString) -> Result { unsafe { let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef()); - if !font_ref.is_null() { - Ok(CGFont::from_ptr(font_ref)) - } else { - Err(()) + match NonNull::new(font_ref) { + Some(font_ref) => Ok(CGFont(font_ref)), + None => Err(()), } } } @@ -67,10 +63,9 @@ impl CGFont { unsafe { let font_ref = CGFontCreateCopyWithVariations(self.as_ptr(), vars.as_concrete_TypeRef()); - if !font_ref.is_null() { - Ok(CGFont::from_ptr(font_ref)) - } else { - Err(()) + match NonNull::new(font_ref) { + Some(font_ref) => Ok(CGFont(font_ref)), + None => Err(()), } } } diff --git a/third_party/rust/core-graphics/src/gradient.rs b/third_party/rust/core-graphics/src/gradient.rs index 5c6cde846e1d..a4fb2bf613bf 100644 --- a/third_party/rust/core-graphics/src/gradient.rs +++ b/third_party/rust/core-graphics/src/gradient.rs @@ -29,11 +29,11 @@ bitflags! { foreign_type! { #[doc(hidden)] - type CType = ::sys::CGGradient; - fn drop = |p| CFRelease(p as *mut _); - fn clone = |p| CFRetain(p as *const _) as *mut _; - pub struct CGGradient; - pub struct CGGradientRef; + pub unsafe type CGGradient { + type CType = ::sys::CGGradient; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + } } impl CGGradient { diff --git a/third_party/rust/core-graphics/src/image.rs b/third_party/rust/core-graphics/src/image.rs index f1b95096d9eb..9e9323f4a1d2 100644 --- a/third_party/rust/core-graphics/src/image.rs +++ b/third_party/rust/core-graphics/src/image.rs @@ -32,11 +32,11 @@ pub enum CGImageByteOrderInfo { foreign_type! { #[doc(hidden)] - type CType = ::sys::CGImage; - fn drop = CGImageRelease; - fn clone = |p| CFRetain(p as *const _) as *mut _; - pub struct CGImage; - pub struct CGImageRef; + pub unsafe type CGImage { + type CType = ::sys::CGImage; + fn drop = CGImageRelease; + fn clone = |p| CFRetain(p as *const _) as *mut _; + } } impl CGImage { diff --git a/third_party/rust/core-graphics/src/lib.rs b/third_party/rust/core-graphics/src/lib.rs index 5238774e7cec..514558fb481a 100644 --- a/third_party/rust/core-graphics/src/lib.rs +++ b/third_party/rust/core-graphics/src/lib.rs @@ -41,3 +41,5 @@ pub mod private; pub mod image; pub mod path; pub mod sys; +#[cfg(target_os = "macos")] +pub mod access; \ No newline at end of file diff --git a/third_party/rust/core-graphics/src/path.rs b/third_party/rust/core-graphics/src/path.rs index dc1c80464472..c5ac93f40b07 100644 --- a/third_party/rust/core-graphics/src/path.rs +++ b/third_party/rust/core-graphics/src/path.rs @@ -21,11 +21,11 @@ use std::slice; foreign_type! { #[doc(hidden)] - type CType = ::sys::CGPath; - fn drop = |p| CFRelease(p as *mut _); - fn clone = |p| CFRetain(p as *const _) as *mut _; - pub struct CGPath; - pub struct CGPathRef; + pub unsafe type CGPath { + type CType = ::sys::CGPath; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + } } impl CGPath { @@ -35,7 +35,7 @@ impl CGPath { None => ptr::null(), Some(transform) => transform as *const CGAffineTransform, }; - CGPath(CGPathCreateWithRect(rect, transform)) + CGPath::from_ptr(CGPathCreateWithRect(rect, transform)) } } diff --git a/third_party/rust/core-text/.cargo-checksum.json b/third_party/rust/core-text/.cargo-checksum.json index 057b26119112..10bc5db09c80 100644 --- a/third_party/rust/core-text/.cargo-checksum.json +++ b/third_party/rust/core-text/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"26a527860e530d18a5ce446ffb595f63a178504506fb4a283993402295053afe","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"98d25015857a430aac32f34bdc979a1a66e672a0ea42c5f92dd9cfe23c1fccfd","src/font.rs":"17d957510eee8d96ef2bc1b5bc97491917ac0336ad3dbf48416dda3685cef579","src/font_collection.rs":"02de0ce2a61683314897a521d31ab9cc572a8b10ceda2ac47181fbe18bf4f235","src/font_descriptor.rs":"43a2fec6bca9689d8172f363ab20ce8c633696974e1653cad2e072e3af776528","src/font_manager.rs":"6e5056a42868187e1f4e696c181ca247423308652d3c68867c708616031876e4","src/frame.rs":"ed1e2aad7be9dafc3e9729f2caecefd4214a9552f834932a414239146142069a","src/framesetter.rs":"13e34b4111cee5f023aa05e2220d2a6f102e96fd18c51a356992bffd6c9fc7c1","src/lib.rs":"1c662e51874eb43ff52a8a1af131d1b2fd84095c3d949a271dc895bf56fd0fc6","src/line.rs":"02fab7f07c3f6a003a7c35ffeb3d37546ae58e4da7fe05f26e520f283397a602","src/run.rs":"b86e9b9b39effe4a79c6002880d95f214742d448029a3111e288734abe75b827","src/string_attributes.rs":"ea0f854d64097d3626a03002323e2276e28affae7a698aaadd89dd6b744dd80f"},"package":"99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"} \ No newline at end of file +{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7a776cd901d7f63a97ad6c1576b00f267ad782ef79ff4cdfbc2cb507a2c144d5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"98d25015857a430aac32f34bdc979a1a66e672a0ea42c5f92dd9cfe23c1fccfd","src/font.rs":"149d4646abc01a884e16d45dde77b44d3151cab27c301c65fa22dda638ff3c48","src/font_collection.rs":"02de0ce2a61683314897a521d31ab9cc572a8b10ceda2ac47181fbe18bf4f235","src/font_descriptor.rs":"43a2fec6bca9689d8172f363ab20ce8c633696974e1653cad2e072e3af776528","src/font_manager.rs":"6e5056a42868187e1f4e696c181ca247423308652d3c68867c708616031876e4","src/frame.rs":"ed1e2aad7be9dafc3e9729f2caecefd4214a9552f834932a414239146142069a","src/framesetter.rs":"13e34b4111cee5f023aa05e2220d2a6f102e96fd18c51a356992bffd6c9fc7c1","src/lib.rs":"1c662e51874eb43ff52a8a1af131d1b2fd84095c3d949a271dc895bf56fd0fc6","src/line.rs":"02fab7f07c3f6a003a7c35ffeb3d37546ae58e4da7fe05f26e520f283397a602","src/run.rs":"b86e9b9b39effe4a79c6002880d95f214742d448029a3111e288734abe75b827","src/string_attributes.rs":"ea0f854d64097d3626a03002323e2276e28affae7a698aaadd89dd6b744dd80f"},"package":"02083d15989d6247553e1a63753561555a72b2038bba1e4239db70602a798742"} \ No newline at end of file diff --git a/third_party/rust/core-text/Cargo.toml b/third_party/rust/core-text/Cargo.toml index a674dc3327fb..26b9c510bb02 100644 --- a/third_party/rust/core-text/Cargo.toml +++ b/third_party/rust/core-text/Cargo.toml @@ -3,30 +3,32 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] name = "core-text" -version = "19.2.0" +version = "20.0.0" authors = ["The Servo Project Developers"] description = "Bindings to the Core Text framework." -license = "MIT/Apache-2.0" +readme = "README.md" +license = "MIT OR Apache-2.0" repository = "https://github.com/servo/core-foundation-rs" + [package.metadata.docs.rs] default-target = "x86_64-apple-darwin" + [dependencies.core-foundation] version = "0.9" [dependencies.core-graphics] -version = "0.22.0" +version = "0.23.0" [dependencies.foreign-types] -version = "0.3" +version = "0.5" [dependencies.libc] version = "0.2" diff --git a/third_party/rust/core-text/src/font.rs b/third_party/rust/core-text/src/font.rs index ebe6d580f578..87a8a530950a 100644 --- a/third_party/rust/core-text/src/font.rs +++ b/third_party/rust/core-text/src/font.rs @@ -78,6 +78,54 @@ pub const kCTFontOptionsDefault: CTFontOptions = 0; pub const kCTFontOptionsPreventAutoActivation: CTFontOptions = 1 << 0; pub const kCTFontOptionsPreferSystemFont: CTFontOptions = 1 << 2; +pub enum CTFontNameSpecifier { + Copyright, + Family, + SubFamily, + Style, + Unique, + Full, + Version, + PostScript, + Trademark, + Manufacturer, + Designer, + Description, + VendorURL, + DesignerURL, + License, + LicenseURL, + SampleText, + PostScriptCID, +} + +impl Into for CTFontNameSpecifier { + fn into(self) -> CFStringRef { + unsafe { + match self { + CTFontNameSpecifier::Copyright => kCTFontCopyrightNameKey, + CTFontNameSpecifier::Family => kCTFontFamilyNameKey, + CTFontNameSpecifier::SubFamily => kCTFontSubFamilyNameKey, + CTFontNameSpecifier::Style => kCTFontStyleNameKey, + CTFontNameSpecifier::Unique => kCTFontUniqueNameKey, + CTFontNameSpecifier::Full => kCTFontFullNameKey, + CTFontNameSpecifier::Version => kCTFontVersionNameKey, + CTFontNameSpecifier::PostScript => kCTFontPostScriptNameKey, + CTFontNameSpecifier::Trademark => kCTFontTrademarkNameKey, + CTFontNameSpecifier::Manufacturer => kCTFontManufacturerNameKey, + CTFontNameSpecifier::Designer => kCTFontDesignerNameKey, + CTFontNameSpecifier::Description => kCTFontDescriptionNameKey, + CTFontNameSpecifier::VendorURL => kCTFontVendorURLNameKey, + CTFontNameSpecifier::DesignerURL => kCTFontDesignerURLNameKey, + CTFontNameSpecifier::License => kCTFontLicenseNameKey, + CTFontNameSpecifier::LicenseURL => kCTFontLicenseURLNameKey, + CTFontNameSpecifier::SampleText => kCTFontSampleTextNameKey, + CTFontNameSpecifier::PostScriptCID => kCTFontPostScriptCIDNameKey, + } + } + } +} + #[repr(C)] pub struct __CTFont(c_void); @@ -144,6 +192,29 @@ pub fn new_from_name(name: &str, pt_size: f64) -> Result { } } +pub fn new_ui_font_for_language(ui_type: CTFontUIFontType, + size: f64, + language: Option) + -> CTFont { + unsafe { + let font_ref = CTFontCreateUIFontForLanguage( + ui_type, + size, + language.as_ref() + .map(|x| x.as_concrete_TypeRef()) + .unwrap_or(std::ptr::null()), + ); + if font_ref.is_null() { + // CTFontCreateUIFontForLanguage can fail, but is unlikely to do so during + // normal usage (if you pass a bad ui_type it will). To make things more + // convenient, just panic if it fails. + panic!(); + } else { + CTFont::wrap_under_create_rule(font_ref) + } + } +} + impl CTFont { // Properties pub fn symbolic_traits(&self) -> CTFontSymbolicTraits { @@ -198,46 +269,45 @@ impl CTFont { } // Names - pub fn family_name(&self) -> String { + pub fn get_string_by_name_key(&self, name_key: CTFontNameSpecifier) -> Option { unsafe { - let value = get_string_by_name_key(self, kCTFontFamilyNameKey); - value.expect("Fonts should always have a family name.") + let result = CTFontCopyName(self.as_concrete_TypeRef(), name_key.into()); + if result.is_null() { + None + } else { + Some(CFString::wrap_under_create_rule(result).to_string()) + } } } + pub fn family_name(&self) -> String { + let value = self.get_string_by_name_key(CTFontNameSpecifier::Family); + value.expect("Fonts should always have a family name.") + } + pub fn face_name(&self) -> String { - unsafe { - let value = get_string_by_name_key(self, kCTFontSubFamilyNameKey); - value.expect("Fonts should always have a face name.") - } + let value = self.get_string_by_name_key(CTFontNameSpecifier::SubFamily); + value.expect("Fonts should always have a face name.") } pub fn unique_name(&self) -> String { - unsafe { - let value = get_string_by_name_key(self, kCTFontUniqueNameKey); - value.expect("Fonts should always have a unique name.") - } + let value = self.get_string_by_name_key(CTFontNameSpecifier::Unique); + value.expect("Fonts should always have a unique name.") } pub fn postscript_name(&self) -> String { - unsafe { - let value = get_string_by_name_key(self, kCTFontPostScriptNameKey); - value.expect("Fonts should always have a PostScript name.") - } + let value = self.get_string_by_name_key(CTFontNameSpecifier::PostScript); + value.expect("Fonts should always have a PostScript name.") } pub fn display_name(&self) -> String { - unsafe { - let value = get_string_by_name_key(self, kCTFontFullNameKey); - value.expect("Fonts should always have a PostScript name.") - } + let value = self.get_string_by_name_key(CTFontNameSpecifier::Full); + value.expect("Fonts should always have a PostScript name.") } pub fn style_name(&self) -> String { - unsafe { - let value = get_string_by_name_key(self, kCTFontStyleNameKey); - value.expect("Fonts should always have a style name.") - } + let value = self.get_string_by_name_key(CTFontNameSpecifier::Style); + value.expect("Fonts should always have a style name.") } pub fn all_traits(&self) -> CTFontTraits { @@ -437,30 +507,17 @@ impl CTFont { } // Helper methods -fn get_string_by_name_key(font: &CTFont, name_key: CFStringRef) -> Option { - unsafe { - let result = CTFontCopyName(font.as_concrete_TypeRef(), name_key); - if result.is_null() { - None - } else { - Some(CFString::wrap_under_create_rule(result).to_string()) - } - } -} - pub fn debug_font_names(font: &CTFont) { - fn get_key(font: &CTFont, key: CFStringRef) -> String { - get_string_by_name_key(font, key).unwrap() + fn get_key(font: &CTFont, key: CTFontNameSpecifier) -> String { + font.get_string_by_name_key(key).unwrap() } - unsafe { - println!("kCTFontFamilyNameKey: {}", get_key(font, kCTFontFamilyNameKey)); - println!("kCTFontSubFamilyNameKey: {}", get_key(font, kCTFontSubFamilyNameKey)); - println!("kCTFontStyleNameKey: {}", get_key(font, kCTFontStyleNameKey)); - println!("kCTFontUniqueNameKey: {}", get_key(font, kCTFontUniqueNameKey)); - println!("kCTFontFullNameKey: {}", get_key(font, kCTFontFullNameKey)); - println!("kCTFontPostScriptNameKey: {}", get_key(font, kCTFontPostScriptNameKey)); - } + println!("kCTFontFamilyNameKey: {}", get_key(font, CTFontNameSpecifier::Family)); + println!("kCTFontSubFamilyNameKey: {}", get_key(font, CTFontNameSpecifier::SubFamily)); + println!("kCTFontStyleNameKey: {}", get_key(font, CTFontNameSpecifier::Style)); + println!("kCTFontUniqueNameKey: {}", get_key(font, CTFontNameSpecifier::Unique)); + println!("kCTFontFullNameKey: {}", get_key(font, CTFontNameSpecifier::Full)); + println!("kCTFontPostScriptNameKey: {}", get_key(font, CTFontNameSpecifier::PostScript)); } pub fn debug_font_traits(font: &CTFont) { @@ -494,28 +551,30 @@ extern { */ /* Name Specifier Constants */ - //static kCTFontCopyrightNameKey: CFStringRef; + static kCTFontCopyrightNameKey: CFStringRef; static kCTFontFamilyNameKey: CFStringRef; static kCTFontSubFamilyNameKey: CFStringRef; static kCTFontStyleNameKey: CFStringRef; static kCTFontUniqueNameKey: CFStringRef; static kCTFontFullNameKey: CFStringRef; - //static kCTFontVersionNameKey: CFStringRef; + static kCTFontVersionNameKey: CFStringRef; static kCTFontPostScriptNameKey: CFStringRef; - //static kCTFontTrademarkNameKey: CFStringRef; - //static kCTFontManufacturerNameKey: CFStringRef; - //static kCTFontDesignerNameKey: CFStringRef; - //static kCTFontDescriptionNameKey: CFStringRef; - //static kCTFontVendorURLNameKey: CFStringRef; - //static kCTFontDesignerURLNameKey: CFStringRef; - //static kCTFontLicenseNameKey: CFStringRef; - //static kCTFontLicenseURLNameKey: CFStringRef; - //static kCTFontSampleTextNameKey: CFStringRef; - //static kCTFontPostScriptCIDNameKey: CFStringRef; + static kCTFontTrademarkNameKey: CFStringRef; + static kCTFontManufacturerNameKey: CFStringRef; + static kCTFontDesignerNameKey: CFStringRef; + static kCTFontDescriptionNameKey: CFStringRef; + static kCTFontVendorURLNameKey: CFStringRef; + static kCTFontDesignerURLNameKey: CFStringRef; + static kCTFontLicenseNameKey: CFStringRef; + static kCTFontLicenseURLNameKey: CFStringRef; + static kCTFontSampleTextNameKey: CFStringRef; + static kCTFontPostScriptCIDNameKey: CFStringRef; - //static kCTFontVariationAxisIdentifierKey: CFStringRef; + #[cfg(test)] + static kCTFontVariationAxisIdentifierKey: CFStringRef; //static kCTFontVariationAxisMinimumValueKey: CFStringRef; - //static kCTFontVariationAxisMaximumValueKey: CFStringRef; + #[cfg(test)] + static kCTFontVariationAxisMaximumValueKey: CFStringRef; //static kCTFontVariationAxisDefaultValueKey: CFStringRef; //static kCTFontVariationAxisNameKey: CFStringRef; @@ -539,7 +598,6 @@ extern { fn CTFontCreateWithFontDescriptor(descriptor: CTFontDescriptorRef, size: CGFloat, matrix: *const CGAffineTransform) -> CTFontRef; //fn CTFontCreateWithFontDescriptorAndOptions - #[cfg(test)] fn CTFontCreateUIFontForLanguage(uiType: CTFontUIFontType, size: CGFloat, language: CFStringRef) -> CTFontRef; fn CTFontCreateCopyWithAttributes(font: CTFontRef, size: CGFloat, matrix: *const CGAffineTransform, attributes: CTFontDescriptorRef) -> CTFontRef; @@ -691,11 +749,9 @@ fn macos_version() -> (i32, i32, i32) { #[test] fn copy_system_font() { - let small = unsafe { - CTFont::wrap_under_create_rule( - CTFontCreateUIFontForLanguage(kCTFontSystemDetailFontType, 19., std::ptr::null()) - ) - }; + use crate::*; + + let small = new_ui_font_for_language(kCTFontSystemDetailFontType, 19., None); let big = small.clone_with_font_size(20.); // ensure that we end up with different fonts for the different sizes before 10.15 @@ -712,6 +768,12 @@ fn copy_system_font() { let ctfont = new_from_descriptor(&desc, 20.); assert_eq!(big.postscript_name(), ctfont.postscript_name()); + // check that we can construct a new version by attributes + let attr = desc.attributes(); + let desc_from_attr = font_descriptor::new_from_attributes(&attr); + let font_from_attr = new_from_descriptor(&desc_from_attr, 19.); + assert_eq!(font_from_attr.postscript_name(), small.postscript_name()); + // on newer versions of macos we can't construct by name anymore if macos_version() < (10, 13, 0) { let ui_font_by_name = new_from_name(&small.postscript_name(), 19.).unwrap(); @@ -741,4 +803,165 @@ fn copy_system_font() { assert!(matching.attributes().find(CFString::from_static_string("NSFontSizeAttribute")).is_none()); assert_eq!(small.postscript_name(), cgfont.postscript_name()); -} \ No newline at end of file +} + +// Tests what happens when variations have values not inbetween min and max +#[test] +fn out_of_range_variations() { + use crate::*; + + let small = new_ui_font_for_language(kCTFontSystemDetailFontType, 19., None); + + let axes = small.get_variation_axes(); + if macos_version() < (10, 12, 0) { + assert!(axes.is_none()); + return; + } + let axes = axes.unwrap(); + let mut vals = Vec::new(); + dbg!(&axes); + for axis in axes.iter() { + let tag = axis.find(unsafe { kCTFontVariationAxisIdentifierKey } ) + .unwrap().downcast::().unwrap().to_i64().unwrap(); + let max = axis.find(unsafe { kCTFontVariationAxisMaximumValueKey } ) + .unwrap().downcast::().unwrap().to_f64().unwrap(); + vals.push((CFNumber::from(tag), CFNumber::from(max + 1.))); + + } + let vals_dict = CFDictionary::from_CFType_pairs(&vals); + let variation_attribute = unsafe { CFString::wrap_under_get_rule(font_descriptor::kCTFontVariationAttribute) }; + let attrs_dict = CFDictionary::from_CFType_pairs(&[(variation_attribute.clone(), vals_dict)]); + let ct_var_font_desc = small.copy_descriptor().create_copy_with_attributes(attrs_dict.to_untyped()).unwrap(); + let variation_font = crate::font::new_from_descriptor(&ct_var_font_desc, 19.); + let var_desc = variation_font.copy_descriptor(); + let var_attrs = var_desc.attributes(); + dbg!(&var_attrs); + // attributes greater than max are dropped on macOS <= 11 + // on macOS 12 they seem to be preserved as is. + let var_attrs = var_attrs.find(variation_attribute); + if macos_version() >= (12, 0, 0) { + let var_attrs = var_attrs.unwrap().downcast::().unwrap(); + assert!(!var_attrs.is_empty()); + let var_attrs: CFDictionary = unsafe { std::mem::transmute(var_attrs) }; + // attributes greater than max remain + for axis in axes.iter() { + let tag = axis.find(unsafe { kCTFontVariationAxisIdentifierKey } ) + .unwrap(); + let max = axis.find(unsafe { kCTFontVariationAxisMaximumValueKey } ) + .unwrap().downcast::().unwrap().to_f64().unwrap(); + let val = var_attrs.find(tag.clone()).unwrap().downcast::().unwrap().to_f64().unwrap(); + assert_eq!(val, max + 1.); + } + } else if macos_version() >= (10, 15, 0) { + assert!(var_attrs.is_none()); + } else { + let var_attrs = var_attrs.unwrap().downcast::().unwrap(); + assert!(var_attrs.is_empty()); + } +} + +#[test] +fn equal_descriptor_different_font() { + use crate::*; + + let variation_attribute = unsafe { CFString::wrap_under_get_rule(font_descriptor::kCTFontVariationAttribute) }; + let size_attribute = unsafe { CFString::wrap_under_get_rule(font_descriptor::kCTFontSizeAttribute) }; + + let sys_font = new_ui_font_for_language(kCTFontSystemDetailFontType, 19., None); + + + // but we can still construct the CGFont by name + let create_vars = |desc| { + let mut vals: Vec<(CFNumber, CFNumber)> = Vec::new(); + vals.push((CFNumber::from(0x6f70737a), CFNumber::from(17.))); + let vals_dict = CFDictionary::from_CFType_pairs(&vals); + let attrs_dict = CFDictionary::from_CFType_pairs(&[(variation_attribute.clone(), vals_dict)]); + let size_attrs_dict = CFDictionary::from_CFType_pairs(&[(size_attribute.clone(), CFNumber::from(120.))]); + dbg!(&desc); + let from_font_desc = new_from_descriptor(&desc, 120.).copy_descriptor(); + let resized_font_desc = desc.create_copy_with_attributes(size_attrs_dict.to_untyped()).unwrap(); + if macos_version() >= (11, 0, 0) { + assert_eq!(from_font_desc, resized_font_desc); + } else { + // we won't have a name if we're using system font desc + if from_font_desc.attributes().find(unsafe { font_descriptor::kCTFontNameAttribute }).is_none() { + // it's surprising that desc's are the not equal but the attributes are + assert_ne!(from_font_desc, resized_font_desc); + assert_eq!(from_font_desc.attributes().to_untyped(), resized_font_desc.attributes().to_untyped()); + } else { + if macos_version() >= (10, 13, 0) { + // this is unsurprising + assert_ne!(from_font_desc, resized_font_desc); + assert_ne!(from_font_desc.attributes().to_untyped(), resized_font_desc.attributes().to_untyped()); + } else { + assert_ne!(from_font_desc, resized_font_desc); + assert_eq!(from_font_desc.attributes().to_untyped(), resized_font_desc.attributes().to_untyped()); + } + } + } + + let from_font_desc = from_font_desc.create_copy_with_attributes(attrs_dict.to_untyped()).unwrap(); + let resized_font_desc = resized_font_desc.create_copy_with_attributes(attrs_dict.to_untyped()).unwrap(); + (from_font_desc, resized_font_desc) + }; + + // setting the variation works properly if we use system font desc + let (from_font_desc, resized_font_desc) = create_vars(sys_font.copy_descriptor()); + assert_eq!(from_font_desc, resized_font_desc); + assert!(resized_font_desc.attributes().find(variation_attribute.clone()).is_some()); + + // but doesn't if we refer to it by name + let ps = sys_font.postscript_name(); + let cgfont = CGFont::from_name(&CFString::new(&ps)).unwrap(); + let ctfont = new_from_CGFont(&cgfont, 0.); + + let (from_font_desc, resized_font_desc) = create_vars(ctfont.copy_descriptor()); + if macos_version() >= (10, 15, 0) { + assert_ne!(from_font_desc, resized_font_desc); + } + + if macos_version() >= (10, 13, 0) { + assert!(from_font_desc.attributes().find(variation_attribute.clone()).is_some()); + if macos_version() >= (11, 0, 0) { + assert!(resized_font_desc.attributes().find(variation_attribute).is_none()); + } else { + assert!(resized_font_desc.attributes().find(variation_attribute).is_some()); + }; + } +} + +#[test] +fn system_font_variation() { + use crate::*; + + let small = new_ui_font_for_language(kCTFontSystemDetailFontType, 19., None); + + // but we can still construct the CGFont by name + let ps = small.postscript_name(); + let cgfont = CGFont::from_name(&CFString::new(&ps)).unwrap(); + let cgfont = new_from_CGFont(&cgfont, 0.); + let desc = cgfont.copy_descriptor(); + + let mut vals: Vec<(CFNumber, CFNumber)> = Vec::new(); + vals.push((CFNumber::from(0x6f70737a /* opsz */), CFNumber::from(17.))); + let vals_dict = CFDictionary::from_CFType_pairs(&vals); + let variation_attribute = unsafe { CFString::wrap_under_get_rule(font_descriptor::kCTFontVariationAttribute) }; + let attrs_dict = CFDictionary::from_CFType_pairs(&[(variation_attribute, vals_dict)]); + let ct_var_font_desc = desc.create_copy_with_attributes(attrs_dict.to_untyped()).unwrap(); + let attrs = ct_var_font_desc.attributes(); + let var_attr = attrs.find(CFString::from_static_string("NSCTFontVariationAttribute")); + if macos_version() >= (11, 0, 0) { + // the variation goes away + assert!(var_attr.is_none()); + } else { + assert!(var_attr.is_some()); + } + + dbg!(ct_var_font_desc); +} + +#[test] +fn ui_font() { + // pass some garbagey inputs + new_ui_font_for_language(kCTFontSystemDetailFontType, 10000009., Some(CFString::from("Gofld"))); +} diff --git a/third_party/rust/foreign-types-macros/.cargo-checksum.json b/third_party/rust/foreign-types-macros/.cargo-checksum.json new file mode 100644 index 000000000000..576d885de8f6 --- /dev/null +++ b/third_party/rust/foreign-types-macros/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"829c9da0910b673669e0401c6affd6564c94c49cf9629740104ffabf46f54d08","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","src/build.rs":"bee8027592dff9052e1235a6b1bfd0ae715389265247131c3e1ed865e561ba40","src/lib.rs":"7bb43075bede4947ee8f07a05e4d1b00e0daedadbde15f1b386f97514853ad1c","src/parse.rs":"d8cc189b7108602dee81ff5436a9480dd45397101f7faad875027441e1477ef1"},"package":"1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"} \ No newline at end of file diff --git a/third_party/rust/foreign-types-macros/Cargo.toml b/third_party/rust/foreign-types-macros/Cargo.toml new file mode 100644 index 000000000000..584d1844c5c2 --- /dev/null +++ b/third_party/rust/foreign-types-macros/Cargo.toml @@ -0,0 +1,35 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "foreign-types-macros" +version = "0.2.3" +authors = ["Steven Fackler "] +description = "An internal crate used by foreign-types" +license = "MIT/Apache-2.0" +repository = "https://github.com/sfackler/foreign-types" + +[lib] +proc-macro = true + +[dependencies.proc-macro2] +version = "1.0" + +[dependencies.quote] +version = "1.0" + +[dependencies.syn] +version = "2.0" +features = ["full"] + +[features] +std = [] diff --git a/third_party/rust/foreign-types-macros/LICENSE-APACHE b/third_party/rust/foreign-types-macros/LICENSE-APACHE new file mode 100644 index 000000000000..8f71f43fee3f --- /dev/null +++ b/third_party/rust/foreign-types-macros/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/third_party/rust/foreign-types-macros/LICENSE-MIT b/third_party/rust/foreign-types-macros/LICENSE-MIT new file mode 100644 index 000000000000..bb76d014691e --- /dev/null +++ b/third_party/rust/foreign-types-macros/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright (c) 2017 The foreign-types Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/rust/foreign-types-macros/src/build.rs b/third_party/rust/foreign-types-macros/src/build.rs new file mode 100644 index 000000000000..b50610f0f32b --- /dev/null +++ b/third_party/rust/foreign-types-macros/src/build.rs @@ -0,0 +1,261 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Ident, Path}; + +use crate::parse::{ForeignType, Input}; + +fn ref_name(input: &ForeignType) -> Ident { + Ident::new(&format!("{}Ref", input.name), input.name.span()) +} + +pub fn build(input: Input) -> TokenStream { + let types = input + .types + .iter() + .map(|t| build_foreign_type(&input.crate_, t)); + quote! { + #(#types)* + } +} + +fn build_foreign_type(crate_: &Path, input: &ForeignType) -> TokenStream { + let decls = build_decls(crate_, input); + let oibits = build_oibits(crate_, input); + let foreign_impls = build_foreign_impls(crate_, input); + let drop_impl = build_drop_impl(crate_, input); + let deref_impls = build_deref_impls(crate_, input); + let borrow_impls = build_borrow_impls(crate_, input); + let as_ref_impls = build_as_ref_impls(crate_, input); + let clone_impl = build_clone_impl(crate_, input); + let to_owned_impl = build_to_owned_impl(crate_, input); + + quote! { + #decls + #oibits + #foreign_impls + #drop_impl + #deref_impls + #borrow_impls + #as_ref_impls + #clone_impl + #to_owned_impl + } +} + +fn build_decls(crate_: &Path, input: &ForeignType) -> TokenStream { + let attrs = &input.attrs; + let vis = &input.visibility; + let name = &input.name; + let generics = &input.generics; + let ctype = &input.ctype; + let phantom_data = input + .phantom_data + .as_ref() + .map(|d| quote!(, #crate_::export::PhantomData<#d>)); + let ref_name = ref_name(input); + let ref_docs = format!( + "A borrowed reference to a [`{name}`](struct.{name}.html).", + name = name + ); + + quote! { + #(#attrs)* + #[repr(transparent)] + #vis struct #name #generics(#crate_::export::NonNull<#ctype> #phantom_data); + + #[doc = #ref_docs] + #vis struct #ref_name #generics(#crate_::Opaque #phantom_data); + } +} + +fn build_oibits(crate_: &Path, input: &ForeignType) -> TokenStream { + let oibits = input.oibits.iter().map(|t| build_oibit(crate_, input, t)); + + quote! { + #(#oibits)* + } +} + +fn build_oibit(crate_: &Path, input: &ForeignType, oibit: &Ident) -> TokenStream { + let name = &input.name; + let ref_name = ref_name(input); + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + + quote! { + unsafe impl #impl_generics #crate_::export::#oibit for #name #ty_generics {} + unsafe impl #impl_generics #crate_::export::#oibit for #ref_name #ty_generics {} + } +} + +fn build_foreign_impls(crate_: &Path, input: &ForeignType) -> TokenStream { + let name = &input.name; + let ctype = &input.ctype; + let ref_name = ref_name(input); + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + let phantom_data = input + .phantom_data + .as_ref() + .map(|_| quote!(, #crate_::export::PhantomData)); + + quote! { + unsafe impl #impl_generics #crate_::ForeignType for #name #ty_generics { + type CType = #ctype; + type Ref = #ref_name #ty_generics; + + #[inline] + unsafe fn from_ptr(ptr: *mut #ctype) -> #name #ty_generics { + debug_assert!(!ptr.is_null()); + #name(<#crate_::export::NonNull<_>>::new_unchecked(ptr) #phantom_data) + } + + #[inline] + fn as_ptr(&self) -> *mut #ctype { + <#crate_::export::NonNull<_>>::as_ptr(self.0) + } + } + + unsafe impl #impl_generics #crate_::ForeignTypeRef for #ref_name #ty_generics { + type CType = #ctype; + } + } +} + +fn build_drop_impl(crate_: &Path, input: &ForeignType) -> TokenStream { + let name = &input.name; + let drop = &input.drop; + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + + quote! { + impl #impl_generics #crate_::export::Drop for #name #ty_generics { + #[inline] + fn drop(&mut self) { + unsafe { + (#drop)(#crate_::ForeignType::as_ptr(self)); + } + } + } + } +} + +fn build_deref_impls(crate_: &Path, input: &ForeignType) -> TokenStream { + let name = &input.name; + let ref_name = ref_name(input); + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + + quote! { + impl #impl_generics #crate_::export::Deref for #name #ty_generics { + type Target = #ref_name #ty_generics; + + #[inline] + fn deref(&self) -> &#ref_name #ty_generics { + unsafe { + #crate_::ForeignTypeRef::from_ptr(#crate_::ForeignType::as_ptr(self)) + } + } + } + + impl #impl_generics #crate_::export::DerefMut for #name #ty_generics { + #[inline] + fn deref_mut(&mut self) -> &mut #ref_name #ty_generics { + unsafe { + #crate_::ForeignTypeRef::from_ptr_mut(#crate_::ForeignType::as_ptr(self)) + } + } + } + } +} + +fn build_borrow_impls(crate_: &Path, input: &ForeignType) -> TokenStream { + let name = &input.name; + let ref_name = ref_name(input); + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + + quote! { + impl #impl_generics #crate_::export::Borrow<#ref_name #ty_generics> for #name #ty_generics { + #[inline] + fn borrow(&self) -> &#ref_name #ty_generics { + &**self + } + } + + impl #impl_generics #crate_::export::BorrowMut<#ref_name #ty_generics> for #name #ty_generics { + #[inline] + fn borrow_mut(&mut self) -> &mut #ref_name #ty_generics { + &mut **self + } + } + } +} + +fn build_as_ref_impls(crate_: &Path, input: &ForeignType) -> TokenStream { + let name = &input.name; + let ref_name = ref_name(input); + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + + quote! { + impl #impl_generics #crate_::export::AsRef<#ref_name #ty_generics> for #name #ty_generics { + #[inline] + fn as_ref(&self) -> &#ref_name #ty_generics { + &**self + } + } + + impl #impl_generics #crate_::export::AsMut<#ref_name #ty_generics> for #name #ty_generics { + #[inline] + fn as_mut(&mut self) -> &mut #ref_name #ty_generics { + &mut **self + } + } + } +} + +fn build_clone_impl(crate_: &Path, input: &ForeignType) -> TokenStream { + let clone = match &input.clone { + Some(clone) => clone, + None => return quote!(), + }; + let name = &input.name; + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + + quote! { + impl #impl_generics #crate_::export::Clone for #name #ty_generics { + #[inline] + fn clone(&self) -> #name #ty_generics { + unsafe { + let ptr = (#clone)(#crate_::ForeignType::as_ptr(self)); + #crate_::ForeignType::from_ptr(ptr) + } + } + } + } +} + +#[cfg(feature = "std")] +fn build_to_owned_impl(crate_: &Path, input: &ForeignType) -> TokenStream { + let clone = match &input.clone { + Some(clone) => clone, + None => return quote!(), + }; + let name = &input.name; + let ref_name = ref_name(input); + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + + quote! { + impl #impl_generics #crate_::export::ToOwned for #ref_name #ty_generics { + type Owned = #name #ty_generics; + + #[inline] + fn to_owned(&self) -> #name #ty_generics { + unsafe { + let ptr = (#clone)(#crate_::ForeignTypeRef::as_ptr(self)); + #crate_::ForeignType::from_ptr(ptr) + } + } + } + } +} + +#[cfg(not(feature = "std"))] +fn build_to_owned_impl(_: &Path, _: &ForeignType) -> TokenStream { + quote!() +} diff --git a/third_party/rust/foreign-types-macros/src/lib.rs b/third_party/rust/foreign-types-macros/src/lib.rs new file mode 100644 index 000000000000..77c1e99fbcae --- /dev/null +++ b/third_party/rust/foreign-types-macros/src/lib.rs @@ -0,0 +1,15 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; +use syn::parse_macro_input; + +use crate::parse::Input; + +mod build; +mod parse; + +#[proc_macro] +pub fn foreign_type_impl(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as Input); + build::build(input).into() +} diff --git a/third_party/rust/foreign-types-macros/src/parse.rs b/third_party/rust/foreign-types-macros/src/parse.rs new file mode 100644 index 000000000000..ba11dc976c41 --- /dev/null +++ b/third_party/rust/foreign-types-macros/src/parse.rs @@ -0,0 +1,140 @@ +use syn::parse::{self, Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token; +use syn::{braced, Attribute, Expr, Generics, Ident, Path, Token, Type, Visibility}; + +mod kw { + syn::custom_keyword!(Sync); + syn::custom_keyword!(Send); + syn::custom_keyword!(PhantomData); + syn::custom_keyword!(CType); + syn::custom_keyword!(drop); + syn::custom_keyword!(clone); +} + +pub struct Input { + pub crate_: Path, + pub types: Vec, +} + +impl Parse for Input { + fn parse(input: ParseStream) -> parse::Result { + let crate_ = input.parse()?; + let mut types = vec![]; + while !input.is_empty() { + types.push(input.parse()?); + } + + Ok(Input { crate_, types }) + } +} + +pub struct ForeignType { + pub attrs: Vec, + pub visibility: Visibility, + pub name: Ident, + pub generics: Generics, + pub oibits: Punctuated, + pub phantom_data: Option, + pub ctype: Type, + pub drop: Expr, + pub clone: Option, +} + +impl Parse for ForeignType { + fn parse(input: ParseStream) -> parse::Result { + let attrs = input.call(Attribute::parse_outer)?; + let visibility = input.parse()?; + input.parse::()?; + input.parse::()?; + let name = input.parse()?; + let generics = input.parse()?; + let oibits = input.call(parse_oibits)?; + let inner; + braced!(inner in input); + let ctype = inner.call(parse_type::)?; + let phantom_data = inner.call(parse_phantom_data)?; + let drop = inner.call(parse_fn::)?; + let clone = inner.call(parse_clone)?; + + Ok(ForeignType { + attrs, + visibility, + name, + generics, + oibits, + ctype, + phantom_data, + drop, + clone, + }) + } +} + +fn parse_oibit(input: ParseStream) -> parse::Result { + let lookahead = input.lookahead1(); + if lookahead.peek(kw::Sync) || lookahead.peek(kw::Send) { + input.parse() + } else { + Err(lookahead.error()) + } +} + +fn parse_oibits(input: ParseStream) -> parse::Result> { + let mut out = Punctuated::new(); + + if input.parse::>()?.is_some() { + loop { + out.push_value(input.call(parse_oibit)?); + if input.peek(token::Brace) { + break; + } + out.push_punct(input.parse()?); + if input.peek(token::Brace) { + break; + } + } + } + + Ok(out) +} + +fn parse_type(input: ParseStream) -> parse::Result +where + T: Parse, +{ + input.parse::()?; + input.parse::()?; + input.parse::()?; + let type_ = input.parse()?; + input.parse::()?; + Ok(type_) +} + +fn parse_phantom_data(input: ParseStream) -> parse::Result> { + if input.peek(Token![type]) && input.peek2(kw::PhantomData) { + input.call(parse_type::).map(Some) + } else { + Ok(None) + } +} + +fn parse_fn(input: ParseStream) -> parse::Result +where + T: Parse, +{ + input.parse::()?; + input.parse::()?; + input.parse::()?; + let path = input.parse()?; + input.parse::()?; + Ok(path) +} + +fn parse_clone(input: ParseStream) -> parse::Result> { + if input.peek(Token![fn]) && input.peek2(kw::clone) { + input.call(parse_fn::).map(Some) + } else { + Ok(None) + } +} diff --git a/third_party/rust/foreign-types-shared/.cargo-checksum.json b/third_party/rust/foreign-types-shared/.cargo-checksum.json index 2d6d8919ab62..c2aee3a118c3 100644 --- a/third_party/rust/foreign-types-shared/.cargo-checksum.json +++ b/third_party/rust/foreign-types-shared/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"6b91ae600fe7b521537096b2269ab7bfd606f8a1fcd97749634dd03ba18daf53","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","src/lib.rs":"77aed289fd36258c273f033e766e572ee05330249083c017d045f0a75662f5df"},"package":"00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"} \ No newline at end of file +{"files":{"Cargo.toml":"096ac915be03aa1eb99b12ad4c5552a50bd550de4d1fb9a52e0799319f98f994","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","src/lib.rs":"60aa483e41abdbdc3b5057e3ff75abd63d0e92263d93a50d8fd739910a0b19e8"},"package":"aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"} \ No newline at end of file diff --git a/third_party/rust/foreign-types-shared/Cargo.toml b/third_party/rust/foreign-types-shared/Cargo.toml index e2cb783b98b1..e029e2c6d77f 100644 --- a/third_party/rust/foreign-types-shared/Cargo.toml +++ b/third_party/rust/foreign-types-shared/Cargo.toml @@ -3,16 +3,16 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] +edition = "2018" name = "foreign-types-shared" -version = "0.1.1" +version = "0.3.1" authors = ["Steven Fackler "] description = "An internal crate used by foreign-types" license = "MIT/Apache-2.0" diff --git a/third_party/rust/foreign-types-shared/src/lib.rs b/third_party/rust/foreign-types-shared/src/lib.rs index cbebc335348c..2f58b53f18a4 100644 --- a/third_party/rust/foreign-types-shared/src/lib.rs +++ b/third_party/rust/foreign-types-shared/src/lib.rs @@ -2,17 +2,29 @@ #![no_std] #![warn(missing_docs)] -#![doc(html_root_url="https://docs.rs/foreign-types-shared/0.1")] +#![doc(html_root_url = "https://docs.rs/foreign-types-shared/0.3")] use core::cell::UnsafeCell; +use core::marker::PhantomData; +use core::mem; /// An opaque type used to define `ForeignTypeRef` types. /// /// A type implementing `ForeignTypeRef` should simply be a newtype wrapper around this type. -pub struct Opaque(UnsafeCell<()>); +pub struct Opaque(PhantomData>); /// A type implemented by wrappers over foreign types. -pub trait ForeignType: Sized { +/// +/// # Safety +/// +/// Implementations of `ForeignType` must guarantee the following: +/// - `Self::from_ptr(x).as_ptr() == x` +/// - `Self::from_ptr(x).into_ptr(x) == x` +/// - `Self::from_ptr(x).deref().as_ptr(x) == x` +/// - `Self::from_ptr(x).deref_mut().as_ptr(x) == x` +/// - `Self::from_ptr(x).as_ref().as_ptr(x) == x` +/// - `Self::from_ptr(x).as_mut().as_ptr(x) == x` +pub unsafe trait ForeignType: Sized { /// The raw C type. type CType; @@ -20,26 +32,55 @@ pub trait ForeignType: Sized { type Ref: ForeignTypeRef; /// Constructs an instance of this type from its raw type. + /// + /// # Safety + /// + /// `ptr` must be a valid, owned instance of the native type. unsafe fn from_ptr(ptr: *mut Self::CType) -> Self; /// Returns a raw pointer to the wrapped value. fn as_ptr(&self) -> *mut Self::CType; + + /// Consumes the wrapper and returns the raw pointer. + #[inline] + fn into_ptr(self) -> *mut Self::CType { + let ptr = self.as_ptr(); + mem::forget(self); + ptr + } } /// A trait implemented by types which reference borrowed foreign types. -pub trait ForeignTypeRef: Sized { +/// +/// # Safety +/// +/// Implementations of `ForeignTypeRef` must guarantee the following: +/// +/// - `Self::from_ptr(x).as_ptr() == x` +/// - `Self::from_mut_ptr(x).as_ptr() == x` +pub unsafe trait ForeignTypeRef: Sized { /// The raw C type. type CType; /// Constructs a shared instance of this type from its raw type. + /// + /// # Safety + /// + /// `ptr` must be a valid, immutable, instance of the type for the `'a` lifetime. #[inline] unsafe fn from_ptr<'a>(ptr: *mut Self::CType) -> &'a Self { + debug_assert!(!ptr.is_null()); &*(ptr as *mut _) } /// Constructs a mutable reference of this type from its raw type. + /// + /// # Safety + /// + /// `ptr` must be a valid, unique, instance of the type for the `'a` lifetime. #[inline] unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CType) -> &'a mut Self { + debug_assert!(!ptr.is_null()); &mut *(ptr as *mut _) } diff --git a/third_party/rust/foreign-types/.cargo-checksum.json b/third_party/rust/foreign-types/.cargo-checksum.json index 7e74bd59b4e5..978653cf7c91 100644 --- a/third_party/rust/foreign-types/.cargo-checksum.json +++ b/third_party/rust/foreign-types/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"1a667c28f60115423b68fea369255c2dcb129b8dce10f30e0e1da73d05f9adab","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","README.md":"6f3f1429f2724a481df811842f318d0d3b83160ada953fd869d4b685f7fd72e4","src/lib.rs":"4f0a33bf8ec94a57d1b71e50f1af8ca410985e447f69fdc9c680545b03ea4566"},"package":"f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"} \ No newline at end of file +{"files":{"Cargo.toml":"2e1b7838114ee31147555eb858dd837f1f8ac80d53f00c62b2c81c5a0121224d","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"333ea3aaa3cadb819f4acd9f9153f9feee060a995ca8710f32bc5bd9a4b91734","README.md":"6f3f1429f2724a481df811842f318d0d3b83160ada953fd869d4b685f7fd72e4","src/lib.rs":"a0039cfb11b235119b81ba8d31987c19d8fd6e1d23abbde57e67747fdd8f0ad0","tests/test.rs":"7913e5e040b75e5b63bf813d25a0491cb8e9b51857a039cf3b56d7f10fc787d3"},"package":"d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"} \ No newline at end of file diff --git a/third_party/rust/foreign-types/Cargo.toml b/third_party/rust/foreign-types/Cargo.toml index 6ff5567de3b4..b3639ede10ed 100644 --- a/third_party/rust/foreign-types/Cargo.toml +++ b/third_party/rust/foreign-types/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,12 +11,20 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "foreign-types" -version = "0.3.2" +version = "0.5.0" authors = ["Steven Fackler "] description = "A framework for Rust wrappers over C APIs" readme = "README.md" license = "MIT/Apache-2.0" repository = "https://github.com/sfackler/foreign-types" +[dependencies.foreign-types-macros] +version = "0.2" + [dependencies.foreign-types-shared] -version = "0.1" +version = "0.3" + +[features] +default = ["std"] +std = ["foreign-types-macros/std"] diff --git a/third_party/rust/foreign-types/src/lib.rs b/third_party/rust/foreign-types/src/lib.rs index 6ce959207f42..00b3db950b2a 100644 --- a/third_party/rust/foreign-types/src/lib.rs +++ b/third_party/rust/foreign-types/src/lib.rs @@ -15,6 +15,7 @@ //! ``` //! use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; //! use std::ops::{Deref, DerefMut}; +//! use std::ptr::NonNull; //! //! mod foo_sys { //! pub enum FOO {} @@ -30,7 +31,7 @@ //! // from raw C pointers. //! pub struct FooRef(Opaque); //! -//! impl ForeignTypeRef for FooRef { +//! unsafe impl ForeignTypeRef for FooRef { //! type CType = foo_sys::FOO; //! } //! @@ -38,24 +39,36 @@ //! // //! // It dereferences to `FooRef`, so methods that do not require ownership //! // should be defined there. -//! pub struct Foo(*mut foo_sys::FOO); +//! pub struct Foo(NonNull); +//! +//! unsafe impl Sync for FooRef {} +//! unsafe impl Send for FooRef {} +//! +//! unsafe impl Sync for Foo {} +//! unsafe impl Send for Foo {} //! //! impl Drop for Foo { //! fn drop(&mut self) { -//! unsafe { foo_sys::FOO_free(self.0) } +//! unsafe { foo_sys::FOO_free(self.as_ptr()) } //! } //! } //! -//! impl ForeignType for Foo { +//! unsafe impl ForeignType for Foo { //! type CType = foo_sys::FOO; //! type Ref = FooRef; //! //! unsafe fn from_ptr(ptr: *mut foo_sys::FOO) -> Foo { -//! Foo(ptr) +//! Foo(NonNull::new_unchecked(ptr)) //! } //! //! fn as_ptr(&self) -> *mut foo_sys::FOO { -//! self.0 +//! self.0.as_ptr() +//! } +//! +//! fn into_ptr(self) -> *mut foo_sys::FOO { +//! let inner = self.as_ptr(); +//! ::core::mem::forget(self); +//! inner //! } //! } //! @@ -63,50 +76,60 @@ //! type Target = FooRef; //! //! fn deref(&self) -> &FooRef { -//! unsafe { FooRef::from_ptr(self.0) } +//! unsafe { FooRef::from_ptr(self.as_ptr()) } //! } //! } //! //! impl DerefMut for Foo { //! fn deref_mut(&mut self) -> &mut FooRef { -//! unsafe { FooRef::from_ptr_mut(self.0) } +//! unsafe { FooRef::from_ptr_mut(self.as_ptr()) } //! } //! } +//! +//! // add in Borrow, BorrowMut, AsRef, AsRefMut, Clone, ToOwned... //! ``` //! //! The `foreign_type!` macro can generate this boilerplate for you: //! //! ``` -//! #[macro_use] -//! extern crate foreign_types; +//! use foreign_types::foreign_type; //! //! mod foo_sys { //! pub enum FOO {} //! //! extern { //! pub fn FOO_free(foo: *mut FOO); -//! pub fn FOO_duplicate(foo: *mut FOO) -> *mut FOO; // Optional +//! pub fn FOO_duplicate(foo: *mut FOO) -> *mut FOO; // optional //! } //! } //! //! foreign_type! { -//! type CType = foo_sys::FOO; -//! fn drop = foo_sys::FOO_free; -//! fn clone = foo_sys::FOO_duplicate; // Optional //! /// A Foo. -//! pub struct Foo; -//! /// A borrowed Foo. -//! pub struct FooRef; +//! pub unsafe type Foo +//! : Sync + Send // optional +//! { +//! type CType = foo_sys::FOO; +//! fn drop = foo_sys::FOO_free; +//! fn clone = foo_sys::FOO_duplicate; // optional +//! } +//! +//! /// A Foo with generic parameters. +//! pub unsafe type GenericFoo { +//! type CType = foo_sys::FOO; +//! // This type is added as a `PhantomData` field to handle variance +//! // of the parameters. However, it has no impact on trait impls: +//! // `GenericFoo` is always `Clone`, even if `T` is not. +//! type PhantomData = T; +//! fn drop = foo_sys::FOO_free; +//! fn clone = foo_sys::FOO_duplicate; +//! } //! } //! //! # fn main() {} //! ``` //! //! If `fn clone` is specified, then it must take `CType` as an argument and return a copy of it as `CType`. -//! It will be used to implement `ToOwned` and `Clone`. -//! -//! `#[derive(…)] is permitted before the lines with `pub struct`. -//! `#[doc(hidden)]` before the `type CType` line will hide the `foreign_type!` implementations from documentation. +//! It will be used to implement `Clone`, and if the `std` Cargo feature is enabled, `ToOwned`. //! //! Say we then have a separate type in our C API that contains a `FOO`: //! @@ -128,10 +151,7 @@ //! modify the `FOO`, so we'll define a pair of accessor methods, one immutable and one mutable: //! //! ``` -//! #[macro_use] -//! extern crate foreign_types; -//! -//! use foreign_types::ForeignTypeRef; +//! use foreign_types::{ForeignTypeRef, foreign_type}; //! //! mod foo_sys { //! pub enum FOO {} @@ -145,22 +165,17 @@ //! } //! //! foreign_type! { -//! #[doc(hidden)] -//! type CType = foo_sys::FOO; -//! fn drop = foo_sys::FOO_free; //! /// A Foo. -//! pub struct Foo; -//! /// A borrowed Foo. -//! pub struct FooRef; -//! } +//! pub unsafe type Foo: Sync + Send { +//! type CType = foo_sys::FOO; +//! fn drop = foo_sys::FOO_free; +//! } //! -//! foreign_type! { -//! type CType = foo_sys::BAR; -//! fn drop = foo_sys::BAR_free; -//! /// A Foo. -//! pub struct Bar; -//! /// A borrowed Bar. -//! pub struct BarRef; +//! /// A Bar. +//! pub unsafe type Bar: Sync + Send { +//! type CType = foo_sys::BAR; +//! fn drop = foo_sys::BAR_free; +//! } //! } //! //! impl BarRef { @@ -177,130 +192,59 @@ //! ``` #![no_std] #![warn(missing_docs)] -#![doc(html_root_url="https://docs.rs/foreign-types/0.3")] -extern crate foreign_types_shared; +#![doc(html_root_url = "https://docs.rs/foreign-types/0.5")] +#[cfg(feature = "std")] +extern crate std; + +#[doc(hidden)] +pub use foreign_types_macros::foreign_type_impl; #[doc(inline)] -pub use foreign_types_shared::*; +pub use foreign_types_shared::{ForeignType, ForeignTypeRef, Opaque}; + +#[doc(hidden)] +pub mod export { + pub use core::borrow::{Borrow, BorrowMut}; + pub use core::clone::Clone; + pub use core::convert::{AsMut, AsRef}; + pub use core::marker::{PhantomData, Send, Sync}; + pub use core::ops::{Deref, DerefMut, Drop}; + pub use core::ptr::NonNull; + + #[cfg(feature = "std")] + pub use std::borrow::ToOwned; +} /// A macro to easily define wrappers for foreign types. /// /// # Examples /// /// ``` -/// #[macro_use] -/// extern crate foreign_types; +/// use foreign_types::foreign_type; /// /// # mod openssl_sys { pub type SSL = (); pub unsafe fn SSL_free(_: *mut SSL) {} pub unsafe fn SSL_dup(x: *mut SSL) -> *mut SSL {x} } +/// # mod foo_sys { pub type THING = (); pub unsafe fn THING_free(_: *mut THING) {} } /// foreign_type! { -/// type CType = openssl_sys::SSL; -/// fn drop = openssl_sys::SSL_free; -/// fn clone = openssl_sys::SSL_dup; /// /// Documentation for the owned type. -/// pub struct Ssl; -/// /// Documentation for the borrowed type. -/// pub struct SslRef; +/// pub unsafe type Ssl: Sync + Send { +/// type CType = openssl_sys::SSL; +/// fn drop = openssl_sys::SSL_free; +/// fn clone = openssl_sys::SSL_dup; +/// } +/// +/// /// This type immutably borrows other data and has a limited lifetime! +/// pub unsafe type Thing<'a>: Send { +/// type CType = foo_sys::THING; +/// type PhantomData = &'a (); +/// fn drop = foo_sys::THING_free; +/// } /// } /// /// # fn main() {} /// ``` -#[macro_export] +#[macro_export(local_inner_macros)] macro_rules! foreign_type { - ( - $(#[$impl_attr:meta])* - type CType = $ctype:ty; - fn drop = $drop:expr; - $(fn clone = $clone:expr;)* - $(#[$owned_attr:meta])* - pub struct $owned:ident; - $(#[$borrowed_attr:meta])* - pub struct $borrowed:ident; - ) => { - $(#[$owned_attr])* - pub struct $owned(*mut $ctype); - - $(#[$impl_attr])* - impl $crate::ForeignType for $owned { - type CType = $ctype; - type Ref = $borrowed; - - #[inline] - unsafe fn from_ptr(ptr: *mut $ctype) -> $owned { - $owned(ptr) - } - - #[inline] - fn as_ptr(&self) -> *mut $ctype { - self.0 - } - } - - impl Drop for $owned { - #[inline] - fn drop(&mut self) { - unsafe { $drop(self.0) } - } - } - - $( - impl Clone for $owned { - #[inline] - fn clone(&self) -> $owned { - unsafe { - let handle: *mut $ctype = $clone(self.0); - $crate::ForeignType::from_ptr(handle) - } - } - } - - impl ::std::borrow::ToOwned for $borrowed { - type Owned = $owned; - #[inline] - fn to_owned(&self) -> $owned { - unsafe { - let handle: *mut $ctype = $clone($crate::ForeignTypeRef::as_ptr(self)); - $crate::ForeignType::from_ptr(handle) - } - } - } - )* - - impl ::std::ops::Deref for $owned { - type Target = $borrowed; - - #[inline] - fn deref(&self) -> &$borrowed { - unsafe { $crate::ForeignTypeRef::from_ptr(self.0) } - } - } - - impl ::std::ops::DerefMut for $owned { - #[inline] - fn deref_mut(&mut self) -> &mut $borrowed { - unsafe { $crate::ForeignTypeRef::from_ptr_mut(self.0) } - } - } - - impl ::std::borrow::Borrow<$borrowed> for $owned { - #[inline] - fn borrow(&self) -> &$borrowed { - &**self - } - } - - impl ::std::convert::AsRef<$borrowed> for $owned { - #[inline] - fn as_ref(&self) -> &$borrowed { - &**self - } - } - - $(#[$borrowed_attr])* - pub struct $borrowed($crate::Opaque); - - $(#[$impl_attr])* - impl $crate::ForeignTypeRef for $borrowed { - type CType = $ctype; - } - } + ($($t:tt)*) => { + $crate::foreign_type_impl!($crate $($t)*); + }; } diff --git a/third_party/rust/foreign-types/tests/test.rs b/third_party/rust/foreign-types/tests/test.rs new file mode 100644 index 000000000000..a1df67e7a1de --- /dev/null +++ b/third_party/rust/foreign-types/tests/test.rs @@ -0,0 +1,22 @@ +use foreign_types::foreign_type; + +mod foo_sys { + pub enum FOO {} + + pub unsafe extern "C" fn foo_drop(_: *mut FOO) {} + pub unsafe extern "C" fn foo_clone(ptr: *mut FOO) -> *mut FOO { ptr } +} + +foreign_type! { + pub unsafe type Foo<'a, T>: Sync + Send { + type CType = foo_sys::FOO; + type PhantomData = &'a T; + fn drop = foo_sys::foo_drop; + fn clone = foo_sys::foo_clone; + } + + pub unsafe type Foo2 { + type CType = foo_sys::FOO; + fn drop = foo_sys::foo_drop; + } +} diff --git a/third_party/rust/gpu-alloc-types/.cargo-checksum.json b/third_party/rust/gpu-alloc-types/.cargo-checksum.json index 4ce7fc40c333..9c6be37d5691 100644 --- a/third_party/rust/gpu-alloc-types/.cargo-checksum.json +++ b/third_party/rust/gpu-alloc-types/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"5ec80402fb950b3e70b291c64a49275dd951221b71ee74f8be5a16a74d42d296","src/device.rs":"1f44d08d50fc59d55bd3f92308e4965bde9134e7f5daa03594e122f7cdb1dfa2","src/lib.rs":"0f77c21a5770b54affa146e5f4c15abcb83599de551226d336ee48ec5185f866","src/types.rs":"8c6acec203faa11856076193835f6d9a1924469682e1fdf11a0325936a1255ee"},"package":"54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5"} \ No newline at end of file +{"files":{"Cargo.toml":"ce92a2d32d4b2e50d617595e689b6bca736b7792280480c4057eaebef15bf325","README.md":"5a96b135d18e172f090bd6147830ab3a1b5cefac5f02be28f06cf88eea61b64f","src/device.rs":"8173609d5fb700f8b82d6335729c592ff62c306b12894a9bab9da45a47810e4a","src/lib.rs":"0f77c21a5770b54affa146e5f4c15abcb83599de551226d336ee48ec5185f866","src/types.rs":"aa861f891a63c232441c5a9fe5fed61cac2d62780108c01ebe6cb64a8547b4e2"},"package":"98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"} \ No newline at end of file diff --git a/third_party/rust/gpu-alloc-types/Cargo.toml b/third_party/rust/gpu-alloc-types/Cargo.toml index a4e0210d0b1c..f6fe81577ac9 100644 --- a/third_party/rust/gpu-alloc-types/Cargo.toml +++ b/third_party/rust/gpu-alloc-types/Cargo.toml @@ -3,24 +3,36 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "gpu-alloc-types" -version = "0.2.0" +version = "0.3.0" authors = ["Zakarum "] description = "Core types of gpu-alloc crate" homepage = "https://github.com/zakarumych/gpu-alloc" -documentation = "https://docs.rs/gpu-alloc-types/0.2.0" -keywords = ["gpu", "vulkan", "allocation", "no-std"] +documentation = "https://docs.rs/gpu-alloc-types" +readme = "README.md" +keywords = [ + "gpu", + "vulkan", + "allocation", + "no-std", +] +categories = [ + "graphics", + "memory-management", + "no-std", + "game-development", +] license = "MIT OR Apache-2.0" repository = "https://github.com/zakarumych/gpu-alloc" + [dependencies.bitflags] -version = "1.2" +version = "2.0" default-features = false diff --git a/third_party/rust/gpu-alloc-types/README.md b/third_party/rust/gpu-alloc-types/README.md new file mode 100644 index 000000000000..8a93d685c1da --- /dev/null +++ b/third_party/rust/gpu-alloc-types/README.md @@ -0,0 +1,51 @@ +# gpu-alloc + +[![crates](https://img.shields.io/crates/v/gpu-alloc.svg?style=for-the-badge&label=gpu-alloc)](https://crates.io/crates/gpu-alloc) +[![docs](https://img.shields.io/badge/docs.rs-gpu--alloc-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white)](https://docs.rs/gpu-alloc) +[![actions](https://img.shields.io/github/workflow/status/zakarumych/gpu-alloc/Rust/main?style=for-the-badge)](https://github.com/zakarumych/gpu-alloc/actions?query=workflow%3ARust) +[![MIT/Apache](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](COPYING) +![loc](https://img.shields.io/tokei/lines/github/zakarumych/gpu-alloc?style=for-the-badge) + + +Implementation agnostic memory allocator for Vulkan like APIs. + +This crate is intended to be used as part of safe API implementations.\ +Use with caution. There are unsafe functions all over the place. + +## Usage + +Start with fetching `DeviceProperties` from `gpu-alloc-` crate for the backend of choice.\ +Then create `GpuAllocator` instance and use it for all device memory allocations.\ +`GpuAllocator` will take care for all necessary bookkeeping like memory object count limit, +heap budget and memory mapping. + +#### Backends implementations + +Backend supporting crates should not depend on this crate.\ +Instead they should depend on `gpu-alloc-types` which is much more stable, +allowing to upgrade `gpu-alloc` version without `gpu-alloc-` upgrade. + + +Supported Rust Versions + +The minimum supported version is 1.40. +The current version is not guaranteed to build on Rust versions earlier than the minimum supported version. + +`gpu-alloc-erupt` crate requires version 1.48 or higher due to dependency on `erupt` crate. + +## License + +Licensed under either of + +* Apache License, Version 2.0, ([license/APACHE](license/APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +* MIT license ([license/MIT](license/MIT) or http://opensource.org/licenses/MIT) + +at your option. + +## Contributions + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +## Donate + +[![Become a patron](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/zakarum) diff --git a/third_party/rust/gpu-alloc-types/src/device.rs b/third_party/rust/gpu-alloc-types/src/device.rs index d05f2e8fdeb3..eb73366799b9 100644 --- a/third_party/rust/gpu-alloc-types/src/device.rs +++ b/third_party/rust/gpu-alloc-types/src/device.rs @@ -67,6 +67,7 @@ pub struct DeviceProperties<'a> { bitflags::bitflags! { /// Allocation flags #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct AllocationFlags : u8 { /// Specifies that the memory can be used for buffers created /// with flag that allows fetching device address. @@ -84,7 +85,7 @@ pub trait MemoryDevice { /// # Safety /// /// `memory_type` must be valid index for memory type associated with this device. - /// Retreiving this information is implementation specific. + /// Retrieving this information is implementation specific. /// /// `flags` must be supported by the device. unsafe fn allocate_memory( diff --git a/third_party/rust/gpu-alloc-types/src/types.rs b/third_party/rust/gpu-alloc-types/src/types.rs index 9c6fd3bd3089..ddda9fa6b9aa 100644 --- a/third_party/rust/gpu-alloc-types/src/types.rs +++ b/third_party/rust/gpu-alloc-types/src/types.rs @@ -1,6 +1,7 @@ bitflags::bitflags! { /// Memory properties type. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct MemoryPropertyFlags: u8 { /// This flag is set for device-local memory types. /// Device-local memory is situated "close" to the GPU cores @@ -42,7 +43,7 @@ pub struct MemoryType { /// Heap index of the memory type. pub heap: u32, - /// Propety flags of the memory type. + /// Property flags of the memory type. pub props: MemoryPropertyFlags, } diff --git a/third_party/rust/gpu-alloc/.cargo-checksum.json b/third_party/rust/gpu-alloc/.cargo-checksum.json index 6f41510d581d..51a8d5b20119 100644 --- a/third_party/rust/gpu-alloc/.cargo-checksum.json +++ b/third_party/rust/gpu-alloc/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"d444caa50cc5b4e0ee201da5347df73c6e77d3eedaae9e69d007c24dd0bb7bfa","src/allocator.rs":"c06b84e062859e1dcd21fa5cd71c8faafcca325b53dcc7b2fee3df945163e820","src/block.rs":"6efc369712e3d880a0d16ab1ef18062a88fefae9bf0a4e626de301cbb1b962ee","src/buddy.rs":"f8eacc183f2ee66faba05dec6f33659afa797e765326c96be4a8bafa651c0e47","src/config.rs":"49bb14c27713c6b1c0c91c094b0f00be22bd26efa660ff979fb1ee1193e9d70e","src/error.rs":"11337a66fc32f3423a1355ffd597d2c7ea28c2b7ce07d707fd5905c330edba08","src/freelist.rs":"3fbbcb96e307e0e021b38df6fe04d129e5d954fcd5a0144e388371442ef20916","src/heap.rs":"03f7c623a0389263073ab48797a191ca06c5611006df7b79c9dc8615c130f495","src/lib.rs":"78800455337d231af24814d84f4e5eb61c5181b12daec06fdcee2d2a75ccb221","src/slab.rs":"2df136b7e0a85eec8a198c7f807678d3a2043c46233e7ec63cd2de72fe562477","src/usage.rs":"0e4788c437718807cdd0b88301228cc27a6b8398313a91e1b70c5f2ab04dcbfb","src/util.rs":"31a496ee3407eb6b0dea255e30e154d805a0d08d777be9c06bdf56d1135bf950"},"package":"7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d"} \ No newline at end of file +{"files":{"Cargo.toml":"3647062a9589eedcc361f51f1e1f0852ae6be3c028d0dc8f8d3c0c944bbca61e","README.md":"5a96b135d18e172f090bd6147830ab3a1b5cefac5f02be28f06cf88eea61b64f","src/allocator.rs":"28f20bbfc3866b4eb94a025027925268178921393f5ab8eb5febad1acf94dce8","src/block.rs":"3553343eb171e7ef8b771a1582489cbbbe22b3a1aca4d54b9ff0174fd30bf0da","src/buddy.rs":"253df5f689b643cf97cfd27be6512ea84b84d3c2097a35f3f2d73f537ab353b3","src/config.rs":"1851264db7576f92f3b455e4667339e1c48b7f1b88f8fae7be95c6a9badde455","src/error.rs":"50e30bccc4ba3b23d99298a65155eec45f7d91b66773e828460907ebdcb8ee41","src/freelist.rs":"92c9241d899f3e92a70b0eb5af0b557a3a76aa14c4a6d23876c3ed7857b5f15b","src/heap.rs":"347c25a8560d39d1abb807fb5c34a6a51d4786c0be24a92293f9c8217bace340","src/lib.rs":"07077fb465fb471b39db99bb0311082133d1c2044c2e192d20f7bbb9e743dd0b","src/slab.rs":"6a2b818087850bd5615b085d912490dbd46bbca0df28daa86932505b3983c64a","src/usage.rs":"99009f2ff532904de3ef66520336cd25bd1b795afcb0158385e78a5908f8308f","src/util.rs":"ce3fd7a278eb4d4bd030d4db5495313f56dc91b0765c394f88d126f11c2b4e75"},"package":"fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"} \ No newline at end of file diff --git a/third_party/rust/gpu-alloc/Cargo.toml b/third_party/rust/gpu-alloc/Cargo.toml index 51c65b43a3b3..6021c6cbf274 100644 --- a/third_party/rust/gpu-alloc/Cargo.toml +++ b/third_party/rust/gpu-alloc/Cargo.toml @@ -12,22 +12,33 @@ [package] edition = "2018" name = "gpu-alloc" -version = "0.5.3" +version = "0.6.0" authors = ["Zakarum "] description = "Implementation agnostic memory allocator for Vulkan like APIs" homepage = "https://github.com/zakarumych/gpu-alloc" documentation = "https://docs.rs/gpu-alloc-types" -readme = "../README.md" -keywords = ["gpu", "vulkan", "allocation", "no-std"] -categories = ["graphics", "memory-management", "no-std", "game-development"] +readme = "README.md" +keywords = [ + "gpu", + "vulkan", + "allocation", + "no-std", +] +categories = [ + "graphics", + "memory-management", + "no-std", + "game-development", +] license = "MIT OR Apache-2.0" repository = "https://github.com/zakarumych/gpu-alloc" + [dependencies.bitflags] -version = "1.2" +version = "2.0" default-features = false [dependencies.gpu-alloc-types] -version = "0.2" +version = "=0.3.0" [dependencies.serde] version = "1.0" @@ -43,4 +54,8 @@ default-features = false [features] default = ["std"] +serde = [ + "dep:serde", + "bitflags/serde", +] std = [] diff --git a/third_party/rust/gpu-alloc/README.md b/third_party/rust/gpu-alloc/README.md new file mode 100644 index 000000000000..8a93d685c1da --- /dev/null +++ b/third_party/rust/gpu-alloc/README.md @@ -0,0 +1,51 @@ +# gpu-alloc + +[![crates](https://img.shields.io/crates/v/gpu-alloc.svg?style=for-the-badge&label=gpu-alloc)](https://crates.io/crates/gpu-alloc) +[![docs](https://img.shields.io/badge/docs.rs-gpu--alloc-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white)](https://docs.rs/gpu-alloc) +[![actions](https://img.shields.io/github/workflow/status/zakarumych/gpu-alloc/Rust/main?style=for-the-badge)](https://github.com/zakarumych/gpu-alloc/actions?query=workflow%3ARust) +[![MIT/Apache](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](COPYING) +![loc](https://img.shields.io/tokei/lines/github/zakarumych/gpu-alloc?style=for-the-badge) + + +Implementation agnostic memory allocator for Vulkan like APIs. + +This crate is intended to be used as part of safe API implementations.\ +Use with caution. There are unsafe functions all over the place. + +## Usage + +Start with fetching `DeviceProperties` from `gpu-alloc-` crate for the backend of choice.\ +Then create `GpuAllocator` instance and use it for all device memory allocations.\ +`GpuAllocator` will take care for all necessary bookkeeping like memory object count limit, +heap budget and memory mapping. + +#### Backends implementations + +Backend supporting crates should not depend on this crate.\ +Instead they should depend on `gpu-alloc-types` which is much more stable, +allowing to upgrade `gpu-alloc` version without `gpu-alloc-` upgrade. + + +Supported Rust Versions + +The minimum supported version is 1.40. +The current version is not guaranteed to build on Rust versions earlier than the minimum supported version. + +`gpu-alloc-erupt` crate requires version 1.48 or higher due to dependency on `erupt` crate. + +## License + +Licensed under either of + +* Apache License, Version 2.0, ([license/APACHE](license/APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +* MIT license ([license/MIT](license/MIT) or http://opensource.org/licenses/MIT) + +at your option. + +## Contributions + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +## Donate + +[![Become a patron](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/zakarum) diff --git a/third_party/rust/gpu-alloc/src/allocator.rs b/third_party/rust/gpu-alloc/src/allocator.rs index 80937c8d0644..3f862ce565b3 100644 --- a/third_party/rust/gpu-alloc/src/allocator.rs +++ b/third_party/rust/gpu-alloc/src/allocator.rs @@ -1,510 +1,611 @@ -use { - crate::{ - align_down, - block::{MemoryBlock, MemoryBlockFlavor}, - buddy::{BuddyAllocator, BuddyBlock}, - config::Config, - error::AllocationError, - freelist::{FreeListAllocator, FreeListBlock}, - heap::Heap, - usage::{MemoryForUsage, UsageFlags}, - MemoryBounds, Request, - }, - alloc::boxed::Box, - core::convert::TryFrom as _, - gpu_alloc_types::{ - AllocationFlags, DeviceProperties, MemoryDevice, MemoryPropertyFlags, MemoryType, - OutOfMemory, - }, -}; - -/// Memory allocator for Vulkan-like APIs. -#[derive(Debug)] -pub struct GpuAllocator { - dedicated_threshold: u64, - preferred_dedicated_threshold: u64, - transient_dedicated_threshold: u64, - max_memory_allocation_size: u64, - memory_for_usage: MemoryForUsage, - memory_types: Box<[MemoryType]>, - memory_heaps: Box<[Heap]>, - allocations_remains: u32, - non_coherent_atom_mask: u64, - starting_free_list_chunk: u64, - final_free_list_chunk: u64, - minimal_buddy_size: u64, - initial_buddy_dedicated_size: u64, - buffer_device_address: bool, - - buddy_allocators: Box<[Option>]>, - freelist_allocators: Box<[Option>]>, -} - -/// Hints for allocator to decide on allocation strategy. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum Dedicated { - /// Allocation directly from device.\ - /// Very slow. - /// Count of allocations is limited.\ - /// Use with caution.\ - /// Must be used if resource has to be bound to dedicated memory object. - Required, - - /// Hint for allocator that dedicated memory object is preferred.\ - /// Should be used if it is known that resource placed in dedicated memory object - /// would allow for better performance.\ - /// Implementation is allowed to return block to shared memory object. - Preferred, -} - -impl GpuAllocator -where - M: MemoryBounds + 'static, -{ - /// Creates new instance of `GpuAllocator`. - /// Provided `DeviceProperties` should match properties of `MemoryDevice` that will be used - /// with created `GpuAllocator` instance. - #[cfg_attr(feature = "tracing", tracing::instrument)] - pub fn new(config: Config, props: DeviceProperties<'_>) -> Self { - assert!( - props.non_coherent_atom_size.is_power_of_two(), - "`non_coherent_atom_size` must be power of two" - ); - - assert!( - isize::try_from(props.non_coherent_atom_size).is_ok(), - "`non_coherent_atom_size` must fit host address space" - ); - - GpuAllocator { - dedicated_threshold: config.dedicated_threshold, - preferred_dedicated_threshold: config - .preferred_dedicated_threshold - .min(config.dedicated_threshold), - - transient_dedicated_threshold: config - .transient_dedicated_threshold - .max(config.dedicated_threshold), - - max_memory_allocation_size: props.max_memory_allocation_size, - - memory_for_usage: MemoryForUsage::new(props.memory_types.as_ref()), - - memory_types: props.memory_types.as_ref().iter().copied().collect(), - memory_heaps: props - .memory_heaps - .as_ref() - .iter() - .map(|heap| Heap::new(heap.size)) - .collect(), - - buffer_device_address: props.buffer_device_address, - - allocations_remains: props.max_memory_allocation_count, - non_coherent_atom_mask: props.non_coherent_atom_size - 1, - - starting_free_list_chunk: config.starting_free_list_chunk, - final_free_list_chunk: config.final_free_list_chunk, - minimal_buddy_size: config.minimal_buddy_size, - initial_buddy_dedicated_size: config.initial_buddy_dedicated_size, - - buddy_allocators: props.memory_types.as_ref().iter().map(|_| None).collect(), - freelist_allocators: props.memory_types.as_ref().iter().map(|_| None).collect(), - } - } - - /// Allocates memory block from specified `device` according to the `request`. - /// - /// # Safety - /// - /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance. - /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance - /// and memory blocks allocated from it. - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn alloc( - &mut self, - device: &impl MemoryDevice, - request: Request, - ) -> Result, AllocationError> { - self.alloc_internal(device, request, None) - } - - /// Allocates memory block from specified `device` according to the `request`. - /// This function allows user to force specific allocation strategy. - /// Improper use can lead to suboptimal performance or too large overhead. - /// Prefer `GpuAllocator::alloc` if doubt. - /// - /// # Safety - /// - /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance. - /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance - /// and memory blocks allocated from it. - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn alloc_with_dedicated( - &mut self, - device: &impl MemoryDevice, - request: Request, - dedicated: Dedicated, - ) -> Result, AllocationError> { - self.alloc_internal(device, request, Some(dedicated)) - } - - unsafe fn alloc_internal( - &mut self, - device: &impl MemoryDevice, - mut request: Request, - dedicated: Option, - ) -> Result, AllocationError> { - enum Strategy { - Buddy, - Dedicated, - FreeList, - } - - request.usage = with_implicit_usage_flags(request.usage); - - if request.usage.contains(UsageFlags::DEVICE_ADDRESS) { - assert!(self.buffer_device_address, "`DEVICE_ADDRESS` cannot be requested when `DeviceProperties::buffer_device_address` is false"); - } - - if request.size > self.max_memory_allocation_size { - return Err(AllocationError::OutOfDeviceMemory); - } - - if let Some(Dedicated::Required) = dedicated { - if self.allocations_remains == 0 { - return Err(AllocationError::TooManyObjects); - } - } - - if 0 == self.memory_for_usage.mask(request.usage) & request.memory_types { - #[cfg(feature = "tracing")] - tracing::error!( - "Cannot serve request {:?}, no memory among bitset `{}` support usage {:?}", - request, - request.memory_types, - request.usage - ); - - return Err(AllocationError::NoCompatibleMemoryTypes); - } - - let transient = request.usage.contains(UsageFlags::TRANSIENT); - - for &index in self.memory_for_usage.types(request.usage) { - if 0 == request.memory_types & (1 << index) { - // Skip memory type incompatible with the request. - continue; - } - - let memory_type = &self.memory_types[index as usize]; - let heap = memory_type.heap; - let heap = &mut self.memory_heaps[heap as usize]; - - let atom_mask = if host_visible_non_coherent(memory_type.props) { - self.non_coherent_atom_mask - } else { - 0 - }; - - let flags = if self.buffer_device_address { - AllocationFlags::DEVICE_ADDRESS - } else { - AllocationFlags::empty() - }; - - let strategy = match (dedicated, transient) { - (Some(Dedicated::Required), _) => Strategy::Dedicated, - (Some(Dedicated::Preferred), _) - if request.size >= self.preferred_dedicated_threshold => - { - Strategy::Dedicated - } - (_, true) => { - let threshold = self.transient_dedicated_threshold.min(heap.size() / 32); - - if request.size < threshold { - Strategy::FreeList - } else { - Strategy::Dedicated - } - } - (_, false) => { - let threshold = self.dedicated_threshold.min(heap.size() / 32); - - if request.size < threshold { - Strategy::Buddy - } else { - Strategy::Dedicated - } - } - }; - - match strategy { - Strategy::Dedicated => { - #[cfg(feature = "tracing")] - tracing::debug!( - "Allocating memory object `{}@{:?}`", - request.size, - memory_type - ); - - match device.allocate_memory(request.size, index, flags) { - Ok(memory) => { - self.allocations_remains -= 1; - heap.alloc(request.size); - - return Ok(MemoryBlock::new( - index, - memory_type.props, - 0, - request.size, - atom_mask, - MemoryBlockFlavor::Dedicated { memory }, - )); - } - Err(OutOfMemory::OutOfDeviceMemory) => continue, - Err(OutOfMemory::OutOfHostMemory) => { - return Err(AllocationError::OutOfHostMemory) - } - } - } - Strategy::FreeList => { - let allocator = match &mut self.freelist_allocators[index as usize] { - Some(allocator) => allocator, - slot => { - let starting_free_list_chunk = match align_down( - self.starting_free_list_chunk.min(heap.size() / 32), - atom_mask, - ) { - 0 => atom_mask, - other => other, - }; - - let final_free_list_chunk = match align_down( - self.final_free_list_chunk - .max(self.starting_free_list_chunk) - .max(self.transient_dedicated_threshold) - .min(heap.size() / 32), - atom_mask, - ) { - 0 => atom_mask, - other => other, - }; - - slot.get_or_insert(FreeListAllocator::new( - starting_free_list_chunk, - final_free_list_chunk, - index, - memory_type.props, - if host_visible_non_coherent(memory_type.props) { - self.non_coherent_atom_mask - } else { - 0 - }, - )) - } - }; - let result = allocator.alloc( - device, - request.size, - request.align_mask, - flags, - heap, - &mut self.allocations_remains, - ); - - match result { - Ok(block) => { - return Ok(MemoryBlock::new( - index, - memory_type.props, - block.offset, - block.size, - atom_mask, - MemoryBlockFlavor::FreeList { - chunk: block.chunk, - ptr: block.ptr, - memory: block.memory, - }, - )) - } - Err(AllocationError::OutOfDeviceMemory) => continue, - Err(err) => return Err(err), - } - } - - Strategy::Buddy => { - let allocator = match &mut self.buddy_allocators[index as usize] { - Some(allocator) => allocator, - slot => { - let minimal_buddy_size = self - .minimal_buddy_size - .min(heap.size() / 1024) - .next_power_of_two(); - - let initial_buddy_dedicated_size = self - .initial_buddy_dedicated_size - .min(heap.size() / 32) - .next_power_of_two(); - - slot.get_or_insert(BuddyAllocator::new( - minimal_buddy_size, - initial_buddy_dedicated_size, - index, - memory_type.props, - if host_visible_non_coherent(memory_type.props) { - self.non_coherent_atom_mask - } else { - 0 - }, - )) - } - }; - let result = allocator.alloc( - device, - request.size, - request.align_mask, - flags, - heap, - &mut self.allocations_remains, - ); - - match result { - Ok(block) => { - return Ok(MemoryBlock::new( - index, - memory_type.props, - block.offset, - block.size, - atom_mask, - MemoryBlockFlavor::Buddy { - chunk: block.chunk, - ptr: block.ptr, - index: block.index, - memory: block.memory, - }, - )) - } - Err(AllocationError::OutOfDeviceMemory) => continue, - Err(err) => return Err(err), - } - } - } - } - - Err(AllocationError::OutOfDeviceMemory) - } - - /// Deallocates memory block previously allocated from this `GpuAllocator` instance. - /// - /// # Safety - /// - /// * Memory block must have been allocated by this `GpuAllocator` instance - /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance - /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance - /// and memory blocks allocated from it - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn dealloc(&mut self, device: &impl MemoryDevice, block: MemoryBlock) { - let memory_type = block.memory_type(); - let offset = block.offset(); - let size = block.size(); - let flavor = block.deallocate(); - match flavor { - MemoryBlockFlavor::Dedicated { memory } => { - let heap = self.memory_types[memory_type as usize].heap; - device.deallocate_memory(memory); - self.allocations_remains += 1; - self.memory_heaps[heap as usize].dealloc(size); - } - MemoryBlockFlavor::Buddy { - chunk, - ptr, - index, - memory, - } => { - let heap = self.memory_types[memory_type as usize].heap; - let heap = &mut self.memory_heaps[heap as usize]; - - let allocator = self.buddy_allocators[memory_type as usize] - .as_mut() - .expect("Allocator should exist"); - - allocator.dealloc( - device, - BuddyBlock { - memory, - ptr, - offset, - size, - chunk, - index, - }, - heap, - &mut self.allocations_remains, - ); - } - MemoryBlockFlavor::FreeList { chunk, ptr, memory } => { - let heap = self.memory_types[memory_type as usize].heap; - let heap = &mut self.memory_heaps[heap as usize]; - - let allocator = self.freelist_allocators[memory_type as usize] - .as_mut() - .expect("Allocator should exist"); - - allocator.dealloc( - device, - FreeListBlock { - memory, - ptr, - chunk, - offset, - size, - }, - heap, - &mut self.allocations_remains, - ); - } - } - } - - /// Deallocates leftover memory objects. - /// Should be used before dropping. - /// - /// # Safety - /// - /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance - /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance - /// and memory blocks allocated from it - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn cleanup(&mut self, device: &impl MemoryDevice) { - for (index, allocator) in self - .freelist_allocators - .iter_mut() - .enumerate() - .filter_map(|(index, allocator)| Some((index, allocator.as_mut()?))) - { - let memory_type = &self.memory_types[index]; - let heap = memory_type.heap; - let heap = &mut self.memory_heaps[heap as usize]; - - allocator.cleanup(device, heap, &mut self.allocations_remains); - } - } -} - -fn host_visible_non_coherent(props: MemoryPropertyFlags) -> bool { - (props & (MemoryPropertyFlags::HOST_COHERENT | MemoryPropertyFlags::HOST_VISIBLE)) - == MemoryPropertyFlags::HOST_VISIBLE -} - -fn with_implicit_usage_flags(usage: UsageFlags) -> UsageFlags { - if usage.is_empty() { - UsageFlags::FAST_DEVICE_ACCESS - } else if usage.intersects(UsageFlags::DOWNLOAD | UsageFlags::UPLOAD) { - usage | UsageFlags::HOST_ACCESS - } else { - usage - } -} +use { + crate::{ + align_down, + block::{MemoryBlock, MemoryBlockFlavor}, + buddy::{BuddyAllocator, BuddyBlock}, + config::Config, + error::AllocationError, + freelist::{FreeListAllocator, FreeListBlock}, + heap::Heap, + usage::{MemoryForUsage, UsageFlags}, + MemoryBounds, Request, + }, + alloc::boxed::Box, + core::convert::TryFrom as _, + gpu_alloc_types::{ + AllocationFlags, DeviceProperties, MemoryDevice, MemoryPropertyFlags, MemoryType, + OutOfMemory, + }, +}; + +/// Memory allocator for Vulkan-like APIs. +#[derive(Debug)] +pub struct GpuAllocator { + dedicated_threshold: u64, + preferred_dedicated_threshold: u64, + transient_dedicated_threshold: u64, + max_memory_allocation_size: u64, + memory_for_usage: MemoryForUsage, + memory_types: Box<[MemoryType]>, + memory_heaps: Box<[Heap]>, + allocations_remains: u32, + non_coherent_atom_mask: u64, + starting_free_list_chunk: u64, + final_free_list_chunk: u64, + minimal_buddy_size: u64, + initial_buddy_dedicated_size: u64, + buffer_device_address: bool, + + buddy_allocators: Box<[Option>]>, + freelist_allocators: Box<[Option>]>, +} + +/// Hints for allocator to decide on allocation strategy. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum Dedicated { + /// Allocation directly from device.\ + /// Very slow. + /// Count of allocations is limited.\ + /// Use with caution.\ + /// Must be used if resource has to be bound to dedicated memory object. + Required, + + /// Hint for allocator that dedicated memory object is preferred.\ + /// Should be used if it is known that resource placed in dedicated memory object + /// would allow for better performance.\ + /// Implementation is allowed to return block to shared memory object. + Preferred, +} + +impl GpuAllocator +where + M: MemoryBounds + 'static, +{ + /// Creates new instance of `GpuAllocator`. + /// Provided `DeviceProperties` should match properties of `MemoryDevice` that will be used + /// with created `GpuAllocator` instance. + #[cfg_attr(feature = "tracing", tracing::instrument)] + pub fn new(config: Config, props: DeviceProperties<'_>) -> Self { + assert!( + props.non_coherent_atom_size.is_power_of_two(), + "`non_coherent_atom_size` must be power of two" + ); + + assert!( + isize::try_from(props.non_coherent_atom_size).is_ok(), + "`non_coherent_atom_size` must fit host address space" + ); + + GpuAllocator { + dedicated_threshold: config.dedicated_threshold, + preferred_dedicated_threshold: config + .preferred_dedicated_threshold + .min(config.dedicated_threshold), + + transient_dedicated_threshold: config + .transient_dedicated_threshold + .max(config.dedicated_threshold), + + max_memory_allocation_size: props.max_memory_allocation_size, + + memory_for_usage: MemoryForUsage::new(props.memory_types.as_ref()), + + memory_types: props.memory_types.as_ref().iter().copied().collect(), + memory_heaps: props + .memory_heaps + .as_ref() + .iter() + .map(|heap| Heap::new(heap.size)) + .collect(), + + buffer_device_address: props.buffer_device_address, + + allocations_remains: props.max_memory_allocation_count, + non_coherent_atom_mask: props.non_coherent_atom_size - 1, + + starting_free_list_chunk: config.starting_free_list_chunk, + final_free_list_chunk: config.final_free_list_chunk, + minimal_buddy_size: config.minimal_buddy_size, + initial_buddy_dedicated_size: config.initial_buddy_dedicated_size, + + buddy_allocators: props.memory_types.as_ref().iter().map(|_| None).collect(), + freelist_allocators: props.memory_types.as_ref().iter().map(|_| None).collect(), + } + } + + /// Allocates memory block from specified `device` according to the `request`. + /// + /// # Safety + /// + /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance. + /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance + /// and memory blocks allocated from it. + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn alloc( + &mut self, + device: &impl MemoryDevice, + request: Request, + ) -> Result, AllocationError> { + self.alloc_internal(device, request, None) + } + + /// Allocates memory block from specified `device` according to the `request`. + /// This function allows user to force specific allocation strategy. + /// Improper use can lead to suboptimal performance or too large overhead. + /// Prefer `GpuAllocator::alloc` if doubt. + /// + /// # Safety + /// + /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance. + /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance + /// and memory blocks allocated from it. + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn alloc_with_dedicated( + &mut self, + device: &impl MemoryDevice, + request: Request, + dedicated: Dedicated, + ) -> Result, AllocationError> { + self.alloc_internal(device, request, Some(dedicated)) + } + + unsafe fn alloc_internal( + &mut self, + device: &impl MemoryDevice, + mut request: Request, + dedicated: Option, + ) -> Result, AllocationError> { + enum Strategy { + Buddy, + Dedicated, + FreeList, + } + + request.usage = with_implicit_usage_flags(request.usage); + + if request.usage.contains(UsageFlags::DEVICE_ADDRESS) { + assert!(self.buffer_device_address, "`DEVICE_ADDRESS` cannot be requested when `DeviceProperties::buffer_device_address` is false"); + } + + if request.size > self.max_memory_allocation_size { + return Err(AllocationError::OutOfDeviceMemory); + } + + if let Some(Dedicated::Required) = dedicated { + if self.allocations_remains == 0 { + return Err(AllocationError::TooManyObjects); + } + } + + if 0 == self.memory_for_usage.mask(request.usage) & request.memory_types { + #[cfg(feature = "tracing")] + tracing::error!( + "Cannot serve request {:?}, no memory among bitset `{}` support usage {:?}", + request, + request.memory_types, + request.usage + ); + + return Err(AllocationError::NoCompatibleMemoryTypes); + } + + let transient = request.usage.contains(UsageFlags::TRANSIENT); + + for &index in self.memory_for_usage.types(request.usage) { + if 0 == request.memory_types & (1 << index) { + // Skip memory type incompatible with the request. + continue; + } + + let memory_type = &self.memory_types[index as usize]; + let heap = memory_type.heap; + let heap = &mut self.memory_heaps[heap as usize]; + + if request.size > heap.size() { + // Impossible to use memory type from this heap. + continue; + } + + let atom_mask = if host_visible_non_coherent(memory_type.props) { + self.non_coherent_atom_mask + } else { + 0 + }; + + let flags = if self.buffer_device_address { + AllocationFlags::DEVICE_ADDRESS + } else { + AllocationFlags::empty() + }; + + let strategy = match (dedicated, transient) { + (Some(Dedicated::Required), _) => Strategy::Dedicated, + (Some(Dedicated::Preferred), _) + if request.size >= self.preferred_dedicated_threshold => + { + Strategy::Dedicated + } + (_, true) => { + let threshold = self.transient_dedicated_threshold.min(heap.size() / 32); + + if request.size < threshold { + Strategy::FreeList + } else { + Strategy::Dedicated + } + } + (_, false) => { + let threshold = self.dedicated_threshold.min(heap.size() / 32); + + if request.size < threshold { + Strategy::Buddy + } else { + Strategy::Dedicated + } + } + }; + + match strategy { + Strategy::Dedicated => { + #[cfg(feature = "tracing")] + tracing::debug!( + "Allocating memory object `{}@{:?}`", + request.size, + memory_type + ); + + match device.allocate_memory(request.size, index, flags) { + Ok(memory) => { + self.allocations_remains -= 1; + heap.alloc(request.size); + + return Ok(MemoryBlock::new( + index, + memory_type.props, + 0, + request.size, + atom_mask, + MemoryBlockFlavor::Dedicated { memory }, + )); + } + Err(OutOfMemory::OutOfDeviceMemory) => continue, + Err(OutOfMemory::OutOfHostMemory) => { + return Err(AllocationError::OutOfHostMemory) + } + } + } + Strategy::FreeList => { + let allocator = match &mut self.freelist_allocators[index as usize] { + Some(allocator) => allocator, + slot => { + let starting_free_list_chunk = match align_down( + self.starting_free_list_chunk.min(heap.size() / 32), + atom_mask, + ) { + 0 => atom_mask, + other => other, + }; + + let final_free_list_chunk = match align_down( + self.final_free_list_chunk + .max(self.starting_free_list_chunk) + .max(self.transient_dedicated_threshold) + .min(heap.size() / 32), + atom_mask, + ) { + 0 => atom_mask, + other => other, + }; + + slot.get_or_insert(FreeListAllocator::new( + starting_free_list_chunk, + final_free_list_chunk, + index, + memory_type.props, + if host_visible_non_coherent(memory_type.props) { + self.non_coherent_atom_mask + } else { + 0 + }, + )) + } + }; + let result = allocator.alloc( + device, + request.size, + request.align_mask, + flags, + heap, + &mut self.allocations_remains, + ); + + match result { + Ok(block) => { + return Ok(MemoryBlock::new( + index, + memory_type.props, + block.offset, + block.size, + atom_mask, + MemoryBlockFlavor::FreeList { + chunk: block.chunk, + ptr: block.ptr, + memory: block.memory, + }, + )) + } + Err(AllocationError::OutOfDeviceMemory) => continue, + Err(err) => return Err(err), + } + } + + Strategy::Buddy => { + let allocator = match &mut self.buddy_allocators[index as usize] { + Some(allocator) => allocator, + slot => { + let minimal_buddy_size = self + .minimal_buddy_size + .min(heap.size() / 1024) + .next_power_of_two(); + + let initial_buddy_dedicated_size = self + .initial_buddy_dedicated_size + .min(heap.size() / 32) + .next_power_of_two(); + + slot.get_or_insert(BuddyAllocator::new( + minimal_buddy_size, + initial_buddy_dedicated_size, + index, + memory_type.props, + if host_visible_non_coherent(memory_type.props) { + self.non_coherent_atom_mask + } else { + 0 + }, + )) + } + }; + let result = allocator.alloc( + device, + request.size, + request.align_mask, + flags, + heap, + &mut self.allocations_remains, + ); + + match result { + Ok(block) => { + return Ok(MemoryBlock::new( + index, + memory_type.props, + block.offset, + block.size, + atom_mask, + MemoryBlockFlavor::Buddy { + chunk: block.chunk, + ptr: block.ptr, + index: block.index, + memory: block.memory, + }, + )) + } + Err(AllocationError::OutOfDeviceMemory) => continue, + Err(err) => return Err(err), + } + } + } + } + + Err(AllocationError::OutOfDeviceMemory) + } + + /// Creates a memory block from an existing memory allocation, transferring ownership to the allocator. + /// + /// This function allows the [`GpuAllocator`] to manage memory allocated outside of the typical + /// [`GpuAllocator::alloc`] family of functions. + /// + /// # Usage + /// + /// If you need to import external memory, such as a Win32 `HANDLE` or a Linux `dmabuf`, import the device + /// memory using the graphics api and platform dependent functions. Once that is done, call this function + /// to make the [`GpuAllocator`] take ownership of the imported memory. + /// + /// When calling this function, you **must** ensure there are [enough remaining allocations](GpuAllocator::remaining_allocations). + /// + /// # Safety + /// + /// - The `memory` must be allocated with the same device that was provided to create this [`GpuAllocator`] + /// instance. + /// - The `memory` must be valid. + /// - The `props`, `offset` and `size` must match the properties, offset and size of the memory allocation. + /// - The memory must have been allocated with the specified `memory_type`. + /// - There must be enough remaining allocations. + /// - The memory allocation must not come from an existing memory block created by this allocator. + /// - The underlying memory object must be deallocated using the returned [`MemoryBlock`] with + /// [`GpuAllocator::dealloc`]. + pub unsafe fn import_memory( + &mut self, + memory: M, + memory_type: u32, + props: MemoryPropertyFlags, + offset: u64, + size: u64, + ) -> MemoryBlock { + // Get the heap which the imported memory is from. + let heap = self + .memory_types + .get(memory_type as usize) + .expect("Invalid memory type specified when importing memory") + .heap; + let heap = &mut self.memory_heaps[heap as usize]; + + #[cfg(feature = "tracing")] + tracing::debug!( + "Importing memory object {:?} `{}@{:?}`", + memory, + size, + memory_type + ); + + assert_ne!( + self.allocations_remains, 0, + "Out of allocations when importing a memory block. Ensure you check GpuAllocator::remaining_allocations before import." + ); + self.allocations_remains -= 1; + + let atom_mask = if host_visible_non_coherent(props) { + self.non_coherent_atom_mask + } else { + 0 + }; + + heap.alloc(size); + + MemoryBlock::new( + memory_type, + props, + offset, + size, + atom_mask, + MemoryBlockFlavor::Dedicated { memory }, + ) + } + + /// Deallocates memory block previously allocated from this `GpuAllocator` instance. + /// + /// # Safety + /// + /// * Memory block must have been allocated by this `GpuAllocator` instance + /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance + /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance + /// and memory blocks allocated from it + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn dealloc(&mut self, device: &impl MemoryDevice, block: MemoryBlock) { + let memory_type = block.memory_type(); + let offset = block.offset(); + let size = block.size(); + let flavor = block.deallocate(); + match flavor { + MemoryBlockFlavor::Dedicated { memory } => { + let heap = self.memory_types[memory_type as usize].heap; + device.deallocate_memory(memory); + self.allocations_remains += 1; + self.memory_heaps[heap as usize].dealloc(size); + } + MemoryBlockFlavor::Buddy { + chunk, + ptr, + index, + memory, + } => { + let heap = self.memory_types[memory_type as usize].heap; + let heap = &mut self.memory_heaps[heap as usize]; + + let allocator = self.buddy_allocators[memory_type as usize] + .as_mut() + .expect("Allocator should exist"); + + allocator.dealloc( + device, + BuddyBlock { + memory, + ptr, + offset, + size, + chunk, + index, + }, + heap, + &mut self.allocations_remains, + ); + } + MemoryBlockFlavor::FreeList { chunk, ptr, memory } => { + let heap = self.memory_types[memory_type as usize].heap; + let heap = &mut self.memory_heaps[heap as usize]; + + let allocator = self.freelist_allocators[memory_type as usize] + .as_mut() + .expect("Allocator should exist"); + + allocator.dealloc( + device, + FreeListBlock { + memory, + ptr, + chunk, + offset, + size, + }, + heap, + &mut self.allocations_remains, + ); + } + } + } + + /// Returns the maximum allocation size supported. + pub fn max_allocation_size(&self) -> u64 { + self.max_memory_allocation_size + } + + /// Returns the number of remaining available allocations. + /// + /// This may be useful if you need know if the allocator can allocate a number of allocations ahead of + /// time. This function is also useful for ensuring you do not allocate too much memory outside allocator + /// (such as external memory). + pub fn remaining_allocations(&self) -> u32 { + self.allocations_remains + } + + /// Sets the number of remaining available allocations. + /// + /// # Safety + /// + /// The caller is responsible for ensuring the number of remaining allocations does not exceed how many + /// remaining allocations there actually are on the memory device. + pub unsafe fn set_remaining_allocations(&mut self, remaining: u32) { + self.allocations_remains = remaining; + } + + /// Deallocates leftover memory objects. + /// Should be used before dropping. + /// + /// # Safety + /// + /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance + /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance + /// and memory blocks allocated from it + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn cleanup(&mut self, device: &impl MemoryDevice) { + for (index, allocator) in self + .freelist_allocators + .iter_mut() + .enumerate() + .filter_map(|(index, allocator)| Some((index, allocator.as_mut()?))) + { + let memory_type = &self.memory_types[index]; + let heap = memory_type.heap; + let heap = &mut self.memory_heaps[heap as usize]; + + allocator.cleanup(device, heap, &mut self.allocations_remains); + } + } +} + +fn host_visible_non_coherent(props: MemoryPropertyFlags) -> bool { + (props & (MemoryPropertyFlags::HOST_COHERENT | MemoryPropertyFlags::HOST_VISIBLE)) + == MemoryPropertyFlags::HOST_VISIBLE +} + +fn with_implicit_usage_flags(usage: UsageFlags) -> UsageFlags { + if usage.is_empty() { + UsageFlags::FAST_DEVICE_ACCESS + } else if usage.intersects(UsageFlags::DOWNLOAD | UsageFlags::UPLOAD) { + usage | UsageFlags::HOST_ACCESS + } else { + usage + } +} diff --git a/third_party/rust/gpu-alloc/src/block.rs b/third_party/rust/gpu-alloc/src/block.rs index 7cac633bf1f9..03e31d9d5205 100644 --- a/third_party/rust/gpu-alloc/src/block.rs +++ b/third_party/rust/gpu-alloc/src/block.rs @@ -1,327 +1,327 @@ -use { - crate::{align_down, align_up, error::MapError}, - alloc::sync::Arc, - core::{ - convert::TryFrom as _, - ptr::{copy_nonoverlapping, NonNull}, - // sync::atomic::{AtomicU8, Ordering::*}, - }, - gpu_alloc_types::{MappedMemoryRange, MemoryDevice, MemoryPropertyFlags}, -}; - -#[derive(Debug)] -struct Relevant; - -impl Drop for Relevant { - fn drop(&mut self) { - report_error_on_drop!("Memory block wasn't deallocated"); - } -} - -/// Memory block allocated by `GpuAllocator`. -#[derive(Debug)] -pub struct MemoryBlock { - memory_type: u32, - props: MemoryPropertyFlags, - offset: u64, - size: u64, - atom_mask: u64, - mapped: bool, - flavor: MemoryBlockFlavor, - relevant: Relevant, -} - -impl MemoryBlock { - pub(crate) fn new( - memory_type: u32, - props: MemoryPropertyFlags, - offset: u64, - size: u64, - atom_mask: u64, - flavor: MemoryBlockFlavor, - ) -> Self { - isize::try_from(atom_mask).expect("`atom_mask` is too large"); - MemoryBlock { - memory_type, - props, - offset, - size, - atom_mask, - flavor, - mapped: false, - relevant: Relevant, - } - } - - pub(crate) fn deallocate(self) -> MemoryBlockFlavor { - core::mem::forget(self.relevant); - self.flavor - } -} - -unsafe impl Sync for MemoryBlock where M: Sync {} -unsafe impl Send for MemoryBlock where M: Send {} - -#[derive(Debug)] -pub(crate) enum MemoryBlockFlavor { - Dedicated { - memory: M, - }, - Buddy { - chunk: usize, - index: usize, - ptr: Option>, - memory: Arc, - }, - FreeList { - chunk: u64, - ptr: Option>, - memory: Arc, - }, -} - -impl MemoryBlock { - /// Returns reference to parent memory object. - #[inline(always)] - pub fn memory(&self) -> &M { - match &self.flavor { - MemoryBlockFlavor::Dedicated { memory } => memory, - MemoryBlockFlavor::Buddy { memory, .. } => &**memory, - MemoryBlockFlavor::FreeList { memory, .. } => &**memory, - } - } - - /// Returns offset in bytes from start of memory object to start of this block. - #[inline(always)] - pub fn offset(&self) -> u64 { - self.offset - } - - /// Returns size of this memory block. - #[inline(always)] - pub fn size(&self) -> u64 { - self.size - } - - /// Returns memory property flags for parent memory object. - #[inline(always)] - pub fn props(&self) -> MemoryPropertyFlags { - self.props - } - - /// Returns index of type of parent memory object. - #[inline(always)] - pub fn memory_type(&self) -> u32 { - self.memory_type - } - - /// Returns pointer to mapped memory range of this block. - /// This blocks becomes mapped. - /// - /// The user of returned pointer must guarantee that any previously submitted command that writes to this range has completed - /// before the host reads from or writes to that range, - /// and that any previously submitted command that reads from that range has completed - /// before the host writes to that region. - /// If the device memory was allocated without the `HOST_COHERENT` property flag set, - /// these guarantees must be made for an extended range: - /// the user must round down the start of the range to the nearest multiple of `non_coherent_atom_size`, - /// and round the end of the range up to the nearest multiple of `non_coherent_atom_size`. - /// - /// # Panics - /// - /// This function panics if block is currently mapped. - /// - /// # Safety - /// - /// `block` must have been allocated from specified `device`. - #[inline(always)] - pub unsafe fn map( - &mut self, - device: &impl MemoryDevice, - offset: u64, - size: usize, - ) -> Result, MapError> { - let size_u64 = u64::try_from(size).expect("`size` doesn't fit device address space"); - assert!(offset < self.size, "`offset` is out of memory block bounds"); - assert!( - size_u64 <= self.size - offset, - "`offset + size` is out of memory block bounds" - ); - - let ptr = match &mut self.flavor { - MemoryBlockFlavor::Dedicated { memory } => { - let end = align_up(offset + size_u64, self.atom_mask) - .expect("mapping end doesn't fit device address space"); - let aligned_offset = align_down(offset, self.atom_mask); - - if !acquire_mapping(&mut self.mapped) { - return Err(MapError::AlreadyMapped); - } - let result = - device.map_memory(memory, self.offset + aligned_offset, end - aligned_offset); - - match result { - // the overflow is checked in `Self::new()` - Ok(ptr) => { - let ptr_offset = (offset - aligned_offset) as isize; - ptr.as_ptr().offset(ptr_offset) - } - Err(err) => { - release_mapping(&mut self.mapped); - return Err(err.into()); - } - } - } - MemoryBlockFlavor::FreeList { ptr: Some(ptr), .. } - | MemoryBlockFlavor::Buddy { ptr: Some(ptr), .. } => { - if !acquire_mapping(&mut self.mapped) { - return Err(MapError::AlreadyMapped); - } - let offset_isize = isize::try_from(offset) - .expect("Buddy and linear block should fit host address space"); - ptr.as_ptr().offset(offset_isize) - } - _ => return Err(MapError::NonHostVisible), - }; - - Ok(NonNull::new_unchecked(ptr)) - } - - /// Unmaps memory range of this block that was previously mapped with `Block::map`. - /// This block becomes unmapped. - /// - /// # Panics - /// - /// This function panics if this block is not currently mapped. - /// - /// # Safety - /// - /// `block` must have been allocated from specified `device`. - #[inline(always)] - pub unsafe fn unmap(&mut self, device: &impl MemoryDevice) -> bool { - if !release_mapping(&mut self.mapped) { - return false; - } - match &mut self.flavor { - MemoryBlockFlavor::Dedicated { memory } => { - device.unmap_memory(memory); - } - MemoryBlockFlavor::Buddy { .. } => {} - MemoryBlockFlavor::FreeList { .. } => {} - } - true - } - - /// Transiently maps block memory range and copies specified data - /// to the mapped memory range. - /// - /// # Panics - /// - /// This function panics if block is currently mapped. - /// - /// # Safety - /// - /// `block` must have been allocated from specified `device`. - /// The caller must guarantee that any previously submitted command that reads or writes to this range has completed. - #[inline(always)] - pub unsafe fn write_bytes( - &mut self, - device: &impl MemoryDevice, - offset: u64, - data: &[u8], - ) -> Result<(), MapError> { - let size = data.len(); - let ptr = self.map(device, offset, size)?; - - copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), size); - let result = if !self.coherent() { - let aligned_offset = align_down(offset, self.atom_mask); - let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap(); - - device.flush_memory_ranges(&[MappedMemoryRange { - memory: self.memory(), - offset: self.offset + aligned_offset, - size: end - aligned_offset, - }]) - } else { - Ok(()) - }; - - self.unmap(device); - result.map_err(Into::into) - } - - /// Transiently maps block memory range and copies specified data - /// from the mapped memory range. - /// - /// # Panics - /// - /// This function panics if block is currently mapped. - /// - /// # Safety - /// - /// `block` must have been allocated from specified `device`. - /// The caller must guarantee that any previously submitted command that reads to this range has completed. - #[inline(always)] - pub unsafe fn read_bytes( - &mut self, - device: &impl MemoryDevice, - offset: u64, - data: &mut [u8], - ) -> Result<(), MapError> { - #[cfg(feature = "tracing")] - { - if !self.cached() { - tracing::warn!("Reading from non-cached memory may be slow. Consider allocating HOST_CACHED memory block for host reads.") - } - } - - let size = data.len(); - let ptr = self.map(device, offset, size)?; - let result = if !self.coherent() { - let aligned_offset = align_down(offset, self.atom_mask); - let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap(); - - device.invalidate_memory_ranges(&[MappedMemoryRange { - memory: self.memory(), - offset: self.offset + aligned_offset, - size: end - aligned_offset, - }]) - } else { - Ok(()) - }; - if result.is_ok() { - copy_nonoverlapping(ptr.as_ptr(), data.as_mut_ptr(), size); - } - - self.unmap(device); - result.map_err(Into::into) - } - - fn coherent(&self) -> bool { - self.props.contains(MemoryPropertyFlags::HOST_COHERENT) - } - - #[cfg(feature = "tracing")] - fn cached(&self) -> bool { - self.props.contains(MemoryPropertyFlags::HOST_CACHED) - } -} - -fn acquire_mapping(mapped: &mut bool) -> bool { - if *mapped { - false - } else { - *mapped = true; - true - } -} - -fn release_mapping(mapped: &mut bool) -> bool { - if *mapped { - *mapped = false; - true - } else { - false - } -} +use { + crate::{align_down, align_up, error::MapError}, + alloc::sync::Arc, + core::{ + convert::TryFrom as _, + ptr::{copy_nonoverlapping, NonNull}, + // sync::atomic::{AtomicU8, Ordering::*}, + }, + gpu_alloc_types::{MappedMemoryRange, MemoryDevice, MemoryPropertyFlags}, +}; + +#[derive(Debug)] +struct Relevant; + +impl Drop for Relevant { + fn drop(&mut self) { + report_error_on_drop!("Memory block wasn't deallocated"); + } +} + +/// Memory block allocated by `GpuAllocator`. +#[derive(Debug)] +pub struct MemoryBlock { + memory_type: u32, + props: MemoryPropertyFlags, + offset: u64, + size: u64, + atom_mask: u64, + mapped: bool, + flavor: MemoryBlockFlavor, + relevant: Relevant, +} + +impl MemoryBlock { + pub(crate) fn new( + memory_type: u32, + props: MemoryPropertyFlags, + offset: u64, + size: u64, + atom_mask: u64, + flavor: MemoryBlockFlavor, + ) -> Self { + isize::try_from(atom_mask).expect("`atom_mask` is too large"); + MemoryBlock { + memory_type, + props, + offset, + size, + atom_mask, + flavor, + mapped: false, + relevant: Relevant, + } + } + + pub(crate) fn deallocate(self) -> MemoryBlockFlavor { + core::mem::forget(self.relevant); + self.flavor + } +} + +unsafe impl Sync for MemoryBlock where M: Sync {} +unsafe impl Send for MemoryBlock where M: Send {} + +#[derive(Debug)] +pub(crate) enum MemoryBlockFlavor { + Dedicated { + memory: M, + }, + Buddy { + chunk: usize, + index: usize, + ptr: Option>, + memory: Arc, + }, + FreeList { + chunk: u64, + ptr: Option>, + memory: Arc, + }, +} + +impl MemoryBlock { + /// Returns reference to parent memory object. + #[inline(always)] + pub fn memory(&self) -> &M { + match &self.flavor { + MemoryBlockFlavor::Dedicated { memory } => memory, + MemoryBlockFlavor::Buddy { memory, .. } => memory, + MemoryBlockFlavor::FreeList { memory, .. } => memory, + } + } + + /// Returns offset in bytes from start of memory object to start of this block. + #[inline(always)] + pub fn offset(&self) -> u64 { + self.offset + } + + /// Returns size of this memory block. + #[inline(always)] + pub fn size(&self) -> u64 { + self.size + } + + /// Returns memory property flags for parent memory object. + #[inline(always)] + pub fn props(&self) -> MemoryPropertyFlags { + self.props + } + + /// Returns index of type of parent memory object. + #[inline(always)] + pub fn memory_type(&self) -> u32 { + self.memory_type + } + + /// Returns pointer to mapped memory range of this block. + /// This blocks becomes mapped. + /// + /// The user of returned pointer must guarantee that any previously submitted command that writes to this range has completed + /// before the host reads from or writes to that range, + /// and that any previously submitted command that reads from that range has completed + /// before the host writes to that region. + /// If the device memory was allocated without the `HOST_COHERENT` property flag set, + /// these guarantees must be made for an extended range: + /// the user must round down the start of the range to the nearest multiple of `non_coherent_atom_size`, + /// and round the end of the range up to the nearest multiple of `non_coherent_atom_size`. + /// + /// # Panics + /// + /// This function panics if block is currently mapped. + /// + /// # Safety + /// + /// `block` must have been allocated from specified `device`. + #[inline(always)] + pub unsafe fn map( + &mut self, + device: &impl MemoryDevice, + offset: u64, + size: usize, + ) -> Result, MapError> { + let size_u64 = u64::try_from(size).expect("`size` doesn't fit device address space"); + assert!(offset < self.size, "`offset` is out of memory block bounds"); + assert!( + size_u64 <= self.size - offset, + "`offset + size` is out of memory block bounds" + ); + + let ptr = match &mut self.flavor { + MemoryBlockFlavor::Dedicated { memory } => { + let end = align_up(offset + size_u64, self.atom_mask) + .expect("mapping end doesn't fit device address space"); + let aligned_offset = align_down(offset, self.atom_mask); + + if !acquire_mapping(&mut self.mapped) { + return Err(MapError::AlreadyMapped); + } + let result = + device.map_memory(memory, self.offset + aligned_offset, end - aligned_offset); + + match result { + // the overflow is checked in `Self::new()` + Ok(ptr) => { + let ptr_offset = (offset - aligned_offset) as isize; + ptr.as_ptr().offset(ptr_offset) + } + Err(err) => { + release_mapping(&mut self.mapped); + return Err(err.into()); + } + } + } + MemoryBlockFlavor::FreeList { ptr: Some(ptr), .. } + | MemoryBlockFlavor::Buddy { ptr: Some(ptr), .. } => { + if !acquire_mapping(&mut self.mapped) { + return Err(MapError::AlreadyMapped); + } + let offset_isize = isize::try_from(offset) + .expect("Buddy and linear block should fit host address space"); + ptr.as_ptr().offset(offset_isize) + } + _ => return Err(MapError::NonHostVisible), + }; + + Ok(NonNull::new_unchecked(ptr)) + } + + /// Unmaps memory range of this block that was previously mapped with `Block::map`. + /// This block becomes unmapped. + /// + /// # Panics + /// + /// This function panics if this block is not currently mapped. + /// + /// # Safety + /// + /// `block` must have been allocated from specified `device`. + #[inline(always)] + pub unsafe fn unmap(&mut self, device: &impl MemoryDevice) -> bool { + if !release_mapping(&mut self.mapped) { + return false; + } + match &mut self.flavor { + MemoryBlockFlavor::Dedicated { memory } => { + device.unmap_memory(memory); + } + MemoryBlockFlavor::Buddy { .. } => {} + MemoryBlockFlavor::FreeList { .. } => {} + } + true + } + + /// Transiently maps block memory range and copies specified data + /// to the mapped memory range. + /// + /// # Panics + /// + /// This function panics if block is currently mapped. + /// + /// # Safety + /// + /// `block` must have been allocated from specified `device`. + /// The caller must guarantee that any previously submitted command that reads or writes to this range has completed. + #[inline(always)] + pub unsafe fn write_bytes( + &mut self, + device: &impl MemoryDevice, + offset: u64, + data: &[u8], + ) -> Result<(), MapError> { + let size = data.len(); + let ptr = self.map(device, offset, size)?; + + copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), size); + let result = if !self.coherent() { + let aligned_offset = align_down(offset, self.atom_mask); + let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap(); + + device.flush_memory_ranges(&[MappedMemoryRange { + memory: self.memory(), + offset: self.offset + aligned_offset, + size: end - aligned_offset, + }]) + } else { + Ok(()) + }; + + self.unmap(device); + result.map_err(Into::into) + } + + /// Transiently maps block memory range and copies specified data + /// from the mapped memory range. + /// + /// # Panics + /// + /// This function panics if block is currently mapped. + /// + /// # Safety + /// + /// `block` must have been allocated from specified `device`. + /// The caller must guarantee that any previously submitted command that reads to this range has completed. + #[inline(always)] + pub unsafe fn read_bytes( + &mut self, + device: &impl MemoryDevice, + offset: u64, + data: &mut [u8], + ) -> Result<(), MapError> { + #[cfg(feature = "tracing")] + { + if !self.cached() { + tracing::warn!("Reading from non-cached memory may be slow. Consider allocating HOST_CACHED memory block for host reads.") + } + } + + let size = data.len(); + let ptr = self.map(device, offset, size)?; + let result = if !self.coherent() { + let aligned_offset = align_down(offset, self.atom_mask); + let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap(); + + device.invalidate_memory_ranges(&[MappedMemoryRange { + memory: self.memory(), + offset: self.offset + aligned_offset, + size: end - aligned_offset, + }]) + } else { + Ok(()) + }; + if result.is_ok() { + copy_nonoverlapping(ptr.as_ptr(), data.as_mut_ptr(), size); + } + + self.unmap(device); + result.map_err(Into::into) + } + + fn coherent(&self) -> bool { + self.props.contains(MemoryPropertyFlags::HOST_COHERENT) + } + + #[cfg(feature = "tracing")] + fn cached(&self) -> bool { + self.props.contains(MemoryPropertyFlags::HOST_CACHED) + } +} + +fn acquire_mapping(mapped: &mut bool) -> bool { + if *mapped { + false + } else { + *mapped = true; + true + } +} + +fn release_mapping(mapped: &mut bool) -> bool { + if *mapped { + *mapped = false; + true + } else { + false + } +} diff --git a/third_party/rust/gpu-alloc/src/buddy.rs b/third_party/rust/gpu-alloc/src/buddy.rs index 5691f4d96d75..dea303b948a8 100644 --- a/third_party/rust/gpu-alloc/src/buddy.rs +++ b/third_party/rust/gpu-alloc/src/buddy.rs @@ -1,458 +1,460 @@ -use { - crate::{ - align_up, error::AllocationError, heap::Heap, slab::Slab, unreachable_unchecked, - util::try_arc_unwrap, MemoryBounds, - }, - alloc::{sync::Arc, vec::Vec}, - core::{convert::TryFrom as _, mem::replace, ptr::NonNull}, - gpu_alloc_types::{AllocationFlags, DeviceMapError, MemoryDevice, MemoryPropertyFlags}, -}; - -#[derive(Debug)] -pub(crate) struct BuddyBlock { - pub memory: Arc, - pub ptr: Option>, - pub offset: u64, - pub size: u64, - pub chunk: usize, - pub index: usize, -} - -unsafe impl Sync for BuddyBlock where M: Sync {} -unsafe impl Send for BuddyBlock where M: Send {} - -#[derive(Clone, Copy, Debug)] -enum PairState { - Exhausted, - Ready { - ready: Side, - next: usize, - prev: usize, - }, -} - -impl PairState { - unsafe fn replace_next(&mut self, value: usize) -> usize { - match self { - PairState::Exhausted => unreachable_unchecked(), - PairState::Ready { next, .. } => replace(next, value), - } - } - - unsafe fn replace_prev(&mut self, value: usize) -> usize { - match self { - PairState::Exhausted => unreachable_unchecked(), - PairState::Ready { prev, .. } => replace(prev, value), - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum Side { - Left, - Right, -} -use Side::*; - -#[derive(Debug)] -struct PairEntry { - state: PairState, - chunk: usize, - offset: u64, - parent: Option, -} - -struct SizeBlockEntry { - chunk: usize, - offset: u64, - index: usize, -} - -#[derive(Debug)] -struct Size { - next_ready: usize, - pairs: Slab, -} -#[derive(Debug)] -enum Release { - None, - Parent(usize), - Chunk(usize), -} - -impl Size { - fn new() -> Self { - Size { - pairs: Slab::new(), - next_ready: 0, - } - } - - unsafe fn add_pair_and_acquire_left( - &mut self, - chunk: usize, - offset: u64, - parent: Option, - ) -> SizeBlockEntry { - if self.next_ready < self.pairs.len() { - unreachable_unchecked() - } - - let index = self.pairs.insert(PairEntry { - state: PairState::Exhausted, - chunk, - offset, - parent, - }); - - let entry = self.pairs.get_unchecked_mut(index); - entry.state = PairState::Ready { - next: index, - prev: index, - ready: Right, // Left is allocated. - }; - self.next_ready = index; - - SizeBlockEntry { - chunk, - offset, - index: index << 1, - } - } - - fn acquire(&mut self, size: u64) -> Option { - if self.next_ready >= self.pairs.len() { - return None; - } - - let ready = self.next_ready; - - let entry = unsafe { self.pairs.get_unchecked_mut(ready) }; - let chunk = entry.chunk; - let offset = entry.offset; - - let bit = match entry.state { - PairState::Exhausted => unsafe { unreachable_unchecked() }, - PairState::Ready { ready, next, prev } => { - entry.state = PairState::Exhausted; - - if prev == self.next_ready { - // The only ready entry. - debug_assert_eq!(next, self.next_ready); - self.next_ready = self.pairs.len(); - } else { - let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) }; - let prev_next = unsafe { prev_entry.state.replace_next(next) }; - debug_assert_eq!(prev_next, self.next_ready); - - let next_entry = unsafe { self.pairs.get_unchecked_mut(next) }; - let next_prev = unsafe { next_entry.state.replace_prev(prev) }; - debug_assert_eq!(next_prev, self.next_ready); - - self.next_ready = next; - } - - match ready { - Left => 0, - Right => 1, - } - } - }; - - Some(SizeBlockEntry { - chunk, - offset: offset + bit as u64 * size, - index: (ready << 1) | bit as usize, - }) - } - - fn release(&mut self, index: usize) -> Release { - let side = match index & 1 { - 0 => Side::Left, - 1 => Side::Right, - _ => unsafe { unreachable_unchecked() }, - }; - let entry_index = index >> 1; - - let len = self.pairs.len(); - - let entry = self.pairs.get_mut(entry_index); - - let chunk = entry.chunk; - let offset = entry.offset; - let parent = entry.parent; - - match entry.state { - PairState::Exhausted => { - if self.next_ready == len { - entry.state = PairState::Ready { - ready: side, - next: entry_index, - prev: entry_index, - }; - self.next_ready = entry_index; - } else { - debug_assert!(self.next_ready < len); - - let next = self.next_ready; - let next_entry = unsafe { self.pairs.get_unchecked_mut(next) }; - let prev = unsafe { next_entry.state.replace_prev(entry_index) }; - - let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) }; - let prev_next = unsafe { prev_entry.state.replace_next(entry_index) }; - debug_assert_eq!(prev_next, next); - - let entry = unsafe { self.pairs.get_unchecked_mut(entry_index) }; - entry.state = PairState::Ready { - ready: side, - next, - prev, - }; - } - Release::None - } - - PairState::Ready { ready, .. } if ready == side => { - panic!("Attempt to dealloate already free block") - } - - PairState::Ready { next, prev, .. } => { - unsafe { - self.pairs.remove_unchecked(entry_index); - } - - if prev == entry_index { - debug_assert_eq!(next, entry_index); - self.next_ready = self.pairs.len(); - } else { - let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) }; - let prev_next = unsafe { prev_entry.state.replace_next(next) }; - debug_assert_eq!(prev_next, entry_index); - - let next_entry = unsafe { self.pairs.get_unchecked_mut(next) }; - let next_prev = unsafe { next_entry.state.replace_prev(prev) }; - debug_assert_eq!(next_prev, entry_index); - - self.next_ready = next; - } - - match parent { - Some(parent) => Release::Parent(parent), - None => { - debug_assert_eq!(offset, 0); - Release::Chunk(chunk) - } - } - } - } - } -} - -#[derive(Debug)] -struct Chunk { - memory: Arc, - ptr: Option>, - size: u64, -} - -#[derive(Debug)] -pub(crate) struct BuddyAllocator { - minimal_size: u64, - chunks: Slab>, - sizes: Vec, - memory_type: u32, - props: MemoryPropertyFlags, - atom_mask: u64, -} - -unsafe impl Sync for BuddyAllocator where M: Sync {} -unsafe impl Send for BuddyAllocator where M: Send {} - -impl BuddyAllocator -where - M: MemoryBounds + 'static, -{ - pub fn new( - minimal_size: u64, - initial_dedicated_size: u64, - memory_type: u32, - props: MemoryPropertyFlags, - atom_mask: u64, - ) -> Self { - assert!( - minimal_size.is_power_of_two(), - "Minimal allocation size of buddy allocator must be power of two" - ); - assert!( - initial_dedicated_size.is_power_of_two(), - "Dedicated allocation size of buddy allocator must be power of two" - ); - - let initial_sizes = (initial_dedicated_size - .trailing_zeros() - .saturating_sub(minimal_size.trailing_zeros())) as usize; - - BuddyAllocator { - minimal_size, - chunks: Slab::new(), - sizes: (0..initial_sizes).map(|_| Size::new()).collect(), - memory_type, - props, - atom_mask: atom_mask | (minimal_size - 1), - } - } - - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn alloc( - &mut self, - device: &impl MemoryDevice, - size: u64, - align_mask: u64, - flags: AllocationFlags, - heap: &mut Heap, - allocations_remains: &mut u32, - ) -> Result, AllocationError> { - let align_mask = align_mask | self.atom_mask; - - let size = align_up(size, align_mask) - .and_then(|size| size.checked_next_power_of_two()) - .ok_or(AllocationError::OutOfDeviceMemory)?; - - let size_index = size.trailing_zeros() - self.minimal_size.trailing_zeros(); - let size_index = - usize::try_from(size_index).map_err(|_| AllocationError::OutOfDeviceMemory)?; - - while self.sizes.len() <= size_index { - self.sizes.push(Size::new()); - } - - let host_visible = self.host_visible(); - - let mut candidate_size_index = size_index; - - let (mut entry, entry_size_index) = loop { - let sizes_len = self.sizes.len(); - - let candidate_size_entry = &mut self.sizes[candidate_size_index]; - let candidate_size = self.minimal_size << candidate_size_index; - - if let Some(entry) = candidate_size_entry.acquire(candidate_size) { - break (entry, candidate_size_index); - } - - if sizes_len == candidate_size_index + 1 { - // That's size of device allocation. - if *allocations_remains == 0 { - return Err(AllocationError::TooManyObjects); - } - - let chunk_size = self.minimal_size << (candidate_size_index + 1); - let mut memory = device.allocate_memory(chunk_size, self.memory_type, flags)?; - *allocations_remains -= 1; - heap.alloc(chunk_size); - - let ptr = if host_visible { - match device.map_memory(&mut memory, 0, chunk_size) { - Ok(ptr) => Some(ptr), - Err(DeviceMapError::OutOfDeviceMemory) => { - return Err(AllocationError::OutOfDeviceMemory) - } - Err(DeviceMapError::MapFailed) | Err(DeviceMapError::OutOfHostMemory) => { - return Err(AllocationError::OutOfHostMemory) - } - } - } else { - None - }; - - let chunk = self.chunks.insert(Chunk { - memory: Arc::new(memory), - ptr, - size: chunk_size, - }); - - let entry = candidate_size_entry.add_pair_and_acquire_left(chunk, 0, None); - - break (entry, candidate_size_index); - } - - candidate_size_index += 1; - }; - - for size_index in (size_index..entry_size_index).rev() { - let size_entry = &mut self.sizes[size_index]; - entry = - size_entry.add_pair_and_acquire_left(entry.chunk, entry.offset, Some(entry.index)); - } - - let chunk_entry = self.chunks.get_unchecked(entry.chunk); - - debug_assert!( - entry - .offset - .checked_add(size) - .map_or(false, |end| end <= chunk_entry.size), - "Offset + size is not in chunk bounds" - ); - - Ok(BuddyBlock { - memory: chunk_entry.memory.clone(), - ptr: chunk_entry - .ptr - .map(|ptr| NonNull::new_unchecked(ptr.as_ptr().add(entry.offset as usize))), - offset: entry.offset, - size, - chunk: entry.chunk, - index: entry.index, - }) - } - - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn dealloc( - &mut self, - device: &impl MemoryDevice, - block: BuddyBlock, - heap: &mut Heap, - allocations_remains: &mut u32, - ) { - debug_assert!(block.size.is_power_of_two()); - - let size_index = - (block.size.trailing_zeros() - self.minimal_size.trailing_zeros()) as usize; - - let mut release_index = block.index; - let mut release_size_index = size_index; - - loop { - match self.sizes[release_size_index].release(release_index) { - Release::Parent(parent) => { - release_size_index += 1; - release_index = parent; - } - Release::Chunk(chunk) => { - debug_assert_eq!(chunk, block.chunk); - debug_assert_eq!( - self.chunks.get(chunk).size, - self.minimal_size << (release_size_index + 1) - ); - let chunk = self.chunks.remove(chunk); - drop(block); - - let memory = try_arc_unwrap(chunk.memory) - .expect("Memory shared after last block deallocated"); - - device.deallocate_memory(memory); - *allocations_remains += 1; - heap.dealloc(chunk.size); - - return; - } - Release::None => return, - } - } - } - - fn host_visible(&self) -> bool { - self.props.contains(MemoryPropertyFlags::HOST_VISIBLE) - } -} +use { + crate::{ + align_up, error::AllocationError, heap::Heap, slab::Slab, unreachable_unchecked, + util::try_arc_unwrap, MemoryBounds, + }, + alloc::{sync::Arc, vec::Vec}, + core::{convert::TryFrom as _, mem::replace, ptr::NonNull}, + gpu_alloc_types::{AllocationFlags, DeviceMapError, MemoryDevice, MemoryPropertyFlags}, +}; + +#[derive(Debug)] +pub(crate) struct BuddyBlock { + pub memory: Arc, + pub ptr: Option>, + pub offset: u64, + pub size: u64, + pub chunk: usize, + pub index: usize, +} + +unsafe impl Sync for BuddyBlock where M: Sync {} +unsafe impl Send for BuddyBlock where M: Send {} + +#[derive(Clone, Copy, Debug)] +enum PairState { + Exhausted, + Ready { + ready: Side, + next: usize, + prev: usize, + }, +} + +impl PairState { + unsafe fn replace_next(&mut self, value: usize) -> usize { + match self { + PairState::Exhausted => unreachable_unchecked(), + PairState::Ready { next, .. } => replace(next, value), + } + } + + unsafe fn replace_prev(&mut self, value: usize) -> usize { + match self { + PairState::Exhausted => unreachable_unchecked(), + PairState::Ready { prev, .. } => replace(prev, value), + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum Side { + Left, + Right, +} +use Side::*; + +#[derive(Debug)] +struct PairEntry { + state: PairState, + chunk: usize, + offset: u64, + parent: Option, +} + +struct SizeBlockEntry { + chunk: usize, + offset: u64, + index: usize, +} + +#[derive(Debug)] +struct Size { + next_ready: usize, + pairs: Slab, +} +#[derive(Debug)] +enum Release { + None, + Parent(usize), + Chunk(usize), +} + +impl Size { + fn new() -> Self { + Size { + pairs: Slab::new(), + next_ready: 0, + } + } + + unsafe fn add_pair_and_acquire_left( + &mut self, + chunk: usize, + offset: u64, + parent: Option, + ) -> SizeBlockEntry { + if self.next_ready < self.pairs.len() { + unreachable_unchecked() + } + + let index = self.pairs.insert(PairEntry { + state: PairState::Exhausted, + chunk, + offset, + parent, + }); + + let entry = self.pairs.get_unchecked_mut(index); + entry.state = PairState::Ready { + next: index, + prev: index, + ready: Right, // Left is allocated. + }; + self.next_ready = index; + + SizeBlockEntry { + chunk, + offset, + index: index << 1, + } + } + + fn acquire(&mut self, size: u64) -> Option { + if self.next_ready >= self.pairs.len() { + return None; + } + + let ready = self.next_ready; + + let entry = unsafe { self.pairs.get_unchecked_mut(ready) }; + let chunk = entry.chunk; + let offset = entry.offset; + + let bit = match entry.state { + PairState::Exhausted => unsafe { unreachable_unchecked() }, + PairState::Ready { ready, next, prev } => { + entry.state = PairState::Exhausted; + + if prev == self.next_ready { + // The only ready entry. + debug_assert_eq!(next, self.next_ready); + self.next_ready = self.pairs.len(); + } else { + let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) }; + let prev_next = unsafe { prev_entry.state.replace_next(next) }; + debug_assert_eq!(prev_next, self.next_ready); + + let next_entry = unsafe { self.pairs.get_unchecked_mut(next) }; + let next_prev = unsafe { next_entry.state.replace_prev(prev) }; + debug_assert_eq!(next_prev, self.next_ready); + + self.next_ready = next; + } + + match ready { + Left => 0, + Right => 1, + } + } + }; + + Some(SizeBlockEntry { + chunk, + offset: offset + bit as u64 * size, + index: (ready << 1) | bit as usize, + }) + } + + fn release(&mut self, index: usize) -> Release { + let side = match index & 1 { + 0 => Side::Left, + 1 => Side::Right, + _ => unsafe { unreachable_unchecked() }, + }; + let entry_index = index >> 1; + + let len = self.pairs.len(); + + let entry = self.pairs.get_mut(entry_index); + + let chunk = entry.chunk; + let offset = entry.offset; + let parent = entry.parent; + + match entry.state { + PairState::Exhausted => { + if self.next_ready == len { + entry.state = PairState::Ready { + ready: side, + next: entry_index, + prev: entry_index, + }; + self.next_ready = entry_index; + } else { + debug_assert!(self.next_ready < len); + + let next = self.next_ready; + let next_entry = unsafe { self.pairs.get_unchecked_mut(next) }; + let prev = unsafe { next_entry.state.replace_prev(entry_index) }; + + let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) }; + let prev_next = unsafe { prev_entry.state.replace_next(entry_index) }; + debug_assert_eq!(prev_next, next); + + let entry = unsafe { self.pairs.get_unchecked_mut(entry_index) }; + entry.state = PairState::Ready { + ready: side, + next, + prev, + }; + } + Release::None + } + + PairState::Ready { ready, .. } if ready == side => { + panic!("Attempt to dealloate already free block") + } + + PairState::Ready { next, prev, .. } => { + unsafe { + self.pairs.remove_unchecked(entry_index); + } + + if prev == entry_index { + debug_assert_eq!(next, entry_index); + self.next_ready = self.pairs.len(); + } else { + let prev_entry = unsafe { self.pairs.get_unchecked_mut(prev) }; + let prev_next = unsafe { prev_entry.state.replace_next(next) }; + debug_assert_eq!(prev_next, entry_index); + + let next_entry = unsafe { self.pairs.get_unchecked_mut(next) }; + let next_prev = unsafe { next_entry.state.replace_prev(prev) }; + debug_assert_eq!(next_prev, entry_index); + + self.next_ready = next; + } + + match parent { + Some(parent) => Release::Parent(parent), + None => { + debug_assert_eq!(offset, 0); + Release::Chunk(chunk) + } + } + } + } + } +} + +#[derive(Debug)] +struct Chunk { + memory: Arc, + ptr: Option>, + size: u64, +} + +#[derive(Debug)] +pub(crate) struct BuddyAllocator { + minimal_size: u64, + chunks: Slab>, + sizes: Vec, + memory_type: u32, + props: MemoryPropertyFlags, + atom_mask: u64, +} + +unsafe impl Sync for BuddyAllocator where M: Sync {} +unsafe impl Send for BuddyAllocator where M: Send {} + +impl BuddyAllocator +where + M: MemoryBounds + 'static, +{ + pub fn new( + minimal_size: u64, + initial_dedicated_size: u64, + memory_type: u32, + props: MemoryPropertyFlags, + atom_mask: u64, + ) -> Self { + assert!( + minimal_size.is_power_of_two(), + "Minimal allocation size of buddy allocator must be power of two" + ); + assert!( + initial_dedicated_size.is_power_of_two(), + "Dedicated allocation size of buddy allocator must be power of two" + ); + + let initial_sizes = (initial_dedicated_size + .trailing_zeros() + .saturating_sub(minimal_size.trailing_zeros())) as usize; + + BuddyAllocator { + minimal_size, + chunks: Slab::new(), + sizes: (0..initial_sizes).map(|_| Size::new()).collect(), + memory_type, + props, + atom_mask: atom_mask | (minimal_size - 1), + } + } + + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn alloc( + &mut self, + device: &impl MemoryDevice, + size: u64, + align_mask: u64, + flags: AllocationFlags, + heap: &mut Heap, + allocations_remains: &mut u32, + ) -> Result, AllocationError> { + let align_mask = align_mask | self.atom_mask; + + let size = align_up(size, align_mask) + .and_then(|size| size.checked_next_power_of_two()) + .ok_or(AllocationError::OutOfDeviceMemory)?; + + let size = size.max(self.minimal_size); + + let size_index = size.trailing_zeros() - self.minimal_size.trailing_zeros(); + let size_index = + usize::try_from(size_index).map_err(|_| AllocationError::OutOfDeviceMemory)?; + + while self.sizes.len() <= size_index { + self.sizes.push(Size::new()); + } + + let host_visible = self.host_visible(); + + let mut candidate_size_index = size_index; + + let (mut entry, entry_size_index) = loop { + let sizes_len = self.sizes.len(); + + let candidate_size_entry = &mut self.sizes[candidate_size_index]; + let candidate_size = self.minimal_size << candidate_size_index; + + if let Some(entry) = candidate_size_entry.acquire(candidate_size) { + break (entry, candidate_size_index); + } + + if sizes_len == candidate_size_index + 1 { + // That's size of device allocation. + if *allocations_remains == 0 { + return Err(AllocationError::TooManyObjects); + } + + let chunk_size = self.minimal_size << (candidate_size_index + 1); + let mut memory = device.allocate_memory(chunk_size, self.memory_type, flags)?; + *allocations_remains -= 1; + heap.alloc(chunk_size); + + let ptr = if host_visible { + match device.map_memory(&mut memory, 0, chunk_size) { + Ok(ptr) => Some(ptr), + Err(DeviceMapError::OutOfDeviceMemory) => { + return Err(AllocationError::OutOfDeviceMemory) + } + Err(DeviceMapError::MapFailed) | Err(DeviceMapError::OutOfHostMemory) => { + return Err(AllocationError::OutOfHostMemory) + } + } + } else { + None + }; + + let chunk = self.chunks.insert(Chunk { + memory: Arc::new(memory), + ptr, + size: chunk_size, + }); + + let entry = candidate_size_entry.add_pair_and_acquire_left(chunk, 0, None); + + break (entry, candidate_size_index); + } + + candidate_size_index += 1; + }; + + for size_index in (size_index..entry_size_index).rev() { + let size_entry = &mut self.sizes[size_index]; + entry = + size_entry.add_pair_and_acquire_left(entry.chunk, entry.offset, Some(entry.index)); + } + + let chunk_entry = self.chunks.get_unchecked(entry.chunk); + + debug_assert!( + entry + .offset + .checked_add(size) + .map_or(false, |end| end <= chunk_entry.size), + "Offset + size is not in chunk bounds" + ); + + Ok(BuddyBlock { + memory: chunk_entry.memory.clone(), + ptr: chunk_entry + .ptr + .map(|ptr| NonNull::new_unchecked(ptr.as_ptr().add(entry.offset as usize))), + offset: entry.offset, + size, + chunk: entry.chunk, + index: entry.index, + }) + } + + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn dealloc( + &mut self, + device: &impl MemoryDevice, + block: BuddyBlock, + heap: &mut Heap, + allocations_remains: &mut u32, + ) { + debug_assert!(block.size.is_power_of_two()); + + let size_index = + (block.size.trailing_zeros() - self.minimal_size.trailing_zeros()) as usize; + + let mut release_index = block.index; + let mut release_size_index = size_index; + + loop { + match self.sizes[release_size_index].release(release_index) { + Release::Parent(parent) => { + release_size_index += 1; + release_index = parent; + } + Release::Chunk(chunk) => { + debug_assert_eq!(chunk, block.chunk); + debug_assert_eq!( + self.chunks.get(chunk).size, + self.minimal_size << (release_size_index + 1) + ); + let chunk = self.chunks.remove(chunk); + drop(block); + + let memory = try_arc_unwrap(chunk.memory) + .expect("Memory shared after last block deallocated"); + + device.deallocate_memory(memory); + *allocations_remains += 1; + heap.dealloc(chunk.size); + + return; + } + Release::None => return, + } + } + } + + fn host_visible(&self) -> bool { + self.props.contains(MemoryPropertyFlags::HOST_VISIBLE) + } +} diff --git a/third_party/rust/gpu-alloc/src/config.rs b/third_party/rust/gpu-alloc/src/config.rs index 0d9da8070ab9..20d53a3d758e 100644 --- a/third_party/rust/gpu-alloc/src/config.rs +++ b/third_party/rust/gpu-alloc/src/config.rs @@ -1,77 +1,77 @@ -/// Configuration for [`GpuAllocator`] -/// -/// [`GpuAllocator`]: type.GpuAllocator -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Config { - /// Size in bytes of request that will be served by dedicated memory object. - /// This value should be large enough to not exhaust memory object limit - /// and not use slow memory object allocation when it is not necessary. - pub dedicated_threshold: u64, - - /// Size in bytes of request that will be served by dedicated memory object if preferred. - /// This value should be large enough to not exhaust memory object limit - /// and not use slow memory object allocation when it is not necessary. - /// - /// This won't make much sense if this value is larger than `dedicated_threshold`. - pub preferred_dedicated_threshold: u64, - - /// Size in bytes of transient memory request that will be served by dedicated memory object. - /// This value should be large enough to not exhaust memory object limit - /// and not use slow memory object allocation when it is not necessary. - /// - /// This won't make much sense if this value is lesser than `dedicated_threshold`. - pub transient_dedicated_threshold: u64, - - /// Size in bytes of first chunk in free-list allocator. - pub starting_free_list_chunk: u64, - - /// Upper limit for size in bytes of chunks in free-list allocator. - pub final_free_list_chunk: u64, - - /// Minimal size for buddy allocator. - pub minimal_buddy_size: u64, - - /// Initial memory object size for buddy allocator. - /// If less than `minimal_buddy_size` then `minimal_buddy_size` is used instead. - pub initial_buddy_dedicated_size: u64, -} - -impl Config { - /// Returns default configuration. - /// - /// This is not `Default` implementation to discourage usage outside of - /// prototyping. - /// - /// Proper configuration should depend on hardware and intended usage.\ - /// But those values can be used as starting point.\ - /// Note that they can simply not work for some platforms with lesser - /// memory capacity than today's "modern" GPU (year 2020). - pub fn i_am_prototyping() -> Self { - // Assume that today's modern GPU is made of 1024 potatoes. - let potato = Config::i_am_potato(); - - Config { - dedicated_threshold: potato.dedicated_threshold * 1024, - preferred_dedicated_threshold: potato.preferred_dedicated_threshold * 1024, - transient_dedicated_threshold: potato.transient_dedicated_threshold * 1024, - starting_free_list_chunk: potato.starting_free_list_chunk * 1024, - final_free_list_chunk: potato.final_free_list_chunk * 1024, - minimal_buddy_size: potato.minimal_buddy_size * 1024, - initial_buddy_dedicated_size: potato.initial_buddy_dedicated_size * 1024, - } - } - - /// Returns default configuration for average sized potato. - pub fn i_am_potato() -> Self { - Config { - dedicated_threshold: 32 * 1024, - preferred_dedicated_threshold: 1024, - transient_dedicated_threshold: 128 * 1024, - starting_free_list_chunk: 8 * 1024, - final_free_list_chunk: 128 * 1024, - minimal_buddy_size: 1, - initial_buddy_dedicated_size: 8 * 1024, - } - } -} +/// Configuration for [`GpuAllocator`] +/// +/// [`GpuAllocator`]: type.GpuAllocator +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Config { + /// Size in bytes of request that will be served by dedicated memory object. + /// This value should be large enough to not exhaust memory object limit + /// and not use slow memory object allocation when it is not necessary. + pub dedicated_threshold: u64, + + /// Size in bytes of request that will be served by dedicated memory object if preferred. + /// This value should be large enough to not exhaust memory object limit + /// and not use slow memory object allocation when it is not necessary. + /// + /// This won't make much sense if this value is larger than `dedicated_threshold`. + pub preferred_dedicated_threshold: u64, + + /// Size in bytes of transient memory request that will be served by dedicated memory object. + /// This value should be large enough to not exhaust memory object limit + /// and not use slow memory object allocation when it is not necessary. + /// + /// This won't make much sense if this value is lesser than `dedicated_threshold`. + pub transient_dedicated_threshold: u64, + + /// Size in bytes of first chunk in free-list allocator. + pub starting_free_list_chunk: u64, + + /// Upper limit for size in bytes of chunks in free-list allocator. + pub final_free_list_chunk: u64, + + /// Minimal size for buddy allocator. + pub minimal_buddy_size: u64, + + /// Initial memory object size for buddy allocator. + /// If less than `minimal_buddy_size` then `minimal_buddy_size` is used instead. + pub initial_buddy_dedicated_size: u64, +} + +impl Config { + /// Returns default configuration. + /// + /// This is not `Default` implementation to discourage usage outside of + /// prototyping. + /// + /// Proper configuration should depend on hardware and intended usage.\ + /// But those values can be used as starting point.\ + /// Note that they can simply not work for some platforms with lesser + /// memory capacity than today's "modern" GPU (year 2020). + pub fn i_am_prototyping() -> Self { + // Assume that today's modern GPU is made of 1024 potatoes. + let potato = Config::i_am_potato(); + + Config { + dedicated_threshold: potato.dedicated_threshold * 1024, + preferred_dedicated_threshold: potato.preferred_dedicated_threshold * 1024, + transient_dedicated_threshold: potato.transient_dedicated_threshold * 1024, + starting_free_list_chunk: potato.starting_free_list_chunk * 1024, + final_free_list_chunk: potato.final_free_list_chunk * 1024, + minimal_buddy_size: potato.minimal_buddy_size * 1024, + initial_buddy_dedicated_size: potato.initial_buddy_dedicated_size * 1024, + } + } + + /// Returns default configuration for average sized potato. + pub fn i_am_potato() -> Self { + Config { + dedicated_threshold: 32 * 1024, + preferred_dedicated_threshold: 1024, + transient_dedicated_threshold: 128 * 1024, + starting_free_list_chunk: 8 * 1024, + final_free_list_chunk: 128 * 1024, + minimal_buddy_size: 1, + initial_buddy_dedicated_size: 8 * 1024, + } + } +} diff --git a/third_party/rust/gpu-alloc/src/error.rs b/third_party/rust/gpu-alloc/src/error.rs index 95cde9bcaa77..98c396b1fea7 100644 --- a/third_party/rust/gpu-alloc/src/error.rs +++ b/third_party/rust/gpu-alloc/src/error.rs @@ -1,116 +1,116 @@ -use { - core::fmt::{self, Display}, - gpu_alloc_types::{DeviceMapError, OutOfMemory}, -}; - -/// Enumeration of possible errors that may occur during memory allocation. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum AllocationError { - /// Backend reported that device memory has been exhausted.\ - /// Deallocating device memory from the same heap may increase chance - /// that another allocation would succeed. - OutOfDeviceMemory, - - /// Backend reported that host memory has been exhausted.\ - /// Deallocating host memory may increase chance that another allocation would succeed. - OutOfHostMemory, - - /// Allocation request cannot be fulfilled as no available memory types allowed - /// by `Request.memory_types` mask is compatible with `request.usage`. - NoCompatibleMemoryTypes, - - /// Reached limit on allocated memory objects count.\ - /// Deallocating device memory may increase chance that another allocation would succeed. - /// Especially dedicated memory blocks. - /// - /// If this error is returned when memory heaps are far from exhausted - /// `Config` should be tweaked to allocate larger memory objects. - TooManyObjects, -} - -impl From for AllocationError { - fn from(err: OutOfMemory) -> Self { - match err { - OutOfMemory::OutOfDeviceMemory => AllocationError::OutOfDeviceMemory, - OutOfMemory::OutOfHostMemory => AllocationError::OutOfHostMemory, - } - } -} - -impl Display for AllocationError { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - AllocationError::OutOfDeviceMemory => fmt.write_str("Device memory exhausted"), - AllocationError::OutOfHostMemory => fmt.write_str("Host memory exhausted"), - AllocationError::NoCompatibleMemoryTypes => fmt.write_str( - "No compatible memory types from requested types support requested usage", - ), - AllocationError::TooManyObjects => { - fmt.write_str("Reached limit on allocated memory objects count") - } - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for AllocationError {} - -/// Enumeration of possible errors that may occur during memory mapping. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum MapError { - /// Backend reported that device memory has been exhausted.\ - /// Deallocating device memory from the same heap may increase chance - /// that another mapping would succeed. - OutOfDeviceMemory, - - /// Backend reported that host memory has been exhausted.\ - /// Deallocating host memory may increase chance that another mapping would succeed. - OutOfHostMemory, - - /// Attempt to map memory block with non-host-visible memory type.\ - /// Ensure to include `UsageFlags::HOST_ACCESS` into allocation request - /// when memory mapping is intended. - NonHostVisible, - - /// Map failed for implementation specific reason.\ - /// For Vulkan backend this includes failed attempt - /// to allocate large enough virtual address space. - MapFailed, - - /// Mapping failed due to block being already mapped. - AlreadyMapped, -} - -impl From for MapError { - fn from(err: DeviceMapError) -> Self { - match err { - DeviceMapError::OutOfDeviceMemory => MapError::OutOfDeviceMemory, - DeviceMapError::OutOfHostMemory => MapError::OutOfHostMemory, - DeviceMapError::MapFailed => MapError::MapFailed, - } - } -} - -impl From for MapError { - fn from(err: OutOfMemory) -> Self { - match err { - OutOfMemory::OutOfDeviceMemory => MapError::OutOfDeviceMemory, - OutOfMemory::OutOfHostMemory => MapError::OutOfHostMemory, - } - } -} - -impl Display for MapError { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - MapError::OutOfDeviceMemory => fmt.write_str("Device memory exhausted"), - MapError::OutOfHostMemory => fmt.write_str("Host memory exhausted"), - MapError::MapFailed => fmt.write_str("Failed to map memory object"), - MapError::NonHostVisible => fmt.write_str("Impossible to map non-host-visible memory"), - MapError::AlreadyMapped => fmt.write_str("Block is already mapped"), - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for MapError {} +use { + core::fmt::{self, Display}, + gpu_alloc_types::{DeviceMapError, OutOfMemory}, +}; + +/// Enumeration of possible errors that may occur during memory allocation. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum AllocationError { + /// Backend reported that device memory has been exhausted.\ + /// Deallocating device memory from the same heap may increase chance + /// that another allocation would succeed. + OutOfDeviceMemory, + + /// Backend reported that host memory has been exhausted.\ + /// Deallocating host memory may increase chance that another allocation would succeed. + OutOfHostMemory, + + /// Allocation request cannot be fulfilled as no available memory types allowed + /// by `Request.memory_types` mask is compatible with `request.usage`. + NoCompatibleMemoryTypes, + + /// Reached limit on allocated memory objects count.\ + /// Deallocating device memory may increase chance that another allocation would succeed. + /// Especially dedicated memory blocks. + /// + /// If this error is returned when memory heaps are far from exhausted + /// `Config` should be tweaked to allocate larger memory objects. + TooManyObjects, +} + +impl From for AllocationError { + fn from(err: OutOfMemory) -> Self { + match err { + OutOfMemory::OutOfDeviceMemory => AllocationError::OutOfDeviceMemory, + OutOfMemory::OutOfHostMemory => AllocationError::OutOfHostMemory, + } + } +} + +impl Display for AllocationError { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AllocationError::OutOfDeviceMemory => fmt.write_str("Device memory exhausted"), + AllocationError::OutOfHostMemory => fmt.write_str("Host memory exhausted"), + AllocationError::NoCompatibleMemoryTypes => fmt.write_str( + "No compatible memory types from requested types support requested usage", + ), + AllocationError::TooManyObjects => { + fmt.write_str("Reached limit on allocated memory objects count") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for AllocationError {} + +/// Enumeration of possible errors that may occur during memory mapping. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum MapError { + /// Backend reported that device memory has been exhausted.\ + /// Deallocating device memory from the same heap may increase chance + /// that another mapping would succeed. + OutOfDeviceMemory, + + /// Backend reported that host memory has been exhausted.\ + /// Deallocating host memory may increase chance that another mapping would succeed. + OutOfHostMemory, + + /// Attempt to map memory block with non-host-visible memory type.\ + /// Ensure to include `UsageFlags::HOST_ACCESS` into allocation request + /// when memory mapping is intended. + NonHostVisible, + + /// Map failed for implementation specific reason.\ + /// For Vulkan backend this includes failed attempt + /// to allocate large enough virtual address space. + MapFailed, + + /// Mapping failed due to block being already mapped. + AlreadyMapped, +} + +impl From for MapError { + fn from(err: DeviceMapError) -> Self { + match err { + DeviceMapError::OutOfDeviceMemory => MapError::OutOfDeviceMemory, + DeviceMapError::OutOfHostMemory => MapError::OutOfHostMemory, + DeviceMapError::MapFailed => MapError::MapFailed, + } + } +} + +impl From for MapError { + fn from(err: OutOfMemory) -> Self { + match err { + OutOfMemory::OutOfDeviceMemory => MapError::OutOfDeviceMemory, + OutOfMemory::OutOfHostMemory => MapError::OutOfHostMemory, + } + } +} + +impl Display for MapError { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MapError::OutOfDeviceMemory => fmt.write_str("Device memory exhausted"), + MapError::OutOfHostMemory => fmt.write_str("Host memory exhausted"), + MapError::MapFailed => fmt.write_str("Failed to map memory object"), + MapError::NonHostVisible => fmt.write_str("Impossible to map non-host-visible memory"), + MapError::AlreadyMapped => fmt.write_str("Block is already mapped"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for MapError {} diff --git a/third_party/rust/gpu-alloc/src/freelist.rs b/third_party/rust/gpu-alloc/src/freelist.rs index 448a961d4fac..a6ece27be382 100644 --- a/third_party/rust/gpu-alloc/src/freelist.rs +++ b/third_party/rust/gpu-alloc/src/freelist.rs @@ -1,528 +1,528 @@ -use { - crate::{ - align_down, align_up, - error::AllocationError, - heap::Heap, - util::{arc_unwrap, is_arc_unique}, - MemoryBounds, - }, - alloc::{sync::Arc, vec::Vec}, - core::{cmp::Ordering, ptr::NonNull}, - gpu_alloc_types::{AllocationFlags, DeviceMapError, MemoryDevice, MemoryPropertyFlags}, -}; - -unsafe fn opt_ptr_add(ptr: Option>, size: u64) -> Option> { - ptr.map(|ptr| { - // Size is within memory region started at `ptr`. - // size is within `chunk_size` that fits `isize`. - NonNull::new_unchecked(ptr.as_ptr().offset(size as isize)) - }) -} - -#[derive(Debug)] -pub(super) struct FreeList { - array: Vec>, - counter: u64, -} - -impl FreeList { - pub fn new() -> Self { - FreeList { - array: Vec::new(), - counter: 0, - } - } - - pub fn get_block_from_new_memory( - &mut self, - memory: Arc, - memory_size: u64, - ptr: Option>, - align_mask: u64, - size: u64, - ) -> FreeListBlock { - debug_assert!(size <= memory_size); - - self.counter += 1; - self.array.push(FreeListRegion { - memory, - ptr, - chunk: self.counter, - start: 0, - end: memory_size, - }); - self.get_block_at(self.array.len() - 1, align_mask, size) - } - - pub fn get_block(&mut self, align_mask: u64, size: u64) -> Option> { - let (index, _) = self.array.iter().enumerate().rev().find(|(_, region)| { - match region.end.checked_sub(size) { - Some(start) => { - let aligned_start = align_down(start, align_mask); - aligned_start >= region.start - } - None => false, - } - })?; - - Some(self.get_block_at(index, align_mask, size)) - } - - fn get_block_at(&mut self, index: usize, align_mask: u64, size: u64) -> FreeListBlock { - let region = &mut self.array[index]; - - let start = region.end - size; - let aligned_start = align_down(start, align_mask); - - if aligned_start > region.start { - let block = FreeListBlock { - offset: aligned_start, - size: region.end - aligned_start, - chunk: region.chunk, - ptr: unsafe { opt_ptr_add(region.ptr, aligned_start - region.start) }, - memory: region.memory.clone(), - }; - - region.end = aligned_start; - - block - } else { - debug_assert_eq!(aligned_start, region.start); - let region = self.array.remove(index); - region.into_block() - } - } - - pub fn insert_block(&mut self, block: FreeListBlock) { - match self.array.binary_search_by(|b| b.cmp(&block)) { - Ok(_) => { - panic!("Overlapping block found in free list"); - } - Err(index) if self.array.len() > index => match &mut self.array[..=index] { - [] => unreachable!(), - [next] => { - debug_assert!(!next.is_suffix_block(&block)); - - if next.is_prefix_block(&block) { - next.merge_prefix_block(block); - } else { - self.array.insert(0, FreeListRegion::from_block(block)); - } - } - [.., prev, next] => { - debug_assert!(!prev.is_prefix_block(&block)); - debug_assert!(!next.is_suffix_block(&block)); - - if next.is_prefix_block(&block) { - next.merge_prefix_block(block); - - if prev.consecutive(&*next) { - let next = self.array.remove(index); - let prev = &mut self.array[index - 1]; - prev.merge(next); - } - } else if prev.is_suffix_block(&block) { - prev.merge_suffix_block(block); - } else { - self.array.insert(index, FreeListRegion::from_block(block)); - } - } - }, - Err(_) => match &mut self.array[..] { - [] => self.array.push(FreeListRegion::from_block(block)), - [.., prev] => { - debug_assert!(!prev.is_prefix_block(&block)); - if prev.is_suffix_block(&block) { - prev.merge_suffix_block(block); - } else { - self.array.push(FreeListRegion::from_block(block)); - } - } - }, - } - } - - pub fn drain(&mut self, keep_last: bool) -> Option + '_> { - // Time to deallocate - - let len = self.array.len(); - - let mut del = 0; - { - let regions = &mut self.array[..]; - - for i in 0..len { - if (i < len - 1 || !keep_last) && is_arc_unique(&mut regions[i].memory) { - del += 1; - } else if del > 0 { - regions.swap(i - del, i); - } - } - } - - if del > 0 { - Some(self.array.drain(len - del..).map(move |region| { - debug_assert_eq!(region.start, 0); - (unsafe { arc_unwrap(region.memory) }, region.end) - })) - } else { - None - } - } -} - -#[derive(Debug)] -struct FreeListRegion { - memory: Arc, - ptr: Option>, - chunk: u64, - start: u64, - end: u64, -} - -unsafe impl Sync for FreeListRegion where M: Sync {} -unsafe impl Send for FreeListRegion where M: Send {} - -impl FreeListRegion { - pub fn cmp(&self, block: &FreeListBlock) -> Ordering { - debug_assert_eq!( - Arc::ptr_eq(&self.memory, &block.memory), - self.chunk == block.chunk - ); - - if self.chunk == block.chunk { - debug_assert_eq!( - Ord::cmp(&self.start, &block.offset), - Ord::cmp(&self.end, &(block.offset + block.size)), - "Free region {{ start: {}, end: {} }} overlaps with block {{ offset: {}, size: {} }}", - self.start, - self.end, - block.offset, - block.size, - ); - } - - Ord::cmp(&self.chunk, &block.chunk).then(Ord::cmp(&self.start, &block.offset)) - } - - fn from_block(block: FreeListBlock) -> Self { - FreeListRegion { - memory: block.memory, - chunk: block.chunk, - ptr: block.ptr, - start: block.offset, - end: block.offset + block.size, - } - } - - fn into_block(self) -> FreeListBlock { - FreeListBlock { - memory: self.memory, - chunk: self.chunk, - ptr: self.ptr, - offset: self.start, - size: self.end - self.start, - } - } - - fn consecutive(&self, other: &Self) -> bool { - if self.chunk != other.chunk { - return false; - } - - debug_assert!(Arc::ptr_eq(&self.memory, &other.memory)); - - debug_assert_eq!( - Ord::cmp(&self.start, &other.start), - Ord::cmp(&self.end, &other.end) - ); - - self.end == other.start - } - - fn merge(&mut self, next: FreeListRegion) { - debug_assert!(self.consecutive(&next)); - self.end = next.end; - } - - fn is_prefix_block(&self, block: &FreeListBlock) -> bool { - if self.chunk != block.chunk { - return false; - } - - debug_assert!(Arc::ptr_eq(&self.memory, &block.memory)); - - debug_assert_eq!( - Ord::cmp(&self.start, &block.offset), - Ord::cmp(&self.end, &(block.offset + block.size)) - ); - - self.start == (block.offset + block.size) - } - - fn merge_prefix_block(&mut self, block: FreeListBlock) { - debug_assert!(self.is_prefix_block(&block)); - self.start = block.offset; - self.ptr = block.ptr; - } - - fn is_suffix_block(&self, block: &FreeListBlock) -> bool { - if self.chunk != block.chunk { - return false; - } - - debug_assert!(Arc::ptr_eq(&self.memory, &block.memory)); - - debug_assert_eq!( - Ord::cmp(&self.start, &block.offset), - Ord::cmp(&self.end, &(block.offset + block.size)) - ); - - self.end == block.offset - } - - fn merge_suffix_block(&mut self, block: FreeListBlock) { - debug_assert!(self.is_suffix_block(&block)); - self.end += block.size; - } -} - -#[derive(Debug)] -pub struct FreeListBlock { - pub memory: Arc, - pub ptr: Option>, - pub chunk: u64, - pub offset: u64, - pub size: u64, -} - -unsafe impl Sync for FreeListBlock where M: Sync {} -unsafe impl Send for FreeListBlock where M: Send {} - -#[derive(Debug)] -pub(crate) struct FreeListAllocator { - freelist: FreeList, - chunk_size: u64, - final_chunk_size: u64, - memory_type: u32, - props: MemoryPropertyFlags, - atom_mask: u64, - - total_allocations: u64, - total_deallocations: u64, -} - -impl Drop for FreeListAllocator { - fn drop(&mut self) { - match Ord::cmp(&self.total_allocations, &self.total_deallocations) { - Ordering::Equal => {} - Ordering::Greater => { - report_error_on_drop!("Not all blocks were deallocated") - } - Ordering::Less => { - report_error_on_drop!("More blocks deallocated than allocated") - } - } - - if !self.freelist.array.is_empty() { - report_error_on_drop!( - "FreeListAllocator has free blocks on drop. Allocator should be cleaned" - ); - } - } -} - -impl FreeListAllocator -where - M: MemoryBounds + 'static, -{ - pub fn new( - starting_chunk_size: u64, - final_chunk_size: u64, - memory_type: u32, - props: MemoryPropertyFlags, - atom_mask: u64, - ) -> Self { - debug_assert_eq!( - align_down(starting_chunk_size, atom_mask), - starting_chunk_size - ); - - let starting_chunk_size = min(starting_chunk_size, isize::max_value()); - - debug_assert_eq!(align_down(final_chunk_size, atom_mask), final_chunk_size); - let final_chunk_size = min(final_chunk_size, isize::max_value()); - - FreeListAllocator { - freelist: FreeList::new(), - chunk_size: starting_chunk_size, - final_chunk_size, - memory_type, - props, - atom_mask, - - total_allocations: 0, - total_deallocations: 0, - } - } - - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn alloc( - &mut self, - device: &impl MemoryDevice, - size: u64, - align_mask: u64, - flags: AllocationFlags, - heap: &mut Heap, - allocations_remains: &mut u32, - ) -> Result, AllocationError> { - debug_assert!( - self.final_chunk_size >= size, - "GpuAllocator must not request allocations equal or greater to chunks size" - ); - - let size = align_up(size, self.atom_mask).expect( - "Any value not greater than final chunk size (which is aligned) has to fit for alignment", - ); - - let align_mask = align_mask | self.atom_mask; - let host_visible = self.host_visible(); - - if size <= self.chunk_size { - // Otherwise there can't be any sufficiently large free blocks - if let Some(block) = self.freelist.get_block(align_mask, size) { - self.total_allocations += 1; - return Ok(block); - } - } - - // New allocation is required. - if *allocations_remains == 0 { - return Err(AllocationError::TooManyObjects); - } - - if size > self.chunk_size { - let multiple = (size - 1) / self.chunk_size + 1; - let multiple = multiple.next_power_of_two(); - - self.chunk_size = (self.chunk_size * multiple).min(self.final_chunk_size); - } - - let mut memory = device.allocate_memory(self.chunk_size, self.memory_type, flags)?; - *allocations_remains -= 1; - heap.alloc(self.chunk_size); - - // Map host visible allocations - let ptr = if host_visible { - match device.map_memory(&mut memory, 0, self.chunk_size) { - Ok(ptr) => Some(ptr), - Err(DeviceMapError::MapFailed) => { - #[cfg(feature = "tracing")] - tracing::error!("Failed to map host-visible memory in linear allocator"); - device.deallocate_memory(memory); - *allocations_remains += 1; - heap.dealloc(self.chunk_size); - - return Err(AllocationError::OutOfHostMemory); - } - Err(DeviceMapError::OutOfDeviceMemory) => { - return Err(AllocationError::OutOfDeviceMemory); - } - Err(DeviceMapError::OutOfHostMemory) => { - return Err(AllocationError::OutOfHostMemory); - } - } - } else { - None - }; - - let memory = Arc::new(memory); - let block = - self.freelist - .get_block_from_new_memory(memory, self.chunk_size, ptr, align_mask, size); - - if self.chunk_size < self.final_chunk_size { - // Double next chunk size - // Limit to final value. - self.chunk_size = (self.chunk_size * 2).min(self.final_chunk_size); - } - - self.total_allocations += 1; - Ok(block) - } - - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn dealloc( - &mut self, - device: &impl MemoryDevice, - block: FreeListBlock, - heap: &mut Heap, - allocations_remains: &mut u32, - ) { - debug_assert!(block.size < self.chunk_size); - debug_assert_ne!(block.size, 0); - self.freelist.insert_block(block); - self.total_deallocations += 1; - - if let Some(memory) = self.freelist.drain(true) { - memory.for_each(|(memory, size)| { - device.deallocate_memory(memory); - *allocations_remains += 1; - heap.dealloc(size); - }); - } - } - - /// Deallocates leftover memory objects. - /// Should be used before dropping. - /// - /// # Safety - /// - /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance - /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance - /// and memory blocks allocated from it - #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] - pub unsafe fn cleanup( - &mut self, - device: &impl MemoryDevice, - heap: &mut Heap, - allocations_remains: &mut u32, - ) { - if let Some(memory) = self.freelist.drain(false) { - memory.for_each(|(memory, size)| { - device.deallocate_memory(memory); - *allocations_remains += 1; - heap.dealloc(size); - }); - } - - #[cfg(feature = "tracing")] - { - if self.total_allocations == self.total_deallocations && !self.freelist.array.is_empty() - { - tracing::error!( - "Some regions were not deallocated on cleanup, although all blocks are free. - This is a bug in `FreeBlockAllocator`. - See array of free blocks left: - {:#?}", - self.freelist.array, - ); - } - } - } - - fn host_visible(&self) -> bool { - self.props.contains(MemoryPropertyFlags::HOST_VISIBLE) - } -} - -fn min(l: L, r: R) -> L -where - R: core::convert::TryInto, - L: Ord, -{ - match r.try_into() { - Ok(r) => core::cmp::min(l, r), - Err(_) => l, - } -} +use { + crate::{ + align_down, align_up, + error::AllocationError, + heap::Heap, + util::{arc_unwrap, is_arc_unique}, + MemoryBounds, + }, + alloc::{sync::Arc, vec::Vec}, + core::{cmp::Ordering, ptr::NonNull}, + gpu_alloc_types::{AllocationFlags, DeviceMapError, MemoryDevice, MemoryPropertyFlags}, +}; + +unsafe fn opt_ptr_add(ptr: Option>, size: u64) -> Option> { + ptr.map(|ptr| { + // Size is within memory region started at `ptr`. + // size is within `chunk_size` that fits `isize`. + NonNull::new_unchecked(ptr.as_ptr().offset(size as isize)) + }) +} + +#[derive(Debug)] +pub(super) struct FreeList { + array: Vec>, + counter: u64, +} + +impl FreeList { + pub fn new() -> Self { + FreeList { + array: Vec::new(), + counter: 0, + } + } + + pub fn get_block_from_new_memory( + &mut self, + memory: Arc, + memory_size: u64, + ptr: Option>, + align_mask: u64, + size: u64, + ) -> FreeListBlock { + debug_assert!(size <= memory_size); + + self.counter += 1; + self.array.push(FreeListRegion { + memory, + ptr, + chunk: self.counter, + start: 0, + end: memory_size, + }); + self.get_block_at(self.array.len() - 1, align_mask, size) + } + + pub fn get_block(&mut self, align_mask: u64, size: u64) -> Option> { + let (index, _) = self.array.iter().enumerate().rev().find(|(_, region)| { + match region.end.checked_sub(size) { + Some(start) => { + let aligned_start = align_down(start, align_mask); + aligned_start >= region.start + } + None => false, + } + })?; + + Some(self.get_block_at(index, align_mask, size)) + } + + fn get_block_at(&mut self, index: usize, align_mask: u64, size: u64) -> FreeListBlock { + let region = &mut self.array[index]; + + let start = region.end - size; + let aligned_start = align_down(start, align_mask); + + if aligned_start > region.start { + let block = FreeListBlock { + offset: aligned_start, + size: region.end - aligned_start, + chunk: region.chunk, + ptr: unsafe { opt_ptr_add(region.ptr, aligned_start - region.start) }, + memory: region.memory.clone(), + }; + + region.end = aligned_start; + + block + } else { + debug_assert_eq!(aligned_start, region.start); + let region = self.array.remove(index); + region.into_block() + } + } + + pub fn insert_block(&mut self, block: FreeListBlock) { + match self.array.binary_search_by(|b| b.cmp(&block)) { + Ok(_) => { + panic!("Overlapping block found in free list"); + } + Err(index) if self.array.len() > index => match &mut self.array[..=index] { + [] => unreachable!(), + [next] => { + debug_assert!(!next.is_suffix_block(&block)); + + if next.is_prefix_block(&block) { + next.merge_prefix_block(block); + } else { + self.array.insert(0, FreeListRegion::from_block(block)); + } + } + [.., prev, next] => { + debug_assert!(!prev.is_prefix_block(&block)); + debug_assert!(!next.is_suffix_block(&block)); + + if next.is_prefix_block(&block) { + next.merge_prefix_block(block); + + if prev.consecutive(&*next) { + let next = self.array.remove(index); + let prev = &mut self.array[index - 1]; + prev.merge(next); + } + } else if prev.is_suffix_block(&block) { + prev.merge_suffix_block(block); + } else { + self.array.insert(index, FreeListRegion::from_block(block)); + } + } + }, + Err(_) => match &mut self.array[..] { + [] => self.array.push(FreeListRegion::from_block(block)), + [.., prev] => { + debug_assert!(!prev.is_prefix_block(&block)); + if prev.is_suffix_block(&block) { + prev.merge_suffix_block(block); + } else { + self.array.push(FreeListRegion::from_block(block)); + } + } + }, + } + } + + pub fn drain(&mut self, keep_last: bool) -> Option + '_> { + // Time to deallocate + + let len = self.array.len(); + + let mut del = 0; + { + let regions = &mut self.array[..]; + + for i in 0..len { + if (i < len - 1 || !keep_last) && is_arc_unique(&mut regions[i].memory) { + del += 1; + } else if del > 0 { + regions.swap(i - del, i); + } + } + } + + if del > 0 { + Some(self.array.drain(len - del..).map(move |region| { + debug_assert_eq!(region.start, 0); + (unsafe { arc_unwrap(region.memory) }, region.end) + })) + } else { + None + } + } +} + +#[derive(Debug)] +struct FreeListRegion { + memory: Arc, + ptr: Option>, + chunk: u64, + start: u64, + end: u64, +} + +unsafe impl Sync for FreeListRegion where M: Sync {} +unsafe impl Send for FreeListRegion where M: Send {} + +impl FreeListRegion { + pub fn cmp(&self, block: &FreeListBlock) -> Ordering { + debug_assert_eq!( + Arc::ptr_eq(&self.memory, &block.memory), + self.chunk == block.chunk + ); + + if self.chunk == block.chunk { + debug_assert_eq!( + Ord::cmp(&self.start, &block.offset), + Ord::cmp(&self.end, &(block.offset + block.size)), + "Free region {{ start: {}, end: {} }} overlaps with block {{ offset: {}, size: {} }}", + self.start, + self.end, + block.offset, + block.size, + ); + } + + Ord::cmp(&self.chunk, &block.chunk).then(Ord::cmp(&self.start, &block.offset)) + } + + fn from_block(block: FreeListBlock) -> Self { + FreeListRegion { + memory: block.memory, + chunk: block.chunk, + ptr: block.ptr, + start: block.offset, + end: block.offset + block.size, + } + } + + fn into_block(self) -> FreeListBlock { + FreeListBlock { + memory: self.memory, + chunk: self.chunk, + ptr: self.ptr, + offset: self.start, + size: self.end - self.start, + } + } + + fn consecutive(&self, other: &Self) -> bool { + if self.chunk != other.chunk { + return false; + } + + debug_assert!(Arc::ptr_eq(&self.memory, &other.memory)); + + debug_assert_eq!( + Ord::cmp(&self.start, &other.start), + Ord::cmp(&self.end, &other.end) + ); + + self.end == other.start + } + + fn merge(&mut self, next: FreeListRegion) { + debug_assert!(self.consecutive(&next)); + self.end = next.end; + } + + fn is_prefix_block(&self, block: &FreeListBlock) -> bool { + if self.chunk != block.chunk { + return false; + } + + debug_assert!(Arc::ptr_eq(&self.memory, &block.memory)); + + debug_assert_eq!( + Ord::cmp(&self.start, &block.offset), + Ord::cmp(&self.end, &(block.offset + block.size)) + ); + + self.start == (block.offset + block.size) + } + + fn merge_prefix_block(&mut self, block: FreeListBlock) { + debug_assert!(self.is_prefix_block(&block)); + self.start = block.offset; + self.ptr = block.ptr; + } + + fn is_suffix_block(&self, block: &FreeListBlock) -> bool { + if self.chunk != block.chunk { + return false; + } + + debug_assert!(Arc::ptr_eq(&self.memory, &block.memory)); + + debug_assert_eq!( + Ord::cmp(&self.start, &block.offset), + Ord::cmp(&self.end, &(block.offset + block.size)) + ); + + self.end == block.offset + } + + fn merge_suffix_block(&mut self, block: FreeListBlock) { + debug_assert!(self.is_suffix_block(&block)); + self.end += block.size; + } +} + +#[derive(Debug)] +pub struct FreeListBlock { + pub memory: Arc, + pub ptr: Option>, + pub chunk: u64, + pub offset: u64, + pub size: u64, +} + +unsafe impl Sync for FreeListBlock where M: Sync {} +unsafe impl Send for FreeListBlock where M: Send {} + +#[derive(Debug)] +pub(crate) struct FreeListAllocator { + freelist: FreeList, + chunk_size: u64, + final_chunk_size: u64, + memory_type: u32, + props: MemoryPropertyFlags, + atom_mask: u64, + + total_allocations: u64, + total_deallocations: u64, +} + +impl Drop for FreeListAllocator { + fn drop(&mut self) { + match Ord::cmp(&self.total_allocations, &self.total_deallocations) { + Ordering::Equal => {} + Ordering::Greater => { + report_error_on_drop!("Not all blocks were deallocated") + } + Ordering::Less => { + report_error_on_drop!("More blocks deallocated than allocated") + } + } + + if !self.freelist.array.is_empty() { + report_error_on_drop!( + "FreeListAllocator has free blocks on drop. Allocator should be cleaned" + ); + } + } +} + +impl FreeListAllocator +where + M: MemoryBounds + 'static, +{ + pub fn new( + starting_chunk_size: u64, + final_chunk_size: u64, + memory_type: u32, + props: MemoryPropertyFlags, + atom_mask: u64, + ) -> Self { + debug_assert_eq!( + align_down(starting_chunk_size, atom_mask), + starting_chunk_size + ); + + let starting_chunk_size = min(starting_chunk_size, isize::max_value()); + + debug_assert_eq!(align_down(final_chunk_size, atom_mask), final_chunk_size); + let final_chunk_size = min(final_chunk_size, isize::max_value()); + + FreeListAllocator { + freelist: FreeList::new(), + chunk_size: starting_chunk_size, + final_chunk_size, + memory_type, + props, + atom_mask, + + total_allocations: 0, + total_deallocations: 0, + } + } + + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn alloc( + &mut self, + device: &impl MemoryDevice, + size: u64, + align_mask: u64, + flags: AllocationFlags, + heap: &mut Heap, + allocations_remains: &mut u32, + ) -> Result, AllocationError> { + debug_assert!( + self.final_chunk_size >= size, + "GpuAllocator must not request allocations equal or greater to chunks size" + ); + + let size = align_up(size, self.atom_mask).expect( + "Any value not greater than final chunk size (which is aligned) has to fit for alignment", + ); + + let align_mask = align_mask | self.atom_mask; + let host_visible = self.host_visible(); + + if size <= self.chunk_size { + // Otherwise there can't be any sufficiently large free blocks + if let Some(block) = self.freelist.get_block(align_mask, size) { + self.total_allocations += 1; + return Ok(block); + } + } + + // New allocation is required. + if *allocations_remains == 0 { + return Err(AllocationError::TooManyObjects); + } + + if size > self.chunk_size { + let multiple = (size - 1) / self.chunk_size + 1; + let multiple = multiple.next_power_of_two(); + + self.chunk_size = (self.chunk_size * multiple).min(self.final_chunk_size); + } + + let mut memory = device.allocate_memory(self.chunk_size, self.memory_type, flags)?; + *allocations_remains -= 1; + heap.alloc(self.chunk_size); + + // Map host visible allocations + let ptr = if host_visible { + match device.map_memory(&mut memory, 0, self.chunk_size) { + Ok(ptr) => Some(ptr), + Err(DeviceMapError::MapFailed) => { + #[cfg(feature = "tracing")] + tracing::error!("Failed to map host-visible memory in linear allocator"); + device.deallocate_memory(memory); + *allocations_remains += 1; + heap.dealloc(self.chunk_size); + + return Err(AllocationError::OutOfHostMemory); + } + Err(DeviceMapError::OutOfDeviceMemory) => { + return Err(AllocationError::OutOfDeviceMemory); + } + Err(DeviceMapError::OutOfHostMemory) => { + return Err(AllocationError::OutOfHostMemory); + } + } + } else { + None + }; + + let memory = Arc::new(memory); + let block = + self.freelist + .get_block_from_new_memory(memory, self.chunk_size, ptr, align_mask, size); + + if self.chunk_size < self.final_chunk_size { + // Double next chunk size + // Limit to final value. + self.chunk_size = (self.chunk_size * 2).min(self.final_chunk_size); + } + + self.total_allocations += 1; + Ok(block) + } + + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn dealloc( + &mut self, + device: &impl MemoryDevice, + block: FreeListBlock, + heap: &mut Heap, + allocations_remains: &mut u32, + ) { + debug_assert!(block.size < self.chunk_size); + debug_assert_ne!(block.size, 0); + self.freelist.insert_block(block); + self.total_deallocations += 1; + + if let Some(memory) = self.freelist.drain(true) { + memory.for_each(|(memory, size)| { + device.deallocate_memory(memory); + *allocations_remains += 1; + heap.dealloc(size); + }); + } + } + + /// Deallocates leftover memory objects. + /// Should be used before dropping. + /// + /// # Safety + /// + /// * `device` must be one with `DeviceProperties` that were provided to create this `GpuAllocator` instance + /// * Same `device` instance must be used for all interactions with one `GpuAllocator` instance + /// and memory blocks allocated from it + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self, device)))] + pub unsafe fn cleanup( + &mut self, + device: &impl MemoryDevice, + heap: &mut Heap, + allocations_remains: &mut u32, + ) { + if let Some(memory) = self.freelist.drain(false) { + memory.for_each(|(memory, size)| { + device.deallocate_memory(memory); + *allocations_remains += 1; + heap.dealloc(size); + }); + } + + #[cfg(feature = "tracing")] + { + if self.total_allocations == self.total_deallocations && !self.freelist.array.is_empty() + { + tracing::error!( + "Some regions were not deallocated on cleanup, although all blocks are free. + This is a bug in `FreeBlockAllocator`. + See array of free blocks left: + {:#?}", + self.freelist.array, + ); + } + } + } + + fn host_visible(&self) -> bool { + self.props.contains(MemoryPropertyFlags::HOST_VISIBLE) + } +} + +fn min(l: L, r: R) -> L +where + R: core::convert::TryInto, + L: Ord, +{ + match r.try_into() { + Ok(r) => core::cmp::min(l, r), + Err(_) => l, + } +} diff --git a/third_party/rust/gpu-alloc/src/heap.rs b/third_party/rust/gpu-alloc/src/heap.rs index fca7538919fc..f049f14768a5 100644 --- a/third_party/rust/gpu-alloc/src/heap.rs +++ b/third_party/rust/gpu-alloc/src/heap.rs @@ -1,32 +1,32 @@ -#[derive(Debug)] -pub(crate) struct Heap { - size: u64, - used: u64, - allocated: u128, - deallocated: u128, -} - -impl Heap { - pub(crate) fn new(size: u64) -> Self { - Heap { - size, - used: 0, - allocated: 0, - deallocated: 0, - } - } - - pub(crate) fn size(&mut self) -> u64 { - self.size - } - - pub(crate) fn alloc(&mut self, size: u64) { - self.used += size; - self.allocated += u128::from(size); - } - - pub(crate) fn dealloc(&mut self, size: u64) { - self.used -= size; - self.deallocated += u128::from(size); - } -} +#[derive(Debug)] +pub(crate) struct Heap { + size: u64, + used: u64, + allocated: u128, + deallocated: u128, +} + +impl Heap { + pub(crate) fn new(size: u64) -> Self { + Heap { + size, + used: 0, + allocated: 0, + deallocated: 0, + } + } + + pub(crate) fn size(&mut self) -> u64 { + self.size + } + + pub(crate) fn alloc(&mut self, size: u64) { + self.used += size; + self.allocated += u128::from(size); + } + + pub(crate) fn dealloc(&mut self, size: u64) { + self.used -= size; + self.deallocated += u128::from(size); + } +} diff --git a/third_party/rust/gpu-alloc/src/lib.rs b/third_party/rust/gpu-alloc/src/lib.rs index 97d04fac7a7e..3533f45124f0 100644 --- a/third_party/rust/gpu-alloc/src/lib.rs +++ b/third_party/rust/gpu-alloc/src/lib.rs @@ -1,124 +1,124 @@ -//! -//! Implementation agnostic memory allocator for Vulkan like APIs. -//! -//! This crate is intended to be used as part of safe API implementations.\ -//! Use with caution. There are unsafe functions all over the place. -//! -//! # Usage -//! -//! Start with fetching `DeviceProperties` from `gpu-alloc-` crate for the backend of choice.\ -//! Then create `GpuAllocator` instance and use it for all device memory allocations.\ -//! `GpuAllocator` will take care for all necessary bookkeeping like memory object count limit, -//! heap budget and memory mapping. -//! -//! ### Backends implementations -//! -//! Backend supporting crates should not depend on this crate.\ -//! Instead they should depend on `gpu-alloc-types` which is much more stable, -//! allowing to upgrade `gpu-alloc` version without `gpu-alloc-` upgrade. -//! - -#![cfg_attr(not(feature = "std"), no_std)] - -extern crate alloc; - -#[cfg(feature = "tracing")] -macro_rules! report_error_on_drop { - ($($tokens:tt)*) => {{ - #[cfg(feature = "std")] - { - if std::thread::panicking() { - return; - } - } - - tracing::error!($($tokens)*) - }}; -} - -#[cfg(all(not(feature = "tracing"), feature = "std"))] -macro_rules! report_error_on_drop { - ($($tokens:tt)*) => {{ - if std::thread::panicking() { - return; - } - eprintln!($($tokens)*) - }}; -} - -#[cfg(all(not(feature = "tracing"), not(feature = "std")))] -macro_rules! report_error_on_drop { - ($($tokens:tt)*) => {{ - panic!($($tokens)*) - }}; -} - -mod allocator; -mod block; -mod buddy; -mod config; -mod error; -mod freelist; -mod heap; -mod slab; -mod usage; -mod util; - -pub use { - self::{allocator::*, block::MemoryBlock, config::*, error::*, usage::*}, - gpu_alloc_types::*, -}; - -/// Memory request for allocator. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct Request { - /// Minimal size of memory block required. - /// Returned block may have larger size, - /// use `MemoryBlock::size` to learn actual size of returned block. - pub size: u64, - - /// Minimal alignment mask required. - /// Returned block may have larger alignment, - /// use `MemoryBlock::align` to learn actual alignment of returned block. - pub align_mask: u64, - - /// Intended memory usage. - /// Returned block may support additional usages, - /// use `MemoryBlock::props` to learn memory properties of returned block. - pub usage: UsageFlags, - - /// Bitset for memory types. - /// Returned block will be from memory type corresponding to one of set bits, - /// use `MemoryBlock::memory_type` to learn memory type index of returned block. - pub memory_types: u32, -} - -/// Aligns `value` up to `align_mask` -/// Returns smallest integer not lesser than `value` aligned by `align_mask`. -/// Returns `None` on overflow. -pub(crate) fn align_up(value: u64, align_mask: u64) -> Option { - Some(value.checked_add(align_mask)? & !align_mask) -} - -/// Align `value` down to `align_mask` -/// Returns largest integer not bigger than `value` aligned by `align_mask`. -pub(crate) fn align_down(value: u64, align_mask: u64) -> u64 { - value & !align_mask -} - -#[cfg(debug_assertions)] -#[allow(unused_unsafe)] -unsafe fn unreachable_unchecked() -> ! { - unreachable!() -} - -#[cfg(not(debug_assertions))] -unsafe fn unreachable_unchecked() -> ! { - core::hint::unreachable_unchecked() -} - -// #[cfg(feature = "tracing")] -use core::fmt::Debug as MemoryBounds; - -// #[cfg(not(feature = "tracing"))] -// use core::any::Any as MemoryBounds; +//! +//! Implementation agnostic memory allocator for Vulkan like APIs. +//! +//! This crate is intended to be used as part of safe API implementations.\ +//! Use with caution. There are unsafe functions all over the place. +//! +//! # Usage +//! +//! Start with fetching `DeviceProperties` from `gpu-alloc-` crate for the backend of choice.\ +//! Then create `GpuAllocator` instance and use it for all device memory allocations.\ +//! `GpuAllocator` will take care for all necessary bookkeeping like memory object count limit, +//! heap budget and memory mapping. +//! +//! ### Backends implementations +//! +//! Backend supporting crates should not depend on this crate.\ +//! Instead they should depend on `gpu-alloc-types` which is much more stable, +//! allowing to upgrade `gpu-alloc` version without `gpu-alloc-` upgrade. +//! + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; + +#[cfg(feature = "tracing")] +macro_rules! report_error_on_drop { + ($($tokens:tt)*) => {{ + #[cfg(feature = "std")] + { + if std::thread::panicking() { + return; + } + } + + tracing::error!($($tokens)*) + }}; +} + +#[cfg(all(not(feature = "tracing"), feature = "std"))] +macro_rules! report_error_on_drop { + ($($tokens:tt)*) => {{ + if std::thread::panicking() { + return; + } + eprintln!($($tokens)*) + }}; +} + +#[cfg(all(not(feature = "tracing"), not(feature = "std")))] +macro_rules! report_error_on_drop { + ($($tokens:tt)*) => {{ + panic!($($tokens)*) + }}; +} + +mod allocator; +mod block; +mod buddy; +mod config; +mod error; +mod freelist; +mod heap; +mod slab; +mod usage; +mod util; + +pub use { + self::{allocator::*, block::MemoryBlock, config::*, error::*, usage::*}, + gpu_alloc_types::*, +}; + +/// Memory request for allocator. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct Request { + /// Minimal size of memory block required. + /// Returned block may have larger size, + /// use `MemoryBlock::size` to learn actual size of returned block. + pub size: u64, + + /// Minimal alignment mask required. + /// Returned block may have larger alignment, + /// use `MemoryBlock::align` to learn actual alignment of returned block. + pub align_mask: u64, + + /// Intended memory usage. + /// Returned block may support additional usages, + /// use `MemoryBlock::props` to learn memory properties of returned block. + pub usage: UsageFlags, + + /// Bitset for memory types. + /// Returned block will be from memory type corresponding to one of set bits, + /// use `MemoryBlock::memory_type` to learn memory type index of returned block. + pub memory_types: u32, +} + +/// Aligns `value` up to `align_mask` +/// Returns smallest integer not lesser than `value` aligned by `align_mask`. +/// Returns `None` on overflow. +pub(crate) fn align_up(value: u64, align_mask: u64) -> Option { + Some(value.checked_add(align_mask)? & !align_mask) +} + +/// Align `value` down to `align_mask` +/// Returns largest integer not bigger than `value` aligned by `align_mask`. +pub(crate) fn align_down(value: u64, align_mask: u64) -> u64 { + value & !align_mask +} + +#[cfg(debug_assertions)] +#[allow(unused_unsafe)] +unsafe fn unreachable_unchecked() -> ! { + unreachable!() +} + +#[cfg(not(debug_assertions))] +unsafe fn unreachable_unchecked() -> ! { + core::hint::unreachable_unchecked() +} + +// #[cfg(feature = "tracing")] +use core::fmt::Debug as MemoryBounds; + +// #[cfg(not(feature = "tracing"))] +// use core::any::Any as MemoryBounds; diff --git a/third_party/rust/gpu-alloc/src/slab.rs b/third_party/rust/gpu-alloc/src/slab.rs index b65c73e656af..de413435fe44 100644 --- a/third_party/rust/gpu-alloc/src/slab.rs +++ b/third_party/rust/gpu-alloc/src/slab.rs @@ -1,97 +1,97 @@ -use {crate::unreachable_unchecked, alloc::vec::Vec, core::mem::replace}; - -#[derive(Debug)] -enum Entry { - Vacant(usize), - Occupied(T), -} -#[derive(Debug)] -pub(crate) struct Slab { - next_vacant: usize, - entries: Vec>, -} - -impl Slab { - pub fn new() -> Self { - Slab { - next_vacant: !0, - entries: Vec::new(), - } - } - - /// Inserts value into this linked vec and returns index - /// at which value can be accessed in constant time. - pub fn insert(&mut self, value: T) -> usize { - if self.next_vacant >= self.entries.len() { - self.entries.push(Entry::Occupied(value)); - self.entries.len() - 1 - } else { - match *unsafe { self.entries.get_unchecked(self.next_vacant) } { - Entry::Vacant(next_vacant) => { - unsafe { - *self.entries.get_unchecked_mut(self.next_vacant) = Entry::Occupied(value); - } - replace(&mut self.next_vacant, next_vacant) - } - _ => unsafe { unreachable_unchecked() }, - } - } - } - - pub fn len(&self) -> usize { - self.entries.len() - } - - pub unsafe fn get_unchecked(&self, index: usize) -> &T { - debug_assert!(index < self.len()); - - match self.entries.get_unchecked(index) { - Entry::Occupied(value) => value, - _ => unreachable_unchecked(), - } - } - - pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T { - debug_assert!(index < self.len()); - - match self.entries.get_unchecked_mut(index) { - Entry::Occupied(value) => value, - _ => unreachable_unchecked(), - } - } - - pub fn get(&self, index: usize) -> &T { - match self.entries.get(index) { - Some(Entry::Occupied(value)) => value, - _ => panic!("Invalid index"), - } - } - - pub fn get_mut(&mut self, index: usize) -> &mut T { - match self.entries.get_mut(index) { - Some(Entry::Occupied(value)) => value, - _ => panic!("Invalid index"), - } - } - - pub unsafe fn remove_unchecked(&mut self, index: usize) -> T { - let entry = replace( - self.entries.get_unchecked_mut(index), - Entry::Vacant(self.next_vacant), - ); - - self.next_vacant = index; - - match entry { - Entry::Occupied(value) => value, - _ => unreachable_unchecked(), - } - } - - pub fn remove(&mut self, index: usize) -> T { - match self.entries.get_mut(index) { - Some(Entry::Occupied(_)) => unsafe { self.remove_unchecked(index) }, - _ => panic!("Invalid index"), - } - } -} +use {crate::unreachable_unchecked, alloc::vec::Vec, core::mem::replace}; + +#[derive(Debug)] +enum Entry { + Vacant(usize), + Occupied(T), +} +#[derive(Debug)] +pub(crate) struct Slab { + next_vacant: usize, + entries: Vec>, +} + +impl Slab { + pub fn new() -> Self { + Slab { + next_vacant: !0, + entries: Vec::new(), + } + } + + /// Inserts value into this linked vec and returns index + /// at which value can be accessed in constant time. + pub fn insert(&mut self, value: T) -> usize { + if self.next_vacant >= self.entries.len() { + self.entries.push(Entry::Occupied(value)); + self.entries.len() - 1 + } else { + match *unsafe { self.entries.get_unchecked(self.next_vacant) } { + Entry::Vacant(next_vacant) => { + unsafe { + *self.entries.get_unchecked_mut(self.next_vacant) = Entry::Occupied(value); + } + replace(&mut self.next_vacant, next_vacant) + } + _ => unsafe { unreachable_unchecked() }, + } + } + } + + pub fn len(&self) -> usize { + self.entries.len() + } + + pub unsafe fn get_unchecked(&self, index: usize) -> &T { + debug_assert!(index < self.len()); + + match self.entries.get_unchecked(index) { + Entry::Occupied(value) => value, + _ => unreachable_unchecked(), + } + } + + pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T { + debug_assert!(index < self.len()); + + match self.entries.get_unchecked_mut(index) { + Entry::Occupied(value) => value, + _ => unreachable_unchecked(), + } + } + + pub fn get(&self, index: usize) -> &T { + match self.entries.get(index) { + Some(Entry::Occupied(value)) => value, + _ => panic!("Invalid index"), + } + } + + pub fn get_mut(&mut self, index: usize) -> &mut T { + match self.entries.get_mut(index) { + Some(Entry::Occupied(value)) => value, + _ => panic!("Invalid index"), + } + } + + pub unsafe fn remove_unchecked(&mut self, index: usize) -> T { + let entry = replace( + self.entries.get_unchecked_mut(index), + Entry::Vacant(self.next_vacant), + ); + + self.next_vacant = index; + + match entry { + Entry::Occupied(value) => value, + _ => unreachable_unchecked(), + } + } + + pub fn remove(&mut self, index: usize) -> T { + match self.entries.get_mut(index) { + Some(Entry::Occupied(_)) => unsafe { self.remove_unchecked(index) }, + _ => panic!("Invalid index"), + } + } +} diff --git a/third_party/rust/gpu-alloc/src/usage.rs b/third_party/rust/gpu-alloc/src/usage.rs index 9834ef41c2c7..683c79d2faf7 100644 --- a/third_party/rust/gpu-alloc/src/usage.rs +++ b/third_party/rust/gpu-alloc/src/usage.rs @@ -1,167 +1,176 @@ -use { - core::fmt::{self, Debug}, - gpu_alloc_types::{MemoryPropertyFlags, MemoryType}, -}; - -bitflags::bitflags! { - /// Memory usage type. - /// Bits set define intended usage for requested memory. - #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] - pub struct UsageFlags: u8 { - /// Hints for allocator to find memory with faster device access. - /// If no flags is specified than `FAST_DEVICE_ACCESS` is implied. - const FAST_DEVICE_ACCESS = 0x01; - - /// Memory will be accessed from host. - /// This flags guarantees that host memory operations will be available. - /// Otherwise implementation is encouraged to use non-host-accessible memory. - const HOST_ACCESS = 0x02; - - /// Hints allocator that memory will be used for data downloading. - /// Allocator will strongly prefer host-cached memory. - /// Implies `HOST_ACCESS` flag. - const DOWNLOAD = 0x04; - - /// Hints allocator that memory will be used for data uploading. - /// If `DOWNLOAD` flag is not set then allocator will assume that - /// host will access memory in write-only manner and may - /// pick not host-cached. - /// Implies `HOST_ACCESS` flag. - const UPLOAD = 0x08; - - /// Hints allocator that memory will be used for short duration - /// allowing to use faster algorithm with less memory overhead. - /// If use holds returned memory block for too long then - /// effective memory overhead increases instead. - /// Best use case is for staging buffer for single batch of operations. - const TRANSIENT = 0x10; - - /// Requests memory that can be addressed with `u64`. - /// Allows fetching device address for resources bound to that memory. - const DEVICE_ADDRESS = 0x20; - } -} - -#[derive(Clone, Copy, Debug)] -struct MemoryForOneUsage { - mask: u32, - types: [u32; 32], - types_count: u32, -} - -pub(crate) struct MemoryForUsage { - usages: [MemoryForOneUsage; 64], -} - -impl Debug for MemoryForUsage { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("MemoryForUsage") - .field("usages", &&self.usages[..]) - .finish() - } -} - -impl MemoryForUsage { - pub fn new(memory_types: &[MemoryType]) -> Self { - assert!( - memory_types.len() <= 32, - "Only up to 32 memory types supported" - ); - - let mut mfu = MemoryForUsage { - usages: [MemoryForOneUsage { - mask: 0, - types: [0; 32], - types_count: 0, - }; 64], - }; - - for usage in 0..64 { - mfu.usages[usage as usize] = - one_usage(UsageFlags::from_bits_truncate(usage), memory_types); - } - - mfu - } - - /// Returns mask with bits set for memory type indices that support the - /// usage. - pub fn mask(&self, usage: UsageFlags) -> u32 { - self.usages[usage.bits() as usize].mask - } - - /// Returns slice of memory type indices that support the usage. - /// Earlier memory type has priority over later. - pub fn types(&self, usage: UsageFlags) -> &[u32] { - let usage = &self.usages[usage.bits() as usize]; - &usage.types[..usage.types_count as usize] - } -} - -fn one_usage(usage: UsageFlags, memory_types: &[MemoryType]) -> MemoryForOneUsage { - let mut types = [0; 32]; - let mut types_count = 0; - - for (index, mt) in memory_types.iter().enumerate() { - if compatible(usage, mt.props) { - types[types_count as usize] = index as u32; - types_count += 1; - } - } - - types[..types_count as usize] - .sort_unstable_by_key(|&index| priority(usage, memory_types[index as usize].props)); - - let mask = types[..types_count as usize] - .iter() - .fold(0u32, |mask, index| mask | 1u32 << index); - - MemoryForOneUsage { - mask, - types, - types_count, - } -} - -fn compatible(usage: UsageFlags, flags: MemoryPropertyFlags) -> bool { - type Flags = MemoryPropertyFlags; - if flags.contains(Flags::LAZILY_ALLOCATED) || flags.contains(Flags::PROTECTED) { - // Unsupported - false - } else if usage.intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD) - { - // Requires HOST_VISIBLE - flags.contains(Flags::HOST_VISIBLE) - } else { - true - } -} - -/// Returns priority of memory with specified flags for specified usage. -/// Lesser value returned = more prioritized. -fn priority(usage: UsageFlags, flags: MemoryPropertyFlags) -> u32 { - type Flags = MemoryPropertyFlags; - - // Highly prefer device local memory when `FAST_DEVICE_ACCESS` usage is specified - // or usage is empty. - let device_local: bool = flags.contains(Flags::DEVICE_LOCAL) - ^ (usage.is_empty() || usage.contains(UsageFlags::FAST_DEVICE_ACCESS)); - - assert!( - flags.contains(Flags::HOST_VISIBLE) - || !usage - .intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD) - ); - - // Prefer cached memory for downloads. - // Or non-cached if downloads are not expected. - let cached: bool = flags.contains(Flags::HOST_CACHED) ^ usage.contains(UsageFlags::DOWNLOAD); - - // Prefer coherent for both uploads and downloads. - // Prefer non-coherent if neither flags is set. - let coherent: bool = flags.contains(Flags::HOST_COHERENT) - ^ (usage.intersects(UsageFlags::UPLOAD | UsageFlags::DOWNLOAD)); - - // Each boolean is false if flags are preferred. - device_local as u32 * 4 + cached as u32 * 2 + coherent as u32 -} +use { + core::fmt::{self, Debug}, + gpu_alloc_types::{MemoryPropertyFlags, MemoryType}, +}; + +bitflags::bitflags! { + /// Memory usage type. + /// Bits set define intended usage for requested memory. + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub struct UsageFlags: u8 { + /// Hints for allocator to find memory with faster device access. + /// If no flags is specified than `FAST_DEVICE_ACCESS` is implied. + const FAST_DEVICE_ACCESS = 0x01; + + /// Memory will be accessed from host. + /// This flags guarantees that host memory operations will be available. + /// Otherwise implementation is encouraged to use non-host-accessible memory. + const HOST_ACCESS = 0x02; + + /// Hints allocator that memory will be used for data downloading. + /// Allocator will strongly prefer host-cached memory. + /// Implies `HOST_ACCESS` flag. + const DOWNLOAD = 0x04; + + /// Hints allocator that memory will be used for data uploading. + /// If `DOWNLOAD` flag is not set then allocator will assume that + /// host will access memory in write-only manner and may + /// pick not host-cached. + /// Implies `HOST_ACCESS` flag. + const UPLOAD = 0x08; + + /// Hints allocator that memory will be used for short duration + /// allowing to use faster algorithm with less memory overhead. + /// If use holds returned memory block for too long then + /// effective memory overhead increases instead. + /// Best use case is for staging buffer for single batch of operations. + const TRANSIENT = 0x10; + + /// Requests memory that can be addressed with `u64`. + /// Allows fetching device address for resources bound to that memory. + const DEVICE_ADDRESS = 0x20; + } +} + +#[derive(Clone, Copy, Debug)] +struct MemoryForOneUsage { + mask: u32, + types: [u32; 32], + types_count: u32, +} + +pub(crate) struct MemoryForUsage { + usages: [MemoryForOneUsage; 64], +} + +impl Debug for MemoryForUsage { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("MemoryForUsage") + .field("usages", &&self.usages[..]) + .finish() + } +} + +impl MemoryForUsage { + pub fn new(memory_types: &[MemoryType]) -> Self { + assert!( + memory_types.len() <= 32, + "Only up to 32 memory types supported" + ); + + let mut mfu = MemoryForUsage { + usages: [MemoryForOneUsage { + mask: 0, + types: [0; 32], + types_count: 0, + }; 64], + }; + + for usage in 0..64 { + mfu.usages[usage as usize] = + one_usage(UsageFlags::from_bits_truncate(usage), memory_types); + } + + mfu + } + + /// Returns mask with bits set for memory type indices that support the + /// usage. + pub fn mask(&self, usage: UsageFlags) -> u32 { + self.usages[usage.bits() as usize].mask + } + + /// Returns slice of memory type indices that support the usage. + /// Earlier memory type has priority over later. + pub fn types(&self, usage: UsageFlags) -> &[u32] { + let usage = &self.usages[usage.bits() as usize]; + &usage.types[..usage.types_count as usize] + } +} + +fn one_usage(usage: UsageFlags, memory_types: &[MemoryType]) -> MemoryForOneUsage { + let mut types = [0; 32]; + let mut types_count = 0; + + for (index, mt) in memory_types.iter().enumerate() { + if compatible(usage, mt.props) { + types[types_count as usize] = index as u32; + types_count += 1; + } + } + + types[..types_count as usize] + .sort_unstable_by_key(|&index| reverse_priority(usage, memory_types[index as usize].props)); + + let mask = types[..types_count as usize] + .iter() + .fold(0u32, |mask, index| mask | 1u32 << index); + + MemoryForOneUsage { + mask, + types, + types_count, + } +} + +fn compatible(usage: UsageFlags, flags: MemoryPropertyFlags) -> bool { + type Flags = MemoryPropertyFlags; + if flags.contains(Flags::LAZILY_ALLOCATED) || flags.contains(Flags::PROTECTED) { + // Unsupported + false + } else if usage.intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD) + { + // Requires HOST_VISIBLE + flags.contains(Flags::HOST_VISIBLE) + } else { + true + } +} + +/// Returns reversed priority of memory with specified flags for specified usage. +/// Lesser value returned = more prioritized. +fn reverse_priority(usage: UsageFlags, flags: MemoryPropertyFlags) -> u32 { + type Flags = MemoryPropertyFlags; + + // Highly prefer device local memory when `FAST_DEVICE_ACCESS` usage is specified + // or usage is empty. + let device_local: bool = flags.contains(Flags::DEVICE_LOCAL) + ^ (usage.is_empty() || usage.contains(UsageFlags::FAST_DEVICE_ACCESS)); + + assert!( + flags.contains(Flags::HOST_VISIBLE) + || !usage + .intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD) + ); + + // Prefer non-host-visible memory when host access is not required. + let host_visible: bool = flags.contains(Flags::HOST_VISIBLE) + ^ usage.intersects(UsageFlags::HOST_ACCESS | UsageFlags::UPLOAD | UsageFlags::DOWNLOAD); + + // Prefer cached memory for downloads. + // Or non-cached if downloads are not expected. + let host_cached: bool = + flags.contains(Flags::HOST_CACHED) ^ usage.contains(UsageFlags::DOWNLOAD); + + // Prefer coherent for both uploads and downloads. + // Prefer non-coherent if neither flags is set. + let host_coherent: bool = flags.contains(Flags::HOST_COHERENT) + ^ (usage.intersects(UsageFlags::UPLOAD | UsageFlags::DOWNLOAD)); + + // Each boolean is false if flags are preferred. + device_local as u32 * 8 + + host_visible as u32 * 4 + + host_cached as u32 * 2 + + host_coherent as u32 +} diff --git a/third_party/rust/gpu-alloc/src/util.rs b/third_party/rust/gpu-alloc/src/util.rs index f02259d958d6..c22d30dbbd7c 100644 --- a/third_party/rust/gpu-alloc/src/util.rs +++ b/third_party/rust/gpu-alloc/src/util.rs @@ -1,44 +1,44 @@ -use alloc::sync::Arc; - -/// Guarantees uniqueness only if `Weak` pointers are never created -/// from this `Arc` or clones. -pub(crate) fn is_arc_unique(arc: &mut Arc) -> bool { - let strong_count = Arc::strong_count(&*arc); - debug_assert_ne!(strong_count, 0, "This Arc should exist"); - - debug_assert!( - strong_count > 1 || Arc::get_mut(arc).is_some(), - "`Weak` pointer exists" - ); - - strong_count == 1 -} - -/// Can be used instead of `Arc::try_unwrap(arc).unwrap()` -/// when it is guaranteed to succeed. -pub(crate) unsafe fn arc_unwrap(mut arc: Arc) -> M { - use core::{mem::ManuallyDrop, ptr::read}; - debug_assert!(is_arc_unique(&mut arc)); - - // Get raw pointer to inner value. - let raw = Arc::into_raw(arc); - - // As `Arc` is unique and no Weak pointers exist - // it won't be dereferenced elsewhere. - let inner = read(raw); - - // Cast to `ManuallyDrop` which guarantees to have same layout - // and will skip dropping. - drop(Arc::from_raw(raw as *const ManuallyDrop)); - inner -} - -/// Can be used instead of `Arc::try_unwrap` -/// only if `Weak` pointers are never created from this `Arc` or clones. -pub(crate) unsafe fn try_arc_unwrap(mut arc: Arc) -> Option { - if is_arc_unique(&mut arc) { - Some(arc_unwrap(arc)) - } else { - None - } -} +use alloc::sync::Arc; + +/// Guarantees uniqueness only if `Weak` pointers are never created +/// from this `Arc` or clones. +pub(crate) fn is_arc_unique(arc: &mut Arc) -> bool { + let strong_count = Arc::strong_count(&*arc); + debug_assert_ne!(strong_count, 0, "This Arc should exist"); + + debug_assert!( + strong_count > 1 || Arc::get_mut(arc).is_some(), + "`Weak` pointer exists" + ); + + strong_count == 1 +} + +/// Can be used instead of `Arc::try_unwrap(arc).unwrap()` +/// when it is guaranteed to succeed. +pub(crate) unsafe fn arc_unwrap(mut arc: Arc) -> M { + use core::{mem::ManuallyDrop, ptr::read}; + debug_assert!(is_arc_unique(&mut arc)); + + // Get raw pointer to inner value. + let raw = Arc::into_raw(arc); + + // As `Arc` is unique and no Weak pointers exist + // it won't be dereferenced elsewhere. + let inner = read(raw); + + // Cast to `ManuallyDrop` which guarantees to have same layout + // and will skip dropping. + drop(Arc::from_raw(raw as *const ManuallyDrop)); + inner +} + +/// Can be used instead of `Arc::try_unwrap` +/// only if `Weak` pointers are never created from this `Arc` or clones. +pub(crate) unsafe fn try_arc_unwrap(mut arc: Arc) -> Option { + if is_arc_unique(&mut arc) { + Some(arc_unwrap(arc)) + } else { + None + } +} diff --git a/third_party/rust/metal/.cargo-checksum.json b/third_party/rust/metal/.cargo-checksum.json index 9bc06c85d0c6..e2acac27fb5d 100644 --- a/third_party/rust/metal/.cargo-checksum.json +++ b/third_party/rust/metal/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.lock":"52f1dbe7e210e54f2e5a580f0119bf73357efd9ae2cfe13ecc5d97d10e383072","Cargo.toml":"90d4cc28d3a0aaae093de4a76b09c83cdac808f626e74dcd2b59a68785becff1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","Makefile":"6fddc61a94f5b31a65b11c1bef8b19c92bff738716998076c5d49c2834223c75","README.md":"6817e12da257b43352f71f595dcc713adf117c734ebf656e6af2d7d04be27cd6","bors.toml":"c2733ec512a08bf76b6a1ed77270810a0edeb888ba24c2a75679e1eb1bd563a5","examples/argument-buffer/main.rs":"a087db6648a4b092520de29616521c704d892e0d3ace935d16f3f339415c4361","examples/bind/main.rs":"a0c85aad05f08666f9b380a7146a8473a6a6fe0db5d523760373093a0af20e5f","examples/bindless/main.rs":"0aaad9e42634c1ea204342a76c1bfe80c8fcf9d3ebe8247846cf63ecb08fb0d5","examples/caps/main.rs":"b7be00c1cc9042140d34ea05051152a7035f316f0bdcd31ac5a660a97e0c4f70","examples/circle/README.md":"e1c97cf5252f0d1f2934ace78b5d839c5f45911f3007dbd2925eeceefb8f0af6","examples/circle/main.rs":"91d80c85a358400ceeddf1ab108a7e1052dd208c4ec72cde925d02284d3cf9d4","examples/circle/screenshot.png":"97bf07c85bf02367447b9c8a81707c124e4a3b420fa386b95ba08b21938f4f2a","examples/circle/shaders.metal":"5e4f40efca5bb386204a09e1b983cc6c634fdf1ca9dd4974227313adbf50e8b5","examples/circle/shaders.metallib":"666a9491d795ef9c0b9c122c7ada571cc2c0e8774d2d89e5b4b996f3dc47962b","examples/compute/compute-argument-buffer.metal":"6530bbd6a0101d9db2893805436f5dc877959e81ea97a27014c0fc52fc9fa77b","examples/compute/compute-argument-buffer.rs":"e3de61fd7cc2f14d9d52300e4878601dbc072bc26d9dafc66115df58f94e0470","examples/compute/embedded-lib.rs":"55f701810fa5270c27ca771e713f9f8cf09e124a997b0b03790b38435593a7ea","examples/compute/main.rs":"f16cbf57cd27dc948ff651251ce26e6bd616cb5d989b8dadb4256c73a9bfba4b","examples/compute/shaders.metal":"f2b15551bb5247b88a3029c3d8ef37c6fa04a4a6cca9f90f069894ed6822b4bf","examples/compute/shaders.metallib":"fef91643e60c0ec99ad2bd2f3916299bcc3e6a80038ea27bed59681badfea7d1","examples/events/main.rs":"9cb35381b0a3918bd7d530171de8f7cceafe3d4851c0f430b4aff1f5c2aae749","examples/fence/main.rs":"47741327e62db1d8bd344b6a9ec26ef13ffb0b56b0dd7077c5d926d43faaeff7","examples/headless-render/README.md":"b1c97b52701cfb41fc0b9e269ba7a7a454d9161746198e2f5789f2636f60842d","examples/headless-render/main.rs":"cf0180839e8d09d4bf403ae947365ac18fa17782172986311bfa04b84f88169e","examples/headless-render/screenshot.png":"01d6ea5791b63b0f01190198756446cf313fc25dc64d0138c1b4f62c9f862dd1","examples/library/main.rs":"a1420ec28a471f28a789b75b3ecf5abb699ed352b337747169914812fb98045a","examples/mps/main.rs":"51f34582bf118f171bbb81d22c11407c7a35f381dbbff2d75c6f8e90d22a2aa1","examples/mps/shaders.metal":"155922d6a4184078ae7ee29504a268e1218f07d908f921eef60e5bfa8a793bda","examples/mps/shaders.metallib":"b62451223549b1e7eb90ec3d3534c0ed4cdfdc581c7df3ffcdc4786a5fcacde4","examples/reflection/main.rs":"01b0cd95558b8c3e547b239a1b2ae7e882ab0f52346f96bcefd2e9616693a98c","examples/shader-dylib/main.rs":"d29ab2105131b8c56a6af6453f1d973e2bda5564f84b652c01e4a4e44b7a70f2","examples/shader-dylib/test_dylib.metal":"3469de785c2c0da784e84758fc0da5a81e474ca15588485d9e04398690641cc8","examples/shader-dylib/test_shader.metal":"1a04ff8ab3288b09d14cd35440b2557e92ddedbff9d07c4144a22e9062e6e1e4","examples/window/README.md":"69655cff298e07887fe70e8a13e27d8a87efcd0cc0da4e15485134e064e1aceb","examples/window/main.rs":"09c508013223de859f33fb69410bde30e8d7f04952850504d8b1f8faf7049b1b","examples/window/screenshot.png":"da7369d7cc297c7f7f6bd773c93e7d708d72442c9c5ff5a20c2f2ee6852552dc","examples/window/shaders.metal":"90dee6c752add5c617dfdca93064b2824b44ff8c01ef63986826f6a1531e95d6","examples/window/shaders.metallib":"16fa82beb70bf16c3501970cae0d5028a747a08164337161dc9c2e8965d4c366","src/argument.rs":"578ca587dfb034a7e8e4551fd93164a86595a4637e5656fc6cc429ae2de6cda2","src/buffer.rs":"80c55c8703340bf0d4d1b5eface518fdf82355ccb897883639cbf7e4933a4344","src/capturedescriptor.rs":"7d90b1e7b87fa9da1e38bba9637cd8d7a18a81f8c3f408149058ed4ea20a6894","src/capturemanager.rs":"bdee9e170da371778452513a9ac363a738ea8bfd3f0870d86c6013459c5af010","src/commandbuffer.rs":"8636043739fb9ea44f443ef315fadfa13675d04827e5fac42abcde0b2c612a0c","src/commandqueue.rs":"5b87621ae4495ae04a5de5ce980d0cde31b4bb0d1e31e932d34c49252240c9d9","src/constants.rs":"d9bea9cb01892f40fb635cef5ca247023c1998b47b33cc5ce39696fac634383b","src/depthstencil.rs":"5bfa4f49940fdc9d12b2af08f7fe710c41f0b7e26bdb6f8709fe17b9a9d7d5eb","src/device.rs":"1af6bc1c60981c60d102338bb9618c3a6bb215994501a64c31997dd1e7976377","src/drawable.rs":"aea0759dc9de002c660e938319dfdfd3e4e82add30ed626ea31e3270698f4b85","src/encoder.rs":"2d0f402f1b286459a7c3b0dbbc640a81a7e3f6698f7ca7a78f5bfa09e9b633e9","src/heap.rs":"fcbb7dfaafb1008fadd75fb2b394776c9843fe98a266e237d7a7b4d80e046b06","src/indirect_encoder.rs":"c61c610ac4607a6b76c551becb88e054c9754b5cc31b144e4b6f26202e6294f7","src/lib.rs":"a297e4d0f831d82bc6fe53ed0692b8d06ac43420e257b26f5ea69a03a459c505","src/library.rs":"985bb5833b55f054b932df425932574d6c65ee2ed11b5e1ccd5a2e279c52d54c","src/mps.rs":"b415be3221754d836fd535f4b5b45ed484d4cc926bd26145e82a9e61d337da4c","src/pipeline/compute.rs":"e4bed01671a466ed460fbc9059ac72dab7cb123a964de63058f0e5aafdc5e2a0","src/pipeline/mod.rs":"5ec3cb524cc03202a3394dad5a7d0b733474f664935353253e76a49aed5513ad","src/pipeline/render.rs":"6738931629f1944d69815622a9f3281e55df0e56dc87d3cdb885cc8c7e2c8820","src/renderpass.rs":"666ca2a35d2bb96564f105a87f03cfbf87d3fd10e6915e473e8ff4c0db49fdef","src/resource.rs":"9753cc15c5d0064e954717c61feb902c218141b1b0e77bce4f9d0653b6d4589b","src/sampler.rs":"adabef3520a18c829bfd9b705897873d9adc37ebe88cfa6864154483dd858b9d","src/sync.rs":"a2c081984630634134b17007a6ff7a016e2aa9070bc46754d3e82500fc25eb53","src/texture.rs":"773bb005cb17c17b4e0138e328fcbeef37d437032406521f874527782d842ef6","src/types.rs":"5a754c8036ff4ab1ec41d01af5fba64f3085f2a9dd1d15d00e907e40b85cf163","src/vertexdescriptor.rs":"5874f54bcc5613adff613ed3e2bb08870b1115ef6d369b21612ce848796b005e"},"package":"de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060"} \ No newline at end of file +{"files":{"Cargo.lock":"184f7d96e94c01f18ce7fafeaae5bad38d6c1084a0f11196710273dbab02d70a","Cargo.toml":"ff4ac6941b706e0baed1fb4ccc0e6993bd4a1d716a6a85d0997a1de01786870a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","Makefile":"99c4c592467981921d1257a4e9e841dce53624448738d0ed52a75431a406f7bc","README.md":"b61a350d23e7c88c34b1cd703083978e17c28a286e4231f1dc0a2383a1f85902","assets/metal.svg":"3a295bd130785bc2fea2f3a91a4f6c7b4b3c40682c3fcb7a75f9887b66b06264","bors.toml":"c2733ec512a08bf76b6a1ed77270810a0edeb888ba24c2a75679e1eb1bd563a5","examples/argument-buffer/main.rs":"a087db6648a4b092520de29616521c704d892e0d3ace935d16f3f339415c4361","examples/bind/main.rs":"a0c85aad05f08666f9b380a7146a8473a6a6fe0db5d523760373093a0af20e5f","examples/bindless/main.rs":"0aaad9e42634c1ea204342a76c1bfe80c8fcf9d3ebe8247846cf63ecb08fb0d5","examples/caps/main.rs":"b7be00c1cc9042140d34ea05051152a7035f316f0bdcd31ac5a660a97e0c4f70","examples/circle/README.md":"e1c97cf5252f0d1f2934ace78b5d839c5f45911f3007dbd2925eeceefb8f0af6","examples/circle/main.rs":"22bd52ccba85debc1ccb3f277750e4759283d3c9b135b9a0da496c747e4cf637","examples/circle/screenshot.png":"97bf07c85bf02367447b9c8a81707c124e4a3b420fa386b95ba08b21938f4f2a","examples/circle/shaders.metal":"5e4f40efca5bb386204a09e1b983cc6c634fdf1ca9dd4974227313adbf50e8b5","examples/circle/shaders.metallib":"666a9491d795ef9c0b9c122c7ada571cc2c0e8774d2d89e5b4b996f3dc47962b","examples/compute/compute-argument-buffer.metal":"6530bbd6a0101d9db2893805436f5dc877959e81ea97a27014c0fc52fc9fa77b","examples/compute/compute-argument-buffer.rs":"e3de61fd7cc2f14d9d52300e4878601dbc072bc26d9dafc66115df58f94e0470","examples/compute/embedded-lib.rs":"55f701810fa5270c27ca771e713f9f8cf09e124a997b0b03790b38435593a7ea","examples/compute/main.rs":"155bfcb6b6289642e4a97582ff8993742fac69dc443cfb23a0b1f170b1e44d4f","examples/compute/shaders.metal":"f2b15551bb5247b88a3029c3d8ef37c6fa04a4a6cca9f90f069894ed6822b4bf","examples/compute/shaders.metallib":"fef91643e60c0ec99ad2bd2f3916299bcc3e6a80038ea27bed59681badfea7d1","examples/events/main.rs":"9cb35381b0a3918bd7d530171de8f7cceafe3d4851c0f430b4aff1f5c2aae749","examples/fence/main.rs":"47741327e62db1d8bd344b6a9ec26ef13ffb0b56b0dd7077c5d926d43faaeff7","examples/headless-render/README.md":"b1c97b52701cfb41fc0b9e269ba7a7a454d9161746198e2f5789f2636f60842d","examples/headless-render/main.rs":"2e6eb5db66f28833d1b53df3f134b4b53907a00036eeb6cdd9e428478e164aae","examples/headless-render/screenshot.png":"01d6ea5791b63b0f01190198756446cf313fc25dc64d0138c1b4f62c9f862dd1","examples/library/main.rs":"a1420ec28a471f28a789b75b3ecf5abb699ed352b337747169914812fb98045a","examples/mesh-shader/main.rs":"49899300f80f2d1e64366176313f69b597b69f3728a52a6a6f56ff7cd54c3c23","examples/mesh-shader/shaders.metal":"6ba934c3edd3ba0b8f6c4ac37be0fd0fe35eeef004e371521b7bf5a2fae9a223","examples/mesh-shader/shaders.metallib":"0af3b7ab0cd6186a90163550b76fab5bd2ef6ba97e791354d4281ca92d4887ff","examples/mps/main.rs":"2cbb532635270bc55cdfa3ee231cc2ee20dd8b3a5e6bf76062cca89ef1e3498f","examples/mps/shaders.metal":"155922d6a4184078ae7ee29504a268e1218f07d908f921eef60e5bfa8a793bda","examples/mps/shaders.metallib":"b62451223549b1e7eb90ec3d3534c0ed4cdfdc581c7df3ffcdc4786a5fcacde4","examples/raytracing/README.md":"6f0d683efac74572099c317ce9f65c3e6ff3c5252c6870c0c38c67f08b37bb01","examples/raytracing/camera.rs":"bed7a1787e1a52060dd0d64ff630a6fb769f15098d0a9d3ea68d4b57aee78b53","examples/raytracing/geometry.rs":"d3db29b4ab2d3d39de74718e0a7133a4e576dc26dcc6b6728c047865fb78952a","examples/raytracing/main.rs":"c3571854cbaaaeea386d7eb8af1fe9ea0492eae9af62b60203f4b6937dc4999a","examples/raytracing/renderer.rs":"d4e704b8f8e61919882aafc009b3a20928902d5b7edb9122d05f3e468d32f613","examples/raytracing/scene.rs":"fc2f214e0ad90e916fdbe2a339567a5dd323ef45b916fa8432c1156b4e94b998","examples/raytracing/screenshot.png":"400bb138f5adb69e4db8626681fb17667e5e112c94864879d9282d5348d970db","examples/raytracing/shaders.metal":"696f6a0ba79d82e2fa0e03eadbff2f6cdeac87acc805c2b7df657b85c1173174","examples/raytracing/shaders.metallib":"249b71998f58ddf8b3de37d79e9cc1f4a3494fba4bd7ba3f5411fb603de9dd5a","examples/reflection/main.rs":"563b49f5c057f1f8d17f3480cbc466e073ea575bfafaf84018a331a984d90a62","examples/shader-dylib/main.rs":"f18f4eb01420e12c196848c42657d41390cf10a3e47e8870025c20a1b29ddc71","examples/shader-dylib/test_dylib.metal":"3469de785c2c0da784e84758fc0da5a81e474ca15588485d9e04398690641cc8","examples/shader-dylib/test_shader.metal":"1a04ff8ab3288b09d14cd35440b2557e92ddedbff9d07c4144a22e9062e6e1e4","examples/window/README.md":"69655cff298e07887fe70e8a13e27d8a87efcd0cc0da4e15485134e064e1aceb","examples/window/main.rs":"09c508013223de859f33fb69410bde30e8d7f04952850504d8b1f8faf7049b1b","examples/window/screenshot.png":"da7369d7cc297c7f7f6bd773c93e7d708d72442c9c5ff5a20c2f2ee6852552dc","examples/window/shaders.metal":"90dee6c752add5c617dfdca93064b2824b44ff8c01ef63986826f6a1531e95d6","examples/window/shaders.metallib":"16fa82beb70bf16c3501970cae0d5028a747a08164337161dc9c2e8965d4c366","src/accelerator_structure.rs":"adb3c65111da0365825b6f7dc686e0c5aad6e3b1c1b5834c480ad4de886475bf","src/argument.rs":"3fa716bdb17bba6fd29289576a13a65689e1f63995eabb26e6c8d00f179ef7d4","src/buffer.rs":"78d9021ab75ef0dad09ff92d126f1ceea241cca606cd7b05553c9351458babed","src/capturedescriptor.rs":"c687c4db298fb83ef640eb34929758c2d7955174a68725e986838e367291e302","src/capturemanager.rs":"c8a42854eebcfb6a7b777d931e368e04a5e35dff2e46c38c481d266dba9b792d","src/commandbuffer.rs":"6c38e9738bb86a095eb4de0dc64ea94277360bf4a35b65ad15a8b69f2ae3a13c","src/commandqueue.rs":"a7d6dee5d064093521465e1da30bded851aa9d59f078942d88926d0f38de82fd","src/computepass.rs":"7c209dc60abc3cb45ed4b1648fd01faaeb561ef980d2b37c3d69a7e5fed9129d","src/constants.rs":"bbfeecf910d4f9ed149a7988d8a79df6e9ad479de81f7fc1294d3434a721b7fd","src/counters.rs":"d36d88f95015eef3655fc114eba1ef680d6a5bf74849389da2d09178244a01c4","src/depthstencil.rs":"d6687878c6e89e1c01b605c3c4e62e32a7d9bb48a8ebd31bf4dcf895e6838588","src/device.rs":"0e8b45d2f2a355485f1e6edafc28a92352f38f0f23aa25d3a0bc30a6e425cb3a","src/drawable.rs":"2006151031fced10a8b347d9cf465ef15f62551f134d3ff1715e3f3831155f23","src/encoder.rs":"aabf819459aa44bba16addfefde979d35c8f34f33e856714a244addc5e28dda7","src/heap.rs":"843536c73cb19643bf7d286433daebf703c28238775d5e006865247c50dabfbf","src/indirect_encoder.rs":"72897df3dd38efd58d8f34f78c3a50012177f725ade9e154071d238206ae7415","src/lib.rs":"56827ece927e6bc72feeb669f030224954215d85c3abba2a9b46f55b95e67d5f","src/library.rs":"e13dae9c74ca3709d1f4e4b5a93c2d2df6a00f1af9c6a65bebd646e426989c97","src/mps.rs":"2db71223faee22ae285ccc6913e79e7a212475ac3e1cc99aff5b335db2499b25","src/pipeline/compute.rs":"6391a19ca5bc5c2d43891a24456087e3945b093d74583cb3ea0adae15ffad98b","src/pipeline/mod.rs":"280916e71b6f3c5fffda6ffee31c616bf4aba6e5a186401ea2febe71c3264145","src/pipeline/render.rs":"bfbbee1d444342e043023dfa8a3f1fde753ed239c93ad026cb9b22a52235eca5","src/renderpass.rs":"01d4bd8001b6b224f8d7ac5fe5cde45bc34712308e2c1ef05c2e1a4b50397c41","src/resource.rs":"319b3f4645f418e2364eb135af992124994ea8c28744ac6f1c589ad1eeca2aad","src/sampler.rs":"780b75b22ab1f6a6675d6e1bd04bd7457660c3325519bffb13a08b1abc64a79c","src/sync.rs":"2cb568bbb81e5f4d2f7ca3d31d6ab8ab493439065d180de4e97ad166f166f7f8","src/texture.rs":"dc26effafd6e46b97a8f6b9ce69870d1de3fd05f290e17808c858c74ab2b0a11","src/types.rs":"d255f9c1b449acdb971616255e1c98d35b3b1ac54d9c388f7cdff6cfc3a8b944","src/vertexdescriptor.rs":"6a1378f270f7adf631319bcc8c8d6831c9f9be55e7b39a7ccfe151af9a9363c4"},"package":"550b24b0cd4cf923f36bae78eca457b3a10d8a6a14a9c84cb2687b527e6a84af"} \ No newline at end of file diff --git a/third_party/rust/metal/Cargo.lock b/third_party/rust/metal/Cargo.lock index 829c3a2b728a..171b3c7b968e 100644 --- a/third_party/rust/metal/Cargo.lock +++ b/third_party/rust/metal/Cargo.lock @@ -3,29 +3,22 @@ version = 3 [[package]] -name = "ab_glyph_rasterizer" -version = "0.1.5" +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "adler32" -version = "1.2.0" +name = "arrayref" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] -name = "andrew" -version = "0.3.1" +name = "arrayvec" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" -dependencies = [ - "bitflags", - "rusttype", - "walkdir", - "xdg", - "xml-rs", -] +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "autocfg" @@ -46,19 +39,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] -name = "byteorder" -version = "1.4.3" +name = "bumpalo" +version = "3.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" [[package]] name = "calloop" -version = "0.6.5" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" +checksum = "1a59225be45a478d772ce015d9743e49e92798ece9e34eda9a6aa2a6a7f40192" dependencies = [ "log", - "nix 0.18.0", + "nix 0.25.1", + "slotmap", + "thiserror", + "vec_map", ] [[package]] @@ -67,18 +69,21 @@ version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "cocoa" version = "0.24.0" @@ -88,10 +93,10 @@ dependencies = [ "bitflags", "block", "cocoa-foundation", - "core-foundation 0.9.3", - "core-graphics 0.22.3", - "foreign-types", - "libc 0.2.126", + "core-foundation", + "core-graphics", + "foreign-types 0.3.2", + "libc 0.2.144", "objc", ] @@ -103,57 +108,29 @@ checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" dependencies = [ "bitflags", "block", - "core-foundation 0.9.3", + "core-foundation", "core-graphics-types", - "foreign-types", - "libc 0.2.126", + "foreign-types 0.3.2", + "libc 0.2.144", "objc", ] -[[package]] -name = "core-foundation" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -dependencies = [ - "core-foundation-sys 0.7.0", - "libc 0.2.126", -] - [[package]] name = "core-foundation" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ - "core-foundation-sys 0.8.3", - "libc 0.2.126", + "core-foundation-sys", + "libc 0.2.144", ] -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" - [[package]] name = "core-foundation-sys" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "core-graphics" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" -dependencies = [ - "bitflags", - "core-foundation 0.7.0", - "foreign-types", - "libc 0.2.126", -] - [[package]] name = "core-graphics" version = "0.22.3" @@ -161,10 +138,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ "bitflags", - "core-foundation 0.9.3", + "core-foundation", "core-graphics-types", - "foreign-types", - "libc 0.2.126", + "foreign-types 0.3.2", + "libc 0.2.144", ] [[package]] @@ -174,22 +151,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" dependencies = [ "bitflags", - "core-foundation 0.9.3", - "foreign-types", - "libc 0.2.126", + "core-foundation", + "foreign-types 0.3.2", + "libc 0.2.144", ] [[package]] -name = "core-video-sys" -version = "0.1.4" +name = "core-text" +version = "19.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" +checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" dependencies = [ - "cfg-if 0.1.10", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", - "libc 0.2.126", - "objc", + "core-foundation", + "core-graphics", + "foreign-types 0.3.2", + "libc 0.2.144", ] [[package]] @@ -198,7 +174,30 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", +] + +[[package]] +name = "crossfont" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21fd3add36ea31aba1520aa5288714dd63be506106753226d0eb387a93bc9c45" +dependencies = [ + "cocoa", + "core-foundation", + "core-foundation-sys", + "core-graphics", + "core-text", + "dwrote", + "foreign-types 0.5.0", + "freetype-rs", + "libc 0.2.144", + "log", + "objc", + "once_cell", + "pkg-config", + "servo-fontconfig", + "winapi", ] [[package]] @@ -209,9 +208,9 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" [[package]] name = "darling" -version = "0.10.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ "darling_core", "darling_macro", @@ -219,68 +218,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.10.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn", + "syn 1.0.98", ] [[package]] name = "darling_macro" -version = "0.10.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn", -] - -[[package]] -name = "deflate" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" -dependencies = [ - "adler32", - "byteorder", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc 0.2.126", - "redox_users", - "winapi 0.3.9", + "syn 1.0.98", ] [[package]] @@ -289,22 +247,13 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" -[[package]] -name = "dlib" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" -dependencies = [ - "libloading 0.6.7", -] - [[package]] name = "dlib" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" dependencies = [ - "libloading 0.7.3", + "libloading", ] [[package]] @@ -313,6 +262,49 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "dwrote" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +dependencies = [ + "lazy_static", + "libc 0.2.144", + "serde", + "serde_derive", + "winapi", + "wio", +] + +[[package]] +name = "expat-sys" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" +dependencies = [ + "cmake", + "pkg-config", +] + +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -325,7 +317,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", ] [[package]] @@ -334,61 +347,89 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "freetype-rs" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74eadec9d0a5c28c54bb9882e54787275152a4e36ce206b45d7451384e5bf5fb" +dependencies = [ + "bitflags", + "freetype-sys", + "libc 0.2.144", +] + +[[package]] +name = "freetype-sys" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +dependencies = [ + "cmake", + "libc 0.2.144", + "pkg-config", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "getrandom" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ - "cfg-if 1.0.0", - "libc 0.2.126", + "cfg-if", + "libc 0.2.144", "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "glam" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc 0.2.126", + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -398,13 +439,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "js-sys" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "wasm-bindgen", ] [[package]] @@ -413,12 +453,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.1.12" @@ -427,19 +461,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "libloading" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libloading" @@ -447,8 +471,8 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", + "cfg-if", + "winapi", ] [[package]] @@ -467,7 +491,7 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -476,7 +500,7 @@ version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" dependencies = [ - "libc 0.2.126", + "libc 0.1.12", ] [[package]] @@ -487,16 +511,25 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.1.0" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ - "libc 0.2.126", + "libc 0.2.144", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", ] [[package]] name = "metal" -version = "0.24.0" +version = "0.25.0" dependencies = [ "bitflags", "block", @@ -504,10 +537,13 @@ dependencies = [ "core-graphics-types", "cty", "dispatch", - "foreign-types", + "foreign-types 0.5.0", + "glam", "log", "objc", + "paste", "png", + "rand 0.8.5", "sema", "winit", ] @@ -520,134 +556,107 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.3.7" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ - "adler32", + "adler", + "simd-adler32", ] [[package]] name = "mio" -version = "0.6.23" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc 0.2.126", + "libc 0.2.144", "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.45.0", ] [[package]] name = "ndk" -version = "0.2.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" dependencies = [ + "bitflags", "jni-sys", "ndk-sys", "num_enum", + "raw-window-handle 0.5.2", "thiserror", ] [[package]] -name = "ndk-glue" -version = "0.2.1" +name = "ndk-context" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-glue" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" dependencies = [ - "lazy_static", - "libc 0.2.126", + "libc 0.2.144", "log", "ndk", + "ndk-context", "ndk-macro", "ndk-sys", + "once_cell", + "parking_lot", ] [[package]] name = "ndk-macro" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" +checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" dependencies = [ "darling", "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] name = "ndk-sys" -version = "0.2.2" +version = "0.4.1+23.1.7779620" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" - -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" dependencies = [ - "cfg-if 0.1.10", - "libc 0.2.126", - "winapi 0.3.9", + "jni-sys", ] [[package]] name = "nix" -version = "0.18.0" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags", - "cc", - "cfg-if 0.1.10", - "libc 0.2.126", + "cfg-if", + "libc 0.2.144", + "memoffset", ] [[package]] name = "nix" -version = "0.20.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ + "autocfg", "bitflags", - "cc", - "cfg-if 1.0.0", - "libc 0.2.126", + "cfg-if", + "libc 0.2.144", + "memoffset", ] [[package]] @@ -662,24 +671,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.4.3" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "derivative", "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.4.3" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -703,44 +711,39 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" - -[[package]] -name = "owned_ttf_parser" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" -dependencies = [ - "ttf-parser", -] +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "parking_lot" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "instant", "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc 0.2.126", + "cfg-if", + "libc 0.2.144", "redox_syscall", "smallvec", - "winapi 0.3.9", + "windows-sys 0.45.0", ] +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -755,39 +758,47 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "png" -version = "0.16.8" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" dependencies = [ "bitflags", "crc32fast", - "deflate", + "fdeflate", + "flate2", "miniz_oxide", ] [[package]] -name = "proc-macro-crate" -version = "0.1.5" +name = "ppv-lite86" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ - "toml", + "once_cell", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.20" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ "proc-macro2", ] @@ -798,7 +809,7 @@ version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" dependencies = [ - "libc 0.2.126", + "libc 0.2.144", "rand 0.4.6", ] @@ -809,10 +820,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" dependencies = [ "fuchsia-cprng", - "libc 0.2.126", + "libc 0.2.144", "rand_core 0.3.1", "rdrand", - "winapi 0.3.9", + "winapi", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc 0.2.144", + "rand_chacha", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] @@ -831,13 +863,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] -name = "raw-window-handle" -version = "0.3.4" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "libc 0.2.126", - "raw-window-handle 0.4.3", + "getrandom", ] [[package]] @@ -849,6 +880,12 @@ dependencies = [ "cty", ] +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + [[package]] name = "rdrand" version = "0.4.0" @@ -868,33 +905,12 @@ dependencies = [ ] [[package]] -name = "redox_users" -version = "0.4.3" +name = "safe_arch" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "c1ff3d6d9696af502cc3110dacce942840fb06ff4514cad92236ecc455f2ce05" dependencies = [ - "getrandom", - "redox_syscall", - "thiserror", -] - -[[package]] -name = "rusttype" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", + "bytemuck", ] [[package]] @@ -909,6 +925,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sctk-adwaita" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61270629cc6b4d77ec1907db1033d5c2e1a404c412743621981a871dc9c12339" +dependencies = [ + "crossfont", + "log", + "smithay-client-toolkit", + "tiny-skia", +] + [[package]] name = "sema" version = "0.1.4" @@ -927,10 +955,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" [[package]] -name = "slab" -version = "0.4.6" +name = "serde_derive" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", +] + +[[package]] +name = "servo-fontconfig" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" +dependencies = [ + "libc 0.2.144", + "servo-fontconfig-sys", +] + +[[package]] +name = "servo-fontconfig-sys" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" +dependencies = [ + "expat-sys", + "freetype-sys", + "pkg-config", +] + +[[package]] +name = "simd-adler32" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" + +[[package]] +name = "slotmap" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" +dependencies = [ + "version_check", +] [[package]] name = "smallvec" @@ -940,18 +1009,18 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "smithay-client-toolkit" -version = "0.12.3" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80" +checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454" dependencies = [ - "andrew", "bitflags", "calloop", - "dlib 0.4.2", + "dlib", "lazy_static", "log", "memmap2", - "nix 0.18.0", + "nix 0.24.3", + "pkg-config", "wayland-client", "wayland-cursor", "wayland-protocols", @@ -959,9 +1028,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -974,6 +1043,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "thiserror" version = "1.0.31" @@ -991,7 +1071,7 @@ checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -1000,25 +1080,52 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ - "libc 0.2.126", + "libc 0.2.144", "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", + "winapi", ] [[package]] -name = "toml" -version = "0.5.9" +name = "tiny-skia" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "642680569bb895b16e4b9d181c60be1ed136fa0c9c7f11d004daf053ba89bf82" dependencies = [ - "serde", + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "png", + "safe_arch", + "tiny-skia-path", ] [[package]] -name = "ttf-parser" +name = "tiny-skia-path" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c114d32f0c2ee43d585367cb013dfaba967ab9f62b90d9af0d696e955e70fa6c" +dependencies = [ + "arrayref", + "bytemuck", +] + +[[package]] +name = "toml_datetime" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" + +[[package]] +name = "toml_edit" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] [[package]] name = "unicode-ident" @@ -1027,15 +1134,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" [[package]] -name = "walkdir" -version = "2.3.2" +name = "vec_map" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi 0.3.9", - "winapi-util", -] +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" @@ -1050,15 +1158,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wayland-client" -version = "0.28.6" +name = "wasm-bindgen" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ab332350e502f159382201394a78e3cc12d0f04db863429260164ea40e0355" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.16", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" + +[[package]] +name = "wayland-client" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" dependencies = [ "bitflags", "downcast-rs", - "libc 0.2.126", - "nix 0.20.0", + "libc 0.2.144", + "nix 0.24.3", "scoped-tls", "wayland-commons", "wayland-scanner", @@ -1067,11 +1229,11 @@ dependencies = [ [[package]] name = "wayland-commons" -version = "0.28.6" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21817947c7011bbd0a27e11b17b337bfd022e8544b071a2641232047966fbda" +checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" dependencies = [ - "nix 0.20.0", + "nix 0.24.3", "once_cell", "smallvec", "wayland-sys", @@ -1079,20 +1241,20 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.28.6" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be610084edd1586d45e7bdd275fe345c7c1873598caa464c4fb835dee70fa65a" +checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" dependencies = [ - "nix 0.20.0", + "nix 0.24.3", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.28.6" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286620ea4d803bacf61fa087a4242ee316693099ee5a140796aaba02b29f861f" +checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" dependencies = [ "bitflags", "wayland-client", @@ -1102,9 +1264,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.28.6" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce923eb2deb61de332d1f356ec7b6bf37094dc5573952e1c8936db03b54c03f1" +checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" dependencies = [ "proc-macro2", "quote", @@ -1113,20 +1275,24 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.28.6" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d841fca9aed7febf9bed2e9796c49bf58d4152ceda8ac949ebe00868d8f0feb8" +checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" dependencies = [ - "dlib 0.5.0", + "dlib", "lazy_static", "pkg-config", ] [[package]] -name = "winapi" -version = "0.2.8" +name = "web-sys" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "winapi" @@ -1138,27 +1304,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1166,44 +1317,163 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "winit" -version = "0.24.0" +name = "windows-sys" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4eda6fce0eb84bd0a33e3c8794eb902e1033d0a1d5a31bc4f19b1b4bbff597" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "winit" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb796d6fbd86b2fd896c9471e6f04d39d750076ebe5680a3958f00f5ab97657c" dependencies = [ "bitflags", "cocoa", - "core-foundation 0.9.3", - "core-graphics 0.22.3", - "core-video-sys", + "core-foundation", + "core-graphics", "dispatch", "instant", - "lazy_static", - "libc 0.2.126", + "libc 0.2.144", "log", "mio", - "mio-extras", "ndk", "ndk-glue", - "ndk-sys", "objc", + "once_cell", "parking_lot", "percent-encoding", - "raw-window-handle 0.3.4", + "raw-window-handle 0.4.3", + "raw-window-handle 0.5.2", + "sctk-adwaita", "smithay-client-toolkit", + "wasm-bindgen", "wayland-client", - "winapi 0.3.9", + "wayland-protocols", + "web-sys", + "windows-sys 0.36.1", "x11-dl", ] [[package]] -name = "ws2_32-sys" -version = "0.2.1" +name = "winnow" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "memchr", +] + +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", ] [[package]] @@ -1213,7 +1483,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" dependencies = [ "lazy_static", - "libc 0.2.126", + "libc 0.2.144", "pkg-config", ] @@ -1226,15 +1496,6 @@ dependencies = [ "nom", ] -[[package]] -name = "xdg" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4583db5cbd4c4c0303df2d15af80f0539db703fa1c68802d4cbbd2dd0f88f6" -dependencies = [ - "dirs", -] - [[package]] name = "xml-rs" version = "0.8.4" diff --git a/third_party/rust/metal/Cargo.toml b/third_party/rust/metal/Cargo.toml index 9b7c52f8bfc4..abd300f93c09 100644 --- a/third_party/rust/metal/Cargo.toml +++ b/third_party/rust/metal/Cargo.toml @@ -10,9 +10,9 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" +edition = "2021" name = "metal" -version = "0.24.0" +version = "0.25.0" authors = ["GFX Developers"] exclude = [ "guide/**/*", @@ -45,6 +45,9 @@ name = "headless-render" [[example]] name = "library" +[[example]] +name = "raytracing" + [[example]] name = "reflection" @@ -101,7 +104,7 @@ version = "0.2" optional = true [dependencies.foreign-types] -version = "0.3.2" +version = "0.5" [dependencies.log] version = "0.4" @@ -110,20 +113,29 @@ version = "0.4" version = "0.2.4" features = ["objc_exception"] +[dependencies.paste] +version = "1" + [dev-dependencies.cocoa] version = "0.24.0" [dev-dependencies.cty] version = "0.2.1" +[dev-dependencies.glam] +version = "0.22" + [dev-dependencies.png] -version = "0.16" +version = "0.17" + +[dev-dependencies.rand] +version = "0.8" [dev-dependencies.sema] version = "0.1.4" [dev-dependencies.winit] -version = "0.24" +version = "0.27" [features] default = [] diff --git a/third_party/rust/metal/Makefile b/third_party/rust/metal/Makefile index bc3587694534..ee7870c4e35b 100644 --- a/third_party/rust/metal/Makefile +++ b/third_party/rust/metal/Makefile @@ -10,3 +10,7 @@ window: circle: xcrun -sdk macosx metal -c examples/circle/shaders.metal -o examples/circle/shaders.air xcrun -sdk macosx metallib examples/circle/shaders.air -o examples/circle/shaders.metallib + +raytracing: + xcrun -sdk macosx metal -c -g examples/raytracing/shaders.metal -o examples/raytracing/shaders.air + xcrun -sdk macosx metallib examples/raytracing/shaders.air -o examples/raytracing/shaders.metallib diff --git a/third_party/rust/metal/README.md b/third_party/rust/metal/README.md index 7fac036e5f62..ef94a72da852 100644 --- a/third_party/rust/metal/README.md +++ b/third_party/rust/metal/README.md @@ -2,7 +2,18 @@ [![Actions Status](https://github.com/gfx-rs/metal-rs/workflows/ci/badge.svg)](https://github.com/gfx-rs/metal-rs/actions) [![Crates.io](https://img.shields.io/crates/v/metal.svg?label=metal)](https://crates.io/crates/metal) -Unsafe Rust bindings for the Metal 3D Graphics API. +

+ +

+ +

Unsafe Rust bindings for the Metal 3D Graphics API.

+ +## Documentation + +Note that [docs.rs](docs.rs) will fail to build the (albeit limited) documentation for this crate! +They build in a Linux container, but of course this will only compile on MacOS. + +Please build the documentation yourself with `cargo docs`. ## Examples diff --git a/third_party/rust/metal/assets/metal.svg b/third_party/rust/metal/assets/metal.svg new file mode 100644 index 000000000000..9f0c87edfbe4 --- /dev/null +++ b/third_party/rust/metal/assets/metal.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/third_party/rust/metal/examples/circle/main.rs b/third_party/rust/metal/examples/circle/main.rs index 18da704421a7..ed17a734024b 100644 --- a/third_party/rust/metal/examples/circle/main.rs +++ b/third_party/rust/metal/examples/circle/main.rs @@ -34,19 +34,30 @@ pub struct AAPLVertex { fn main() { // Create a window for viewing the content let event_loop = EventLoop::new(); - let events_loop = winit::event_loop::EventLoop::new(); let size = winit::dpi::LogicalSize::new(800, 600); let window = winit::window::WindowBuilder::new() .with_inner_size(size) .with_title("Metal".to_string()) - .build(&events_loop) + .build(&event_loop) .unwrap(); // Set up the GPU device found in the system let device = Device::system_default().expect("no device found"); println!("Your device is: {}", device.name(),); + // Scaffold required to sample the GPU and CPU timestamps + let mut cpu_start = 0; + let mut gpu_start = 0; + device.sample_timestamps(&mut cpu_start, &mut gpu_start); + let counter_sample_buffer = create_counter_sample_buffer(&device); + let destination_buffer = device.new_buffer( + (std::mem::size_of::() * 4 as usize) as u64, + MTLResourceOptions::StorageModeShared, + ); + let counter_sampling_point = MTLCounterSamplingPoint::AtStageBoundary; + assert!(device.supports_counter_sampling(counter_sampling_point)); + let binary_archive_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("examples/circle/binary_archive.metallib"); @@ -141,7 +152,14 @@ fn main() { // Obtain a renderPassDescriptor generated from the view's drawable textures. let render_pass_descriptor = RenderPassDescriptor::new(); - prepare_render_pass_descriptor(&render_pass_descriptor, drawable.texture()); + handle_render_pass_color_attachment( + &render_pass_descriptor, + drawable.texture(), + ); + handle_render_pass_sample_buffer_attachment( + &render_pass_descriptor, + &counter_sample_buffer, + ); // Create a render command encoder. let encoder = @@ -153,11 +171,23 @@ fn main() { encoder.draw_primitives(MTLPrimitiveType::TriangleStrip, 0, 1080); encoder.end_encoding(); + resolve_samples_into_buffer( + &command_buffer, + &counter_sample_buffer, + &destination_buffer, + ); + // Schedule a present once the framebuffer is complete using the current drawable. command_buffer.present_drawable(&drawable); // Finalize rendering here & push the command buffer to the GPU. command_buffer.commit(); + command_buffer.wait_until_completed(); + + let mut cpu_end = 0; + let mut gpu_end = 0; + device.sample_timestamps(&mut cpu_end, &mut gpu_end); + handle_timestamps(&destination_buffer, cpu_start, cpu_end, gpu_start, gpu_end); } _ => (), } @@ -211,7 +241,20 @@ fn create_vertex_points_for_circle() -> Vec { v } -fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) { +fn handle_render_pass_sample_buffer_attachment( + descriptor: &RenderPassDescriptorRef, + counter_sample_buffer: &CounterSampleBufferRef, +) { + let sample_buffer_attachment_descriptor = + descriptor.sample_buffer_attachments().object_at(0).unwrap(); + sample_buffer_attachment_descriptor.set_sample_buffer(&counter_sample_buffer); + sample_buffer_attachment_descriptor.set_start_of_vertex_sample_index(0 as NSUInteger); + sample_buffer_attachment_descriptor.set_end_of_vertex_sample_index(1 as NSUInteger); + sample_buffer_attachment_descriptor.set_start_of_fragment_sample_index(2 as NSUInteger); + sample_buffer_attachment_descriptor.set_end_of_fragment_sample_index(3 as NSUInteger); +} + +fn handle_render_pass_color_attachment(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) { let color_attachment = descriptor.color_attachments().object_at(0).unwrap(); color_attachment.set_texture(Some(texture)); @@ -249,3 +292,86 @@ fn prepare_pipeline_state( .new_render_pipeline_state(&pipeline_state_descriptor) .unwrap() } + +fn resolve_samples_into_buffer( + command_buffer: &CommandBufferRef, + counter_sample_buffer: &CounterSampleBufferRef, + destination_buffer: &BufferRef, +) { + let blit_encoder = command_buffer.new_blit_command_encoder(); + blit_encoder.resolve_counters( + &counter_sample_buffer, + crate::NSRange::new(0_u64, 4), + &destination_buffer, + 0_u64, + ); + blit_encoder.end_encoding(); +} + +fn handle_timestamps( + resolved_sample_buffer: &BufferRef, + cpu_start: u64, + cpu_end: u64, + gpu_start: u64, + gpu_end: u64, +) { + let samples = unsafe { + std::slice::from_raw_parts(resolved_sample_buffer.contents() as *const u64, 4 as usize) + }; + let vertex_pass_start = samples[0]; + let vertex_pass_end = samples[1]; + let fragment_pass_start = samples[2]; + let fragment_pass_end = samples[3]; + + let cpu_time_span = cpu_end - cpu_start; + let gpu_time_span = gpu_end - gpu_start; + + let vertex_micros = microseconds_between_begin( + vertex_pass_start, + vertex_pass_end, + gpu_time_span, + cpu_time_span, + ); + let fragment_micros = microseconds_between_begin( + fragment_pass_start, + fragment_pass_end, + gpu_time_span, + cpu_time_span, + ); + + println!("Vertex pass duration: {:.2} µs", vertex_micros); + println!("Fragment pass duration: {:.2} µs\n", fragment_micros); +} + +fn create_counter_sample_buffer(device: &Device) -> CounterSampleBuffer { + let counter_sample_buffer_desc = metal::CounterSampleBufferDescriptor::new(); + counter_sample_buffer_desc.set_storage_mode(metal::MTLStorageMode::Shared); + counter_sample_buffer_desc.set_sample_count(4_u64); + counter_sample_buffer_desc.set_counter_set(&fetch_timestamp_counter_set(device)); + + device + .new_counter_sample_buffer_with_descriptor(&counter_sample_buffer_desc) + .unwrap() +} + +fn fetch_timestamp_counter_set(device: &Device) -> metal::CounterSet { + let counter_sets = device.counter_sets(); + let mut timestamp_counter = None; + for cs in counter_sets.iter() { + if cs.name() == "timestamp" { + timestamp_counter = Some(cs); + break; + } + } + timestamp_counter + .expect("No timestamp counter found") + .clone() +} + +/// +fn microseconds_between_begin(begin: u64, end: u64, gpu_time_span: u64, cpu_time_span: u64) -> f64 { + let time_span = (end as f64) - (begin as f64); + let nanoseconds = time_span / (gpu_time_span as f64) * (cpu_time_span as f64); + let microseconds = nanoseconds / 1000.0; + return microseconds; +} diff --git a/third_party/rust/metal/examples/compute/main.rs b/third_party/rust/metal/examples/compute/main.rs index 6497c790ae67..066997d9d700 100644 --- a/third_party/rust/metal/examples/compute/main.rs +++ b/third_party/rust/metal/examples/compute/main.rs @@ -1,66 +1,41 @@ -// Copyright 2017 GFX developers -// -// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be -// copied, modified, or distributed except according to those terms. - use metal::*; use objc::rc::autoreleasepool; -use std::mem; +use std::path::PathBuf; + +const NUM_SAMPLES: u64 = 2; +const NUM_ELEMENTS: u64 = 64 * 64; fn main() { autoreleasepool(|| { - let device = Device::system_default().expect("no device found"); - let command_queue = device.new_command_queue(); + let device = Device::system_default().expect("No device found"); + let mut cpu_start = 0; + let mut gpu_start = 0; + device.sample_timestamps(&mut cpu_start, &mut gpu_start); - let data = [ - 1u32, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, - ]; - - let buffer = device.new_buffer_with_data( - unsafe { mem::transmute(data.as_ptr()) }, - (data.len() * mem::size_of::()) as u64, - MTLResourceOptions::CPUCacheModeDefaultCache, + let counter_sample_buffer = create_counter_sample_buffer(&device); + let destination_buffer = device.new_buffer( + (std::mem::size_of::() * NUM_SAMPLES as usize) as u64, + MTLResourceOptions::StorageModeShared, ); - let sum = { - let data = [0u32]; - device.new_buffer_with_data( - unsafe { mem::transmute(data.as_ptr()) }, - (data.len() * mem::size_of::()) as u64, - MTLResourceOptions::CPUCacheModeDefaultCache, - ) - }; + let counter_sampling_point = MTLCounterSamplingPoint::AtStageBoundary; + assert!(device.supports_counter_sampling(counter_sampling_point)); + let command_queue = device.new_command_queue(); let command_buffer = command_queue.new_command_buffer(); - command_buffer.set_label("label"); - let block = block::ConcreteBlock::new(move |buffer: &metal::CommandBufferRef| { - println!("{}", buffer.label()); - }) - .copy(); - - command_buffer.add_completed_handler(&block); - - let encoder = command_buffer.new_compute_command_encoder(); - let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("examples/compute/shaders.metallib"); - - let library = device.new_library_with_file(library_path).unwrap(); - let kernel = library.get_function("sum", None).unwrap(); - - let pipeline_state_descriptor = ComputePipelineDescriptor::new(); - pipeline_state_descriptor.set_compute_function(Some(&kernel)); - - let pipeline_state = device - .new_compute_pipeline_state_with_function( - pipeline_state_descriptor.compute_function().unwrap(), - ) - .unwrap(); + let compute_pass_descriptor = ComputePassDescriptor::new(); + handle_compute_pass_sample_buffer_attachment( + &compute_pass_descriptor, + &counter_sample_buffer, + ); + let encoder = + command_buffer.compute_command_encoder_with_descriptor(&compute_pass_descriptor); + let pipeline_state = create_pipeline_state(&device); encoder.set_compute_pipeline_state(&pipeline_state); + + let (buffer, sum) = create_input_and_output_buffers(&device); encoder.set_buffer(0, Some(&buffer), 0); encoder.set_buffer(1, Some(&sum), 0); @@ -73,19 +48,141 @@ fn main() { }; let thread_group_size = MTLSize { - width: (data.len() as u64 + width) / width, + width: (NUM_ELEMENTS + width) / width, height: 1, depth: 1, }; encoder.dispatch_thread_groups(thread_group_count, thread_group_size); encoder.end_encoding(); + + resolve_samples_into_buffer(&command_buffer, &counter_sample_buffer, &destination_buffer); + command_buffer.commit(); command_buffer.wait_until_completed(); + let mut cpu_end = 0; + let mut gpu_end = 0; + device.sample_timestamps(&mut cpu_end, &mut gpu_end); let ptr = sum.contents() as *mut u32; + println!("Compute shader sum: {}", unsafe { *ptr }); + unsafe { - assert_eq!(465, *ptr); + assert_eq!(NUM_ELEMENTS as u32, *ptr); } + + handle_timestamps(&destination_buffer, cpu_start, cpu_end, gpu_start, gpu_end); }); } + +fn create_pipeline_state(device: &Device) -> ComputePipelineState { + let library_path = + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("examples/compute/shaders.metallib"); + let library = device.new_library_with_file(library_path).unwrap(); + let kernel = library.get_function("sum", None).unwrap(); + + let pipeline_state_descriptor = ComputePipelineDescriptor::new(); + pipeline_state_descriptor.set_compute_function(Some(&kernel)); + + device + .new_compute_pipeline_state_with_function( + pipeline_state_descriptor.compute_function().unwrap(), + ) + .unwrap() +} + +fn handle_compute_pass_sample_buffer_attachment( + compute_pass_descriptor: &ComputePassDescriptorRef, + counter_sample_buffer: &CounterSampleBufferRef, +) { + let sample_buffer_attachment_descriptor = compute_pass_descriptor + .sample_buffer_attachments() + .object_at(0) + .unwrap(); + + sample_buffer_attachment_descriptor.set_sample_buffer(&counter_sample_buffer); + sample_buffer_attachment_descriptor.set_start_of_encoder_sample_index(0); + sample_buffer_attachment_descriptor.set_end_of_encoder_sample_index(1); +} + +fn resolve_samples_into_buffer( + command_buffer: &CommandBufferRef, + counter_sample_buffer: &CounterSampleBufferRef, + destination_buffer: &BufferRef, +) { + let blit_encoder = command_buffer.new_blit_command_encoder(); + blit_encoder.resolve_counters( + &counter_sample_buffer, + crate::NSRange::new(0_u64, NUM_SAMPLES), + &destination_buffer, + 0_u64, + ); + blit_encoder.end_encoding(); +} + +fn handle_timestamps( + resolved_sample_buffer: &BufferRef, + cpu_start: u64, + cpu_end: u64, + gpu_start: u64, + gpu_end: u64, +) { + let samples = unsafe { + std::slice::from_raw_parts( + resolved_sample_buffer.contents() as *const u64, + NUM_SAMPLES as usize, + ) + }; + let pass_start = samples[0]; + let pass_end = samples[1]; + + let cpu_time_span = cpu_end - cpu_start; + let gpu_time_span = gpu_end - gpu_start; + + let micros = microseconds_between_begin(pass_start, pass_end, gpu_time_span, cpu_time_span); + println!("Compute pass duration: {} µs", micros); +} + +fn create_counter_sample_buffer(device: &Device) -> CounterSampleBuffer { + let counter_sample_buffer_desc = metal::CounterSampleBufferDescriptor::new(); + counter_sample_buffer_desc.set_storage_mode(metal::MTLStorageMode::Shared); + counter_sample_buffer_desc.set_sample_count(NUM_SAMPLES); + let counter_sets = device.counter_sets(); + + let timestamp_counter = counter_sets.iter().find(|cs| cs.name() == "timestamp"); + + counter_sample_buffer_desc + .set_counter_set(×tamp_counter.expect("No timestamp counter found")); + + device + .new_counter_sample_buffer_with_descriptor(&counter_sample_buffer_desc) + .unwrap() +} + +fn create_input_and_output_buffers(device: &Device) -> (metal::Buffer, metal::Buffer) { + let data = [1u32; 64 * 64]; + + let buffer = device.new_buffer_with_data( + unsafe { std::mem::transmute(data.as_ptr()) }, + (data.len() * std::mem::size_of::()) as u64, + MTLResourceOptions::CPUCacheModeDefaultCache, + ); + + let sum = { + let data = [0u32]; + device.new_buffer_with_data( + unsafe { std::mem::transmute(data.as_ptr()) }, + (data.len() * std::mem::size_of::()) as u64, + MTLResourceOptions::CPUCacheModeDefaultCache, + ) + }; + (buffer, sum) +} + +/// +fn microseconds_between_begin(begin: u64, end: u64, gpu_time_span: u64, cpu_time_span: u64) -> f64 { + let time_span = (end as f64) - (begin as f64); + let nanoseconds = time_span / (gpu_time_span as f64) * (cpu_time_span as f64); + let microseconds = nanoseconds / 1000.0; + return microseconds; +} diff --git a/third_party/rust/metal/examples/headless-render/main.rs b/third_party/rust/metal/examples/headless-render/main.rs index ed68da1a538e..449170251f00 100644 --- a/third_party/rust/metal/examples/headless-render/main.rs +++ b/third_party/rust/metal/examples/headless-render/main.rs @@ -103,7 +103,7 @@ fn save_image(texture: &TextureRef) { let ref mut w = BufWriter::new(file); let mut encoder = png::Encoder::new(w, VIEW_WIDTH as u32, VIEW_HEIGHT as u32); - encoder.set_color(ColorType::RGBA); + encoder.set_color(ColorType::Rgba); encoder.set_depth(png::BitDepth::Eight); let mut writer = encoder.write_header().unwrap(); diff --git a/third_party/rust/metal/examples/mesh-shader/main.rs b/third_party/rust/metal/examples/mesh-shader/main.rs new file mode 100644 index 000000000000..8edb30ce1f5e --- /dev/null +++ b/third_party/rust/metal/examples/mesh-shader/main.rs @@ -0,0 +1,118 @@ +extern crate objc; + +use cocoa::{appkit::NSView, base::id as cocoa_id}; +use core_graphics_types::geometry::CGSize; + +use metal::*; +use objc::{rc::autoreleasepool, runtime::YES}; +use std::mem; +use winit::platform::macos::WindowExtMacOS; + +use winit::{ + event::{Event, WindowEvent}, + event_loop::ControlFlow, +}; + +fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) { + let color_attachment = descriptor.color_attachments().object_at(0).unwrap(); + + color_attachment.set_texture(Some(texture)); + color_attachment.set_load_action(MTLLoadAction::Clear); + color_attachment.set_clear_color(MTLClearColor::new(0.2, 0.2, 0.25, 1.0)); + color_attachment.set_store_action(MTLStoreAction::Store); +} + +fn main() { + let events_loop = winit::event_loop::EventLoop::new(); + let size = winit::dpi::LogicalSize::new(800, 600); + + let window = winit::window::WindowBuilder::new() + .with_inner_size(size) + .with_title("Metal Mesh Shader Example".to_string()) + .build(&events_loop) + .unwrap(); + + let device = Device::system_default().expect("no device found"); + + let layer = MetalLayer::new(); + layer.set_device(&device); + layer.set_pixel_format(MTLPixelFormat::BGRA8Unorm); + layer.set_presents_with_transaction(false); + + unsafe { + let view = window.ns_view() as cocoa_id; + view.setWantsLayer(YES); + view.setLayer(mem::transmute(layer.as_ref())); + } + + let draw_size = window.inner_size(); + layer.set_drawable_size(CGSize::new(draw_size.width as f64, draw_size.height as f64)); + + let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("examples/mesh-shader/shaders.metallib"); + let library = device.new_library_with_file(library_path).unwrap(); + + let mesh = library.get_function("mesh_function", None).unwrap(); + let frag = library.get_function("fragment_function", None).unwrap(); + + let pipeline_state_desc = MeshRenderPipelineDescriptor::new(); + pipeline_state_desc + .color_attachments() + .object_at(0) + .unwrap() + .set_pixel_format(MTLPixelFormat::BGRA8Unorm); + pipeline_state_desc.set_mesh_function(Some(&mesh)); + pipeline_state_desc.set_fragment_function(Some(&frag)); + + let pipeline_state = device + .new_mesh_render_pipeline_state(&pipeline_state_desc) + .unwrap(); + + let command_queue = device.new_command_queue(); + + events_loop.run(move |event, _, control_flow| { + autoreleasepool(|| { + *control_flow = ControlFlow::Poll; + + match event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::Resized(size) => { + layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64)); + } + _ => (), + }, + Event::MainEventsCleared => { + window.request_redraw(); + } + Event::RedrawRequested(_) => { + let drawable = match layer.next_drawable() { + Some(drawable) => drawable, + None => return, + }; + + let render_pass_descriptor = RenderPassDescriptor::new(); + + prepare_render_pass_descriptor(&render_pass_descriptor, drawable.texture()); + + let command_buffer = command_queue.new_command_buffer(); + let encoder = + command_buffer.new_render_command_encoder(&render_pass_descriptor); + + encoder.set_render_pipeline_state(&pipeline_state); + encoder.draw_mesh_threads( + MTLSize::new(1, 1, 1), + MTLSize::new(1, 1, 1), + MTLSize::new(1, 1, 1), + ); + + encoder.end_encoding(); + + command_buffer.present_drawable(&drawable); + command_buffer.commit(); + } + _ => {} + } + }); + }); +} diff --git a/third_party/rust/metal/examples/mesh-shader/shaders.metal b/third_party/rust/metal/examples/mesh-shader/shaders.metal new file mode 100644 index 000000000000..1a8253074281 --- /dev/null +++ b/third_party/rust/metal/examples/mesh-shader/shaders.metal @@ -0,0 +1,30 @@ +#include + +using namespace metal; + +struct VertexOut { + float4 position [[position]]; +}; + +using mesh_t = mesh; + +[[mesh]] void mesh_function(mesh_t m) { + VertexOut v; + v.position = float4(-1.0, -1.0, 0.0, 1.0); + + m.set_primitive_count(1); + + m.set_vertex(0, v); + v.position = float4(0.0, 1.0, 0.0, 1.0); + m.set_vertex(1, v); + v.position = float4(1.0, -1.0, 0.0, 1.0); + m.set_vertex(2, v); + + m.set_index(0, 0); + m.set_index(1, 1); + m.set_index(2, 2); +} + +fragment half4 fragment_function() { + return half4(0.1, 1.0, 0.1, 1.0); +} \ No newline at end of file diff --git a/third_party/rust/metal/examples/mesh-shader/shaders.metallib b/third_party/rust/metal/examples/mesh-shader/shaders.metallib new file mode 100644 index 0000000000000000000000000000000000000000..4af8d60ddcf200aae627bc160c81bf9ee1c10a2f GIT binary patch literal 6314 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 as u64); - ray_intersector.set_ray_data_type(MPSRayDataType::OriginMinDistanceDirectionMaxDistance); + ray_intersector.set_ray_data_type(mps::MPSRayDataType::OriginMinDistanceDirectionMaxDistance); ray_intersector.set_intersection_stride(mem::size_of::() as u64); - ray_intersector - .set_intersection_data_type(MPSIntersectionDataType::DistancePrimitiveIndexCoordinates); + ray_intersector.set_intersection_data_type( + mps::MPSIntersectionDataType::DistancePrimitiveIndexCoordinates, + ); // Create a buffer to hold generated rays and intersection results let ray_count = 1024; @@ -114,7 +115,7 @@ fn main() { // Intersect rays with triangles inside acceleration structure ray_intersector.encode_intersection_to_command_buffer( &command_buffer, - MPSIntersectionType::Nearest, + mps::MPSIntersectionType::Nearest, &ray_buffer, 0, &intersection_buffer, diff --git a/third_party/rust/metal/examples/raytracing/README.md b/third_party/rust/metal/examples/raytracing/README.md new file mode 100644 index 000000000000..0071e59747c5 --- /dev/null +++ b/third_party/rust/metal/examples/raytracing/README.md @@ -0,0 +1,11 @@ +## Raytracing + +A good showcase of Metal 3 raytracing features. + +![Screenshot of the final render](./screenshot.png) + +## To Run + +``` +cargo run --example raytracing +``` diff --git a/third_party/rust/metal/examples/raytracing/camera.rs b/third_party/rust/metal/examples/raytracing/camera.rs new file mode 100644 index 000000000000..5548445c0667 --- /dev/null +++ b/third_party/rust/metal/examples/raytracing/camera.rs @@ -0,0 +1,20 @@ +use glam::f32::Vec4; + +#[repr(C)] +pub struct Camera { + pub position: Vec4, + pub right: Vec4, + pub up: Vec4, + pub forward: Vec4, +} + +impl Camera { + pub fn new() -> Self { + Self { + position: Vec4::new(0.0, 3.0, 10.0, 0.0), + right: Vec4::new(1.0, 0.0, 0.0, 0.0), + up: Vec4::new(0.0, 1.0, 0.0, 0.0), + forward: Vec4::new(0.0, 0.0, -1.0, 0.0), + } + } +} diff --git a/third_party/rust/metal/examples/raytracing/geometry.rs b/third_party/rust/metal/examples/raytracing/geometry.rs new file mode 100644 index 000000000000..93fdc196d1e1 --- /dev/null +++ b/third_party/rust/metal/examples/raytracing/geometry.rs @@ -0,0 +1,448 @@ +use std::{ + mem::{size_of, transmute}, + sync::Arc, +}; + +use glam::{ + f32::{Mat4, Vec3, Vec4}, + Vec4Swizzles, +}; + +use metal::*; + +pub const GEOMETRY_MASK_TRIANGLE: u32 = 1; +pub const GEOMETRY_MASK_SPHERE: u32 = 2; +pub const GEOMETRY_MASK_LIGHT: u32 = 4; + +pub const FACE_MASK_NONE: u16 = 0; +pub const FACE_MASK_NEGATIVE_X: u16 = 1 << 0; +pub const FACE_MASK_POSITIVE_X: u16 = 1 << 1; +pub const FACE_MASK_NEGATIVE_Y: u16 = 1 << 2; +pub const FACE_MASK_POSITIVE_Y: u16 = 1 << 3; +pub const FACE_MASK_NEGATIVE_Z: u16 = 1 << 4; +pub const FACE_MASK_POSITIVE_Z: u16 = 1 << 5; +pub const FACE_MASK_ALL: u16 = (1 << 6) - 1; + +pub trait Geometry { + fn upload_to_buffers(&mut self) { + todo!() + } + fn clear(&mut self) { + todo!() + } + fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor { + todo!() + } + fn get_resources(&self) -> Vec { + todo!() + } + fn get_intersection_function_name(&self) -> Option<&str> { + None + } +} + +pub fn compute_triangle_normal(v0: &Vec3, v1: &Vec3, v2: &Vec3) -> Vec3 { + let e1 = Vec3::normalize(*v1 - *v0); + let e2 = Vec3::normalize(*v2 - *v0); + return Vec3::cross(e1, e2); +} + +#[derive(Default)] +#[repr(C)] +pub struct Triangle { + pub normals: [Vec4; 3], + pub colours: [Vec4; 3], +} + +pub fn get_managed_buffer_storage_mode() -> MTLResourceOptions { + return MTLResourceOptions::StorageModeManaged; +} + +pub struct TriangleGeometry { + pub device: Device, + pub name: String, + pub index_buffer: Option, + pub vertex_position_buffer: Option, + pub vertex_normal_buffer: Option, + pub vertex_colour_buffer: Option, + pub per_primitive_data_buffer: Option, + pub indices: Vec, + pub vertices: Vec, + pub normals: Vec, + pub colours: Vec, + pub triangles: Vec, +} + +impl TriangleGeometry { + pub fn new(device: Device, name: String) -> Self { + Self { + device, + name, + index_buffer: None, + vertex_position_buffer: None, + vertex_normal_buffer: None, + vertex_colour_buffer: None, + per_primitive_data_buffer: None, + indices: Vec::new(), + vertices: Vec::new(), + normals: Vec::new(), + colours: Vec::new(), + triangles: Vec::new(), + } + } + + pub fn add_cube_face_with_cube_vertices( + &mut self, + cube_vertices: &[Vec3], + colour: Vec3, + i0: u16, + i1: u16, + i2: u16, + i3: u16, + inward_normals: bool, + ) { + let v0 = cube_vertices[i0 as usize]; + let v1 = cube_vertices[i1 as usize]; + let v2 = cube_vertices[i2 as usize]; + let v3 = cube_vertices[i3 as usize]; + + let n0 = compute_triangle_normal(&v0, &v1, &v2) * if inward_normals { -1f32 } else { 1f32 }; + let n1 = compute_triangle_normal(&v0, &v2, &v3) * if inward_normals { -1f32 } else { 1f32 }; + + let first_index = self.indices.len(); + let base_index = self.vertices.len() as u16; + + self.indices.push(base_index + 0); + self.indices.push(base_index + 1); + self.indices.push(base_index + 2); + self.indices.push(base_index + 0); + self.indices.push(base_index + 2); + self.indices.push(base_index + 3); + + self.vertices.push(From::from((v0, 0.0))); + self.vertices.push(From::from((v1, 0.0))); + self.vertices.push(From::from((v2, 0.0))); + self.vertices.push(From::from((v3, 0.0))); + + self.normals + .push(From::from((Vec3::normalize(n0 + n1), 0.0))); + self.normals.push(From::from((n0, 0.0))); + self.normals + .push(From::from((Vec3::normalize(n0 + n1), 0.0))); + self.normals.push(From::from((n1, 0.0))); + + for _ in 0..4 { + self.colours.push(From::from((colour, 0.0))); + } + + for triangle_index in 0..2 { + let mut triangle = Triangle::default(); + for i in 0..3 { + let index = self.indices[first_index + triangle_index * 3 + i]; + triangle.normals[i] = self.normals[index as usize]; + triangle.colours[i] = self.colours[index as usize]; + } + self.triangles.push(triangle); + } + } + + pub fn add_cube_with_faces( + &mut self, + face_mask: u16, + colour: Vec3, + transform: Mat4, + inward_normals: bool, + ) { + let mut cube_vertices = [ + Vec3::new(-0.5, -0.5, -0.5), + Vec3::new(0.5, -0.5, -0.5), + Vec3::new(-0.5, 0.5, -0.5), + Vec3::new(0.5, 0.5, -0.5), + Vec3::new(-0.5, -0.5, 0.5), + Vec3::new(0.5, -0.5, 0.5), + Vec3::new(-0.5, 0.5, 0.5), + Vec3::new(0.5, 0.5, 0.5), + ]; + + for i in 0..8 { + let transformed_vertex = Vec4::from((cube_vertices[i], 1.0)); + let transformed_vertex = transform * transformed_vertex; + cube_vertices[i] = transformed_vertex.xyz(); + } + + const CUBE_INDICES: [[u16; 4]; 6] = [ + [0, 4, 6, 2], + [1, 3, 7, 5], + [0, 1, 5, 4], + [2, 6, 7, 3], + [0, 2, 3, 1], + [4, 5, 7, 6], + ]; + + for face in 0..6 { + if face_mask & (1 << face) != 0 { + self.add_cube_face_with_cube_vertices( + &cube_vertices, + colour, + CUBE_INDICES[face][0], + CUBE_INDICES[face][1], + CUBE_INDICES[face][2], + CUBE_INDICES[face][3], + inward_normals, + ); + } + } + } +} + +impl Geometry for TriangleGeometry { + fn upload_to_buffers(&mut self) { + self.index_buffer = Some(unsafe { + self.device.new_buffer_with_data( + transmute(self.indices.as_ptr()), + (self.indices.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ) + }); + self.vertex_position_buffer = Some(unsafe { + self.device.new_buffer_with_data( + transmute(self.vertices.as_ptr()), + (self.vertices.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ) + }); + self.vertex_normal_buffer = Some(unsafe { + self.device.new_buffer_with_data( + transmute(self.normals.as_ptr()), + (self.normals.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ) + }); + self.vertex_colour_buffer = Some(unsafe { + self.device.new_buffer_with_data( + transmute(self.colours.as_ptr()), + (self.colours.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ) + }); + self.per_primitive_data_buffer = Some(unsafe { + self.device.new_buffer_with_data( + transmute(self.triangles.as_ptr()), + (self.triangles.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ) + }); + self.index_buffer + .as_ref() + .unwrap() + .did_modify_range(NSRange::new( + 0, + self.index_buffer.as_ref().unwrap().length(), + )); + self.vertex_position_buffer + .as_ref() + .unwrap() + .did_modify_range(NSRange::new( + 0, + self.vertex_position_buffer.as_ref().unwrap().length(), + )); + self.vertex_normal_buffer + .as_ref() + .unwrap() + .did_modify_range(NSRange::new( + 0, + self.vertex_normal_buffer.as_ref().unwrap().length(), + )); + self.vertex_colour_buffer + .as_ref() + .unwrap() + .did_modify_range(NSRange::new( + 0, + self.vertex_colour_buffer.as_ref().unwrap().length(), + )); + self.per_primitive_data_buffer + .as_ref() + .unwrap() + .did_modify_range(NSRange::new( + 0, + self.per_primitive_data_buffer.as_ref().unwrap().length(), + )); + + self.index_buffer + .as_ref() + .unwrap() + .set_label(&format!("index buffer of {}", self.name)); + self.vertex_position_buffer + .as_ref() + .unwrap() + .set_label(&format!("vertex position buffer of {}", self.name)); + self.vertex_normal_buffer + .as_ref() + .unwrap() + .set_label(&format!("vertex normal buffer of {}", self.name)); + self.vertex_colour_buffer + .as_ref() + .unwrap() + .set_label(&format!("vertex colour buffer of {}", self.name)); + self.per_primitive_data_buffer + .as_ref() + .unwrap() + .set_label(&format!("per primitive data buffer of {}", self.name)); + } + + fn clear(&mut self) { + self.indices.clear(); + self.vertices.clear(); + self.normals.clear(); + self.colours.clear(); + self.triangles.clear(); + } + + fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor { + let descriptor = AccelerationStructureTriangleGeometryDescriptor::descriptor(); + + descriptor.set_index_buffer(Some(self.index_buffer.as_ref().unwrap())); + descriptor.set_index_type(MTLIndexType::UInt16); + descriptor.set_vertex_buffer(Some(self.vertex_position_buffer.as_ref().unwrap())); + descriptor.set_vertex_stride(size_of::() as NSUInteger); + descriptor.set_triangle_count((self.indices.len() / 3) as NSUInteger); + descriptor + .set_primitive_data_buffer(Some(self.per_primitive_data_buffer.as_ref().unwrap())); + descriptor.set_primitive_data_stride(size_of::() as NSUInteger); + descriptor.set_primitive_data_element_size(size_of::() as NSUInteger); + From::from(descriptor) + } + + fn get_resources(&self) -> Vec { + vec![ + From::from(self.index_buffer.as_ref().unwrap().clone()), + From::from(self.vertex_normal_buffer.as_ref().unwrap().clone()), + From::from(self.vertex_colour_buffer.as_ref().unwrap().clone()), + ] + } +} + +#[repr(C)] +pub struct BoundingBox { + pub min: Vec3, + pub max: Vec3, +} + +#[repr(C)] +pub struct Sphere { + pub origin_radius_squared: Vec4, + pub colour_radius: Vec4, +} + +pub struct SphereGeometry { + pub device: Device, + pub sphere_buffer: Option, + pub bounding_box_buffer: Option, + pub per_primitive_data_buffer: Option, + pub spheres: Vec, +} + +impl SphereGeometry { + pub fn new(device: Device) -> Self { + Self { + device, + sphere_buffer: None, + bounding_box_buffer: None, + per_primitive_data_buffer: None, + spheres: Vec::new(), + } + } + + pub fn add_sphere_with_origin(&mut self, origin: Vec3, radius: f32, colour: Vec3) { + self.spheres.push(Sphere { + origin_radius_squared: Vec4::from((origin, radius * radius)), + colour_radius: Vec4::from((colour, radius)), + }); + } +} + +impl Geometry for SphereGeometry { + fn upload_to_buffers(&mut self) { + self.sphere_buffer = Some(unsafe { + self.device.new_buffer_with_data( + transmute(self.spheres.as_ptr()), + (self.spheres.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ) + }); + self.sphere_buffer + .as_ref() + .unwrap() + .set_label("sphere buffer"); + let mut bounding_boxes = Vec::new(); + for sphere in &self.spheres { + bounding_boxes.push(BoundingBox { + min: sphere.origin_radius_squared.xyz() - sphere.colour_radius.w, + max: sphere.origin_radius_squared.xyz() + sphere.colour_radius.w, + }); + } + self.bounding_box_buffer = Some(unsafe { + self.device.new_buffer_with_data( + transmute(bounding_boxes.as_ptr()), + (bounding_boxes.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ) + }); + self.bounding_box_buffer + .as_ref() + .unwrap() + .set_label("bounding box buffer"); + self.sphere_buffer + .as_ref() + .unwrap() + .did_modify_range(NSRange::new( + 0, + self.sphere_buffer.as_ref().unwrap().length(), + )); + self.bounding_box_buffer + .as_ref() + .unwrap() + .did_modify_range(NSRange::new( + 0, + self.bounding_box_buffer.as_ref().unwrap().length(), + )); + } + + fn clear(&mut self) { + self.spheres.clear(); + } + + fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor { + let descriptor = AccelerationStructureBoundingBoxGeometryDescriptor::descriptor(); + descriptor.set_bounding_box_buffer(Some(self.bounding_box_buffer.as_ref().unwrap())); + descriptor.set_bounding_box_count(self.spheres.len() as NSUInteger); + descriptor.set_primitive_data_buffer(Some(&self.sphere_buffer.as_ref().unwrap())); + descriptor.set_primitive_data_stride(size_of::() as NSUInteger); + descriptor.set_primitive_data_element_size(size_of::() as NSUInteger); + From::from(descriptor) + } + + fn get_resources(&self) -> Vec { + return vec![From::from(self.sphere_buffer.as_ref().unwrap().clone())]; + } + + fn get_intersection_function_name(&self) -> Option<&str> { + Some("sphereIntersectionFunction") + } +} + +pub struct GeometryInstance { + pub geometry: Arc, + pub transform: Mat4, + pub mask: u32, + pub index_in_scene: NSUInteger, +} + +#[repr(C)] +pub struct AreaLight { + pub position: Vec4, + pub forward: Vec4, + pub right: Vec4, + pub up: Vec4, + pub colour: Vec4, +} diff --git a/third_party/rust/metal/examples/raytracing/main.rs b/third_party/rust/metal/examples/raytracing/main.rs new file mode 100644 index 000000000000..68eaf3df5927 --- /dev/null +++ b/third_party/rust/metal/examples/raytracing/main.rs @@ -0,0 +1,87 @@ +extern crate objc; + +use cocoa::{appkit::NSView, base::id as cocoa_id}; +use core_graphics_types::geometry::CGSize; +use metal::*; +use objc::{rc::autoreleasepool, runtime::YES}; +use std::mem; +use winit::{ + event::{Event, WindowEvent}, + event_loop::ControlFlow, + platform::macos::WindowExtMacOS, +}; + +pub mod camera; +pub mod geometry; +pub mod renderer; +pub mod scene; + +fn find_raytracing_supporting_device() -> Device { + for device in Device::all() { + if !device.supports_raytracing() { + continue; + } + if device.is_low_power() { + continue; + } + return device; + } + + panic!("No device in this machine supports raytracing!") +} + +fn main() { + let events_loop = winit::event_loop::EventLoop::new(); + let size = winit::dpi::LogicalSize::new(800, 600); + + let window = winit::window::WindowBuilder::new() + .with_inner_size(size) + .with_title("Metal Raytracing Example".to_string()) + .build(&events_loop) + .unwrap(); + + let device = find_raytracing_supporting_device(); + + let layer = MetalLayer::new(); + layer.set_device(&device); + layer.set_pixel_format(MTLPixelFormat::RGBA16Float); + layer.set_presents_with_transaction(false); + + unsafe { + let view = window.ns_view() as cocoa_id; + view.setWantsLayer(YES); + view.setLayer(mem::transmute(layer.as_ref())); + } + + let draw_size = window.inner_size(); + let cg_size = CGSize::new(draw_size.width as f64, draw_size.height as f64); + layer.set_drawable_size(cg_size); + + let mut renderer = renderer::Renderer::new(device); + renderer.window_resized(cg_size); + + events_loop.run(move |event, _, control_flow| { + autoreleasepool(|| { + *control_flow = ControlFlow::Poll; + + match event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::Resized(size) => { + let size = CGSize::new(size.width as f64, size.height as f64); + layer.set_drawable_size(size); + renderer.window_resized(size); + } + _ => (), + }, + Event::MainEventsCleared => { + window.request_redraw(); + } + Event::RedrawRequested(_) => { + renderer.draw(&layer); + } + _ => {} + } + }); + }); +} diff --git a/third_party/rust/metal/examples/raytracing/renderer.rs b/third_party/rust/metal/examples/raytracing/renderer.rs new file mode 100644 index 000000000000..f483d3e0a81e --- /dev/null +++ b/third_party/rust/metal/examples/raytracing/renderer.rs @@ -0,0 +1,512 @@ +use core_graphics_types::{base::CGFloat, geometry::CGSize}; +use std::{ + collections::BTreeMap, + ffi::c_void, + mem::{size_of, transmute}, + ops::Index, + sync::{Arc, Condvar, Mutex}, +}; + +use glam::{Vec3, Vec4, Vec4Swizzles}; +use rand::{thread_rng, RngCore}; + +use metal::{foreign_types::ForeignType, *}; + +use crate::{camera::Camera, geometry::get_managed_buffer_storage_mode, scene::Scene}; + +#[repr(C)] +struct Uniforms { + pub width: u32, + pub height: u32, + pub frame_index: u32, + pub light_count: u32, + pub camera: Camera, +} + +pub const MAX_FRAMES_IN_FLIGHT: NSUInteger = 3; +pub const ALIGNED_UNIFORMS_SIZE: NSUInteger = (size_of::() as NSUInteger + 255) & !255; +pub const UNIFORM_BUFFER_SIZE: NSUInteger = MAX_FRAMES_IN_FLIGHT * ALIGNED_UNIFORMS_SIZE; + +#[derive(Clone)] +struct Semaphore { + data: Arc<(Mutex, Condvar)>, +} + +impl Semaphore { + fn new(capacity: usize) -> Self { + Self { + data: Arc::new((Mutex::new(capacity), Condvar::new())), + } + } + + fn acquire(&self) { + let mut value = self.data.0.lock().unwrap(); + while *value == 0 { + value = self.data.1.wait(value).unwrap(); + } + *value -= 1; + } + + fn release(&self) { + let mut value = self.data.0.lock().unwrap(); + *value += 1; + self.data.1.notify_one(); + } +} + +pub struct Renderer { + pub device: Device, + pub scene: Scene, + pub uniform_buffer: Buffer, + pub resource_buffer: Buffer, + pub instance_acceleration_structure: AccelerationStructure, + pub accumulation_targets: [Texture; 2], + pub random_texture: Texture, + pub frame_index: NSUInteger, + pub uniform_buffer_index: NSUInteger, + pub uniform_buffer_offset: NSUInteger, + pub size: CGSize, + semaphore: Semaphore, + pub queue: CommandQueue, + instance_buffer: Buffer, + intersection_function_table: IntersectionFunctionTable, + primitive_acceleration_structures: Vec, + raytracing_pipeline: ComputePipelineState, + copy_pipeline: RenderPipelineState, +} + +impl Renderer { + pub fn new(device: Device) -> Self { + let scene = Scene::new(device.clone()); + + let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("examples/raytracing/shaders.metallib"); + let library = device.new_library_with_file(library_path).unwrap(); + let queue = device.new_command_queue(); + + let buffer_data = [0u8; UNIFORM_BUFFER_SIZE as usize]; + let uniform_buffer = device.new_buffer_with_data( + buffer_data.as_ptr() as *const c_void, + UNIFORM_BUFFER_SIZE, + get_managed_buffer_storage_mode(), + ); + uniform_buffer.set_label("uniform buffer"); + let resources_stride = { + let mut max = 0; + for geometry in &scene.geometries { + let s = geometry.get_resources().len(); + if s > max { + max = s; + } + } + max + }; + let mut resource_buffer_data = vec![0u64; resources_stride * scene.geometries.len()]; + for geometry_index in 0..scene.geometries.len() { + let geometry = scene.geometries[geometry_index].as_ref(); + let resource_buffer_begin_index = resources_stride * geometry_index; + let resources = geometry.get_resources(); + + for argument_index in 0..resources.len() { + let resource_buffer_index = resource_buffer_begin_index + argument_index; + let resource = resources[argument_index].clone(); + resource_buffer_data[resource_buffer_index] = + if resource.conforms_to_protocol::().unwrap() { + let buffer = unsafe { Buffer::from_ptr(transmute(resource.into_ptr())) }; + buffer.gpu_address() + } else if resource.conforms_to_protocol::().unwrap() { + let texture = unsafe { Texture::from_ptr(transmute(resource.into_ptr())) }; + texture.gpu_resource_id()._impl + } else { + panic!("Unexpected resource!") + } + } + } + let resource_buffer = device.new_buffer_with_data( + resource_buffer_data.as_ptr() as *const c_void, + (resource_buffer_data.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ); + resource_buffer.set_label("resource buffer"); + resource_buffer.did_modify_range(NSRange::new(0, resource_buffer.length())); + + let mut primitive_acceleration_structures = Vec::new(); + for i in 0..scene.geometries.len() { + let mesh = scene.geometries[i].as_ref(); + let geometry_descriptor = mesh.get_geometry_descriptor(); + geometry_descriptor.set_intersection_function_table_offset(i as NSUInteger); + let geometry_descriptors = Array::from_owned_slice(&[geometry_descriptor]); + let accel_descriptor = PrimitiveAccelerationStructureDescriptor::descriptor(); + accel_descriptor.set_geometry_descriptors(&geometry_descriptors); + let accel_descriptor: AccelerationStructureDescriptor = From::from(accel_descriptor); + primitive_acceleration_structures.push( + Self::new_acceleration_structure_with_descriptor( + &device, + &queue, + &accel_descriptor, + ), + ); + } + + let mut instance_descriptors = vec![ + MTLAccelerationStructureInstanceDescriptor::default(); + scene.geometry_instances.len() + ]; + for instance_index in 0..scene.geometry_instances.len() { + let instance = scene.geometry_instances[instance_index].as_ref(); + let geometry_index = instance.index_in_scene; + instance_descriptors[instance_index].acceleration_structure_index = + geometry_index as u32; + instance_descriptors[instance_index].options = + if instance.geometry.get_intersection_function_name().is_none() { + MTLAccelerationStructureInstanceOptions::Opaque + } else { + MTLAccelerationStructureInstanceOptions::None + }; + instance_descriptors[instance_index].intersection_function_table_offset = 0; + instance_descriptors[instance_index].mask = instance.mask as u32; + for column in 0..4 { + for row in 0..3 { + instance_descriptors[instance_index].transformation_matrix[column][row] = + *instance.transform.col(column).index(row); + } + } + } + let instance_buffer = device.new_buffer_with_data( + instance_descriptors.as_ptr() as *const c_void, + (size_of::() + * scene.geometry_instances.len()) as NSUInteger, + get_managed_buffer_storage_mode(), + ); + instance_buffer.set_label("instance buffer"); + instance_buffer.did_modify_range(NSRange::new(0, instance_buffer.length())); + + let accel_descriptor = InstanceAccelerationStructureDescriptor::descriptor(); + accel_descriptor.set_instanced_acceleration_structures(&Array::from_owned_slice( + &primitive_acceleration_structures, + )); + accel_descriptor.set_instance_count(scene.geometry_instances.len() as NSUInteger); + accel_descriptor.set_instance_descriptor_buffer(&instance_buffer); + let accel_descriptor: AccelerationStructureDescriptor = From::from(accel_descriptor); + let instance_acceleration_structure = + Self::new_acceleration_structure_with_descriptor(&device, &queue, &accel_descriptor); + + let mut intersection_functions = BTreeMap::::new(); + for geometry in &scene.geometries { + if let Some(name) = geometry.get_intersection_function_name() { + if !intersection_functions.contains_key(name) { + let intersection_function = Self::new_specialised_function_with_name( + &library, + resources_stride as u32, + name, + ); + intersection_functions.insert(name.to_string(), intersection_function); + } + } + } + let raytracing_function = Self::new_specialised_function_with_name( + &library, + resources_stride as u32, + "raytracingKernel", + ); + let intersection_function_array: Vec<&FunctionRef> = intersection_functions + .values() + .map(|f| -> &FunctionRef { f }) + .collect(); + let raytracing_pipeline = Self::new_compute_pipeline_state_with_function( + &device, + &raytracing_function, + &intersection_function_array, + ); + let intersection_function_table_descriptor = IntersectionFunctionTableDescriptor::new(); + intersection_function_table_descriptor + .set_function_count(scene.geometries.len() as NSUInteger); + let intersection_function_table = raytracing_pipeline + .new_intersection_function_table_with_descriptor( + &intersection_function_table_descriptor, + ); + for geometry_index in 0..scene.geometries.len() { + let geometry = scene.geometries[geometry_index].as_ref(); + if let Some(intersection_function_name) = geometry.get_intersection_function_name() { + let intersection_function = &intersection_functions[intersection_function_name]; + let handle = raytracing_pipeline + .function_handle_with_function(intersection_function) + .unwrap(); + intersection_function_table.set_function(handle, geometry_index as NSUInteger); + } + } + let render_descriptor = RenderPipelineDescriptor::new(); + render_descriptor + .set_vertex_function(Some(&library.get_function("copyVertex", None).unwrap())); + render_descriptor + .set_fragment_function(Some(&library.get_function("copyFragment", None).unwrap())); + render_descriptor + .color_attachments() + .object_at(0) + .unwrap() + .set_pixel_format(MTLPixelFormat::RGBA16Float); + let copy_pipeline = device + .new_render_pipeline_state(&render_descriptor) + .unwrap(); + + let texture_descriptor = Self::create_target_descriptor(1024, 1024); + let accumulation_targets = [ + device.new_texture(&texture_descriptor), + device.new_texture(&texture_descriptor), + ]; + let random_texture = device.new_texture(&texture_descriptor); + + Self { + device, + scene, + uniform_buffer, + resource_buffer, + instance_acceleration_structure, + accumulation_targets, + random_texture, + frame_index: 0, + uniform_buffer_index: 0, + uniform_buffer_offset: 0, + size: CGSize::new(1024 as CGFloat, 1024 as CGFloat), + semaphore: Semaphore::new((MAX_FRAMES_IN_FLIGHT - 2) as usize), + instance_buffer, + queue, + intersection_function_table, + primitive_acceleration_structures, + raytracing_pipeline, + copy_pipeline, + } + } + + fn create_target_descriptor(width: NSUInteger, height: NSUInteger) -> TextureDescriptor { + let texture_descriptor = TextureDescriptor::new(); + texture_descriptor.set_pixel_format(MTLPixelFormat::RGBA32Float); + texture_descriptor.set_texture_type(MTLTextureType::D2); + texture_descriptor.set_width(width); + texture_descriptor.set_height(height); + texture_descriptor.set_storage_mode(MTLStorageMode::Private); + texture_descriptor.set_usage(MTLTextureUsage::ShaderRead | MTLTextureUsage::ShaderWrite); + texture_descriptor + } + + pub fn window_resized(&mut self, size: CGSize) { + self.size = size; + let texture_descriptor = + Self::create_target_descriptor(size.width as NSUInteger, size.height as NSUInteger); + self.accumulation_targets[0] = self.device.new_texture(&texture_descriptor); + self.accumulation_targets[1] = self.device.new_texture(&texture_descriptor); + texture_descriptor.set_pixel_format(MTLPixelFormat::R32Uint); + texture_descriptor.set_usage(MTLTextureUsage::ShaderRead); + texture_descriptor.set_storage_mode(MTLStorageMode::Managed); + self.random_texture = self.device.new_texture(&texture_descriptor); + let mut rng = thread_rng(); + let mut random_values = vec![0u32; (size.width * size.height) as usize]; + for v in &mut random_values { + *v = rng.next_u32(); + } + self.random_texture.replace_region( + MTLRegion::new_2d(0, 0, size.width as NSUInteger, size.height as NSUInteger), + 0, + random_values.as_ptr() as *const c_void, + size_of::() as NSUInteger * size.width as NSUInteger, + ); + self.frame_index = 0; + } + + fn update_uniforms(&mut self) { + self.uniform_buffer_offset = ALIGNED_UNIFORMS_SIZE * self.uniform_buffer_index; + + let uniforms = unsafe { + &mut *((self.uniform_buffer.contents() as *mut u8) + .add(self.uniform_buffer_offset as usize) as *mut Uniforms) + }; + + let position = self.scene.camera.position; + let target = self.scene.camera.forward; + let up = self.scene.camera.up; + + let forward = Vec3::normalize(target.xyz() - position.xyz()); + let right = Vec3::normalize(Vec3::cross(forward, up.xyz())); + let up = Vec3::normalize(Vec3::cross(right, forward)); + + uniforms.camera.position = position; + uniforms.camera.forward = Vec4::from((forward, 0.0)); + uniforms.camera.right = Vec4::from((right, 0.0)); + uniforms.camera.up = Vec4::from((up, 0.0)); + + let field_of_view = 45.0 * (std::f32::consts::PI / 180.0); + let aspect_ratio = self.size.width as f32 / self.size.height as f32; + let image_plane_height = f32::tan(field_of_view / 2.0); + let image_plane_width = aspect_ratio * image_plane_height; + + uniforms.camera.right *= image_plane_width; + uniforms.camera.up *= image_plane_height; + + uniforms.width = self.size.width as u32; + uniforms.height = self.size.height as u32; + + uniforms.frame_index = self.frame_index as u32; + self.frame_index += 1; + + uniforms.light_count = self.scene.lights.len() as u32; + + self.uniform_buffer.did_modify_range(NSRange { + location: self.uniform_buffer_offset, + length: ALIGNED_UNIFORMS_SIZE, + }); + + self.uniform_buffer_index = (self.uniform_buffer_index + 1) % MAX_FRAMES_IN_FLIGHT; + } + + pub fn draw(&mut self, layer: &MetalLayer) { + self.semaphore.acquire(); + self.update_uniforms(); + let command_buffer = self.queue.new_command_buffer(); + let sem = self.semaphore.clone(); + let block = block::ConcreteBlock::new(move |_| { + sem.release(); + }) + .copy(); + command_buffer.add_completed_handler(&block); + let width = self.size.width as NSUInteger; + let height = self.size.height as NSUInteger; + let threads_per_thread_group = MTLSize::new(8, 8, 1); + let thread_groups = MTLSize::new( + (width + threads_per_thread_group.width - 1) / threads_per_thread_group.width, + (height + threads_per_thread_group.height - 1) / threads_per_thread_group.height, + 1, + ); + let compute_encoder = command_buffer.new_compute_command_encoder(); + compute_encoder.set_buffer(0, Some(&self.uniform_buffer), self.uniform_buffer_offset); + compute_encoder.set_buffer(2, Some(&self.instance_buffer), 0); + compute_encoder.set_buffer(3, Some(&self.scene.lights_buffer), 0); + compute_encoder.set_acceleration_structure(4, Some(&self.instance_acceleration_structure)); + compute_encoder.set_intersection_function_table(5, Some(&self.intersection_function_table)); + compute_encoder.set_texture(0, Some(&self.random_texture)); + compute_encoder.set_texture(1, Some(&self.accumulation_targets[0])); + compute_encoder.set_texture(2, Some(&self.accumulation_targets[1])); + for geometry in &self.scene.geometries { + for resource in geometry.get_resources() { + compute_encoder.use_resource(&resource, MTLResourceUsage::Read); + } + } + for primitive_acceleration_structure in &self.primitive_acceleration_structures { + let resource: Resource = From::from(primitive_acceleration_structure.clone()); + compute_encoder.use_resource(&resource, MTLResourceUsage::Read); + } + compute_encoder.set_compute_pipeline_state(&self.raytracing_pipeline); + compute_encoder.dispatch_thread_groups(thread_groups, threads_per_thread_group); + compute_encoder.end_encoding(); + (self.accumulation_targets[0], self.accumulation_targets[1]) = ( + self.accumulation_targets[1].clone(), + self.accumulation_targets[0].clone(), + ); + if let Some(drawable) = layer.next_drawable() { + let render_pass_descriptor = RenderPassDescriptor::new(); + let colour_attachment = render_pass_descriptor + .color_attachments() + .object_at(0) + .unwrap(); + colour_attachment.set_texture(Some(drawable.texture())); + colour_attachment.set_load_action(MTLLoadAction::Clear); + colour_attachment.set_clear_color(MTLClearColor::new(0.0, 0.0, 0.0, 1.0)); + let render_encoder = command_buffer.new_render_command_encoder(render_pass_descriptor); + render_encoder.set_render_pipeline_state(&self.copy_pipeline); + render_encoder.set_fragment_texture(0, Some(&self.accumulation_targets[0])); + render_encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 6); + render_encoder.end_encoding(); + command_buffer.present_drawable(&drawable); + } + command_buffer.commit(); + } + + fn new_acceleration_structure_with_descriptor( + device: &Device, + queue: &CommandQueue, + descriptor: &AccelerationStructureDescriptorRef, + ) -> AccelerationStructure { + let accel_sizes = device.acceleration_structure_sizes_with_descriptor(descriptor); + let acceleration_structure = + device.new_acceleration_structure_with_size(accel_sizes.acceleration_structure_size); + let scratch_buffer = device.new_buffer( + accel_sizes.build_scratch_buffer_size, + MTLResourceOptions::StorageModePrivate, + ); + let command_buffer = queue.new_command_buffer(); + let command_encoder = command_buffer.new_acceleration_structure_command_encoder(); + let compacted_size_buffer = device.new_buffer( + size_of::() as NSUInteger, + MTLResourceOptions::StorageModeShared, + ); + command_encoder.build_acceleration_structure( + &acceleration_structure, + &descriptor, + &scratch_buffer, + 0, + ); + command_encoder.write_compacted_acceleration_structure_size( + &acceleration_structure, + &compacted_size_buffer, + 0, + ); + command_encoder.end_encoding(); + command_buffer.commit(); + command_buffer.wait_until_completed(); + let compacted_size: *const u32 = unsafe { transmute(compacted_size_buffer.contents()) }; + let compacted_size = unsafe { *compacted_size } as NSUInteger; + let compacted_acceleration_structure = + device.new_acceleration_structure_with_size(compacted_size); + let command_buffer = queue.new_command_buffer(); + let command_encoder = command_buffer.new_acceleration_structure_command_encoder(); + command_encoder.copy_and_compact_acceleration_structure( + &acceleration_structure, + &compacted_acceleration_structure, + ); + command_encoder.end_encoding(); + command_buffer.commit(); + compacted_acceleration_structure + } + + fn new_specialised_function_with_name( + library: &Library, + resources_stride: u32, + name: &str, + ) -> Function { + let constants = FunctionConstantValues::new(); + let resources_stride = resources_stride * size_of::() as u32; + constants.set_constant_value_at_index( + &resources_stride as *const u32 as *const c_void, + MTLDataType::UInt, + 0, + ); + let v = true; + constants.set_constant_value_at_index( + &v as *const bool as *const c_void, + MTLDataType::Bool, + 1, + ); + constants.set_constant_value_at_index( + &v as *const bool as *const c_void, + MTLDataType::Bool, + 2, + ); + library.get_function(name, Some(constants)).unwrap() + } + + fn new_compute_pipeline_state_with_function( + device: &Device, + function: &Function, + linked_functions: &[&FunctionRef], + ) -> ComputePipelineState { + let linked_functions = { + let lf = LinkedFunctions::new(); + lf.set_functions(linked_functions); + lf + }; + let descriptor = ComputePipelineDescriptor::new(); + descriptor.set_compute_function(Some(function)); + descriptor.set_linked_functions(linked_functions.as_ref()); + descriptor.set_thread_group_size_is_multiple_of_thread_execution_width(true); + device.new_compute_pipeline_state(&descriptor).unwrap() + } +} diff --git a/third_party/rust/metal/examples/raytracing/scene.rs b/third_party/rust/metal/examples/raytracing/scene.rs new file mode 100644 index 000000000000..8ecf8568de15 --- /dev/null +++ b/third_party/rust/metal/examples/raytracing/scene.rs @@ -0,0 +1,135 @@ +use std::{ffi::c_void, mem::size_of, sync::Arc}; + +use glam::{Mat4, Vec3, Vec4}; +use rand::{thread_rng, Rng}; + +use metal::{Buffer, Device, NSRange, NSUInteger}; + +use super::{camera::Camera, geometry::*}; + +pub struct Scene { + pub device: Device, + pub camera: Camera, + pub geometries: Vec>, + pub geometry_instances: Vec>, + pub lights: Vec, + pub lights_buffer: Buffer, +} + +impl Scene { + pub fn new(device: Device) -> Self { + let mut geometries = Vec::>::new(); + let mut light_mesh = TriangleGeometry::new(device.clone(), "light".to_string()); + let transform = Mat4::from_translation(Vec3::new(0.0, 1.0, 0.0)) + * Mat4::from_scale(Vec3::new(0.5, 1.98, 0.5)); + light_mesh.add_cube_with_faces( + FACE_MASK_POSITIVE_Y, + Vec3::new(1.0, 1.0, 1.0), + transform, + true, + ); + light_mesh.upload_to_buffers(); + let light_mesh = Arc::new(light_mesh); + geometries.push(light_mesh.clone()); + + let mut geometry_mesh = TriangleGeometry::new(device.clone(), "geometry".to_string()); + let transform = Mat4::from_translation(Vec3::new(0.0, 1.0, 0.0)) + * Mat4::from_scale(Vec3::new(2.0, 2.0, 2.0)); + geometry_mesh.add_cube_with_faces( + FACE_MASK_NEGATIVE_Y | FACE_MASK_POSITIVE_Y | FACE_MASK_NEGATIVE_Z, + Vec3::new(0.725, 0.71, 0.68), + transform, + true, + ); + geometry_mesh.add_cube_with_faces( + FACE_MASK_NEGATIVE_X, + Vec3::new(0.63, 0.065, 0.05), + transform, + true, + ); + geometry_mesh.add_cube_with_faces( + FACE_MASK_POSITIVE_X, + Vec3::new(0.14, 0.45, 0.091), + transform, + true, + ); + let transform = Mat4::from_translation(Vec3::new(-0.335, 0.6, -0.29)) + * Mat4::from_rotation_y(0.3) + * Mat4::from_scale(Vec3::new(0.6, 1.2, 0.6)); + geometry_mesh.add_cube_with_faces( + FACE_MASK_ALL, + Vec3::new(0.725, 0.71, 0.68), + transform, + false, + ); + geometry_mesh.upload_to_buffers(); + let geometry_mesh = Arc::new(geometry_mesh); + geometries.push(geometry_mesh.clone()); + + let mut sphere_geometry = SphereGeometry::new(device.clone()); + sphere_geometry.add_sphere_with_origin( + Vec3::new(0.3275, 0.3, 0.3725), + 0.3, + Vec3::new(0.725, 0.71, 0.68), + ); + sphere_geometry.upload_to_buffers(); + let sphere_geometry = Arc::new(sphere_geometry); + geometries.push(sphere_geometry.clone()); + + let mut rng = thread_rng(); + let mut geometry_instances = Vec::new(); + let mut lights = Vec::new(); + for y in -1..2 { + for x in -1..2 { + let transform = + Mat4::from_translation(Vec3::new(x as f32 * 2.5, y as f32 * 2.5, 0.0)); + geometry_instances.push(Arc::new(GeometryInstance { + geometry: light_mesh.clone(), + transform, + mask: GEOMETRY_MASK_LIGHT, + index_in_scene: 0, + })); + geometry_instances.push(Arc::new(GeometryInstance { + geometry: geometry_mesh.clone(), + transform, + mask: GEOMETRY_MASK_TRIANGLE, + index_in_scene: 1, + })); + geometry_instances.push(Arc::new(GeometryInstance { + geometry: sphere_geometry.clone(), + transform, + mask: GEOMETRY_MASK_SPHERE, + index_in_scene: 2, + })); + lights.push(AreaLight { + position: Vec4::new(x as f32 * 2.5, y as f32 * 2.5 + 1.98, 0.0, 0.0), + forward: Vec4::new(0.0, -1.0, 0.0, 0.0), + right: Vec4::new(0.25, 0.0, 0.0, 0.0), + up: Vec4::new(0.0, 0.0, 0.25, 0.0), + colour: Vec4::new( + rng.gen_range(0f32..=1.0), + rng.gen_range(0f32..=1.0), + rng.gen_range(0f32..=1.0), + 0.0, + ), + }); + } + } + let lights_buffer = device.new_buffer_with_data( + lights.as_ptr() as *const c_void, + (lights.len() * size_of::()) as NSUInteger, + get_managed_buffer_storage_mode(), + ); + lights_buffer.did_modify_range(NSRange::new(0, lights_buffer.length())); + lights_buffer.set_label("lights buffer"); + + Self { + device, + camera: Camera::new(), + geometries, + geometry_instances, + lights, + lights_buffer, + } + } +} diff --git a/third_party/rust/metal/examples/raytracing/screenshot.png b/third_party/rust/metal/examples/raytracing/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..417a1d746dea6b7f495df7171ed2da50c0650e9c GIT binary patch literal 2245032 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]hfH8iRYK$~w?S>`_& ziZuOe1h?fV_-u#U(BRjhVfe+ZJLVhY0^5F$c}%9I*gdJ~FFvtc4d&Hy^OiVqcCRn< zzNna@G7a4p3tw-4`YcXXL0`a5q|WBWxPgdG^WT`F-=4$}fIo#V!A2e(pEROoq|DS?!!P-p`sF6=4$) z8pFS)iKvUltRLe~g>TNPt~ugF+a9qLH*{XpXlP4znvWoa?y`ziVSlSP`uRC>qL=A3bYHQ2 z3j(~8W0IVGO-Nhf*j*^@CI#4>!&IuJ9eT@Umsp=)PU0?K83yy%&q#-~UNGam zdSSCImH|*zeG4L9m{4rMt<$cb2)%&SW1ySjx+RhW+s=E5Y+545{`+uVd8q3j+wg)} z<438uiWytpO`&JWoQFZhueqLoYaHXdBaG#gkvuZrDBw)nKzu zD@X$JE>^K*X1gva>DVlb(W_;C=r&zfX%|37kFU)d_NtVNB=0}R!YrjQJ_m9GRLV{qX#zMzRM$8)XdCAVQFjNKUatY!=Y&J1a5G#KMbah1tgl35L?dv_g_X=@P z$Q=d{K$IYpSg7aHjOzqH!J7hcTV+d$JQ%_r4EjRI2s_1qbbl5Kmg>D6Ax@n7CJALP zQ+}QaNVrX{f94B3OA0{Yr+4|rdpZPKVEr^&smUJ~xBcj)K;4>0*!3~D6wuvNkQlaQ zV?}j?(fCuWc5>%v;6dFpu~J6bskh!PEmPe9QGKQjOv?-iVKTKP&xpYW0YARl^}kyQKat8dmg@J1Pbwb(v5YZ_CeEzM7Rm)`Aj^z^e`SK4+D`XtMdo z&MhFy%j|)Tf}}la7f%ho@u77V=I1fm!Wxt)ilOF`|7-WxYw)g7vMYVYYa) zSgE<1(yUEAS^nYw@ve@;putj#^<|cmdmj`&Vigk(y5)TBCs-Wl*E%v)oN^1!ZI|Ay z;F&U{f;*e^%iA}qn8kmUlb1BCQdZc{75XJ-*=_d*t@u{Y$?;lE0rlT1VF04^=Epb2 z@PEN)eEYIqkL!ONAs^5rXRAXh4W=mQxDz6{(>cEQ*ycSkp#^0C==SpTonLd0d^GK$ zJNW`X|8&=8-hCle~y}aA@!0Z?=9gNjJM(a6M zK1uJ&rq1S!k#&*7n&Gs+lk!WbTKp2oHgx;dM5il#JUrF@j3L-G?KZwn(z2pu3f1$%ch)LMe^MT=xujpj#x4ux!o=)Ry|e7J{%~rqm7lSZ4nv6225~F zMN+K0l@DElS7G_*TQ4?_9&RsJ$ovG)X(BAmU5`kiS8*!-T=y%ro`=Z5`|!Xm`N0dT zoW^bz<%q`b?OIydvL`3ak54BvdWvT6&>HcHZkl-GqePr1Zt5xpF@gKr(Z@K`%a)67 z#FL`i!yKg17^6yq_=guG@hk+TgE9D?B7}@5t@X;4$~m9$a489j@j2B)1YKe>=SmjN z&cyfoRG3=nXL(*XlFupGe17Un$Hr0aSdbc{b;B=RpeE;n*Q?n#ixj2>F$&0)EEqU? zM;B`r_45AG$LJ0uqrQ9j(v3uWRYsQNKlpn9){0fT@2n=*{z(wpGn5Ryu*hcqT}^Ov zDpf7e;|+^qQaf)ls;Ss)itQ4nEM3o3`C?c?nbMFxC?b6t>(9F~qGbc-1i>~oZdcfr zCTc&97`Sqk45P7I=DiqNNz>xRxve6YGprQ==Mufc)A2)%|=aAw5?)xXe+(;7|TDf1pP>1()Q@b#f~(kDjz zN85p$cLC`jygL*cdS8LRvkj{0yAJ+fOQg%khHycwr8#MUotEq{%`iAmL$x`FD zwI&wF#l?b!A6sHw8FmON%^O?Jt<2ItQL}aVha705`u*~P9uMOVeALWGcXpzP^DN+! zl}$+(+4O-S6x-Q^dD$XM0Ydqzt$s*!N6gzo;+ACJC4Hv9jv|bD90``Tsui(!$+cHB zMcy0;$;ABdW@pS}QcK{cIg&@Zk$9;5pxvK2=(k)S)UPZ!hOwYcMdZO7>PrH@vuF8Q8kG5^G_Bj{8ASpR%C^) z9%}>)R8g^!<0Spd=Cu(?e`v+qd7T7&@Ye3@MFIPrXXO zr5^y4q-s6kpI_JOoEoe31c3=8_Pzf&D%@xHs9&_0F7CnI5mQ>BOSqL&T}5f|UbP@n z4H3))G7C1LXm0{|Ri;pgJFM6yVX!vu9J*l5c2n|rco=ES^XO~pz@-S{iBErj-tct+ z$l1&b2YQ-+fw-n;b0UEH@lPNWdhuDvd!_NKurk5T@pAMxsFkVO3q7#;v;`x`(l zoHU~2)6KXNu&TRFidkEkXyH8l-uUGx#jf5~b~a}ClE^4JZlamNGddg`Q~2Vx$&HOV zS4Dj?40!Fkjix26j@wZjG8D_VF%-bp40zOdKly{(26Jcp>?VfjBBp45i62aFRS;$z z;3J2Ii9{>sPEie%{6Qnk<%uI``J{pW+)3$+SA|F>AS)y0mFYN zAzjlQ=b2ct@1vw+alGhjgA@xxhv@V?KCvBcBjGRJ#F4n+@~wsdN4K+s!TH0|ByL5Q zQNlW!oqste$ENkANQ=fp0DY5YeZ47|Twpgwr|L^2l~suCi8JVz3!&awAR5|cx%Fk^ z@$8;qKB%N3dhS^Xb6PH}_Lc39rfdlyyQq1*&ku{;Tj6(>%?BIj7-8OIG0jTs2J>>n zS*x6{j-XFCidBYo3yx31-UYWgEhEu{m=c7NoM{O_V})PjLegyb_6g@`2Qd8tHH2J^CjRp#KmugEZw%S|NcV+C2*M&i7gM)s&lb_ zL$J&cHQZ%;vA8GEZRu-{E`TFov869ALbZ0%IOW^U)oB=WgdO3J>nCt_^2jch8l?I?AXfC{VR)j$w9jJAH9ST7r$m69(Ts z5PDolVPx=$&D3ukWF47XmZ@`;$=!XrU-L%Ajb>1RtEdHo=Kak8`X8B?oH&^Z94;T$ z_fO&kt*v+vB6mN6!QWOJ4zOL>UAu@u9EECOzN_Bbs>exhXxkiomW3tW_-@~yvq@_t z82bn)+Y)SN?sQGRp8tHBRL_-umW4ubX@AlE+3Gn98u8{re$M9vSG?-+4!((!$iDE~ z4Eb$3|7lfrK0|NT!eQbNF5A_dGRdD9Y}wXnB{U9A%C(}K4=0;4>=7AVl`UhJPXVTY z1}DfW#SJOg95Xo{YSXCOU3u&lc_~5$VzP2XNB5Pqv6^g#?rO;k{b$KJ9wdLUwohg5 z?zxOx$0~~g%;l(Lg@{%+2UR&dK3@oRnoSnbp2_se$nxkyW)*MrEOra zO}q*C(|XkTk{e%s@gVy9#zBP?N(IrvgxfnL%c9Jn z4Xoceh2J{?>Sde@(I4X8h?fsOhx7jIzeHnv={WCiFG_&fL3pAiPSy2$HEQMO#$GK= zFaN}aslw)9(++ye7`Sd<qz{o+PXTBc0OAx1UA;&b}D1zxEPxcZ;!i@(;zX)dT+ zI}1{Xw)=YmM$D;XT`n^Y5@X5I0XS;l5R@mRC&)qR4oho9jaLZkc8l;r=8sSd-yWd} znm?sU1;^>_52YY?o}YE~%?POsUc1J8k3ZZd7Sh4I@4xrH-bKY80Nv>8n_ zuI|vARi1-o&Nxjwm>DYkDt@E0Kdh3HzWWw>i!c{y}mA}4gfBkTH^zdTinDg;> z2Rj=Roa!!D==b4yZ3vg{cRej1uCTuy7{xpD?D`jJs+-~b>l(L9^GHvo>L;eDr$^h~ z6Q+l|;W!`-j41D9Qz5QR7JJ4;giCv2o7Q}vp{OWXr& zL9{09%Hts!1a}WhL_g#=9`V{>4Dg%E%7fFOlf#eWauA8*6XAu=^|%CTpDA zJN%xtjLFJcmOS*h<^F)Kg;j~R7I4tmR1@?ymD17lu97kY_)SbwAhVxIQoMh&ry^PB z?MIUEv5@vq{w0Q6%!U}nGXqjAuk2SE5Gj5Min$*1yJ&8jJFk5Rz1p8He0f*l*A&Qm6#2#n!b8X-6f4MgUO8;KnQ6qOjYHtr7s7xA3TGj&`jE|Ih zA~cn2kVz8ic=P5=IN|{PU*l6SoM$cd*CW!G7Fkgx+dst}bL!yW3c{!v3lPH#Z|NWT zkJtI%+}0OZeQ~xevY2%Lne^bxM?9(i{A8bOYVVy&7nH7^NV6+1VY=y9-2Z%aI$0H! z8;lEEl)4-yo|q7#&p6jzB$^dVwI6iRQ6T+kTHVmfv#u)&#;teG@vO>%TuS2H)ZKr>a zte4lw#rQo`**sqVr9JdRQ`0n)9seCCLmKKv`)6D*-nlWLjTEV7Wg(R-bfy zUAh&GrOW)H8aBu^2fb{uXa2tJ8;xaO5^Bg3JTX@GXk!jX3=x2g`IKD=*WRm6#>eAt9pag+VjW9` z3nu5T%kxWKq6RbapVS!^40{M6XtrWSbG9+oxh}58&ZTtM#o%&{ts%!lmSqmI>%&*f zp|Ui1jNAS>xI&+v-JRftDw)CgbVZ5QqK{zt`_+0YXi=BAYt4eq_4!jLsOA72k-7a~ zLOY*cm1r@o6ApzCq(&8xZ;W6!vtki@(nAQUCKGI%@BdBr?}0+tntcK=b7vY5W^ZICFLTj}{YkDN^tXZoMo9f$0IeA}tL3)UDmYyL7G2LKk{mQ-bV?A?MbjiDi?n4uqTM)eYGwVrx_i3lx zNr;7dpe@OU-8$1Qr0_**{_jyuR|&Xt3ptFmSbbb}9P<)p+RGa!$Il9S)e%cFILg!B zQup01R}W_VnlA||TpTzB`5^kNm_K8yS2|}>fIzjDt69@?J?sZvUplcE^sRZHvg@Z+ zx+dppe<_Azqz$Y%kc7s3B1)$u1*i&9sfsftE%Sngs-@aCKhN>?o10vD6KZ?Pm#92$ z!WpSt7%MJv7iStMoWwm~MO-Z+#?G%l6yCFhM!Eq<*LJ^6>rbaHh^o_F)~AAC+f0du zP#c>jCBB|bx{}sEiR*Ie5IY@H6ps;U8Ojd|e9yU`u!wH>OV@W^eOyoBG3?AmH!}DC z6DKvd4d4QyrHR8uo%sD>UZ>7>tLn-Ihf_crS3d244WCY* zbHNYOQ;|x46H(UP7y0((M(r7%mVcp?=@>RN4BK6!;wn4?!joSRaS(wFyy7!d^u>eE z!)b@ylN@+-OUyQ55Tf%6vugVy<1=>Qiv?SuDMC;xBgC^hlboW@<@qi^K~mk#4gurj z6fVKsT5*vS!aNmNkWnin0FtIJ~=&fs%V zOUfELiez`E`X{Dup0W5&$osby?zkudzh~lKFjFWO8dXnf!xF2B=dv|rSxJ_Z^CQT$ zO77{pR^`p#?Z)D-hDv^H_GO^Y=R&t}V7|7I&;e{M{@k-O;?Bn%!9B^&4i3iJSG!y; zI+tDZ&24 ztr}vngjk|)5S{4%eV%uIGw&DQm@&q^*L_~+bsV;3DW5k@bFL)zy=SL;!6QhBuO^bu;4QoXEn zoCG96V4V{u`Z!xrC}A&}V2sG?pp;|T2%5#={vyQPk!8k!-$@cMxoUoaQ3NFGEA`zA znGGV?Yb99h$Voz@KjOr@98F{OYO?f0=XF zPmA4M7?C@8Q22YQTS-Hg_lwkh4SugP?RT1u%UR6ozMY%1w6e~BOISrVkG3A6^;jvj z>Nb>g_c1`XS)LX3gEz!xrvVsEHype{`yO9}z6(z!^-%bYQmX?Bh+a;&XN5Ywn+3r> zy|feA%~;PZbxM=90~KYae%KBX)erz=PX_V6Tlr2Fk{fCOpn+@H^>eG9cCehKlKLs4 zURwNEhzA0GyhoC{#QK=Li6I_!*9>4OBDZ~I;Gws>B??x=`vwp$j%K+CQLYp;G3?L_ z82zQU`>WvdulVd%-FpT0T+3DjV0bP;qTy1Zk6K3#di7PabO84}48o?VEh@J#^a&2^x!`o))?YJ2-_`T|kfVl0IS}>|cXGqoYruSl3=F>X74RH5oo1%K{Y3<=; z?QR49ymS}&4_W*9KLt_G7rNg4tS@>=|039#uCOZBLTUfp|F8(I{eAG|q$P0UIU;;) zJUlgLuw~CZP-;%rrvriXy3&nw53Fb$uz0o_34MOt6Nigin?G+^p6%h7aRtd5$o1c!ZEoU~kjuVqMs9twXxCOb^oeba541SjR#r^9f zxclb)@6Q}T8@EC9&f(9ZC$Z4<5SI1gLeIajjPA&r!F8f0CWVF;Y4XMOam(=a)>GTy z_s^-g7=w=|U;jIMJr^9xV}5rf5WlOhY9s^s9)3rfHO@DX7WpGO=d-s`P~vD}y73di z+o)2(ID@r+tG|N|w-91#1Ik5;-nrBIXKJV5+Rf1cnICls3jnxMU2|0Z1h3bqFzfrD zEuN5v{z{`MB0o2GriZIp8HThU#WTCC1)SPNy` zvFEw*`|N)ryay}`YQOC|ZeO;-Qe|pI*^s=Dr1*Vx00kuX?9IMNZLK;=X#H9Co;djF zOnQn~ACPTVWz_q<)2jEYD3-FXr|>HfHICyTGEb_8`jg-=1eHSUqCtE4uk zd`zi}KEPYJLdF$*ES6S8GHIdLL{mu8T@Ppw+-Zay7f~Yu54@t7^iR_QMGzg9+*UEkJu3Lv)j8TfACr`aR_7#UQkB2at%uJe#8PoHAf0+xBy zb#u;0aK3D(5l{<+T8j=@*iR6Tz z79+gpecaqJsaC5NtIB<{!S~YdeyxJP<}{ZLP&~L}*{cI#N!dW@)Bq;Pbu&k3c@6YB z_!$*jpBy~hYz!w>F3l4wrVN1=l3+A_hvI%om#$px-;~aPn4;>uGVzH6#sK<5 z!pcdL>bzMhEzj6R?)7H|GyyVHp5boSS(3|F6@^#)Yi9Z^c1Z#vpY6tyJ1iwz9&0iI%vXBX)Fd*o4+;{ENU=w$^deXt7Zf z$yoKK4HMPp8^&TK8`;^NGE1ah#y06eR5u@SXV3 zDJ@Hnqv#C%5aTS_Zq3^KAv%B*qU$ZJ%e{52nN`ZBz)eQo_8!zMAfgu?sw>(4PoW7z zmC>x%i_iA=1hJRwa!)cxCDEdTrncwsPt_kkSI@)lq71lnrR|cLC%f%Xe@Z1T8U$wU zttRFVa7JNK{pOF6t1f%XKIl#df;h;vj#8+^xdJo`wUqv|JMZ&+%zrzC8Q-WZoCe0wqA)PUAOuCo2nV6IaL?(RZ!`hCnFicoW9=Ffh*gu7r80 zqc18uKo%Go_h}tZu@1gcY~*e#acR(Ze+lN4Bnef#nw{qw3Q6-l6$u}oTORzqo}zE} z0ejWYLDRx?X_B}7W)A(e8cg*%ebtN#L7l3vW?<6ILPg>kc_{5wEIE_q#v}9}b#6iS z)MaxnQuN}+K1w|D)7`r})JPV#FH^fIh&K2N)?&4)!NO@)Z2$Ha%rENK_+EUmdOo@}@AnicTxKDz7wHX%Chr^4u`x{QMt^)LeZs9B zXP0|^=w{5ND*7yd@Cy$wuUz4OJuG5tU>7W53)*{lkZmcIuf&9Ra-Jq92t|}22Mhs> zGmV#0)XCktKjI}b-IzU0Lo_$(_7|AdQy?ZBy;}p7I};-p>F?KY<)8lXTei>)g<9s9 zt1udWN`!cP3Lv+GJ}8`)SPHG}#>P3xg2SF}TcUNFFlc1*rg3L=m}47Vb*}dT;=oK{ z1GBdAQM#6Zbi8pAQSCH4$p_O_gBUfwAnv+b!)K%3u=aM{gvF6 zc~$$Ii-*kPsY#uAdl(H!+_V~V;O&%4YP`d@zi(5S+P(7Hyz($r8>KGVy@SJvnI<$& zuDL|WUcVfY8a_e=doD3n_QwoluEYaM`9BGfPU*{ZYxrPONZXF=LLatKb;=(S<}Wym z?G6njL-k8+`@~*23o6YpO&))`w~eVqOrlyFEsJFSM!Y+Gq1RSfM@u7d>#sIo?CB{otDC_|o|nWAA=!rtW}^%_cA2t%nIa*)u?UQ))y#_|%IdKn z^A_VeRwa@6YOVl^jy=fCrAfh@umjS3(ZsMq<~1-`Qh_rTKX=<#K%Ng`fVg&1a%)gZ zJx~gr2QIW9ZKq^f0YmaY&ctX&G>NCcH4W&YZNo>ns*5qupwMl`+$}p)d$K^ziCX-k zcOG+hl;x*yFlqUk#2nHmynFT)e90B)s$6>Ht1IGG_Rev(tcbzUg6{E3E$bPn!GuRs zzq2Awzp)pIn$EhOunwPp*LD+3ynNUQ)ckf+kxy;+D?I7+Yj)cPQgK(;K7?MWF>tu( zmOrl?a8OvbScIYjM4iy(>GE5cTrCt($yYU@18Xx?@?c^9$TL8mhSg4CZ3{f z#@~UA*JbNZ1IS#rPcrN7_{19i1qAMdBiXEpk5|`AzkeAIYXJ=Fl56o>Q;L2Qd1MdZ~ZF&7Az*>OF4U-4glMU+3_# z7iS)iUWd;FaOkRwydSFr^MjtkX&W7u%)VK#PPt=UQ3Z!^6553n>O`3P5bEw-J$)xjRX ze-jeFIjXY^-9+G5Y0=SKrQz`$5Eap01H6s|w;?tT(#4xI-@2$2`CTOpn8|&#Q0?nh z53&Z_ELVQ=N-RVTnU5CpKtgq5wjLqR!x2xlVzV)kNab^Ts%>^)?pN)6M_YoD9*@OE zm+_%1l1afNw66eU3=Ei2|Dyj4L{_hEYsF^u)sj;Xtu-=aY?ibEr!ZRa7!h@|Mo>;anWF|jyNc8)S zdN>2wAIQ8fK5-SV(%esDh-fovoY-)kV5SmfGtlHj7Yc(vxN-ht-R$=VO4>{Mvhx%C-q5=?r$)V@jb#qm;;cP zMS>&bmhP&ZYMccEI{uX!_fdfn{%Nda)Z$nvf|QlWYQI}w;&R=q?vV+NF8b^317p>-e0Mp{h`0IR^I8Tc%3`kKU>9{rWrRZ z!8%x({f;{#ykCw=-JmOk2pciv1Hcu^)a-1>6prBx}zLCQ(d*vga4obgqX zu31M4j1s2R8Wuw#n&Qi51+y;>`k&H^9}FV$ZU!Seqsqt?lQnlIL(daLa(%$48YzPg zw=dX;OpO~w5Fa2APLT<3BQJuX&=ke$oI3AQ%kX2b<_3HOIv};_f?1RvQiy#4;Ed*!{r+|l@pBtvi5ma= zB(-m&1oyJ-8qNMy!Qt7I1MRA2-#X{1t?K8*g-Z$ejf+src+LP@QE~o*jGjf78P{%7 z*9%89irXR(FvzmBy0i_@U`1kH0wnc0-HhoHQs|1aWJ>Nh;^x+AC9P=a`Yv2Madlhv-%G7kc8dSc0! z#c-D(wy3&PX(ZYqq6y|>6b96B;t z)qn!GIp6*D1Gw8wKD5f67k(AEPh>upU`DD{qX#z;gUS?bi}U0J@nQiy`ULL>^fTR2 z>4y;s0+T9%T1OyFmR*xRus8ij&cg$7Evj)oD6Qj-05qSNNON^ZOhI={`Nj`5Smb`p_E!wo@uI z#4ofcH9u(IG4|6C_X=)n|8Ge5F+wmHx*$PW^ zjVl;W@eK4r@2MAc@rd&=7(IEV4b^WTQiG60CofUQGN714oS_kl9k~e3PGK75Kfczy z%sxrE8;5nV`_Fe9tjDBmxeOZjM8iGexOB|g!ajorRL(J$3CrA8h!u&D_4@!fdeRX;ag?yN?jSP+xepBqgVPl!v>}H|73^9VO1a zXR8Z!KQ;VjA>M#RJ&W6`eAgp=(cd5N$SK9jzPG8r+CI}*HR(1ID&A*Av&v;RX$Pme zX@%bjSVF`Vzf@Lre^KOOx?ToON|G2lTnls7Mwy#du|)nID2Fi8(LkvHvrQKTmZ%OI zjMGY0zJ=iQt6T$8gieoU0@16VYel)Fy)3hb z*_X1pN@-Z{0ssv=MlAS1Tx#ZxMo2#axO{*)&950hHy)X&)z{w4ZXhEtl~z@y+MQ-i z;Wh^`f>J5lH&s_nMf4lovn48{?uK<{1XDxu;|L=%4A9fLSKI}8dTcNj=y-Uwq8Fs% zaZr;CGu;{-si;hBs4=ah!5>4(TK_?dJDS2&xk`C5rThcy78{+t=xng&-&vEa9N&W1 zR_bVu++Ql?IE zG>b;H6BlL9pVE-kjoE>aO%E{KUv%_>38|&2pA>A7(bZ00b=4gnRC#gUjqBL>{~N3> z<4YBWN}n(Hr}*hIezDRn6+0QpYaEEmMNpm?CSRf1p1lzTo;)?3h;&5cW%R$Li|`1) ziqcq>C&FJV{?>3CFz)yTcW~X_qIaR=Z{&ES+Veei_+=>x!`1rp26y3~zft|Ke^3wp zm3+`Bf20=f-e7%}1DO3Ggo_7q_4I{ST$+}|g!*)Bj2V&B=fxrhDfj+;`ukAQjID+ zZ$~|6pJ6{reO}<+V%gfBzz+1&V2E<)rxf!ec8*1Q5eiIje7DDHzt%8~CO7Kz4hbQ80ClWvy3`ZBF?G|{=m7|Pmct%q-J9Y>-=dI| z=YbgtzkR=q1|0iNdeyf;GyF;k!7r))rlb_nDz+a_YAqM;BwISsTjo}NrOTDGdm9C@ zo-_}6>hA#YASI7wL@9il2~2BXg($`ss9A95kZ)Lz_mXYPayD9Z%mq5Cd*|4k2^cHu z`Rds;tv$oENcD}EbXTJaWYeQ&e5idm1;LzpQ;pUM$cv|){pKbdLZ~|0`0iTcU4Y^V zN_C#;_-*5@V`&K?oT{GH{N0PYa+uf-`T4Ea8iS*$@%w=z}iBEd^ z3vVf=S#wS7Jtf1`pv09)l!^M>7sWj$CcOyGiI^}bs42+8MI|JuLQ;l48cc-2&sVQl zRdwGwgXR}ONY$)DHJS&JOs%mH{+@bsg45;j?0pmWzL)!SYhCk=w3iqEWJBnKI)4{k zcf1}yBla1>1q4*(r)I{4=gUg6Q<+^tZ;>ygRlax*NzJv<=X*|YZq?wp^FrOz-0gtu zDNFXJdg$p5-+)6yKo5cJTH5G_C4it#6heBOq791O+{ne1x{BLkEk~?t6=L*RBHTjJ zAO-Vb%cc6alU8EZE4Sh1-1745OVH;XKSP6YNoJ1vRe_0SBZle}X6V;Hur7%Qx@vUj?GVF6*Ni2bD1YZ7X{aTgnaS(vM3D zf0C;qv%Q_kw@ed-yBgvQ<_|fR0OmRvL%DRCvYNQ@DY#w4?b*7h3x46WP(yXz-#bT_>JMZA6}x?k4>VO4OcKrjrYOLI z0Rl0K%qO&4pI;Te&BCkT_v#eox9?T$)85@$Ta#V73rVual%xrgxI$#C^6|Q+bSF;z*7;2%ZtT#{ z-Zk9n$2psCU3f9;VKlSBL&Kd9@PK0oW6s2gf3EVUEEcC@axb0^d3%sun=pLUc9=@m zxN{Q{93Q(lnxz8LONEoG|MZsf-YH%bHjxx*-EH)b;u<@8379;DQ-ioP!;PiYbvbPC z36E~?uD_Z9wsV;BP@lR@?eBM$S^yy}GY1E51^KLF8=d|Q)XdTO^M&rK3Palu-*WjV zk2ysX_3YTKw#XY;hE@-9lsNmlq9gyNl%FxUGW`1mNB3||C4X@K&ZK7O!-qF>2w2WC z>#hEGLn|3in)B&z7Sq+NZ7Q~}dSVfqBK2O$?iE-310ST@3T7i~9Qd{LO>foc76sof zZkhRT;-XOYXAR}nwR7@yt`2#_Q0Hm>lsJQ-=hXtZFwlY;Rw@1^7C_9?&|X!Tzg}SQ zYM{n8`txqd5>2NXFup;`KiE@lfAB{q<&)GVn0_Qs?=ja(XhdRRwCM+nk9}t_si~fl zQ>)rndJF^x(%{Ye`K12ZQ1>HApLKrJlr^VldB0<=gPFJCiOuZ zTSi9am7FpfQ|sp9HwX?BrV67I7QeNGynaP zFcx2RQY=o%&Dp(5eX$d-v4``4+SRnThJH<#F0Q|DjmD8NZ=#=P5mS`i(p!mc3g%~~ zHSQ8`KyF{mat5lvx1Dv->DIF!GSkt-@uDk@e3}W7^E<*CM?FOsXoz1XCtN_K4pJ>~ z)e)F%vIc&vGu&Vb0Pz+;>I0~4$FdEoCnjj+UCFwX()DWnJBq(a_vvFkQ?PZDuzooH*<8eh}m%n5r7B*;n2loYD3qWni!fr1PEp*1Z zZ#Vu|J-_*Hh$W9epGfgn==wsh_b*`1Zhu(=em^+)n&t#U=5IvF*78*-eYyEP*5QV` z*)d<#&j@AVyVbjstM0p@ZPZ%vxvm5D@Vxl^q`$U5$o-;TJ_xpi)uu0(kQ4z*=pQdZ zRqEBQqNE9+uv+%dUM^y6+L6Tv8`{{WVTo!R`6@(`C%xu|V@Jvu~@xNc--h87xNJ4T*+EoWB z)XJq(R78!mdk+?Viz#Xl3Y=DWG~uus#{{B(gYK{hR;NA`GyOd!sB0d*H5(JGhxkJ% zc{$NE@yUlGIW?+rR$*L#OvoO1rikgC^DAOPEsr2~Z#7cG@@qA||Ixc-ov$qH*v6uT zGPK4yd9en6vls#FMQF{7=F}&d2RM*3K$?zj5SK18MJCOX29kD@tIO<2?9^#eg^&zY zf1heV-9fH++V1SzAi+=PB+h7z!s^Evp_`g~p`Ch6XF9ktsGinK3_8Eu7RE#oc|Fy2 zmMI#^_)XPg~0wrfxkve8i0k>LswO zf__p+ie0!s8^8Jn)bS{GEk>$MzaT)48zKPv)g6`m&g9D%J977J)QFh&U}5lyAyFFa0wl0maQz*$j?=OE0P@>mwrg^X?A?lX z{$e%$A2We|r%Ttq$;wWrFK;+1(Mgx295;d=o(l3x<M~w5guvCVbL6FRgvqMoBBS@-@`@HzJJ6_ z^%u#2NE6DQ0xtuz(qU2G(th7h1dWb;1~?S5r5*Ay*~C0v*;qOI>`D35dbMo#wh1xN zK99{Y74i}u66IEZuDY>}F2e!Bsnf#qihW3ITj4U8YU37#p|Yiuf(8c4KhqXUAat;t zdi>Bn13zU^(H|duQ+-TM#{t~L#O`RkrHA&?Pyr3gk^K|;6)Qpr`F@0Z?Ayru={3=; zRY5C)H7HJqM!E{P3z$Nr2FveeR{f4Izh*y zYAeDwNgdskSzn!@Vl<7-kK9TS^`#=IJou@pW04FNc z)72YKZgRvJ|43EaJ_um{CtRW{NU>Iat<*}|;M8C;+Akcd4oEelt~PbkxrFD>uxO4$ z<^kwj>R)|#xQF-^#yO-7jFYlZWdx1^dt%1Ll>!sOp|x`TxXhw9f3Cb^RNi9Zo@Ube zjh4b7jl-ruH|%SKo$tc8^ywc6jiLl2rdbKieokUE&w7DMJOnQUv69X5(mpLnI#GgW zL6%tROBKTa@r3p)v4;#~W{17$3Z140+IYkc8F!&-H9wxbvcczG?l*LEdWD)jhtjT< zki~vx`p{PTmaK_GaX^R{mD~q5HcHe2uS^m{SUmATA8b|P%K*12Gu`Q{9BAj zVxTDAuPZQMo~10=!#dZ<#ys>v6aJGjA|>CaullI~#F)q385mtK{zhYzQ4sx7P{HGT zpxWS19K2*zX#Z5;j-xuS?OKJ;mF1DiiqNwEbAqJMTXv`8pYB^CvaS0ux_ehas?5=u zhTb3%@5vG?ntJDGpQWGaWowGpztsN^4vcfF?_$mWiZW{GR6u$oVrh2r|WQjV#7biu20c}R;y@=H|1R0sc)N(aUjsIHTLCOLS>ruAnk`l~vn zU3us~=+T%P#>v1XtNRdY1mop$tEo$A^GbMzuN}F+$(CYz*#avB2_wv{y!Z#F9_P$y zW)XhvxfZ%%uc8)dhVsQn8^YdT)(23W>=9X@e~>1ISn%<{b?rV@%Us(|FAToLwp zg5DRQOmlpSw_odd;DVG8Hjx}@lQMrz#$d1pIMdzvwpLz)%lkE6yTwa0Zlz%NtcTSu zS2F{%L&^c{w9rAE043L7zHIbg{8g6Y&eQx^wuDF{ss(_GG}3L*xP@IR5Bvdg5dNZU zhnJ~h6PIcN`)vxR4iaO5dfg1jtr5^Y{N2;@1Wly(249PX2lpPe{fH$p1+=u!)#pqv z2w!rpXbV>7s_8^?en4FK_qNhWYgxK;J`8oP1*3qD9BR=T-N|hxqwWJ7;#v6g4 z`CrW~w63*ef^1#PiJM}hKPXiZCN)m9?bwU6o%r=Kwo9$G4EPs+tcP7Tr7~GioF0Qr z!t3l%39&E=n%cJ?{Ofgv57xa5Qm`yO`@b$gZX`D==Yb%%X;^+-W+ML*DR?!B(q8TL zd1+T+m_rD88$@)-qnptVas}&Kaw9KlFt7_z(Geo0D&fFg|3Pvb4>z?^&!;D&r7cP`mg&UN0FpeRM)I}^q9!2H5 zNrbv2NVuM1=Bvcj+w+zd`t*~*@6Z1&P=!Z4kDL_rsTbf(-1ID^qboluDtU(y8PO1G zLhm;g<4tSc804Jh1uc&ImqnNv%2)ARVWmI6nFGrIs0|{z6OrF`l84Q|x#~`j{%CFS zOuzITG5O^-S&D()`Wy2`Zr~O$QcvwWmX{piR@GjMU}L(=;tgHeNzR{}f#f|j;~SLO zC9BSeo`rsVLMG1e(V4Kd&c?vY&DoNbW&R3UozuTa>+ZD(VwnZUu;wRIjC

95b-$a%pZ_$kwbgBSU+dDPspu*~DS09tcFxI^Y&AMW3d*2ebJ{TPbsJ*dEPu#4Pu}&TQB^_i{9uO2(w19j zVF5(w5_rbW-m?_ieMDs1CiDtiP1Bwmm#+J_T}v5X;#vxeBrC@=*gH&e<=H4AXCqR+ z2cwadlNvmtot?1cm!E=HQaw1I&?-S3GDHbDDQc=si&OJUN&Hh>oN-Rw=ifucT?b>U ze?9O(uteiL=nIM=*qQJ7l(YPpZpNE10wfSAmL1d!9pP41B~95JHt0<}{KD!PtlX>N zfulzmsMZwnUBOq zl_?2Q2urCqj^d?*+<4K<2y!iGdR_tCjHGt>$FpAjVu>*Hv zhbhcgC(mP~6-mVAtg80Q#^jLbivXYP2bCFqwXq^IfsIQag`Y*WZB8Y=;+M4fGch4Z1p#p^ zPh7)Zr-EcrfESv{;~jhP{}kg%KiOV67hgG6C3T-1~yreZ#PY%-ng&aC^5MX3}ha zI%|x7UI2X6%Gs(rKK_Zgkym3<^pzJ+tmc2*Hvih^q&j-eXIQ9ZBWNA!iwmX%P3EfFp?$ z94&`SwffW|0>Oo)=T0SmdS8<9!EEUWgbftbDU%Un|93*Ly+J*m+HDsjk$kUIS4Lj z$n{|=ob_jQ3X_C<8zR>`X^~0d45Y%-$x+^_$5H>gpY$#+0EM)+%a9!j0rq&90ysf% z@7eNB+YRxd5b9L?sCjlDM;A`w6DEZvpuh*}pP;PfEt503tznihS{(5WTre%Aj*eZ= zf}vilqG{IXr5KSi3%ekXE&lj%*$&qp)*<%LeBrN~6{4z&3h^Qz39l8;b8{LE1A!75 zUS~)a!3g}7nguMAJ=(+;1zz)l@a@~Q;P3urtCPVUW>MS#D&0tuiKLkjG<|q~pY!5V z5Q*@ah!7l(&YiS(AP(|au;en+8w_g7O$%{~Z@O~I3h2{Ijjr6$HDd;@Yx4L;uDjWr zV@&?-ClApkWem9tef$*la~sTdR+Segv{2*{OIwy&vP7FDbM#S+nx37)L{O((>DqN* z@aogG++LF!+_8`gdT{xx#{7L!w&CTE)v^?(6V*P-`?A@m)fY@KAR6g!FkAB~CObI| z@Hd4xKK~yN>c&r;(%GqW^tAR_Oej`|bn>By|DT_`%^$;zBncKop6xa`|$bH z56fYDpI}1$PfY|7x;zODeOvis48wZpW8(lR%at-m^I6_wLVENsdw^e9EA-#g-JWgg zbw-BB18cxVc$R*+YGml*%FKq@^Pu|kJt1z!L#o3zv-Qo>^YO^sRZPWuIlYQog|>*4 zfa`dp@`#|e8}ZRc6!0MC-%Wb+bHwp@#N^Fkq<;#1?BX~}%^d^$?%(f_(g=}nk+;8Z zm=vBa1|JTW=k5mma`Xm&jGk)o@&2!K*5dOxcb0aiM|#Ek|&+QON!4 zW^vMBu~IL(7#mR!j_7WIZ<17t(>lE@8E$#Ast}T@9FoC0v1s>W!?oD#mxAb2a#bFrA5jF-dLgNbdXgzn@!4RHE&(J4*j93&u#WB{=BhHXB6GAxZi+nRbl_IeXO(ORiFZ1o(@9 zjdQ1`p88NISj~{KfZSSAR!4)W_FJkL`$3;R8PdG}sEG~SW>m!|3#t6-#y{Cxh7M7k^y%@rp-FR20dFPgUAtjz0 zYf=?C(ii%*BGVHGk{NaD(`q%Fk8BlH3$ZnvA{7vFz-|;3>yZ@C87g|ef;AqIp_REW zOiI}aFl|i7l>tp5 zoI%toIR>VJVPi{t9 zMz@`#1^c$+B8poFI=W}Jn0rmStOR8%bvAeZX+rm=lp2Mj>^WVEqNkDFS#Y}yHzil> z-^1zr&q{9Q0u!sKS!s0PeAI*_Z-M>mduwdy1#M{^cr!KcvyaE^-v?QIWV#5)U0qNh zTP^-RMTpj7ISyaOIX8K#u@D(}c#kb7RZKxT-Z<+&KLDTRVJv4hosM`CQ;Ob-m~I{2 zepfzra`?ypqH$llt=4`s)BxLoE7MEIiWXVO&DCmCXC+G{fT~x}EvD`;(qDA%V1@ou zN4DCM9iL+1uR?WPJnB&2;P_VDmwaf&Mb-b!$!u0vePVXH7f!TPsF$Iv*{@*|3go|6 z&Q=RK;nRnB@?*LJ@>2kQ;S<4E{lNX;S7G*VXYnJ1M#p;`=@NZ9tq&v_AvQ zZP<+<3$G~pFJND^b#U_6N7*qRgsL0*$tD?y@H|} zHHz?BbjV@Ifq928Qri3*ikJtmN#G%N3AC>ES8vH)h4xLgwWhgCQBK%&EZ|7#0fwoQ zMSV}II-w1&=q|9tdZ$-+I~09zQV$6oK4pWL)Wj#TI2bxVjL{E)WXEV12{dgsW?M7Q9v(lr#i~s$j>W}&xzD2e0PZwnx@};|@N_&FrH5s)eqgQSfk3e3_g=5p+=iv6- zF{wgo5i*nHsJR(3W;|WF{(`$E;uyPAiWnk%s0cSTtHuSCfl^0VYIEQ8n2cB2#MM(W z8OQIHTkrI`KAmq%_Sob3WGD?ea6X`87IPcqoh@=#819N}XsN zGdpF>LJ0Jy0>Je{M3N@o366w@kCV!e zpP1R6V+;AIJCoO=DB5yAI{lo|IBNn8iOhCrt`ZZx2@Q@tD?!AfAm+tEjxp`gf-T`} zmjmhn$c-aZHKG=xjmHki8hE?P=n(Vf>087wE!!FkzS(Lb0NWY zcn9F${p=p%0x_0C)h47N$sa|#eGp7>tMqu+E zAUI|2e{Q>$e|H~2UU1!9>dp~tb3&AO``v^jOQA$lb zBy`n$gJG_z#+5SA?g$PQ@Q;t9eO*0KKjFvsE~||Ft!8R#2!Jo;6+~A8LvVaf_Iq9G zVX5c;RkKVZo<;~GdvG%X*cc9_2dXcY2NJd!=~n1T(oUXT36Z1Y4!ieU{rC1ufr@QU zim)?%k%xoZ)IcB!VWGu6!;9M$uUo6g(4&Sh`qk~2{hPYTGxEpdyg!lKjN1R`DHxVw zxTa!W-mQTD{ZqNe!a5ctua_etr%x85PnQ0@{RVndXLJ?i{qO7OMdg(|3FSBzQuz%@ z(w^etL!tLAhs@W=qICE&Vg1C--0k4Q=?I~&?r7u_P3?*D`@0iMhQ*CuqK7T){|~yw zZT`Gq*G3u$3?2XSb6wm^k5#iSVHOt3PCitV!uZ)!lLQ|?>}*|{I4Xzraz;1Cob%%z zLY$MSbY93P5uxWim6fR22}pKtp0;_GI}jGm2|6jIWk`J8=&ad~9l!OEeSSWViTKl9 zLLqAJ*eljAYQ{SfXGEQxy_0fjr0d{L4$%W2d;AcbrZ_c`vUkggh%FHO24o(*->aeB zL5ZM5*^{WD zK`eDGyHz$wq1021ldo65@kDjeGySJnckwXpL!3Q-QHd$cW2BjVi!;Mh)8GTZFc1mB zVbn`gu|)IG+L}pWT6AU3rWeJOOwR9a%Df6wqSBFVXNfi_F?*YC{jyvBk)`zYA?ig& zS07f_Idt%k$fYt76|{VWhA?lfYY$Vqv#y7pu&A{0=o4uxOU({5@oia2d77Wf>G=%@ zt52uy`qtE>SVWh3$M<+FUjP7_cM)prJW(dN)T-(@FHb&H<^oDxO^;J#JYQ$hR0>X= z?vB6SBI%9jt%zzxhb&1rPj+;V#WIxsvYLng9$??)p}8oaP?=`<9;#kIGud2rTwwo} zqf)Y%X`C&Fs}kQfG0RC#$OSpcW$tZ$T!#ln+%?0#&Ovq+Wq3g>6{Qz%q=cg?YXcQ6 z+bd0q2!$jHD9Z)2V`p*HdT6u$_{}C}xKufxUHgt8GF3>e^KViJ3OAXR34H`^Q2+2@ zAn}VdCYE~`@t{?Priac1)E?=9_|_iA>i9xLWE zga5>-IT^vLIp7$kNf`R}3uBUTSpk{h1NwY<&B}2wPh-cuU069cmGy&m zs(sH#>L8kG=8Jz!iQXcj*7Iyz;5?NEgPjj$If{g-XK%oC>Lf2N$G2nmFPxiv{HsV; zQqpd?Tc<3 zOjIymS|{qqdoMyy3u~b?QG~uNYJ_8YJ&<*v)t-LBv`T;7AK-PMjc=L$nj&(TQ@LO{ zpLd{r6qUna#Mt5By2}`bj#N09wqPQpT(X>82Rc4YP?A^D)*G8d4!aQJyEl3*r*4`6 zTgu4P0nxQI8ij&dULN$Q3SOt_Edogn=B;;-8^^VVad&E_x4x*bNEEZd42mqQPn+Vj zngDMW*QP4cCo;X3N@;gt4fO(J_Bv6pPcEYBB!SQwm70zy6VlE(Ia}t$W3kmLU2KBZ zPOd5f`vku8!rkDPRS{+LpLzt;oX=hZ*4o5ip_QPN3d4{Q>3H!MG5%rn<_0Fz-}PB^ z!rqohZ&%-EMyY9Y_d3FR0MsrVo>yGhONqM2B57PI(U!ZNR?}*FX@Z7jH}21Z5oEsc zf;=WfGeCF2=b1y$yc%X-c!GeW>N2dMX!}x}_&n7^A~P8L9o@j}0Bq<+9`nxq*Y#S9 z@AJhD?M89MFMIcx&wI4hpi3*Rdf6UAy8gC{j)oOCQoKe%rUpiwmA7Xqg$HvkO*So9 z(e4-qUO|WgpOubc5TW#33{j^ZrrFbb6r^Q`@yEQT5Z`?SVJAY~Q(=e@oxzI;$$opB^hBn3*6{Rx>2Obv0Fcqe4ig_Zp@B`Si zRC1n^yZYPj$>=EfSvIM^OB>l_rXJVDyvQO)N~G(3@e9aPDCNig3|YZ|>E{woU4Svh zKuGGjOT*lcf9ed=J<{&}v2B@|8q~HL=6dOx0Lfw!gd|w0?8$w@JS?bj0Gh{@GxR0N zLn>Kz?R~bPATnji_5@h?5_kFL+a5uSs$$VyAxe7j^{%WtQ+^eWh!RJeaM`19^G+6= zq&xU{L3ilq3fA?EC{+GDH>(YD`UO<@?u5&anthhrUe&42-D*sFEzv&m4WsuSP&+AJ z2$(CsybV(g(3sybo1A@p%~AF%J6gN84&GZ4XZ}-Mt+0cdUmXZ~lgkWkYEAu){I1d> zCrCS;TghjxTiVNEVH&2-^!UCD-@R}{L6ZlH`$ADIqg+o}0w;|{g*ec{B59*bNZpoA zP%S`*e2Kq&y7--R(o%6vaRv`V=5V3#hA9mUenE>g199I!BBD&$P+mVM|Hzxl{93ihre(#=@e9uIqWA91dC1>N21BseZYw*az{- z_oXo|vF(W2eMfj8i0z&<-CTV7Pky2c;<6beVBifNcS!=5RftFBd>xJ#Z@yVRl zUXIeU2}QVXXl^yap;Dkh4lS-YTg7@#Eyvv>xPTdLU)GKccqXAKi;Q{yBf?Vl`i+^}ZeT+OO*rGs%cDdoE0wPTdyJKI}I`TaKPLx%R6> zo`fWEtH_yzM(3}$G}LfIy&PMk6@(z`9l;_c3)*6JwzJE8O5*sZL+{M77Gb}(K1FXl z$VzG$J@?TG`yVny{iMcs=jEM7w|Vrd=Hi$H=wA9`|1!3+CDYHfcHcXQd4L?o;s`s|*}Fm) z2YKGxv$dr}u|fHp{4{K(3ec1qIfk^Am-@W6d*ZxQmtALzw+y9+m_cPoG<5x|&sKJA z2sp2IMYu+6>z9&5yKddvLzbw?Nlx*TE~!RT=%>(YgqDE(HmzMq9JdgoL!%vBw50N>lvps!NR zje5hUzMn_aCQMH0WSy}s&Ot5tLZ0Pu7Q|cd(#5F@J=>E)ie0*r>@!DgPpXOkS~hNH zuh!E2j;Hl1T+c|%p0z_Z?<{Pd4!uO2P2bi|Ug=dOtNoycv_)tzTB*>*AVb)fz|8Ye zUUCr&!(ARaEt6loYbdc)?56y(O{~TZ-$UH||A8E1m)Jx;`nLK}73t-F%x;QRXNXIY zIZ5uuktb0VE=sd>l7tfuZ*NcTbTn?oPC`tHUv?MMFkc$+y1yV-lO8EFwHrHm>x}{! z?ME9B^EWp^MDstrt)z10HN77e{`jI7CWMCMHk4#L2O>B~A)StIFEt$_aUzCE6e#Zh zy{8vmZIPM3d1}N5KI@U7IeahHs zN8R^&Sn=JD54cTibe~xR{$T9*bkco3G%|SM4gQm$aLb*RZ{fY=`SpKNP)-Uf^v@MS zB>zM+wt#FY*cpdlt9eY++{(#wUON|y`r_EzmMcxxbswh2IdrQVx%Cd;<+V(^S8i8n zbUTAF9c(s3GrNWpzf1=FB+D(*SJO$idwzT0ea~oXqlV)46eq{p-}#xReV)AazC;Te zyI+0U(rbI&R#g&sPKzG=r>uA_PhUt%!@30_VXHyeAMGKNti(pkt`GB>x zWz$Z!XY2y3@+Yz$etRv;s2=9`hI!ES$9r@e^b_U_;jq1i(pgF9bqodR#h(y~4BFd|{=Q(j$8Z zu);(kYnWC?zg~!O_iCPHMLd4KJN*nZR;)nE(4H$B3IqDKR9L$_ZIbJR{>A62-o@UtWwF>T}f?_IhtpzJGIYx{zG55r^b>!!W8G!y%E%%yll3GqF;0V9?{e9N^EgCIRm6&QHfPc zfB3&3tl`@uk{ZhEpzD#x-pAnUOVxCL&HFg)hMK3iR7T=wjhBuAXNX%yTn{N6|8)$Q zhV=d6HRRC~)jf|bC;X6hF>6Q$*$uTUz25UhbeBIpz}6p#Szq7C=F&0ty}iS(lmUo+ z+g&9L~j=0!`O9_;I#6_ z4FxEnm$~(OIKF1Mt_woTT`qy&?qh5oV$AS@9`1JET=n$wR&=LTKmJe9DTsBi0FD5! z-k_G)z#mBp5lfN27@_y*o<3*D?i2^QxLnyt3l@U5`Uv7xsxv0FU6QzfJvElheg&u| zM6qZW{{H-f#2m{n-Mr_dmiWtgFfePM95{BO|?jN6G7tj zrRrW2{tp#QLm=ULbghNi3-P;5zucB%aKyGB{oZ7XQV0BWV3Y^&E*`Ma7(Np0Z~8^= z6$X^DNkHm}c)0f|0Po$q_A%KcQKL%WX*H; zgBQiUHU&m>IK}?0XG+v4`WGe-bd{e)I72MSbH8w=6%mx{t^6V1($Oh7kS)T|DEY_i zXkE&;^r^Z3#dyW(wFUvbT1Q(G+2n5(@j!b5WI291B1r&AgHD5+G5oyrP0@4Yh)5^O zKuSV|T2S1!ww!Lh5=B_k&kkgx*O##*Cxx@R*p(}t0-y_fY~JiEr#Iy1T%I*WU#45w zYuwIxel2I0TupN*s7GJy$V-U$+$USLk3iFea;;d?+T*i&*@|84H zFXc2P*tIR+Y>QI84dBQnCYYzcwDoQGl7p-)fXLrgVT3C+2cISR(Rbive ztbysbP(m52xbjvx`&52KDehXW$OIM)`(*#7HR#bP#4x+K3a7kq>Etzf#fY$N^g^Pw zqM!quMnh-=T^2vdflVM_%j=Q&SmLlt`MLZg=LXG?suo0^4@W zn(POcyo15Khvl=n)4L0A|Lt zsQyV`xt?MUIA5wIzw2E!=Q;nR9h86KE9+{dB0BFBigMpvGgRA44V}mH@iZ4HeGj*& z$%#%5p$WC}>9HFrXf5cghf*q=n4c*drXvNGyj>-6R%0#eG1b-`d@MOe&vqnh?-Jgw zO6l2QNMe1AH|!z|84-$bxC4$UZElHk1{kVv(wEj>521yF_lm|nwAx0cE@O>OA4~8j z#^TLWb90)Vjb${RgJ^P1R5u|a@u{Nm*%iaG;~NGI!+I)t*G6iU8|kc+6~ajG+y*DO z9~!(XnqgTyj?qqE0-{#%#p4|jY;{i|((ZO%_!u5IK~}mf=|HDN*mXG}(Ec)nSkWul z&FMVrYiyxJle$XBoVMI89(XSmbPSpbMTm==3q#x3pGo?1%-dqp@zJ&i(y>-d5veSc zuFtAMSZ>q$dG~L^r|=ELcd5O>c3NaE2&J*W(hKDRX)iOv5K`K2)7rYE>M8SB0nQD< zaGQ`Aj$OsBlQH*~9A?L94iqngu-1mk#qu9l36P973X2a4*B6bg;6_PjeP9Kc-i zm`My=Gv$UG#%H@A*U%ZbVA{Bh`;cep-b`tVbZTSO{!ng2#O0E4ua8BT(p!Cl6Wzxs zLElR}b;fiLZHb>YkbL97iK;>>*voab0@TdiCy?FE;Sg(41VI!fMSABU z>f`3)R!SP+z2&({T93t|f1aS6&=qZS3<+`LZI%-Axf@Z>nTBmw)#TzqnZE; z+$$VY^rjV3P-z5P*^UDp4K2v!TFb>zf4(K@{k(esLmhNJ-FL70Z?rJ}VG>)>-DMGw z)yvNJq{u${affb>>M9Q|$VLSpWLi^{9*@Y+dtpJ=J$uC>Wnd*ua^$2n{C`>qEh)qo z*}PsNN5ZYlIK?fStz({7~_19r&uz`JLs)3QVYj-)xe7~ouolyjb!hmlzOwsY=@=px;Y9a^ef+9vVdKxHGfv0QK$pB5*QcUbhwKyQV=-Np9MJ z@#sVdoYK@~)88k#_HsIF5)T?o9GrSNr*^oduRX)&^v-YInTMoiYa2VpWgo4NeLnbO zx&!kQ8pX-Q!XiN*S#lOY5YolS0Amnltx2FCjGHX_N4WX6Szm2bhu@2%P+0CCbfdG2 zE%rOXtYYRxqdJCyBepxuOk`Ws`#}2KHMKE#*88qanICcV7k^F8`Ee#EJG0@Zr}@-i zD_cI2?=g)bPX#jE?Q2vzPH}DCQ#|g}dy8FTT%ZG^@&?3`!mR7E^fUyf4w{nCs$S{J z>!Vat1cB>Q-j~J}>GW}ayD-4)dILo>4R$~b>fIN^bfV)0Odj}4lB8irX|x90x`8em z(4sQ2s??deSf+6`oOkwRYDyHsV?*XcIR7%rCgi$3-Xry`kb+q1D>zLc7X;Lr*r__r zn+W}BXfUU$#d78)bKND}{ok5j8fD=1D)#$h-luzBnw@Vo_rkU3aOGJ>GXI0cqaSr` z;E$w?jLkW>iSac@?%9{Y-hXbWvwTr;OXc);hD518*M6`1R33tlZ#lkKVe?<0l{rCm zk5@5E4?Ⓢ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%0DkoasgqL@^H2N_Y9^awC#UQTzU@HXE^+QIJ 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 V7(BQ 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