diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index dae2e12c..0f2518ed 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -10,84 +10,11 @@ on: env: # For setup-rust, see https://github.com/moonrepo/setup-rust/issues/22 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CARGO_GPU_COMMITSH: 31153a8edd3bc626d4b9fb0cd7bdb7a8b30797d3 # Nightly toolchain used for rustfmt in CI and in renderling-build's codegen. - # Bump deliberately: reformat + regenerate shaders in the same PR. + # Bump deliberately: reformat + regenerate linkage in the same PR. RUST_NIGHTLY_TOOLCHAIN: nightly-2026-10-10 jobs: - # Installs cargo deps and sets the cache directory for subsequent jobs - install-cargo-gpu: - strategy: - matrix: - os: [ubuntu-24.04, macos-latest] - runs-on: ${{ matrix.os }} - defaults: - run: - shell: bash - env: - RUST_LOG: debug - RUNNER_OS: ${{ matrix.os }} - outputs: - cachepath-macOS: ${{ steps.cachepathstep.outputs.cachepath-macOS }} - cachepath-Linux: ${{ steps.cachepathstep.outputs.cachepath-Linux }} - cachepath-Windows: ${{ steps.cachepathstep.outputs.cachepath-Windows }} - steps: - - uses: actions/checkout@v2 - - uses: actions/cache@v4 - with: - path: ~/.cargo - # THIS KEY MUST MATCH BELOW - key: cargo-cache-2-${{ env.CARGO_GPU_COMMITSH }}-${{ matrix.os }} - - uses: moonrepo/setup-rust@v1 - with: - cache: false - - run: rustup default stable - - run: rustup update - - run: | - cargo install --git https://github.com/rust-gpu/cargo-gpu --rev $CARGO_GPU_COMMITSH cargo-gpu - - run: cargo gpu show commitsh - - id: cachepathstep - run: | - CACHE_PATH=`cargo gpu show cache-directory` - echo $CACHE_PATH - echo "cachepath-$RUNNER_OS=$CACHE_PATH" >> "$GITHUB_OUTPUT" - - # Ensures the generated linkage code matches what is committed. - # - # NOTE: `cargo shaders` (rust-gpu SPIR-V compilation) is temporarily skipped. - # The pinned rust-gpu rev (05b34493, toolchain nightly-2025-02-16, rustc - # 1.86) predates naga 30's MSRV of 1.87, which fails the shader build's - # dependency resolution. The committed .spv files are rust-gpu output and do - # not change with the wgpu version, so they are kept as-is. To re-enable, - # bump the rust-gpu rev (v0.11 uses nightly-2026-08-15) and restore the - # `cargo shaders` step, the `crates/renderling/shaders` deletion and the - # `needs: install-cargo-gpu` + cargo-gpu cache steps. - renderling-build-shaders: - strategy: - fail-fast: false - matrix: - # temporarily skip windows, revisit after a fix for this error is found: - # https://github.com/rust-lang/cc-rs/issues/1331 - os: [ubuntu-24.04, macos-latest] #, windows-latest] - runs-on: ${{ matrix.os }} - defaults: - run: - shell: bash - env: - RUST_LOG: debug - steps: - - uses: actions/checkout@v2 - - uses: moonrepo/setup-rust@v1 - with: - cache: false - - run: rustup install $RUST_NIGHTLY_TOOLCHAIN - - run: rustup component add --toolchain $RUST_NIGHTLY_TOOLCHAIN rustfmt - - run: rm -rf crates/renderling/src/linkage/* - - run: cargo linkage - - run: cargo build -p renderling - - run: git diff --exit-code --no-ext-diff - # Ensures code is properly formatted with nightly rustfmt renderling-fmt: runs-on: ubuntu-latest @@ -97,7 +24,7 @@ jobs: with: path: ~/.cargo # THIS KEY MUST MATCH ABOVE - key: renderling-fmt-${{ env.CARGO_GPU_COMMITSH }}-ubuntu-24.04 + key: renderling-fmt-ubuntu-24.04 - run: mkdir -p $HOME/.cargo/bin - uses: moonrepo/setup-rust@v1 - run: rustup install $RUST_NIGHTLY_TOOLCHAIN diff --git a/Cargo.lock b/Cargo.lock index bc810d1e..6fb1af08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "ab_glyph" -version = "0.2.30" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0f4f6fbdc5ee39f2ede9f5f3ec79477271a6d6a2baff22310d51736bda6cea" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -14,18 +14,9 @@ dependencies = [ [[package]] name = "ab_glyph_rasterizer" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" - -[[package]] -name = "addr2line" -version = "0.24.2" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "adler2" @@ -40,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -48,13 +39,22 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + [[package]] name = "aligned-vec" version = "0.6.4" @@ -72,23 +72,21 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-activity" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" dependencies = [ "android-properties", - "bitflags 2.9.1", + "bitflags 2.13.2", "cc", - "cesu8", "jni", - "jni-sys", "libc", "log", "ndk", "ndk-context", "ndk-sys", "num_enum", - "thiserror 1.0.69", + "thiserror 2.0.21", ] [[package]] @@ -97,17 +95,11 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" dependencies = [ "libc", ] @@ -123,9 +115,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.19" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -138,44 +130,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "approx" @@ -197,9 +189,9 @@ dependencies = [ [[package]] name = "arbitrary" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +checksum = "3bc62ac97cc33321f50863d514c3bc38a453947a8f9e781137e47c7401020aed" [[package]] name = "arg_enum_proc_macro" @@ -209,7 +201,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] @@ -220,9 +212,9 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "as-raw-xcb-connection" @@ -230,6 +222,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "ash" version = "0.38.0+1.3.281" @@ -275,7 +276,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ "async-lock", - "autocfg 1.5.0", + "autocfg 1.5.1", "blocking", "futures-lite 1.13.0", ] @@ -329,20 +330,40 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.5.0", + "autocfg 1.5.1", ] [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "av-scenechange" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.21", + "v_frame", + "y4m", +] [[package]] name = "av1-grain" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" dependencies = [ "anyhow", "arrayvec", @@ -354,18 +375,18 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ea8ef51aced2b9191c08197f55450d830876d9933f8f48a429b354f1d496b42" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" dependencies = [ "arrayvec", ] [[package]] name = "axum" -version = "0.8.4" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core", "bytes", @@ -382,8 +403,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -397,9 +417,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", @@ -408,28 +428,12 @@ dependencies = [ "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper", "tower-layer", "tower-service", "tracing", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base64" version = "0.13.1" @@ -442,6 +446,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "bit-set" version = "0.10.0" @@ -459,9 +469,9 @@ checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" [[package]] name = "bit_field" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitflags" @@ -471,15 +481,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "bitstream-io" -version = "2.6.0" +version = "4.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] [[package]] name = "block" @@ -493,7 +506,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "objc2 0.5.2", + "objc2 0.5.3", ] [[package]] @@ -507,47 +520,47 @@ dependencies = [ [[package]] name = "blocking" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa" dependencies = [ "async-channel 2.5.0", "async-task", "futures-io", - "futures-lite 2.6.0", + "futures-lite 2.6.1", "piper", ] [[package]] name = "built" -version = "0.7.7" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.9.3" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1" +checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] @@ -564,9 +577,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "calloop" @@ -574,7 +587,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "log", "polling", "rustix 0.38.44", @@ -602,36 +615,21 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.29" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "877bf67ac8e52449eb2f9e98a344ea163beb70dd1f9eebe3cc5357dcfeaee4df" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "cfg_aliases" @@ -651,18 +649,28 @@ dependencies = [ "serde", ] +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.1", +] + [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -676,15 +684,15 @@ dependencies = [ "bitflags 1.3.2", "strsim 0.8.0", "textwrap", - "unicode-width", + "unicode-width 0.1.14", "vec_map", ] [[package]] name = "clap" -version = "4.5.40" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", "clap_derive", @@ -692,9 +700,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.40" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", @@ -704,21 +712,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.40" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" [[package]] name = "cloudabi" @@ -737,7 +745,7 @@ checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", - "unicode-width", + "unicode-width 0.2.2", ] [[package]] @@ -748,15 +756,15 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" -version = "4.6.7" +version = "4.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "4356eba6976435498d05a311ee9fc486da3bc81c200d3f0d7dd9703b41913f92" dependencies = [ "bytes", "memchr", @@ -773,9 +781,9 @@ dependencies = [ [[package]] name = "console_log" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" +checksum = "86919cef3e37b9356ccf54d4421208c17ecfda01beae61393e7ffd72916c0ef1" dependencies = [ "log", "web-sys", @@ -837,7 +845,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "core-foundation 0.10.1", "libc", ] @@ -854,6 +862,21 @@ dependencies = [ "libc", ] +[[package]] +name = "core_detect" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" + +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "craballoc" version = "0.3.3" @@ -862,8 +885,23 @@ checksum = "defed8174e995d5ecb5556d71bfe4d709dd4ce0b6a69f8ee2f6ab9797a22284e" dependencies = [ "async-channel 1.9.0", "bytemuck", - "crabslab", - "crabslab-derive", + "crabslab 0.6.6", + "crabslab-derive 0.4.6", + "log", + "rustc-hash 1.1.0", + "snafu 0.8.9", + "tracing", + "wgpu", +] + +[[package]] +name = "craballoc" +version = "0.5.0" +source = "git+https://github.com/schell/crabslab?branch=feat-wgsl-rs-std-slabitem#a2e2a2ea66fdf5a9f78a456c066d07eac2b5d813" +dependencies = [ + "async-channel 1.9.0", + "bytemuck", + "crabslab 0.7.1", "log", "rustc-hash 1.1.0", "snafu 0.8.9", @@ -877,12 +915,22 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c9866f967260166a968eb2c7382c62f97bbf0a9896fa5c444730e49b3ca3f08" dependencies = [ - "crabslab-derive", + "crabslab-derive 0.4.6", "futures-lite 1.13.0", "glam", "spirv-std", ] +[[package]] +name = "crabslab" +version = "0.7.1" +source = "git+https://github.com/schell/crabslab?branch=feat-wgsl-rs-std-slabitem#a2e2a2ea66fdf5a9f78a456c066d07eac2b5d813" +dependencies = [ + "crabslab-derive 0.7.0", + "futures-lite 1.13.0", + "wgsl-rs", +] + [[package]] name = "crabslab-derive" version = "0.4.6" @@ -891,32 +939,43 @@ checksum = "cdc3fdfc4f885d410742aad05c6cc3d2867627be16f79f6f3859c2d0484ce778" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", +] + +[[package]] +name = "crabslab-derive" +version = "0.7.0" +source = "git+https://github.com/schell/crabslab?branch=feat-wgsl-rs-std-slabitem#a2e2a2ea66fdf5a9f78a456c066d07eac2b5d813" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "0ba106e844045ddc02c20768ac4b0b7cb45f2cc2ecbd833ac9f5dacb183c2055" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -924,18 +983,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] name = "crunch" @@ -956,7 +1015,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] @@ -967,14 +1026,15 @@ checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" [[package]] name = "dagga" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cf0d7dcd307c9c5d81277737c35d1faf08af9e2cb262966a01c91021686b68" +checksum = "38ab704088f6d77cb65f8537838b1e8cc74178974b70cffc97cdd3a1086ad3b8" dependencies = [ "dot2", "log", "rustc-hash 1.1.0", - "snafu 0.7.5", + "serde", + "snafu 0.8.9", ] [[package]] @@ -1001,7 +1061,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1016,41 +1076,41 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "objc2 0.6.5", ] [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] name = "dlib" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" dependencies = [ "libloading", ] [[package]] name = "doc-comment" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -1075,9 +1135,9 @@ checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" [[package]] name = "dwrote" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe1f192fcce01590bd8d839aca53ce0d11d803bf291b2a6c4ad925a8f0024be" +checksum = "9e1b35532432acc8b19ceed096e35dfa088d3ea037fe4f3c085f1f97f33b4d02" dependencies = [ "lazy_static", "libc", @@ -1087,17 +1147,22 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" [[package]] name = "encoding_rs" -version = "0.8.35" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "8e985e0451871ad22fb8d2b6b076e2028a502a0d3950998c2c5c0a4f9b5d9679" dependencies = [ "cfg-if", + "core_detect", + "multiversion_no_op", + "rustversion", + "scopeguard", + "simdutf8", ] [[package]] @@ -1130,30 +1195,30 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "euclid" -version = "0.22.11" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" dependencies = [ "num-traits", ] @@ -1166,11 +1231,10 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" dependencies = [ - "concurrent-queue", "parking", "pin-project-lite", ] @@ -1181,7 +1245,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.2", "pin-project-lite", ] @@ -1189,13 +1253,13 @@ dependencies = [ name = "example" version = "0.1.0" dependencies = [ - "clap 4.5.40", - "craballoc", + "clap 4.6.7", + "craballoc 0.3.3", "env_logger", "futures-lite 1.13.0", "gltf", "icosahedron", - "image 0.25.6", + "image 0.25.10", "img-diff", "lazy_static", "loading-bytes", @@ -1215,7 +1279,7 @@ version = "0.1.0" dependencies = [ "env_logger", "example", - "fastrand 2.3.0", + "fastrand 2.5.0", "log", "renderling", "winit", @@ -1236,14 +1300,16 @@ dependencies = [ [[package]] name = "exr" -version = "1.73.0" +version = "1.74.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +checksum = "711fe42c9964295e01ee3fba3f9fe0e1d24b98886950d68efe81b1c76e21adf3" dependencies = [ "bit_field", "half", "lebe", - "miniz_oxide", + "miniz_oxide 0.8.9", + "num-complex", + "pulp", "rayon-core", "smallvec", "zune-inflate", @@ -1260,9 +1326,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" [[package]] name = "fdeflate" @@ -1273,6 +1345,12 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -1281,12 +1359,13 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.9.1", + "zlib-rs", ] [[package]] @@ -1325,7 +1404,7 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c7e611d49285d4c4b2e1727b72cf05353558885cc5252f93707b845dfcaf3d3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "byteorder", "core-foundation 0.9.4", "core-graphics", @@ -1365,13 +1444,13 @@ dependencies = [ [[package]] name = "foreign-types-macros" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] @@ -1414,24 +1493,24 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-lite" @@ -1450,9 +1529,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ "futures-core", "pin-project-lite", @@ -1460,32 +1539,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-core", "futures-io", @@ -1494,41 +1573,52 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] [[package]] name = "gethostname" -version = "0.4.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ + "rustix 1.1.5", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", "libc", - "windows-targets 0.48.5", + "wasi", ] [[package]] name = "getrandom" -version = "0.2.16" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "r-efi 5.3.0", + "wasip2", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "r-efi 6.0.0", + "rand_core 0.10.1", ] [[package]] @@ -1543,20 +1633,14 @@ dependencies = [ [[package]] name = "gif" -version = "0.13.3" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" dependencies = [ "color_quant", "weezl", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "gl_generator" version = "0.14.0" @@ -1598,7 +1682,7 @@ dependencies = [ "base64 0.13.1", "byteorder", "gltf-json", - "image 0.25.6", + "image 0.25.10", "lazy_static", "serde_json", "urlencoding", @@ -1613,7 +1697,7 @@ dependencies = [ "inflections", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] @@ -1646,7 +1730,7 @@ dependencies = [ "glyph_brush_draw_cache", "glyph_brush_layout", "ordered-float", - "rustc-hash 2.1.1", + "rustc-hash 2.1.3", "twox-hash", ] @@ -1661,7 +1745,7 @@ dependencies = [ "crossbeam-deque", "linked-hash-map", "rayon", - "rustc-hash 2.1.1", + "rustc-hash 2.1.3", ] [[package]] @@ -1685,15 +1769,15 @@ dependencies = [ "hashbrown 0.16.1", "log", "presser", - "thiserror 2.0.12", + "thiserror 2.0.21", "windows", ] [[package]] name = "h2" -version = "0.4.12" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "7d29020232d6aa3fb1daca64c1127cf662cf97f254ae16c18c05b8ab635fc118" dependencies = [ "atomic-waker", "bytes", @@ -1710,23 +1794,22 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", "num-traits", + "zerocopy", ] [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", "foldhash 0.1.5", ] @@ -1773,26 +1856,25 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" [[package]] name = "http" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", - "fnv", "itoa", ] [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", "http", @@ -1800,9 +1882,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ "bytes", "futures-core", @@ -1831,15 +1913,15 @@ checksum = "f58b778a5761513caf593693f8951c97a5b610841e754788400f32102eefdff1" [[package]] name = "humantime" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" [[package]] name = "hyper" -version = "1.7.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "2c3e324da4c95177d6291d4c8730197c0d1822f8a9766814a4a44fa5ab797c9c" dependencies = [ "atomic-waker", "bytes", @@ -1852,7 +1934,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -1860,15 +1941,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53" dependencies = [ "http", "hyper", "hyper-util", "rustls", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", @@ -1892,17 +1972,17 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", + "httparse", "hyper", "ipnet", "libc", @@ -1918,9 +1998,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1928,7 +2008,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core", ] [[package]] @@ -1956,12 +2036,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "fe090a42a0d3140fed8c63263ed1fecc02422cb2f4bfe55cd8de2de1b8e105dd" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -1969,9 +2050,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "25d29b57c17c6528d0dc4c2141cfa2d08200465acb537a3909c8b9b8a4a984c0" dependencies = [ "displaydoc", "litemap", @@ -1982,11 +2063,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "404a3b8c486f205c87fe7f23ab6894d84a4ad76d6e4671ae1981ba7def87c599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1997,42 +2077,39 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "20f0088bfb7441f7a37fa0c9e20cb1e9cba1cac6b9ce8cd2a6dc44294f8e8cbc" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "2ea83d991c56158f7cf898bf86436c1dfe7c07ee82fe88951f2695c9f37a379f" dependencies = [ "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "b98f29af82d02b163fe50161388350e743bb3107cc8e8c2f7314cb505faddfcf" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "413099315636c588ee8f011190b329b971a09a8fae9d157e01dcae8379468514" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -2053,9 +2130,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -2072,23 +2149,24 @@ dependencies = [ "color_quant", "jpeg-decoder", "num-traits", - "png", + "png 0.17.16", ] [[package]] name = "image" -version = "0.25.6" +version = "0.25.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", "color_quant", "exr", - "gif 0.13.3", + "gif 0.14.2", "image-webp", + "moxcms", "num-traits", - "png", + "png 0.18.1", "qoi", "ravif", "rayon", @@ -2100,9 +2178,9 @@ dependencies = [ [[package]] name = "image-webp" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" dependencies = [ "byteorder-lite", "quick-error", @@ -2113,7 +2191,7 @@ name = "img-diff" version = "0.1.0" dependencies = [ "glam", - "image 0.25.6", + "image 0.25.10", "log", "renderling_build", "snafu 0.7.5", @@ -2121,9 +2199,9 @@ dependencies = [ [[package]] name = "imgref" -version = "1.11.0" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" +checksum = "6e44b0a4eaa4c82f441d50a963f2d5f05a787240aeee097597033e72accfd22f" [[package]] name = "indexmap" @@ -2158,97 +2236,112 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", -] - -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "libc", + "syn 2.0.119", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] +checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0" [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ - "hermit-abi 0.5.2", + "hermit-abi 0.5.3", "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-macros", + "jni-sys 0.4.1", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.21", "walkdir", - "windows-sys 0.45.0", + "windows-link", ] [[package]] -name = "jni-sys" -version = "0.3.0" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.4.3", "libc", ] @@ -2288,15 +2381,15 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" [[package]] name = "lebe" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" @@ -2306,9 +2399,9 @@ checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" [[package]] name = "libfuzzer-sys" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" dependencies = [ "arbitrary", "cc", @@ -2316,12 +2409,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-link", ] [[package]] @@ -2332,13 +2425,14 @@ checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" -version = "0.1.4" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "libc", - "redox_syscall 0.5.13", + "plain", + "redox_syscall 0.9.5", ] [[package]] @@ -2355,21 +2449,21 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" [[package]] name = "litrs" -version = "0.4.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" +checksum = "4744e383959f0db86ede514b809b1c53251889093803c05267acc7d4e7030d70" [[package]] name = "loading-bytes" @@ -2388,11 +2482,10 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg 1.5.0", "scopeguard", ] @@ -2413,9 +2506,9 @@ dependencies = [ [[package]] name = "lyon" -version = "1.0.1" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7f9cda98b5430809e63ca5197b06c7d191bf7e26dfc467d5a3f0290e2a74f" +checksum = "bd0578bdecb7d6d88987b8b2b1e3a4e2f81df9d0ece1078623324a567904e7b7" dependencies = [ "lyon_algorithms", "lyon_tessellation", @@ -2423,9 +2516,9 @@ dependencies = [ [[package]] name = "lyon_algorithms" -version = "1.0.5" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f13c9be19d257c7d37e70608ed858e8eab4b2afcea2e3c9a622e892acbf43c08" +checksum = "f3a6b9d4e8b48acd531fbf1241ad9b270df6e60b6b92bdea1469f4f40899d805" dependencies = [ "lyon_path", "num-traits", @@ -2433,9 +2526,9 @@ dependencies = [ [[package]] name = "lyon_geom" -version = "1.0.6" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af69edc087272df438b3ee436c4bb6d7c04aa8af665cfd398feae627dbd8570" +checksum = "d82dd26aa4dc0b5b70b9115de59824842bcb43cf4a28e1b1e6d0ad148c93f93e" dependencies = [ "arrayvec", "euclid", @@ -2444,9 +2537,9 @@ dependencies = [ [[package]] name = "lyon_path" -version = "1.0.7" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0047f508cd7a85ad6bad9518f68cce7b1bf6b943fb71f6da0ee3bc1e8cb75f25" +checksum = "5c463f9c428b7fc5ec885dcd39ce4aa61e29111d0e33483f6f98c74e89d8621e" dependencies = [ "lyon_geom", "num-traits", @@ -2454,9 +2547,9 @@ dependencies = [ [[package]] name = "lyon_tessellation" -version = "1.0.15" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579d42360a4b09846eff2feef28f538696c7d6c7439bfa65874ff3cbe0951b2c" +checksum = "fd4872650e70dc907dd4f7ebc449d7d657a0d2658e423b2e724970870bbbf75b" dependencies = [ "float_next_after", "lyon_path", @@ -2490,15 +2583,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memmap2" -version = "0.9.5" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "6b0ca1155a9ecc25aa12e8313a119f32edf0255fea2f44839c4ac0a12b2ac157" dependencies = [ "libc", ] @@ -2509,7 +2602,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block", "core-graphics-types 0.2.0", "foreign-types 0.5.0", @@ -2535,16 +2628,20 @@ dependencies = [ ] [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] [[package]] name = "miniz_oxide" -version = "0.8.9" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" dependencies = [ "adler2", "simd-adler32", @@ -2552,15 +2649,31 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", ] +[[package]] +name = "multiversion_no_op" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d" + [[package]] name = "naga" version = "30.0.1" @@ -2569,7 +2682,7 @@ checksum = "a616d2fb8c89516ac2723a581f69d6c18576046bed761bd6b305e5618e6ae130" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.9.1", + "bitflags 2.13.2", "cfg-if", "cfg_aliases", "codespan-reporting", @@ -2584,7 +2697,7 @@ dependencies = [ "petgraph", "rustc-hash 1.1.0", "spirv", - "thiserror 2.0.12", + "thiserror 2.0.21", "unicode-ident", ] @@ -2597,14 +2710,14 @@ dependencies = [ "hashbrown 0.17.1", "indexmap", "rustc-hash 1.1.0", - "thiserror 2.0.12", + "thiserror 2.0.21", ] [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", @@ -2623,8 +2736,8 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.9.1", - "jni-sys", + "bitflags 2.13.2", + "jni-sys 0.3.1", "log", "ndk-sys", "num_enum", @@ -2644,7 +2757,7 @@ version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "jni-sys", + "jni-sys 0.3.1", ] [[package]] @@ -2663,14 +2776,22 @@ dependencies = [ "unicase", ] +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + [[package]] name = "nom" -version = "7.1.3" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" dependencies = [ "memchr", - "minimal-lexical", ] [[package]] @@ -2685,14 +2806,14 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" dependencies = [ "num-integer", "num-traits", @@ -2704,6 +2825,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ + "bytemuck", "num-traits", ] @@ -2715,14 +2837,14 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" dependencies = [ "num-traits", ] @@ -2744,15 +2866,15 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.5.0", + "autocfg 1.5.1", "libm", ] [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -2760,14 +2882,14 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] @@ -2787,9 +2909,9 @@ checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" [[package]] name = "objc2" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +checksum = "19d5490aaf8f1d7cf7688dfa9b0ce07900e168852c45cd2c03f534dfd27cfd0b" dependencies = [ "objc-sys", "objc2-encode", @@ -2810,10 +2932,10 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", "libc", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-core-data", "objc2-core-image", "objc2-foundation 0.2.2", @@ -2826,9 +2948,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-core-location", "objc2-foundation 0.2.2", ] @@ -2840,7 +2962,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" dependencies = [ "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-foundation 0.2.2", ] @@ -2850,9 +2972,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-foundation 0.2.2", ] @@ -2862,7 +2984,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "dispatch2", "objc2 0.6.5", ] @@ -2886,7 +3008,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-foundation 0.2.2", "objc2-metal 0.2.2", ] @@ -2898,7 +3020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" dependencies = [ "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-contacts", "objc2-foundation 0.2.2", ] @@ -2915,11 +3037,11 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", "dispatch", "libc", - "objc2 0.5.2", + "objc2 0.5.3", ] [[package]] @@ -2928,7 +3050,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "objc2 0.6.5", "objc2-core-foundation", ] @@ -2939,7 +3061,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "objc2 0.6.5", "objc2-core-foundation", ] @@ -2951,7 +3073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" dependencies = [ "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-app-kit", "objc2-foundation 0.2.2", ] @@ -2962,9 +3084,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-foundation 0.2.2", ] @@ -2974,7 +3096,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.6.2", "objc2 0.6.5", "objc2-foundation 0.3.2", @@ -2986,9 +3108,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-foundation 0.2.2", "objc2-metal 0.2.2", ] @@ -2999,7 +3121,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "objc2 0.6.5", "objc2-core-foundation", "objc2-core-graphics", @@ -3013,7 +3135,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "objc2 0.5.2", + "objc2 0.5.3", "objc2-foundation 0.2.2", ] @@ -3023,9 +3145,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-cloud-kit", "objc2-core-data", "objc2-core-image", @@ -3045,7 +3167,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" dependencies = [ "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-foundation 0.2.2", ] @@ -3055,33 +3177,24 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-core-location", "objc2-foundation 0.2.2", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oorandom" @@ -3091,15 +3204,14 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "cfg-if", "foreign-types 0.3.2", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -3112,20 +3224,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "cc", "libc", @@ -3141,27 +3253,28 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orbclient" -version = "0.3.48" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" dependencies = [ + "libc", "libredox", ] [[package]] name = "ordered-float" -version = "5.0.0" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" +checksum = "8c7c9e0d9b23589f26070720bac724174bfec1083e82f7854cdd0267518343c0" dependencies = [ "num-traits", ] [[package]] name = "owned_ttf_parser" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" dependencies = [ "ttf-parser 0.25.1", ] @@ -3174,9 +3287,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -3184,15 +3297,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.13", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -3201,6 +3314,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + [[package]] name = "pathdiff" version = "0.2.3" @@ -3219,78 +3338,78 @@ dependencies = [ [[package]] name = "pathfinder_simd" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf9027960355bf3afff9841918474a81a5f972ac6d226d518060bba758b5ad57" +checksum = "4500030c302e4af1d423f36f3b958d1aecb6c04184356ed5a833bf6b60435777" dependencies = [ "rustc_version", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", - "hashbrown 0.15.4", + "hashbrown 0.15.5", "indexmap", ] [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", - "fastrand 2.3.0", + "fastrand 2.5.0", "futures-io", ] [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "plotters" @@ -3348,44 +3467,56 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", ] [[package]] name = "polling" -version = "3.8.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.5.2", + "hermit-abi 0.5.3", "pin-project-lite", - "rustix 1.0.7", - "tracing", - "windows-sys 0.59.0", + "rustix 1.1.5", + "windows-sys 0.61.2", ] [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" dependencies = [ "zerovec", ] @@ -3426,41 +3557,70 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" dependencies = [ "profiling-procmacros", ] [[package]] name = "profiling-procmacros" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" dependencies = [ "quote", - "syn 2.0.104", + "syn 2.0.119", +] + +[[package]] +name = "pulp" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a" +dependencies = [ + "bytemuck", + "cfg-if", + "libm", + "num-complex", + "paste", + "pulp-wasm-simd-flag", + "raw-cpuid", + "reborrow", + "version_check", ] +[[package]] +name = "pulp-wasm-simd-flag" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740" + +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + [[package]] name = "qoi" version = "0.4.1" @@ -3478,18 +3638,18 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.37.5" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -3500,6 +3660,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.6.5" @@ -3509,7 +3675,7 @@ dependencies = [ "autocfg 0.1.8", "libc", "rand_chacha 0.1.1", - "rand_core 0.4.2", + "rand_core 0.4.3", "rand_hc", "rand_isaac", "rand_jitter", @@ -3521,23 +3687,23 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] name = "rand" -version = "0.9.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -3547,17 +3713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ "autocfg 0.1.8", - "rand_core 0.3.1", -] - -[[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", + "rand_core 0.3.2", ] [[package]] @@ -3567,41 +3723,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] name = "rand_core" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "96f815e01bbd9678b50d927f79aa1cf3ffdfdb1b9787317c1284dadb894ad0e8" dependencies = [ - "rand_core 0.4.2", + "rand_core 0.4.3", ] [[package]] name = "rand_core" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +checksum = "0e5937858e6fd18cd595d558f90bb5de3b72ae23f9e3763af0e805949b04ef60" [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.3.4", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", -] +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rand_hc" @@ -3609,7 +3762,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" dependencies = [ - "rand_core 0.3.1", + "rand_core 0.3.2", ] [[package]] @@ -3618,7 +3771,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" dependencies = [ - "rand_core 0.3.1", + "rand_core 0.3.2", ] [[package]] @@ -3628,7 +3781,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ "libc", - "rand_core 0.4.2", + "rand_core 0.4.3", "winapi", ] @@ -3641,7 +3794,7 @@ dependencies = [ "cloudabi", "fuchsia-cprng", "libc", - "rand_core 0.4.2", + "rand_core 0.4.3", "rdrand", "winapi", ] @@ -3653,7 +3806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" dependencies = [ "autocfg 0.1.8", - "rand_core 0.4.2", + "rand_core 0.4.3", ] [[package]] @@ -3662,24 +3815,26 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" dependencies = [ - "rand_core 0.3.1", + "rand_core 0.3.2", ] [[package]] name = "range-alloc" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" [[package]] name = "rav1e" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" dependencies = [ + "aligned-vec", "arbitrary", "arg_enum_proc_macro", "arrayvec", + "av-scenechange", "av1-grain", "bitstream-io", "built", @@ -3694,23 +3849,21 @@ dependencies = [ "noop_proc_macro", "num-derive", "num-traits", - "once_cell", "paste", "profiling", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand 0.9.5", + "rand_chacha 0.9.0", "simd_helpers", - "system-deps", - "thiserror 1.0.69", + "thiserror 2.0.21", "v_frame", "wasm-bindgen", ] [[package]] name = "ravif" -version = "0.11.20" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" dependencies = [ "avif-serialize", "imgref", @@ -3721,6 +3874,15 @@ dependencies = [ "rgb", ] +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.13.2", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -3741,9 +3903,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -3751,9 +3913,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -3765,9 +3927,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.1", + "rand_core 0.3.2", ] +[[package]] +name = "reborrow" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" + [[package]] name = "redox_syscall" version = "0.4.1" @@ -3779,29 +3947,37 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.2", +] + +[[package]] +name = "redox_syscall" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "580c875845b41ecb1564ad1ae4703044cef774145e3d7a94dc2b3fa7c97868fd" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" dependencies = [ - "getrandom 0.2.16", "libredox", - "thiserror 2.0.12", + "thiserror 2.0.21", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -3811,9 +3987,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -3822,9 +3998,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "renderdoc-sys" @@ -3841,21 +4017,24 @@ dependencies = [ "bytemuck", "cfg_aliases", "console_log", - "craballoc", - "crabslab", + "craballoc 0.3.3", + "craballoc 0.5.0", + "crabslab 0.6.6", + "crabslab 0.7.1", + "crabslab-derive 0.4.6", "crunch", "ctor", "dagga", "env_logger", "example", - "fastrand 2.3.0", + "fastrand 2.5.0", "futures-lite 1.13.0", "glam", "gltf", "half", "human-repr", "icosahedron", - "image 0.25.6", + "image 0.25.10", "img-diff", "loading-bytes", "log", @@ -3878,6 +4057,8 @@ dependencies = [ "web-sys", "wgpu", "wgpu-core", + "wgsl-rs", + "wgsl-rs-linkage-wgpu", "winit", "wire-types", ] @@ -3887,13 +4068,13 @@ name = "renderling-ui" version = "0.1.0" dependencies = [ "bytemuck", - "craballoc", - "crabslab", + "craballoc 0.3.3", + "crabslab 0.6.6", "env_logger", "futures-lite 1.13.0", "glam", "glyph_brush", - "image 0.25.6", + "image 0.25.10", "img-diff", "loading-bytes", "log", @@ -3918,9 +4099,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", @@ -3961,9 +4142,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.51" +version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a457e416a0f90d246a4c3288bd7a25b2304ca727f253f95be383dd17af56be8f" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" [[package]] name = "ring" @@ -3973,18 +4154,12 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -3993,9 +4168,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -4008,9 +4183,9 @@ dependencies = [ [[package]] name = "rustfft" -version = "6.4.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f140db74548f7c9d7cce60912c9ac414e74df5e718dc947d514b051b42f3f4" +checksum = "21db5f9893e91f41798c88680037dba611ca6674703c1a18601b01a72c8adb89" dependencies = [ "num-complex", "num-integer", @@ -4026,31 +4201,31 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.52.0", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "once_cell", "rustls-pki-types", @@ -4061,18 +4236,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ "ring", "rustls-pki-types", @@ -4081,15 +4256,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -4102,11 +4277,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "9cb23c424d8ee841bb4d813677ca237e2a610067d594fec130f87d6093495ab5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4136,12 +4311,12 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.9.1", - "core-foundation 0.9.4", + "bitflags 2.13.2", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -4149,9 +4324,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -4159,9 +4334,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "send_wrapper" @@ -4171,53 +4346,56 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] name = "serde_path_to_error" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -4234,24 +4412,35 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] [[package]] name = "simd_helpers" @@ -4262,6 +4451,12 @@ dependencies = [ "quote", ] +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "similarity" version = "0.2.0" @@ -4269,31 +4464,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccc60ff94fb3aba15a5a89bcab3ed826bf8f25b15c531aab64671ea1b237fa10" dependencies = [ "num-traits", - "rand 0.9.1", + "rand 0.9.5", "rayon", "rustfft", ] [[package]] name = "slab" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "version_check", ] [[package]] name = "smallvec" -version = "1.15.1" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" [[package]] name = "smithay-client-toolkit" @@ -4301,7 +4496,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "calloop", "calloop-wayland-source", "cursor-icon", @@ -4366,20 +4561,20 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4388,7 +4583,7 @@ version = "0.4.0+sdk-1.4.341.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", ] [[package]] @@ -4412,7 +4607,7 @@ dependencies = [ "proc-macro2", "quote", "spirv-std-types", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] @@ -4422,9 +4617,9 @@ source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=05b34493ce661dccd6694 [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -4475,9 +4670,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.104" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -4506,22 +4701,22 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -4536,36 +4731,17 @@ dependencies = [ "libc", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck 0.5.0", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - [[package]] name = "tempfile" -version = "3.21.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "fastrand 2.3.0", - "getrandom 0.3.3", + "fastrand 2.5.0", + "getrandom 0.4.3", "once_cell", - "rustix 1.0.7", - "windows-sys 0.60.2", + "rustix 1.1.5", + "windows-sys 0.61.2", ] [[package]] @@ -4583,7 +4759,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -4597,11 +4773,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.21", ] [[package]] @@ -4612,29 +4788,32 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] name = "tiff" -version = "0.9.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" dependencies = [ + "fax", "flate2", - "jpeg-decoder", + "half", + "quick-error", "weezl", + "zune-jpeg", ] [[package]] @@ -4664,9 +4843,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "abc840c238154d58f9e86b2792261edfde565a17696e1cda1a449de27979801a" dependencies = [ "displaydoc", "zerovec", @@ -4674,33 +4853,30 @@ dependencies = [ [[package]] name = "tokio" -version = "1.47.1" +version = "1.54.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "b52fd3255258d26fac7264ab5a76b53c13367136dc011d3d6ad4f8ed070396a3" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] [[package]] @@ -4715,9 +4891,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" dependencies = [ "rustls", "tokio", @@ -4725,56 +4901,53 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b" dependencies = [ "bytes", "futures-core", "futures-sink", + "libc", "pin-project-lite", "tokio", ] [[package]] -name = "toml" -version = "0.8.23" +name = "toml_datetime" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", + "serde_core", ] [[package]] -name = "toml_datetime" -version = "0.6.11" +name = "toml_edit" +version = "0.25.17+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "e3641d5bbb5349a79e1020a242d251efbc546ad8048d133958323ce9c40a9c9c" dependencies = [ - "serde", + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", ] [[package]] -name = "toml_edit" -version = "0.22.27" +name = "toml_parser" +version = "1.1.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", "winnow", ] [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -4788,20 +4961,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "bytes", "futures-util", "http", "http-body", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -4818,9 +4991,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -4830,20 +5003,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] @@ -4878,30 +5051,30 @@ checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" [[package]] name = "twox-hash" -version = "2.1.1" +version = "2.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56" +checksum = "86a801b3cea342a06d468c8710662aa29e5e05e4f5c0d62f00bbb7f2ad7941c2" dependencies = [ - "rand 0.9.1", + "rand 0.10.3", ] [[package]] name = "unicase" -version = "2.8.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "357cc3acc6a036009fd6c973ed009037c732d60d0b4f6c673e9041497482a28f" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" @@ -4909,6 +5082,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "untrusted" version = "0.9.0" @@ -4917,13 +5096,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -4967,12 +5147,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" - [[package]] name = "version_check" version = "0.9.5" @@ -4997,9 +5171,9 @@ dependencies = [ [[package]] name = "want" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "ec4cdd0dd910afe868b7ef477227d8d538b46b3075031afee8a9f2acb0a2ed0b" dependencies = [ "try-lock", ] @@ -5011,12 +5185,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] @@ -5129,13 +5303,13 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.10" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121" +checksum = "38a91b4eaddff87b1cd1074985e3713da4af2c49742d1b356b2c01670a67a078" dependencies = [ "cc", "downcast-rs", - "rustix 0.38.44", + "rustix 1.1.5", "scoped-tls", "smallvec", "wayland-sys", @@ -5143,12 +5317,12 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.10" +version = "0.31.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61" +checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073" dependencies = [ - "bitflags 2.9.1", - "rustix 0.38.44", + "bitflags 2.13.2", + "rustix 1.1.5", "wayland-backend", "wayland-scanner", ] @@ -5159,29 +5333,29 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.10" +version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" dependencies = [ - "rustix 0.38.44", + "rustix 1.1.5", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.32.8" +version = "0.32.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a" +checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "wayland-backend", "wayland-client", "wayland-scanner", @@ -5189,11 +5363,11 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "wayland-backend", "wayland-client", "wayland-protocols", @@ -5202,11 +5376,11 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "wayland-backend", "wayland-client", "wayland-protocols", @@ -5215,9 +5389,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.6" +version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484" +checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0" dependencies = [ "proc-macro2", "quick-xml", @@ -5226,9 +5400,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.6" +version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" dependencies = [ "dlib", "log", @@ -5258,9 +5432,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "wgpu" @@ -5269,7 +5443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527ccdf43dd5b2e8676eed9984ce00e2bbb0a1b85b70c1969dcb6cd2eb55ab9e" dependencies = [ "arrayvec", - "bitflags 2.9.1", + "bitflags 2.13.2", "bytemuck", "cfg-if", "cfg_aliases", @@ -5301,7 +5475,7 @@ dependencies = [ "arrayvec", "bit-set", "bit-vec", - "bitflags 2.9.1", + "bitflags 2.13.2", "bytemuck", "cfg_aliases", "document-features", @@ -5317,7 +5491,7 @@ dependencies = [ "raw-window-handle", "rustc-hash 1.1.0", "smallvec", - "thiserror 2.0.12", + "thiserror 2.0.21", "wgpu-core-deps-apple", "wgpu-core-deps-emscripten", "wgpu-core-deps-windows-linux-android", @@ -5363,7 +5537,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.6.2", "bytemuck", "cfg-if", @@ -5398,15 +5572,15 @@ dependencies = [ "renderdoc-sys", "smallvec", "static_assertions", - "thiserror 2.0.12", + "thiserror 2.0.21", "wasm-bindgen", "wayland-sys", "web-sys", "wgpu-naga-bridge", "wgpu-types", "windows", - "windows-core 0.62.2", - "windows-result 0.4.1", + "windows-core", + "windows-result", ] [[package]] @@ -5425,7 +5599,7 @@ version = "30.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99dad6f1fbdbbdb4c278a6508b059d44688f5cebddf78d005a46a31340269286" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "bytemuck", "js-sys", "log", @@ -5435,6 +5609,50 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wgsl-rs" +version = "0.1.0-beta.6" +source = "git+https://github.com/schell/wgsl-rs?branch=feat-std-display-impls#f4f699ad1a87a34ec5817851356c39c408f4b16b" +dependencies = [ + "glam", + "half", + "naga", + "paste", + "rayon", + "snafu 0.8.9", + "wgsl-rs-ir", + "wgsl-rs-macros", +] + +[[package]] +name = "wgsl-rs-ir" +version = "0.1.0-beta.6" +source = "git+https://github.com/schell/wgsl-rs?branch=feat-std-display-impls#f4f699ad1a87a34ec5817851356c39c408f4b16b" + +[[package]] +name = "wgsl-rs-linkage-wgpu" +version = "0.1.0-beta.6" +source = "git+https://github.com/schell/wgsl-rs?branch=feat-std-display-impls#f4f699ad1a87a34ec5817851356c39c408f4b16b" +dependencies = [ + "snafu 0.8.9", + "wgpu", + "wgsl-rs", + "wgsl-rs-ir", +] + +[[package]] +name = "wgsl-rs-macros" +version = "0.1.0-beta.6" +source = "git+https://github.com/schell/wgsl-rs?branch=feat-std-display-impls#f4f699ad1a87a34ec5817851356c39c408f4b16b" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "snafu 0.8.9", + "syn 2.0.119", + "wgsl-rs-ir", +] + [[package]] name = "winapi" version = "0.3.9" @@ -5453,11 +5671,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5473,7 +5691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ "windows-collections", - "windows-core 0.62.2", + "windows-core", "windows-future", "windows-numerics", ] @@ -5484,20 +5702,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-core 0.62.2", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-core", ] [[package]] @@ -5508,9 +5713,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -5519,8 +5724,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", + "windows-core", + "windows-link", "windows-threading", ] @@ -5532,7 +5737,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] @@ -5543,15 +5748,9 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" @@ -5564,28 +5763,19 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", + "windows-core", + "windows-link", ] [[package]] name = "windows-registry" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" -dependencies = [ - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-result" -version = "0.3.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.1.3", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -5594,16 +5784,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -5612,16 +5793,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", + "windows-link", ] [[package]] @@ -5630,7 +5802,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -5639,46 +5811,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.2", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "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 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-link", ] [[package]] @@ -5687,30 +5829,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -5719,199 +5845,67 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] -[[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_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[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_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[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_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[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_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winit" -version = "0.30.12" +version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.9.1", + "bitflags 2.13.2", "block2 0.5.1", "bytemuck", "calloop", @@ -5925,7 +5919,7 @@ dependencies = [ "libc", "memmap2", "ndk", - "objc2 0.5.2", + "objc2 0.5.3", "objc2-app-kit", "objc2-foundation 0.2.2", "objc2-ui-kit", @@ -5956,9 +5950,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.11" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" dependencies = [ "memchr", ] @@ -5980,19 +5974,16 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" [[package]] name = "x11-dl" @@ -6007,30 +5998,30 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", "libloading", "once_cell", - "rustix 0.38.44", + "rustix 1.1.5", "x11rb-protocol", ] [[package]] name = "x11rb-protocol" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" [[package]] name = "xcursor" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" +checksum = "163b33ed8786455e2fa5d72f554057ce3f3182425434f756cd39c99839d88e23" [[package]] name = "xi-unicode" @@ -6044,7 +6035,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.13.2", "dlib", "log", "once_cell", @@ -6059,19 +6050,19 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.26" +version = "0.8.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" +checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" [[package]] name = "xtask" version = "0.1.0" dependencies = [ "axum", - "clap 4.5.40", + "clap 4.6.7", "env_logger", "futures-util", - "image 0.25.6", + "image 0.25.10", "img-diff", "log", "new_mime_guess", @@ -6081,6 +6072,12 @@ dependencies = [ "wire-types", ] +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + [[package]] name = "yansi" version = "1.0.1" @@ -6089,9 +6086,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yeslogic-fontconfig-sys" -version = "6.0.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "503a066b4c037c440169d995b869046827dbc71263f6e8f3be6d77d4f3229dbd" +checksum = "1d8b8abf912b9a29ff112e1671c97c33636903d13a69712037190e6805af4f76" dependencies = [ "dlib", "once_cell", @@ -6100,11 +6097,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "417ef3fcf6c300b7dbd25c85531a746931c02ad536f3cf4786ed1e88223340b3" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -6112,68 +6108,68 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "e5fe1f8f1b06191a00962174c61aa5005e0bb391a6d80d07e24d115c01a92ed8" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "863ad3ac83293fb4d740aedbfdc9240dd8d1a50c1099acd76ce80ce7c7230c7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.119", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" dependencies = [ "displaydoc", "yoke", @@ -6182,9 +6178,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "f58a2799cfe9a1670c7ea8edbd52ef8edb93cb37a7f83bf31ba9e35d9dae6a40" dependencies = [ "yoke", "zerofrom", @@ -6193,20 +6189,32 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "c3743ddbf47738d929cd1ae2e199d40d0162979dfe31aef8ae646d2bf00bf97a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.9", ] +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + [[package]] name = "zune-core" -version = "0.4.12" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" [[package]] name = "zune-inflate" @@ -6219,9 +6227,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.19" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" dependencies = [ "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index 19a3e1b4..3f873d8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ futures-util = "0.3.31" glam = { version = "0.30", default-features = false } gltf = { version = "1.4,1", features = ["KHR_lights_punctual", "KHR_materials_unlit", "KHR_materials_emissive_strength", "extras", "extensions"] } glyph_brush = "0.7.8" -image = "0.25" +image = { version = "0.25", features = ["exr"] } log = "0.4" loading-bytes = { path = "crates/loading-bytes", version = "0.1.1" } lyon = "1.0.1" @@ -64,8 +64,13 @@ web-sys = "0.3" winit = { version = "0.30.12" } wgpu = { version = "30.0" } wgpu-core = { version = "30.0" } +wgsl-rs = { git = "https://github.com/schell/wgsl-rs", branch = "feat-std-display-impls" } +wgsl-rs-linkage-wgpu = { git = "https://github.com/schell/wgsl-rs", branch = "feat-std-display-impls" } metal = "0.32" +crabslab_wgsl = { package = "crabslab", git = "https://github.com/schell/crabslab", branch = "feat-wgsl-rs-std-slabitem" } +craballoc_wgsl = { package = "craballoc", git = "https://github.com/schell/crabslab", branch = "feat-wgsl-rs-std-slabitem" } + [profile.dev] opt-level = 1 diff --git a/crates/example-culling/src/main.rs b/crates/example-culling/src/main.rs index 3592e2ca..9f197414 100644 --- a/crates/example-culling/src/main.rs +++ b/crates/example-culling/src/main.rs @@ -14,7 +14,6 @@ use renderling::{ math::hex_to_vec4, primitive::Primitive, stage::Stage, - tonemapping::srgba_to_linear, }; use winit::{ application::ApplicationHandler, @@ -216,9 +215,12 @@ impl TestAppHandler for CullingExample { let frustum = frustum_camera.0.frustum(); log::info!("frustum.planes: {:#?}", frustum.planes); - let blue_color = srgba_to_linear(hex_to_vec4(0x7EACB5FF)); - let red_color = srgba_to_linear(hex_to_vec4(0xC96868FF)); - let yellow_color = srgba_to_linear(hex_to_vec4(0xFADFA1FF)); + // Convert sRGB hex colors to linear space for the material's + // albedo factor (same pow(2.2) approximation the shader uses). + let to_linear = |v: Vec4| v.truncate().powf(2.2).extend(v.w); + let blue_color = to_linear(hex_to_vec4(0x7EACB5FF)); + let red_color = to_linear(hex_to_vec4(0xC96868FF)); + let yellow_color = to_linear(hex_to_vec4(0xFADFA1FF)); let material_aabb_overlapping = stage.new_material().with_albedo_factor(blue_color); let material_aabb_outside = stage.new_material().with_albedo_factor(red_color); diff --git a/crates/examples/src/animation.rs b/crates/examples/src/animation.rs index 4048d7a6..bd2c2fe8 100644 --- a/crates/examples/src/animation.rs +++ b/crates/examples/src/animation.rs @@ -1,5 +1,4 @@ //! Animation examples: playback, skinning and morph targets. - use crate::{cwd_to_manual_assets_dir, workspace_dir}; #[tokio::test] @@ -80,8 +79,10 @@ async fn manual_animation() { // The animation should have moved the triangle. let pixel_diff = |a: &[u8], b: &[u8]| { - a.chunks_exact(4) - .zip(b.chunks_exact(4)) + a.as_chunks::<4>() + .0 + .iter() + .zip(b.as_chunks::<4>().0.iter()) .filter(|(a, b)| a != b) .count() }; @@ -182,8 +183,10 @@ async fn manual_morph_targets() { // ANCHOR_END: morph let pixel_diff = |a: &[u8], b: &[u8]| { - a.chunks_exact(4) - .zip(b.chunks_exact(4)) + a.as_chunks::<4>() + .0 + .iter() + .zip(b.as_chunks::<4>().0.iter()) .filter(|(a, b)| a != b) .count() }; diff --git a/crates/examples/src/debug.rs b/crates/examples/src/debug.rs index 7b432a3f..a044e738 100644 --- a/crates/examples/src/debug.rs +++ b/crates/examples/src/debug.rs @@ -136,8 +136,10 @@ async fn manual_debug() { // Each step should have changed the rendering. let pixel_diff = |a: &[u8], b: &[u8]| { - a.chunks_exact(4) - .zip(b.chunks_exact(4)) + a.as_chunks::<4>() + .0 + .iter() + .zip(b.as_chunks::<4>().0.iter()) .filter(|(a, b)| a != b) .count() }; diff --git a/crates/examples/src/material.rs b/crates/examples/src/material.rs index 6ae5dd04..753e873b 100644 --- a/crates/examples/src/material.rs +++ b/crates/examples/src/material.rs @@ -55,8 +55,10 @@ fn uv_unit_cube() -> Vec { /// Returns the number of pixels that differ between two raw RGBA images. fn pixel_diff(a: &[u8], b: &[u8]) -> usize { - a.chunks_exact(4) - .zip(b.chunks_exact(4)) + a.as_chunks::<4>() + .0 + .iter() + .zip(b.as_chunks::<4>().0.iter()) .filter(|(a, b)| a != b) .count() } @@ -257,7 +259,9 @@ async fn manual_materials() { // The textured render should contain far more distinct colors than a // flat, untextured render. let unique_colors = |raw: &[u8]| { - raw.chunks_exact(4) + raw.as_chunks::<4>() + .0 + .iter() .map(|p| [p[0], p[1], p[2], p[3]]) .collect::>() .len() diff --git a/crates/examples/src/performance.rs b/crates/examples/src/performance.rs index 89ff78bc..6dd5a857 100644 --- a/crates/examples/src/performance.rs +++ b/crates/examples/src/performance.rs @@ -107,8 +107,10 @@ async fn manual_culling() { // ANCHOR_END: culling let pixel_diff = |a: &[u8], b: &[u8]| { - a.chunks_exact(4) - .zip(b.chunks_exact(4)) + a.as_chunks::<4>() + .0 + .iter() + .zip(b.as_chunks::<4>().0.iter()) .filter(|(a, b)| a != b) .count() }; @@ -236,8 +238,10 @@ async fn manual_light_tiling() { // Tiling should produce nearly the same picture for much less work. let pixel_diff = |a: &[u8], b: &[u8]| { - a.chunks_exact(4) - .zip(b.chunks_exact(4)) + a.as_chunks::<4>() + .0 + .iter() + .zip(b.as_chunks::<4>().0.iter()) .filter(|(a, b)| a != b) .count() }; diff --git a/crates/examples/src/postprocessing.rs b/crates/examples/src/postprocessing.rs index 026b0380..0dd4ff08 100644 --- a/crates/examples/src/postprocessing.rs +++ b/crates/examples/src/postprocessing.rs @@ -85,12 +85,12 @@ async fn manual_postprocessing() { // ANCHOR_END: exposure // ANCHOR: tonemap - use renderling::tonemapping::Tonemap; + use renderling::tonemapping::shader::Tonemap; - // By default no tone mapping algorithm is used (`Tonemap::NONE`), and + // By default no tone mapping algorithm is used (`Tonemap::None`), and // HDR values outside the display range simply clip. A filmic operator // like ACES compresses the highlights instead. - config.tonemap = Tonemap::ACES_HILL_EXPOSURE_BOOST; + config.tonemap = Tonemap::AcesHillExposureBoost; config.exposure = 1.0; stage.tonemapping().set_tonemapping_config(config); @@ -103,7 +103,9 @@ async fn manual_postprocessing() { // Each step should have changed the rendering. let pixel_diff = |a: &[u8], b: &[u8]| { - a.chunks_exact(4) + a.as_chunks::<4>() + .0 + .iter() .zip(b.chunks_exact(4)) .filter(|(a, b)| a != b) .count() diff --git a/crates/examples/src/scene.rs b/crates/examples/src/scene.rs index 4c477f75..a9ec036c 100644 --- a/crates/examples/src/scene.rs +++ b/crates/examples/src/scene.rs @@ -108,7 +108,9 @@ async fn manual_scene() { // Each step should have changed the rendering. let pixel_diff = |a: &[u8], b: &[u8]| { - a.chunks_exact(4) + a.as_chunks::<4>() + .0 + .iter() .zip(b.chunks_exact(4)) .filter(|(a, b)| a != b) .count() diff --git a/crates/examples/src/shadow.rs b/crates/examples/src/shadow.rs index 3dc27031..5b06cd50 100644 --- a/crates/examples/src/shadow.rs +++ b/crates/examples/src/shadow.rs @@ -172,7 +172,9 @@ async fn manual_shadow_mapping() { let with = img_with_shadow.as_raw(); assert_eq!(without.len(), with.len()); let changed = without - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .zip(with.chunks_exact(4)) .filter(|(a, b)| a != b) .count(); diff --git a/crates/img-diff/src/lib.rs b/crates/img-diff/src/lib.rs index 4b28b3e7..7f4da9a6 100644 --- a/crates/img-diff/src/lib.rs +++ b/crates/img-diff/src/lib.rs @@ -33,6 +33,16 @@ pub struct DiffCfg { /// Difference is measured as the magnitude of vector subtraction /// between the two pixels. pub pixel_threshold: f32, + /// The relative pixel threshold. + /// + /// Useful when comparing HDR pixels, where legitimate floating-point + /// differences scale with magnitude. + /// + /// A pixel is considered different when + /// `delta.length() > pixel_threshold + pixel_relative_threshold * max(|l|, + /// |r|, 1)` (delta and lengths measured on the premultiplied rgb). The + /// default `0.0` preserves the previous absolute-only behavior. + pub pixel_relative_threshold: f32, /// The percentage of "different" pixels (as determined using /// `pixel_threshold`) to "correct" pixels that the image must contain /// before it is considered an error. @@ -47,6 +57,7 @@ impl Default for DiffCfg { fn default() -> Self { Self { pixel_threshold: PIXEL_MAGNITUDE_THRESHOLD, + pixel_relative_threshold: 0.0, image_threshold: IMAGE_DIFF_THRESHOLD, test_name: None, output_dir: test_output_dir(), @@ -66,6 +77,7 @@ fn get_results( left_image: &Rgba32FImage, right_image: &Rgba32FImage, threshold: f32, + relative_threshold: f32, ) -> Result, ImgDiffError> { let lid @ (width, height) = left_image.dimensions(); let rid = right_image.dimensions(); @@ -84,8 +96,9 @@ fn get_results( let right_pixel = Vec4::from(right_pixel.0); let right_pixel = (right_pixel * right_pixel.w).xyz(); let delta = (left_pixel - right_pixel).abs(); - if delta.length() > threshold { - Some((x, y, delta)) + let scale = left_pixel.length().max(right_pixel.length()).max(1.0); + if delta.length() > threshold + relative_threshold * scale { + Some((x, y, delta)) // counted as differing } else { None } @@ -133,8 +146,13 @@ pub fn save_to( let path = dir.as_ref().join(filename); std::fs::create_dir_all(path.parent().unwrap()).unwrap(); let img: DynamicImage = seen.into(); - let img_buffer = img.into_rgba8(); - let img = DynamicImage::from(img_buffer); + let img = if path.extension().and_then(|s| s.to_str()) == Some("exr") { + let img_buffer = img.into_rgba32f(); + DynamicImage::from(img_buffer) + } else { + let img_buffer = img.into_rgba8(); + DynamicImage::from(img_buffer) + }; img.save(path).map_err(|e| e.to_string()) } @@ -153,11 +171,12 @@ pub fn assert_eq_cfg( let rhs = rhs.into().into_rgba32f(); let DiffCfg { pixel_threshold, + pixel_relative_threshold, image_threshold, test_name, output_dir, } = cfg; - let results = match get_results(&lhs, &rhs, pixel_threshold) { + let results = match get_results(&lhs, &rhs, pixel_threshold, pixel_relative_threshold) { Ok(maybe_diff) => maybe_diff, Err(e) => return Err(format!("Asserting {filename} failed: {e}")), }; @@ -169,7 +188,10 @@ pub fn assert_eq_cfg( avg_delta_length, }) = results { - println!("{filename} has {diffs} pixel differences (threshold={pixel_threshold})"); + println!( + "{filename} has {diffs} pixel differences (threshold={pixel_threshold} \ + relative_threshold={pixel_relative_threshold})" + ); println!(" max_delta_length: {max_delta_length}"); println!( " avg_delta_length: {avg_delta_length} (average of deltas of pixels past the \ @@ -272,3 +294,78 @@ mod test { assert_img_eq("jolt.png", img); } } + + +#[cfg(test)] +mod relative_threshold_test { + use crate::{assert_eq_cfg, DiffCfg}; + + fn img_of(values: &[[f32; 4]]) -> image::Rgba32FImage { + let mut img = image::Rgba32FImage::new(1, values.len() as u32); + for (i, v) in values.iter().enumerate() { + img.put_pixel(0, i as u32, image::Rgba(*v)); + } + img + } + + fn cfg(pixel_threshold: f32, relative: f32, output_dir: &str) -> DiffCfg { + DiffCfg { + pixel_threshold, + pixel_relative_threshold: relative, + image_threshold: 0.0, + test_name: Some("relative_threshold_boundary"), + output_dir: std::path::PathBuf::from(output_dir), + } + } + + /// Deltas are allowed up to + /// `pixel_threshold + pixel_relative_threshold * pixel_magnitude`. + /// + /// Asserts the exact boundary in both directions for the absolute-only + /// default and the relative mode. + #[test] + fn relative_threshold_boundary() { + let base = [0.0, 0.0, 100.0, 1.0]; + let out = std::env::temp_dir() + .join("img-diff-relative-threshold-out") + .to_str() + .unwrap() + .to_string(); + + // Default (absolute-only): 0.05 within the threshold, no diffs. + let r = assert_eq_cfg( + "relative-threshold-t0", + img_of(&[base]), + img_of(&[[0.0, 0.0, 100.05, 1.0]]), + cfg(0.1, 0.0, &out), + ); + assert!(r.is_ok(), "t0 should pass: {r:?}"); + + // Default (absolute-only): 0.2 is past 0.1 -> one differing pixel. + let r = assert_eq_cfg( + "relative-threshold-t1", + img_of(&[base]), + img_of(&[[0.0, 0.0, 100.2, 1.0]]), + cfg(0.1, 0.0, &out), + ); + assert!(r.is_err(), "t1 should fail: {r:?}"); + + // Relative: 2.0 is within 0.1 + 0.05 * 100 = 5.1, no diffs. + let r = assert_eq_cfg( + "relative-threshold-t2", + img_of(&[base]), + img_of(&[[0.0, 0.0, 102.0, 1.0]]), + cfg(0.1, 0.05, &out), + ); + assert!(r.is_ok(), "t2 should pass: {r:?}"); + + // Relative: 10.0 is past 5.1 -> one differing pixel. + let r = assert_eq_cfg( + "relative-threshold-t3", + img_of(&[base]), + img_of(&[[0.0, 0.0, 110.0, 1.0]]), + cfg(0.1, 0.05, &out), + ); + assert!(r.is_err(), "t3 should fail: {r:?}"); + } +} diff --git a/crates/renderling/Cargo.toml b/crates/renderling/Cargo.toml index 50030b18..59a51959 100644 --- a/crates/renderling/Cargo.toml +++ b/crates/renderling/Cargo.toml @@ -55,7 +55,10 @@ glam = { workspace = true, default-features = false, features = ["libm"] } async-channel = {workspace = true} bytemuck = {workspace = true} craballoc.workspace = true +craballoc_wgsl.workspace = true crabslab = { workspace = true, features = ["default"] } +crabslab_wgsl.workspace = true +crabslab-derive = "=0.4.6" crunch = "0.5" dagga = {workspace=true} futures-lite = { workspace = true, optional = true } @@ -70,6 +73,8 @@ rustc-hash = {workspace = true} serde_json = {workspace = true, optional = true} snafu = {workspace = true} wgpu = { workspace = true, features = ["spirv"] } +wgsl-rs.workspace = true +wgsl-rs-linkage-wgpu.workspace = true winit = { workspace = true, optional = true } # dependencies for WASM CPU code diff --git a/crates/renderling/shaders/bloom-shader-bloom_downsample_fragment.spv b/crates/renderling/shaders/bloom-shader-bloom_downsample_fragment.spv deleted file mode 100644 index 9ffcf8d3..00000000 Binary files a/crates/renderling/shaders/bloom-shader-bloom_downsample_fragment.spv and /dev/null differ diff --git a/crates/renderling/shaders/bloom-shader-bloom_mix_fragment.spv b/crates/renderling/shaders/bloom-shader-bloom_mix_fragment.spv deleted file mode 100644 index 4601da7c..00000000 Binary files a/crates/renderling/shaders/bloom-shader-bloom_mix_fragment.spv and /dev/null differ diff --git a/crates/renderling/shaders/bloom-shader-bloom_upsample_fragment.spv b/crates/renderling/shaders/bloom-shader-bloom_upsample_fragment.spv deleted file mode 100644 index 3b19809c..00000000 Binary files a/crates/renderling/shaders/bloom-shader-bloom_upsample_fragment.spv and /dev/null differ diff --git a/crates/renderling/shaders/bloom-shader-bloom_vertex.spv b/crates/renderling/shaders/bloom-shader-bloom_vertex.spv deleted file mode 100644 index 647e86ff..00000000 Binary files a/crates/renderling/shaders/bloom-shader-bloom_vertex.spv and /dev/null differ diff --git a/crates/renderling/shaders/compositor-compositor_fragment.spv b/crates/renderling/shaders/compositor-compositor_fragment.spv deleted file mode 100644 index 24ff6b8e..00000000 Binary files a/crates/renderling/shaders/compositor-compositor_fragment.spv and /dev/null differ diff --git a/crates/renderling/shaders/compositor-compositor_vertex.spv b/crates/renderling/shaders/compositor-compositor_vertex.spv deleted file mode 100644 index 974db32e..00000000 Binary files a/crates/renderling/shaders/compositor-compositor_vertex.spv and /dev/null differ diff --git a/crates/renderling/shaders/manifest.json b/crates/renderling/shaders/manifest.json index e5ffbc09..9c302c6b 100644 --- a/crates/renderling/shaders/manifest.json +++ b/crates/renderling/shaders/manifest.json @@ -1,227 +1,187 @@ [ { - "source_path": "shaders/atlas-shader-atlas_blit_fragment.spv", "entry_point": "atlas::shader::atlas_blit_fragment", + "source_path": "shaders/atlas-shader-atlas_blit_fragment.spv", "wgsl_entry_point": "atlasshaderatlas_blit_fragment" }, { - "source_path": "shaders/atlas-shader-atlas_blit_vertex.spv", "entry_point": "atlas::shader::atlas_blit_vertex", + "source_path": "shaders/atlas-shader-atlas_blit_vertex.spv", "wgsl_entry_point": "atlasshaderatlas_blit_vertex" }, { - "source_path": "shaders/bloom-shader-bloom_downsample_fragment.spv", - "entry_point": "bloom::shader::bloom_downsample_fragment", - "wgsl_entry_point": "bloomshaderbloom_downsample_fragment" - }, - { - "source_path": "shaders/bloom-shader-bloom_mix_fragment.spv", - "entry_point": "bloom::shader::bloom_mix_fragment", - "wgsl_entry_point": "bloomshaderbloom_mix_fragment" - }, - { - "source_path": "shaders/bloom-shader-bloom_upsample_fragment.spv", - "entry_point": "bloom::shader::bloom_upsample_fragment", - "wgsl_entry_point": "bloomshaderbloom_upsample_fragment" - }, - { - "source_path": "shaders/bloom-shader-bloom_vertex.spv", - "entry_point": "bloom::shader::bloom_vertex", - "wgsl_entry_point": "bloomshaderbloom_vertex" - }, - { - "source_path": "shaders/compositor-compositor_fragment.spv", - "entry_point": "compositor::compositor_fragment", - "wgsl_entry_point": "compositorcompositor_fragment" - }, - { - "source_path": "shaders/compositor-compositor_vertex.spv", - "entry_point": "compositor::compositor_vertex", - "wgsl_entry_point": "compositorcompositor_vertex" - }, - { - "source_path": "shaders/convolution-shader-brdf_lut_convolution_fragment.spv", "entry_point": "convolution::shader::brdf_lut_convolution_fragment", + "source_path": "shaders/convolution-shader-brdf_lut_convolution_fragment.spv", "wgsl_entry_point": "convolutionshaderbrdf_lut_convolution_fragment" }, { - "source_path": "shaders/convolution-shader-brdf_lut_convolution_vertex.spv", "entry_point": "convolution::shader::brdf_lut_convolution_vertex", + "source_path": "shaders/convolution-shader-brdf_lut_convolution_vertex.spv", "wgsl_entry_point": "convolutionshaderbrdf_lut_convolution_vertex" }, { - "source_path": "shaders/convolution-shader-generate_mipmap_fragment.spv", "entry_point": "convolution::shader::generate_mipmap_fragment", + "source_path": "shaders/convolution-shader-generate_mipmap_fragment.spv", "wgsl_entry_point": "convolutionshadergenerate_mipmap_fragment" }, { - "source_path": "shaders/convolution-shader-generate_mipmap_vertex.spv", "entry_point": "convolution::shader::generate_mipmap_vertex", + "source_path": "shaders/convolution-shader-generate_mipmap_vertex.spv", "wgsl_entry_point": "convolutionshadergenerate_mipmap_vertex" }, { - "source_path": "shaders/convolution-shader-prefilter_environment_cubemap_fragment.spv", "entry_point": "convolution::shader::prefilter_environment_cubemap_fragment", + "source_path": "shaders/convolution-shader-prefilter_environment_cubemap_fragment.spv", "wgsl_entry_point": "convolutionshaderprefilter_environment_cubemap_fragment" }, { - "source_path": "shaders/convolution-shader-prefilter_environment_cubemap_vertex.spv", "entry_point": "convolution::shader::prefilter_environment_cubemap_vertex", + "source_path": "shaders/convolution-shader-prefilter_environment_cubemap_vertex.spv", "wgsl_entry_point": "convolutionshaderprefilter_environment_cubemap_vertex" }, { - "source_path": "shaders/cubemap-shader-cubemap_sampling_test_fragment.spv", "entry_point": "cubemap::shader::cubemap_sampling_test_fragment", + "source_path": "shaders/cubemap-shader-cubemap_sampling_test_fragment.spv", "wgsl_entry_point": "cubemapshadercubemap_sampling_test_fragment" }, { - "source_path": "shaders/cubemap-shader-cubemap_sampling_test_vertex.spv", "entry_point": "cubemap::shader::cubemap_sampling_test_vertex", + "source_path": "shaders/cubemap-shader-cubemap_sampling_test_vertex.spv", "wgsl_entry_point": "cubemapshadercubemap_sampling_test_vertex" }, { - "source_path": "shaders/cull-shader-compute_copy_depth_to_pyramid.spv", "entry_point": "cull::shader::compute_copy_depth_to_pyramid", + "source_path": "shaders/cull-shader-compute_copy_depth_to_pyramid.spv", "wgsl_entry_point": "cullshadercompute_copy_depth_to_pyramid" }, { - "source_path": "shaders/cull-shader-compute_copy_depth_to_pyramid_multisampled.spv", "entry_point": "cull::shader::compute_copy_depth_to_pyramid_multisampled", + "source_path": "shaders/cull-shader-compute_copy_depth_to_pyramid_multisampled.spv", "wgsl_entry_point": "cullshadercompute_copy_depth_to_pyramid_multisampled" }, { - "source_path": "shaders/cull-shader-compute_culling.spv", "entry_point": "cull::shader::compute_culling", + "source_path": "shaders/cull-shader-compute_culling.spv", "wgsl_entry_point": "cullshadercompute_culling" }, { - "source_path": "shaders/cull-shader-compute_downsample_depth_pyramid.spv", "entry_point": "cull::shader::compute_downsample_depth_pyramid", + "source_path": "shaders/cull-shader-compute_downsample_depth_pyramid.spv", "wgsl_entry_point": "cullshadercompute_downsample_depth_pyramid" }, { - "source_path": "shaders/debug-shader-debug_overlay_fragment.spv", "entry_point": "debug::shader::debug_overlay_fragment", + "source_path": "shaders/debug-shader-debug_overlay_fragment.spv", "wgsl_entry_point": "debugshaderdebug_overlay_fragment" }, { - "source_path": "shaders/debug-shader-debug_overlay_vertex.spv", "entry_point": "debug::shader::debug_overlay_vertex", + "source_path": "shaders/debug-shader-debug_overlay_vertex.spv", "wgsl_entry_point": "debugshaderdebug_overlay_vertex" }, { - "source_path": "shaders/light-shader-light_tiling_bin_lights.spv", "entry_point": "light::shader::light_tiling_bin_lights", + "source_path": "shaders/light-shader-light_tiling_bin_lights.spv", "wgsl_entry_point": "lightshaderlight_tiling_bin_lights" }, { - "source_path": "shaders/light-shader-light_tiling_clear_tiles.spv", "entry_point": "light::shader::light_tiling_clear_tiles", + "source_path": "shaders/light-shader-light_tiling_clear_tiles.spv", "wgsl_entry_point": "lightshaderlight_tiling_clear_tiles" }, { - "source_path": "shaders/light-shader-light_tiling_compute_tile_min_and_max_depth.spv", "entry_point": "light::shader::light_tiling_compute_tile_min_and_max_depth", + "source_path": "shaders/light-shader-light_tiling_compute_tile_min_and_max_depth.spv", "wgsl_entry_point": "lightshaderlight_tiling_compute_tile_min_and_max_depth" }, { - "source_path": "shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.spv", "entry_point": "light::shader::light_tiling_compute_tile_min_and_max_depth_multisampled", + "source_path": "shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.spv", "wgsl_entry_point": "lightshaderlight_tiling_compute_tile_min_and_max_depth_multisampled" }, { - "source_path": "shaders/light-shader-light_tiling_depth_pre_pass.spv", "entry_point": "light::shader::light_tiling_depth_pre_pass", + "source_path": "shaders/light-shader-light_tiling_depth_pre_pass.spv", "wgsl_entry_point": "lightshaderlight_tiling_depth_pre_pass" }, { - "source_path": "shaders/light-shader-shadow_mapping_fragment.spv", "entry_point": "light::shader::shadow_mapping_fragment", + "source_path": "shaders/light-shader-shadow_mapping_fragment.spv", "wgsl_entry_point": "lightshadershadow_mapping_fragment" }, { - "source_path": "shaders/light-shader-shadow_mapping_vertex.spv", "entry_point": "light::shader::shadow_mapping_vertex", + "source_path": "shaders/light-shader-shadow_mapping_vertex.spv", "wgsl_entry_point": "lightshadershadow_mapping_vertex" }, { - "source_path": "shaders/pbr-ibl-shader-di_convolution_fragment.spv", "entry_point": "pbr::ibl::shader::di_convolution_fragment", + "source_path": "shaders/pbr-ibl-shader-di_convolution_fragment.spv", "wgsl_entry_point": "pbriblshaderdi_convolution_fragment" }, { - "source_path": "shaders/primitive-shader-primitive_fragment.spv", "entry_point": "primitive::shader::primitive_fragment", + "source_path": "shaders/primitive-shader-primitive_fragment.spv", "wgsl_entry_point": "primitiveshaderprimitive_fragment" }, { - "source_path": "shaders/primitive-shader-primitive_vertex.spv", "entry_point": "primitive::shader::primitive_vertex", + "source_path": "shaders/primitive-shader-primitive_vertex.spv", "wgsl_entry_point": "primitiveshaderprimitive_vertex" }, { - "source_path": "shaders/skybox-shader-skybox_cubemap_fragment.spv", "entry_point": "skybox::shader::skybox_cubemap_fragment", + "source_path": "shaders/skybox-shader-skybox_cubemap_fragment.spv", "wgsl_entry_point": "skyboxshaderskybox_cubemap_fragment" }, { - "source_path": "shaders/skybox-shader-skybox_cubemap_vertex.spv", "entry_point": "skybox::shader::skybox_cubemap_vertex", + "source_path": "shaders/skybox-shader-skybox_cubemap_vertex.spv", "wgsl_entry_point": "skyboxshaderskybox_cubemap_vertex" }, { - "source_path": "shaders/skybox-shader-skybox_equirectangular_fragment.spv", "entry_point": "skybox::shader::skybox_equirectangular_fragment", + "source_path": "shaders/skybox-shader-skybox_equirectangular_fragment.spv", "wgsl_entry_point": "skyboxshaderskybox_equirectangular_fragment" }, { - "source_path": "shaders/skybox-shader-skybox_vertex.spv", "entry_point": "skybox::shader::skybox_vertex", + "source_path": "shaders/skybox-shader-skybox_vertex.spv", "wgsl_entry_point": "skyboxshaderskybox_vertex" }, { - "source_path": "shaders/tonemapping-tonemapping_fragment.spv", - "entry_point": "tonemapping::tonemapping_fragment", - "wgsl_entry_point": "tonemappingtonemapping_fragment" - }, - { - "source_path": "shaders/tonemapping-tonemapping_vertex.spv", - "entry_point": "tonemapping::tonemapping_vertex", - "wgsl_entry_point": "tonemappingtonemapping_vertex" - }, - { - "source_path": "shaders/tutorial-implicit_isosceles_vertex.spv", "entry_point": "tutorial::implicit_isosceles_vertex", + "source_path": "shaders/tutorial-implicit_isosceles_vertex.spv", "wgsl_entry_point": "tutorialimplicit_isosceles_vertex" }, { - "source_path": "shaders/tutorial-passthru_fragment.spv", "entry_point": "tutorial::passthru_fragment", + "source_path": "shaders/tutorial-passthru_fragment.spv", "wgsl_entry_point": "tutorialpassthru_fragment" }, { - "source_path": "shaders/tutorial-slabbed_renderlet.spv", "entry_point": "tutorial::slabbed_renderlet", + "source_path": "shaders/tutorial-slabbed_renderlet.spv", "wgsl_entry_point": "tutorialslabbed_renderlet" }, { - "source_path": "shaders/tutorial-slabbed_vertices.spv", "entry_point": "tutorial::slabbed_vertices", + "source_path": "shaders/tutorial-slabbed_vertices.spv", "wgsl_entry_point": "tutorialslabbed_vertices" }, { - "source_path": "shaders/tutorial-slabbed_vertices_no_instance.spv", "entry_point": "tutorial::slabbed_vertices_no_instance", + "source_path": "shaders/tutorial-slabbed_vertices_no_instance.spv", "wgsl_entry_point": "tutorialslabbed_vertices_no_instance" }, { - "source_path": "shaders/ui_slab-shader-ui_fragment.spv", "entry_point": "ui_slab::shader::ui_fragment", + "source_path": "shaders/ui_slab-shader-ui_fragment.spv", "wgsl_entry_point": "ui_slabshaderui_fragment" }, { - "source_path": "shaders/ui_slab-shader-ui_vertex.spv", "entry_point": "ui_slab::shader::ui_vertex", + "source_path": "shaders/ui_slab-shader-ui_vertex.spv", "wgsl_entry_point": "ui_slabshaderui_vertex" } -] \ No newline at end of file +] diff --git a/crates/renderling/shaders/tonemapping-tonemapping_fragment.spv b/crates/renderling/shaders/tonemapping-tonemapping_fragment.spv deleted file mode 100644 index cf72d613..00000000 Binary files a/crates/renderling/shaders/tonemapping-tonemapping_fragment.spv and /dev/null differ diff --git a/crates/renderling/shaders/tonemapping-tonemapping_vertex.spv b/crates/renderling/shaders/tonemapping-tonemapping_vertex.spv deleted file mode 100644 index 35d08888..00000000 Binary files a/crates/renderling/shaders/tonemapping-tonemapping_vertex.spv and /dev/null differ diff --git a/crates/renderling/src/atlas/atlas_image.rs b/crates/renderling/src/atlas/atlas_image.rs index 0a757cb3..6aef01d3 100644 --- a/crates/renderling/src/atlas/atlas_image.rs +++ b/crates/renderling/src/atlas/atlas_image.rs @@ -300,23 +300,19 @@ pub fn convert_pixels( bytes.into_iter().flat_map(|r| [r, 0, 0, 255]).collect() } (AtlasImageFormat::R8G8, wgpu::TextureFormat::Rgba8Unorm) => bytes - .chunks_exact(2) - .flat_map(|p| { - if let [r, g] = p { - [*r, *g, 0, 255] - } else { - unreachable!() - } + .as_chunks::<2>() + .0 + .iter() + .flat_map(|p| match p { + [r, g] => [*r, *g, 0, 255], }) .collect(), (AtlasImageFormat::R8G8B8, wgpu::TextureFormat::Rgba8Unorm) => bytes - .chunks_exact(3) - .flat_map(|p| { - if let [r, g, b] = p { - [*r, *g, *b, 255] - } else { - unreachable!() - } + .as_chunks::<3>() + .0 + .iter() + .flat_map(|p| match p { + [r, g, b] => [*r, *g, *b, 255], }) .collect(), (AtlasImageFormat::R8G8B8A8, wgpu::TextureFormat::Rgba8Unorm) => bytes, @@ -328,25 +324,21 @@ pub fn convert_pixels( } (AtlasImageFormat::R16G16, wgpu::TextureFormat::Rgba8Unorm) => { bytemuck::cast_slice::(&bytes) - .chunks_exact(2) - .flat_map(|p| { - if let [r, g] = p { - [u16_to_u8(*r), u16_to_u8(*g), 0, 255] - } else { - unreachable!() - } + .as_chunks::<2>() + .0 + .iter() + .flat_map(|p| match p { + [r, g] => [u16_to_u8(*r), u16_to_u8(*g), 0, 255], }) .collect() } (AtlasImageFormat::R16G16B16, wgpu::TextureFormat::Rgba8Unorm) => { bytemuck::cast_slice::(&bytes) - .chunks_exact(3) - .flat_map(|p| { - if let [r, g, b] = p { - [u16_to_u8(*r), u16_to_u8(*g), u16_to_u8(*b), 255] - } else { - unreachable!() - } + .as_chunks::<3>() + .0 + .iter() + .flat_map(|p| match p { + [r, g, b] => [u16_to_u8(*r), u16_to_u8(*g), u16_to_u8(*b), 255], }) .collect() } @@ -363,25 +355,21 @@ pub fn convert_pixels( .iter() .map(|bits| half::f16::from_bits(*bits).to_f32()) .collect::>() - .chunks_exact(4) - .flat_map(|p| { - if let [r, g, b, a] = p { - [f32_to_u8(*r), f32_to_u8(*g), f32_to_u8(*b), f32_to_u8(*a)] - } else { - unreachable!() - } + .as_chunks::<4>() + .0 + .iter() + .flat_map(|p| match p { + [r, g, b, a] => [f32_to_u8(*r), f32_to_u8(*g), f32_to_u8(*b), f32_to_u8(*a)], }) .collect() } (AtlasImageFormat::R32G32B32FLOAT, wgpu::TextureFormat::Rgba8Unorm) => { bytemuck::cast_slice::(&bytes) - .chunks_exact(3) - .flat_map(|p| { - if let [r, g, b] = p { - [f32_to_u8(*r), f32_to_u8(*g), f32_to_u8(*b), 255] - } else { - unreachable!() - } + .as_chunks::<3>() + .0 + .iter() + .flat_map(|p| match p { + [r, g, b] => [f32_to_u8(*r), f32_to_u8(*g), f32_to_u8(*b), 255], }) .collect() } diff --git a/crates/renderling/src/bloom.rs b/crates/renderling/src/bloom.rs index 011ad9f4..5bc7da39 100644 --- a/crates/renderling/src/bloom.rs +++ b/crates/renderling/src/bloom.rs @@ -2,9 +2,1031 @@ //! //! As described in [learnopengl.com's Physically Based Bloom //! article](https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom). -#[cfg(not(target_arch = "spirv"))] -mod cpu; -#[cfg(not(target_arch = "spirv"))] -pub use cpu::*; -pub mod shader; +// #[cfg(not(target_arch = "spirv"))] +// mod cpu; +// #[cfg(not(target_arch = "spirv"))] +// pub use cpu::*; + +// pub mod shader; + +#[wgsl_rs::wgsl] +pub mod vertex { + use crate::shader::constants::*; + use wgsl_rs::std::*; + + pub struct BloomVertexInput { + #[builtin(vertex_index)] + vertex_index: u32, + #[builtin(instance_index)] + id: u32, + } + + pub struct BloomInterStage { + #[location(0)] + pub uv: Vec2f, + + #[location(1)] + #[interpolate(flat)] + pub id: u32, + + #[builtin(position)] + pub clip_pos: Vec4f, + } + + /// Bloom vertex shader. + /// + /// This is a pass-through vertex shader to facilitate a bloom effect. + #[vertex] + pub fn bloom_vertex(input: BloomVertexInput) -> BloomInterStage { + let i = (input.vertex_index % 6) as usize; + BloomInterStage { + uv: UV_COORD_QUAD_CCW[i], + id: input.id, + clip_pos: CLIP_SPACE_COORD_QUAD_CCW[i], + } + } +} + +#[wgsl_rs::wgsl(extensions = [crabslab_wgsl::SlabItemExt])] +pub mod sample { + //! Downsampling and upsampling fragment shaders. + + use crabslab_wgsl::*; + use wgsl_rs::std::*; + + use super::vertex::*; + + storage!(group(0), binding(0), SLAB: RuntimeArray); + // Remember to add bilinear minification filter for this texture! + // Remember to use a floating-point texture format (for HDR)! + // Remember to use edge clamping for this texture! + texture!(group(0), binding(1), TEXTURE: Texture2D); + sampler!(group(0), binding(2), SAMPLER: Sampler); + + /// Bloom downsampling shader. + /// + /// Performs successive downsampling from a source texture. + /// + /// As taken from Call Of Duty method - presented at ACM Siggraph 2014. + /// + /// This particular method was designed to eliminate + /// "pulsating artifacts and temporal stability issues". + #[fragment] + pub fn bloom_downsample_fragment(input: BloomInterStage) -> Vec4f { + let in_pixel_size: Vec2f; + slab_read!(Vec2f, get!(SLAB), input.id, in_pixel_size); + // TODO: once destructuring is supported in wgsl-rs, uncomment this. + // let Vec2 { x, y } = slab.read(in_pixel_size_id); + let x = in_pixel_size.x; + let y = in_pixel_size.y; + + // Take 13 samples around current texel: + // a - b - c + // - j - k - + // d - e - f + // - l - m - + // g - h - i + // === ('e' is the current texel) === + let a = texture_sample( + TEXTURE, + SAMPLER, + vec2f(input.uv.x - 2.0 * x, input.uv.y + 2.0 * y), + ); + let b = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x, input.uv.y + 2.0 * y)); + let c = texture_sample( + TEXTURE, + SAMPLER, + vec2f(input.uv.x + 2.0 * x, input.uv.y + 2.0 * y), + ); + + let d = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x - 2.0 * x, input.uv.y)); + let e = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x, input.uv.y)); + let f = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x + 2.0 * x, input.uv.y)); + + let g = texture_sample( + TEXTURE, + SAMPLER, + vec2f(input.uv.x - 2.0 * x, input.uv.y - 2.0 * y), + ); + let h = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x, input.uv.y - 2.0 * y)); + let i = texture_sample( + TEXTURE, + SAMPLER, + vec2f(input.uv.x + 2.0 * x, input.uv.y - 2.0 * y), + ); + + let j = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x - x, input.uv.y + y)); + let k = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x + x, input.uv.y + y)); + let l = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x - x, input.uv.y - y)); + let m = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x + x, input.uv.y - y)); + + // Apply weighted distribution: + // 0.5 + 0.125 + 0.125 + 0.125 + 0.125 = 1 + // a,b,d,e * 0.125 + // b,c,e,f * 0.125 + // d,e,g,h * 0.125 + // e,f,h,i * 0.125 + // j,k,l,m * 0.5 + // This shows 5 square areas that are being sampled. But some of them + // overlap, so to have an energy preserving downsample we need to make + // some adjustments. The weights are the distributed so that the sum of + // j,k,l,m (e.g.) contribute 0.5 to the final color output. The code + // below is written to effectively yield this sum. We get: + // 0.125*5 + 0.03125*4 + 0.0625*4 = 1 + let f1 = 0.125; + let f2 = 0.0625; + let f3 = 0.03125; + let center = e * f1; + let inner = (j + k + l + m) * f1; + let outer = (b + d + h + f) * f2; + let furthest = (a + c + g + i) * f3; + // TODO: use vec3f_splat when it's available + // let min = Vec3::splat(f32::EPSILON).extend(1.0); + let ep = 1.1920929e-7; + let min = vec4f(ep, ep, ep, 1.0); + max(center + inner + outer + furthest, min) + } + + /// Bloom upsampling shader. + /// + /// This shader performs successive upsampling on a source texture. + /// + /// Taken from Call Of Duty method, presented at ACM Siggraph 2014. + #[fragment] + pub fn bloom_upsample_fragment(input: BloomInterStage) -> Vec4f { + // The filter kernel is applied with a radius, specified in texture + // coordinates, so that the radius will vary across mip resolutions. + // let Vec2 { x, y } = slab.read(filter_radius_id); + let filter_radius: Vec2f; + slab_read!(Vec2f, get!(SLAB), input.id, filter_radius); + let x = filter_radius.x; + let y = filter_radius.y; + + // Take 9 samples around current texel: + // a - b - c + // d - e - f + // g - h - i + // === ('e' is the current texel) === + let a = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x - x, input.uv.y + y)).xyz(); + let b = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x, input.uv.y + y)).xyz(); + let c = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x + x, input.uv.y + y)).xyz(); + + let d = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x - x, input.uv.y)).xyz(); + let e = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x, input.uv.y)).xyz(); + let f = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x + x, input.uv.y)).xyz(); + + let g = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x - x, input.uv.y - y)).xyz(); + let h = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x, input.uv.y - y)).xyz(); + let i = texture_sample(TEXTURE, SAMPLER, vec2f(input.uv.x + x, input.uv.y - y)).xyz(); + + // Apply weighted distribution, by using a 3x3 tent filter: + // 1 | 1 2 1 | + // -- * | 2 4 2 | + // 16 | 1 2 1 | + let mut sample = e * 4.0; + sample += (b + d + f + h) * 2.0; + sample += a + c + g + i; + sample *= 1.0 / 16.0; + + vec4f(sample.x, sample.y, sample.z, 0.5) + } +} + +#[wgsl_rs::wgsl(extensions = [crabslab_wgsl::SlabItemExt])] +pub mod mix { + use crabslab_wgsl::*; + use wgsl_rs::std::*; + + use super::vertex::*; + + storage!(group(0), binding(0), SLAB: RuntimeArray); + texture!(group(0), binding(1), HDR_TEXTURE: Texture2D); + sampler!(group(0), binding(2), HDR_SAMPLER: Sampler); + texture!(group(0), binding(3), BLOOM_TEXTURE: Texture2D); + sampler!(group(0), binding(4), BLOOM_SAMPLER: Sampler); + + #[fragment] + /// Bloom "mix" shader. + /// + /// This is the final step in applying bloom in which the computed bloom is + /// mixed with the source texture according to a strength factor. + pub fn bloom_mix_fragment(input: BloomInterStage) -> Vec4f { + let bloom_strength: Vec2f; + slab_read!(Vec2f, get!(SLAB), input.id, bloom_strength); + + let hdr = texture_sample(HDR_TEXTURE, HDR_SAMPLER, input.uv).rgb(); + let bloom = texture_sample(BLOOM_TEXTURE, BLOOM_SAMPLER, input.uv).rgb(); + let s = bloom_strength.x(); + let color = mix(hdr, bloom, vec3f(s, s, s)); + vec4f(color.r(), color.g(), color.b(), 1.0) + } +} + +pub mod wgsl { + //! wgsl-rs based bloom module. + //! + //! Temporary until the wgsl-rs port is done. Once the port is done this + //! becomes the main module here. + use core::ops::Deref; + use std::sync::{Arc, RwLock}; + + use craballoc_wgsl::{ + arena::{Arena, Value}, + buffer::SlabBuffer, + runtime::WgpuRuntime, + }; + use crabslab_wgsl::Id; + use wgsl_rs::std::{vec2f, vec2u, Vec2f, Vec2u}; + use wgsl_rs_linkage_wgpu::{analysis::assemble_ir, IrModuleExt, WgpuLinkage}; + + use crate::texture::{self, Texture}; + + use super::{mix, sample, vertex}; + + struct BloomLinkage { + vertex: WgpuLinkage, + sample: WgpuLinkage, + mix: WgpuLinkage, + } + + impl BloomLinkage { + pub fn new() -> Self { + let vertex_module = assemble_ir(&vertex::WGSL_SOURCE).expect("bloom vertex assembly"); + let sample_module = + assemble_ir(&sample::WGSL_SOURCE).expect("bloom [up|down]sample assembly"); + let mix_module = assemble_ir(&mix::WGSL_SOURCE).expect("bloom mix assembly"); + + BloomLinkage { + vertex: vertex_module.generate_linkage(), + sample: sample_module.generate_linkage(), + mix: mix_module.generate_linkage(), + } + } + + fn create_bloom_downsample_pipeline( + &mut self, + device: &wgpu::Device, + ) -> wgpu::RenderPipeline { + let label = Some("bloom downsample"); + let layout = self.sample.pipeline_layout(device, label); + let vertex_module = self.vertex.shader_module(device); + let fragment_module = self.sample.shader_module(device); + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label, + layout: Some(&layout), + vertex: wgpu::VertexState { + module: &vertex_module, + entry_point: Some("bloom_vertex"), + buffers: &[], + compilation_options: Default::default(), + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + fragment: Some(wgpu::FragmentState { + module: &fragment_module, + entry_point: Some("bloom_downsample_fragment"), + targets: &[Some(wgpu::ColorTargetState { + format: wgpu::TextureFormat::Rgba16Float, + blend: None, + write_mask: wgpu::ColorWrites::all(), + })], + compilation_options: Default::default(), + }), + multiview_mask: None, + cache: None, + }) + } + + fn create_bloom_upsample_pipeline( + &mut self, + device: &wgpu::Device, + ) -> wgpu::RenderPipeline { + let label = Some("bloom upsample"); + let layout = self.sample.pipeline_layout(device, label); + let vertex_module = self.vertex.shader_module(device); + let fragment_module = self.sample.shader_module(device); + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label, + layout: Some(&layout), + vertex: wgpu::VertexState { + module: &vertex_module, + entry_point: Some("bloom_vertex"), + buffers: &[], + compilation_options: Default::default(), + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + fragment: Some(wgpu::FragmentState { + module: &fragment_module, + entry_point: Some("bloom_upsample_fragment"), + targets: &[Some(wgpu::ColorTargetState { + format: wgpu::TextureFormat::Rgba16Float, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::all(), + })], + compilation_options: Default::default(), + }), + multiview_mask: None, + cache: None, + }) + } + + fn create_mix_pipeline(&mut self, device: &wgpu::Device) -> wgpu::RenderPipeline { + let label = Some("bloom mix"); + let layout = self.mix.pipeline_layout(device, label); + let vertex_module = self.vertex.shader_module(device); + let fragment_module = self.mix.shader_module(device); + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label, + layout: Some(&layout), + vertex: wgpu::VertexState { + module: &vertex_module, + entry_point: Some("bloom_vertex"), + buffers: &[], + compilation_options: Default::default(), + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + fragment: Some(wgpu::FragmentState { + module: &fragment_module, + entry_point: Some("bloom_mix_fragment"), + targets: &[Some(wgpu::ColorTargetState { + format: wgpu::TextureFormat::Rgba16Float, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::all(), + })], + compilation_options: Default::default(), + }), + multiview_mask: None, + cache: None, + }) + } + + /// Create a bindgroup for either downsample or upsample shaders. + fn create_sample_bindgroup( + &mut self, + device: &wgpu::Device, + buffer: &wgpu::Buffer, + tex: &Texture, + ) -> wgpu::BindGroup { + self.sample + .create_bind_group_named( + 0, + device, + &[ + ( + "SLAB", + wgpu::BindingResource::Buffer(buffer.as_entire_buffer_binding()), + ), + ("TEXTURE", wgpu::BindingResource::TextureView(&tex.view)), + ("SAMPLER", wgpu::BindingResource::Sampler(&tex.sampler)), + ], + ) + .expect("bloom downsample bindgroup") + } + + /// Create a sample bindgroup for each give texture. + fn create_bindgroups( + &mut self, + device: &wgpu::Device, + buffer: &wgpu::Buffer, + textures: &[Texture], + ) -> Vec { + textures + .iter() + .map(|tex| self.create_sample_bindgroup(device, buffer, tex)) + .collect() + } + + fn create_mix_bindgroup( + &mut self, + device: &wgpu::Device, + slab_buffer: &wgpu::Buffer, + hdr_texture: &Texture, + bloom_texture: &Texture, + ) -> wgpu::BindGroup { + self.mix + .create_bind_group_named( + 0, + device, + &[ + ( + "SLAB", + wgpu::BindingResource::Buffer(slab_buffer.as_entire_buffer_binding()), + ), + ( + "HDR_TEXTURE", + wgpu::BindingResource::TextureView(&hdr_texture.view), + ), + ( + "HDR_SAMPLER", + wgpu::BindingResource::Sampler(&hdr_texture.sampler), + ), + ( + "BLOOM_TEXTURE", + wgpu::BindingResource::TextureView(&bloom_texture.view), + ), + ( + "BLOOM_SAMPLER", + wgpu::BindingResource::Sampler(&bloom_texture.sampler), + ), + ], + ) + .expect("bloom mix bindgroup") + } + } + + pub(crate) fn config_resolutions(resolution: Vec2u) -> impl Iterator { + let num_textures = resolution.x.min(resolution.y).ilog2(); + (0..=num_textures).map(move |i| Vec2u { + x: resolution.x >> i, + y: resolution.y >> i, + }) + } + + fn create_texture( + runtime: impl AsRef, + width: u32, + height: u32, + label: Option<&str>, + extra_usages: wgpu::TextureUsages, + ) -> texture::Texture { + let sampler = runtime + .as_ref() + .device + .create_sampler(&wgpu::SamplerDescriptor { + label, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::MipmapFilterMode::Linear, + ..Default::default() + }); + Texture::new_with_wgsl( + runtime, + label, + Some( + wgpu::TextureUsages::RENDER_ATTACHMENT + | wgpu::TextureUsages::TEXTURE_BINDING + | wgpu::TextureUsages::COPY_SRC + | extra_usages, + ), + Some(sampler), + wgpu::TextureFormat::Rgba16Float, + 4, + 2, + width, + height, + 1, + &[], + ) + } + + fn create_textures( + runtime: impl AsRef, + resolution: Vec2u, + ) -> Vec { + let resolutions = config_resolutions(resolution).collect::>(); + log::trace!( + "creating {} bloom textures at resolution {resolution:?}", + resolutions.len() + ); + let mut textures = vec![]; + for ( + i, + Vec2u { + x: width, + y: height, + }, + ) in resolutions.into_iter().skip(1).enumerate() + { + let title = format!("bloom texture[{i}]"); + let label = Some(title.as_str()); + let texture = create_texture( + runtime.as_ref(), + width, + height, + label, + wgpu::TextureUsages::empty(), + ); + textures.push(texture); + } + textures + } + + /// Performs a "physically based" bloom effect on a texture. CPU only. + /// + /// Contains pipelines, down/upsampling textures, a buffer + /// to communicate configuration to the shaders, and bindgroups. + /// + /// Clones of [`Bloom`] all point to the same resources. + #[derive(Clone)] + pub struct Bloom { + arena: Arena, + slab_buffer: SlabBuffer, + + linkage: Arc>, + + downsample_pixel_sizes: Value<[Vec2f]>, + downsample_pipeline: Arc, + + upsample_filter_radius: Value, + upsample_pipeline: Arc, + + textures: Arc>>, + bindgroups: Arc>>, + hdr_texture_downsample_bindgroup: Arc>, + + mix_pipeline: Arc, + mix_bindgroup: Arc>, + mix_texture: Arc>, + mix_strength: Value, + } + + impl Bloom { + pub fn new(runtime: impl AsRef, hdr_texture: &Texture) -> Self { + let runtime = runtime.as_ref(); + let resolution = vec2u(hdr_texture.width(), hdr_texture.height()); + + let arena = Arena::new(runtime, "bloom-slab", None); + let downsample_pixel_sizes = arena.new_array( + config_resolutions(resolution).map(|r| 1.0 / vec2f(r.x as f32, r.y as f32)), + ); + let upsample_filter_radius = + arena.new_value(1.0 / vec2f(resolution.x as f32, resolution.y as f32)); + let mix_strength = arena.new_value(0.04f32); + let slab_buffer = arena.commit(); + + let mut linkage = BloomLinkage::new(); + + let downsample_pipeline = + Arc::new(linkage.create_bloom_downsample_pipeline(&runtime.device)); + let upsample_pipeline = + Arc::new(linkage.create_bloom_upsample_pipeline(&runtime.device)); + let mix_pipeline = Arc::new(linkage.create_mix_pipeline(&runtime.device)); + + let hdr_texture_downsample_bindgroup = + linkage.create_sample_bindgroup(&runtime.device, &slab_buffer, hdr_texture); + + let mix_texture = create_texture( + runtime, + resolution.x, + resolution.y, + Some("bloom mix"), + wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::COPY_DST, + ); + + let textures = create_textures(runtime, resolution); + let bindgroups = linkage.create_bindgroups(&runtime.device, &slab_buffer, &textures); + + let mix_bindgroup = linkage.create_mix_bindgroup( + &runtime.device, + &slab_buffer, + hdr_texture, + &textures[0], + ); + + Self { + arena, + slab_buffer, + linkage: Arc::new(RwLock::new(linkage)), + downsample_pixel_sizes, + downsample_pipeline, + upsample_filter_radius, + upsample_pipeline, + textures: Arc::new(RwLock::new(textures)), + bindgroups: Arc::new(RwLock::new(bindgroups)), + hdr_texture_downsample_bindgroup: Arc::new(RwLock::new( + hdr_texture_downsample_bindgroup, + )), + mix_pipeline, + mix_texture: Arc::new(RwLock::new(mix_texture)), + mix_bindgroup: Arc::new(RwLock::new(mix_bindgroup)), + mix_strength, + } + } + + pub(crate) fn arena(&self) -> &Arena { + &self.arena + } + + pub fn set_mix_strength(&self, strength: f32) { + self.mix_strength.set(strength); + } + + pub fn get_mix_strength(&self) -> f32 { + self.mix_strength.get() + } + + /// Set the filter radius in pixels. + pub fn set_filter_radius(&self, filter_radius: f32) { + let size = self.get_size(); + let filter_radius = vec2f(filter_radius / size.x as f32, filter_radius / size.y as f32); + self.upsample_filter_radius.set(filter_radius); + } + + pub fn get_filter_radius(&self) -> Vec2f { + self.upsample_filter_radius.get() + } + + pub fn get_size(&self) -> Vec2u { + let mix_texture = self.get_mix_texture(); + vec2u(mix_texture.width(), mix_texture.height()) + } + + /// Recreates this bloom using the new HDR texture. + pub fn set_hdr_texture(&self, runtime: impl AsRef, hdr_texture: &Texture) { + let resolution = vec2u(hdr_texture.width(), hdr_texture.height()); + let runtime = runtime.as_ref(); + let textures = create_textures(runtime, resolution); + let mut linkage = self.linkage.write().expect("poisoned"); + + *self.bindgroups.write().expect("bloom bindgroups write") = + linkage.create_bindgroups(&runtime.device, &self.slab_buffer, &textures); + *self + .hdr_texture_downsample_bindgroup + .write() + .expect("bloom hdr downsample bindgroup write") = + linkage.create_sample_bindgroup(&runtime.device, &self.slab_buffer, hdr_texture); + *self.mix_texture.write().expect("bloom mix_texture write") = create_texture( + runtime, + resolution.x, + resolution.y, + Some("bloom mix"), + wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::COPY_DST, + ); + *self + .mix_bindgroup + .write() + .expect("bloom mix_bindgroup write") = linkage.create_mix_bindgroup( + &runtime.device, + &self.slab_buffer, + hdr_texture, + &textures[0], + ); + *self.textures.write().expect("bloom textures write") = textures; + } + + /// Returns a clone of the current mix texture. + /// + /// The mix texture is the result of mixing the bloom by the hdr using + /// the mix strength. + pub fn get_mix_texture(&self) -> Texture { + // UNWRAP: not safe but we want to panic + self.mix_texture + .read() + .expect("bloom mix_texture read") + .clone() + } + + pub(crate) fn render_downsamples(&self, device: &wgpu::Device, queue: &wgpu::Queue) { + struct DownsampleItem<'a> { + view: &'a wgpu::TextureView, + bindgroup: &'a wgpu::BindGroup, + pixel_size: Id, + } + // Get all the bindgroups (which are what we're reading from), + // starting with the hdr frame. + // Since `bindgroups` are one element greater (we pushed + // `hdr_texture_bindgroup` to the front) the last bindgroup will + // not be used, which is good - we don't need to read from the + // smallest texture during downsampling. UNWRAP: not safe but we + // want to panic + let textures_guard = self.textures.read().expect("bloom textures read"); + let hdr_texture_downsample_bindgroup_guard = self + .hdr_texture_downsample_bindgroup + .read() + .expect("bloom hdr downsample bindgroup read"); + let hdr_texture_downsample_bindgroup: &wgpu::BindGroup = + &hdr_texture_downsample_bindgroup_guard; + let bindgroups_guard = self.bindgroups.read().expect("bloom bindgroups read"); + let bindgroups = + std::iter::once(hdr_texture_downsample_bindgroup).chain(bindgroups_guard.iter()); + let items = textures_guard + .iter() + .zip(bindgroups) + .zip(self.downsample_pixel_sizes.array().iter()) + .map(|((tex, bindgroup), pixel_size)| DownsampleItem { + view: &tex.view, + bindgroup, + pixel_size, + }); + for ( + i, + DownsampleItem { + view, + bindgroup, + pixel_size, + }, + ) in items.enumerate() + { + let title = format!("bloom downsample {i}"); + let label = Some(title.as_str()); + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: wgpu::StoreOp::Store, + }, + depth_slice: None, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + multiview_mask: None, + }); + render_pass.set_pipeline(&self.downsample_pipeline); + render_pass.set_bind_group(0, Some(bindgroup), &[]); + let id = pixel_size.into(); + render_pass.draw(0..6, id..id + 1); + } + queue.submit(std::iter::once(encoder.finish())); + } + } + + fn render_upsamples(&self, device: &wgpu::Device, queue: &wgpu::Queue) { + struct UpsampleItem<'a> { + view: &'a wgpu::TextureView, + bindgroup: &'a wgpu::BindGroup, + } + // Get all the bindgroups (which are what we're reading from), + // starting with the last mip. + // UNWRAP: not safe but we want to panic + let bindgroups_guard = self.bindgroups.read().expect("bloom bindgroups read"); + let bindgroups = bindgroups_guard.iter().rev(); + // Get all the texture views (which are what we're writing to), + // starting with the second-to-last mip. + let textures_guard = self.textures.read().expect("bloom textures read"); + let views = textures_guard.iter().rev().skip(1).map(|t| &t.view); + let items = bindgroups + .zip(views) + .map(|(bindgroup, view)| UpsampleItem { view, bindgroup }); + for (i, UpsampleItem { view, bindgroup }) in items.enumerate() { + let title = format!("bloom upsample {}", textures_guard.len() - i - 1); + let label = Some(title.as_str()); + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }, + depth_slice: None, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + multiview_mask: None, + }); + render_pass.set_pipeline(&self.upsample_pipeline); + render_pass.set_bind_group(0, Some(bindgroup), &[]); + let id = self.upsample_filter_radius.id().into(); + render_pass.draw(0..6, id..id + 1); + } + queue.submit(std::iter::once(encoder.finish())); + } + } + + fn render_mix(&self, device: &wgpu::Device, queue: &wgpu::Queue) { + let label = Some("bloom mix"); + // UNWRAP: not safe but we want to panic + let mix_texture = self.mix_texture.read().expect("bloom mix_texture read"); + let mix_bindgroup = self.mix_bindgroup.read().expect("bloom mix_bindgroup read"); + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &mix_texture.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: wgpu::StoreOp::Store, + }, + depth_slice: None, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + multiview_mask: None, + }); + render_pass.set_pipeline(&self.mix_pipeline); + render_pass.set_bind_group(0, Some(mix_bindgroup.deref()), &[]); + let id = self.mix_strength.id().into(); + render_pass.draw(0..6, id..id + 1); + } + + queue.submit(std::iter::once(encoder.finish())); + } + + pub fn bloom(&self, runtime: impl AsRef) { + let latest_buffer = self.arena.commit(); + assert!( + self.slab_buffer.creation_time() == latest_buffer.creation_time(), + "bloom slab buffer resized (it shouldn't)" + ); + + let WgpuRuntime { device, queue } = runtime.as_ref(); + self.render_downsamples(device, queue); + self.render_upsamples(device, queue); + self.render_mix(device, queue); + } + } +} + +#[cfg(test)] +mod test { + use wgsl_rs::std::{vec2f, vec2u, vec3f, Vec3f}; + + use crate::{context::Context, test::BlockOnFuture, texture::Texture}; + + use super::wgsl::*; + + #[test] + fn bloom_texture_sizes_sanity() { + let sizes = config_resolutions(vec2u(1024, 800)).collect::>(); + assert_eq!( + vec![ + vec2u(1024, 800), + vec2u(512, 400), + vec2u(256, 200), + vec2u(128, 100), + vec2u(64, 50), + vec2u(32, 25), + vec2u(16, 12), + vec2u(8, 6), + vec2u(4, 3), + vec2u(2, 1), + ], + sizes + ); + let pixel_sizes = config_resolutions(vec2u(1024, 800)) + .map(|r| 1.0 / vec2f(r.x as f32, r.y as f32)) + .collect::>(); + assert_eq!( + vec![ + vec2f(0.0009765625, 0.00125), + vec2f(0.001953125, 0.0025), + vec2f(0.00390625, 0.005), + vec2f(0.0078125, 0.01), + vec2f(0.015625, 0.02), + vec2f(0.03125, 0.04), + vec2f(0.0625, 0.083333336), + vec2f(0.125, 0.16666667), + vec2f(0.25, 0.33333334), + vec2f(0.5, 1.0) + ], + pixel_sizes + ); + } + + #[test] + fn bloom_sanity() { + let width = 48; + let height = 48; + let ctx = Context::headless(width, height).block(); + + // Rgba16Float, RENDER_ATTACHMENT|TEXTURE_BINDING|COPY_DST|COPY_SRC + // already set + let hdr = Texture::create_hdr_texture(ctx.get_device(), width, height, 1); + + fn fill_tex(width: u32, height: u32, ctx: &Context, tex: &Texture) { + // procedural HDR content, converted to f16 (the format is + // Rgba16Float!) + let mut texels = vec![0u16; (width * height * 4) as usize]; + for y in 0..height { + for x in 0..width { + let i = ((y * width + x) * 4) as usize; + let dx = x as f32 - width as f32 * 0.5; + let dy = y as f32 - height as f32 * 0.5; + let in_blob = dx * dx + dy * dy < 16.0 * 16.0; + let v = [ + 0.02, // dim field + 0.02, + if in_blob { 50.0 } else { 0.05 }, // bright blue blob + 1.0, + ]; + for (slot, val) in v.iter().enumerate() { + texels[i + slot] = half::f16::from_f32(*val).to_bits(); + } + } + } + ctx.get_queue().write_texture( + wgpu::TexelCopyTextureInfo { + texture: &tex.texture, + mip_level: 0, + origin: Default::default(), + aspect: wgpu::TextureAspect::All, + }, + bytemuck::cast_slice(&texels), + wgpu::TexelCopyBufferLayout { + offset: 0, + bytes_per_row: Some(width * 4 * 2), + rows_per_image: Some(height), + }, + wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }, + ); + } + fill_tex(width, height, &ctx, &hdr); + + let runtime = craballoc_wgsl::runtime::WgpuRuntime { + device: ctx.runtime().device.clone(), + queue: ctx.runtime().queue.clone(), + }; + + let bloom = Bloom::new(&runtime, &hdr); + bloom.bloom(&runtime); + + let result = bloom + .get_mix_texture() + .read_hdr_image(&ctx) + .block() + .unwrap(); + img_diff::assert_img_eq("bloom/result.exr", result); + } + + #[test] + /// Tests that the Bloom filter is properly integrated into `Stage`. + fn bloom_integration() { + let width = 256; + let height = 128; + let ctx = Context::headless(width, height).block(); + let stage = ctx.new_stage().with_bloom(false); + let projection = crate::camera::perspective(width as f32, height as f32); + let view = crate::camera::look_at(vec3f(0.0, 2.0, 18.0), Vec3f::ZERO, Vec3f::Y); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); + let skybox = stage + .new_skybox_from_path("../../img/hdr/night.hdr") + .unwrap(); + stage.use_skybox(&skybox); + let ibl = stage.new_ibl(&skybox); + stage.use_ibl(&ibl); + + let _doc = stage + .load_gltf_document_from_path("../../gltf/EmissiveStrengthTest.glb") + .unwrap(); + + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + let img = frame.read_image().block().unwrap(); + img_diff::assert_img_eq("bloom/without.png", img); + frame.present(); + + // now render the whole thing with default values + stage.set_has_bloom(true); + stage.set_bloom_mix_strength(0.1); + stage.set_bloom_filter_radius(2.0); + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + let img = frame.read_image().block().unwrap(); + img_diff::assert_img_eq("bloom/with.png", img); + } +} diff --git a/crates/renderling/src/bloom/cpu.rs b/crates/renderling/src/bloom/cpu.rs deleted file mode 100644 index 4015b40c..00000000 --- a/crates/renderling/src/bloom/cpu.rs +++ /dev/null @@ -1,802 +0,0 @@ -//! Bloom. -use core::ops::Deref; -use std::sync::{Arc, RwLock}; - -use craballoc::{ - prelude::{Hybrid, HybridArray, SlabAllocator}, - runtime::WgpuRuntime, - slab::SlabBuffer, -}; -use crabslab::Id; -use glam::{UVec2, Vec2}; - -use crate::texture::{self, Texture}; - -fn create_bindgroup_layout(device: &wgpu::Device, label: Option<&str>) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label, - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - }) -} - -fn create_bloom_downsample_pipeline(device: &wgpu::Device) -> wgpu::RenderPipeline { - let label = Some("bloom downsample"); - let bindgroup_layout = create_bindgroup_layout(device, label); - let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label, - bind_group_layouts: &[Some(&bindgroup_layout)], - immediate_size: 0, - }); - let vertex_module = crate::linkage::bloom_vertex::linkage(device); - let fragment_module = crate::linkage::bloom_downsample_fragment::linkage(device); - device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - multiview_mask: None, - label, - layout: Some(&layout), - vertex: wgpu::VertexState { - module: &vertex_module.module, - entry_point: Some(vertex_module.entry_point), - buffers: &[], - compilation_options: Default::default(), - }, - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - unclipped_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - fragment: Some(wgpu::FragmentState { - module: &fragment_module.module, - entry_point: Some(fragment_module.entry_point), - targets: &[Some(wgpu::ColorTargetState { - format: wgpu::TextureFormat::Rgba16Float, - blend: None, - write_mask: wgpu::ColorWrites::all(), - })], - compilation_options: Default::default(), - }), - cache: None, - }) -} - -fn create_bloom_upsample_pipeline(device: &wgpu::Device) -> wgpu::RenderPipeline { - let label = Some("bloom upsample"); - let bindgroup_layout = create_bindgroup_layout(device, label); - let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label, - bind_group_layouts: &[Some(&bindgroup_layout)], - immediate_size: 0, - }); - let vertex_module = crate::linkage::bloom_vertex::linkage(device); - let fragment_module = crate::linkage::bloom_upsample_fragment::linkage(device); - device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - multiview_mask: None, - label, - layout: Some(&layout), - vertex: wgpu::VertexState { - module: &vertex_module.module, - entry_point: Some(vertex_module.entry_point), - buffers: &[], - compilation_options: Default::default(), - }, - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - unclipped_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - fragment: Some(wgpu::FragmentState { - module: &fragment_module.module, - entry_point: Some(fragment_module.entry_point), - targets: &[Some(wgpu::ColorTargetState { - format: wgpu::TextureFormat::Rgba16Float, - blend: Some(wgpu::BlendState::ALPHA_BLENDING), - write_mask: wgpu::ColorWrites::all(), - })], - compilation_options: Default::default(), - }), - cache: None, - }) -} - -fn config_resolutions(resolution: UVec2) -> impl Iterator { - let num_textures = resolution.x.min(resolution.y).ilog2(); - (0..=num_textures).map(move |i| UVec2::new(resolution.x >> i, resolution.y >> i)) -} - -fn create_texture( - runtime: impl AsRef, - width: u32, - height: u32, - label: Option<&str>, - extra_usages: wgpu::TextureUsages, -) -> texture::Texture { - let sampler = runtime - .as_ref() - .device - .create_sampler(&wgpu::SamplerDescriptor { - label, - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::MipmapFilterMode::Linear, - ..Default::default() - }); - Texture::new_with( - runtime, - label, - Some( - wgpu::TextureUsages::RENDER_ATTACHMENT - | wgpu::TextureUsages::TEXTURE_BINDING - | wgpu::TextureUsages::COPY_SRC - | extra_usages, - ), - Some(sampler), - wgpu::TextureFormat::Rgba16Float, - 4, - 2, - width, - height, - 1, - &[], - ) -} - -fn create_textures(runtime: impl AsRef, resolution: UVec2) -> Vec { - let resolutions = config_resolutions(resolution).collect::>(); - log::trace!( - "creating {} bloom textures at resolution {resolution}", - resolutions.len() - ); - let mut textures = vec![]; - for ( - i, - UVec2 { - x: width, - y: height, - }, - ) in resolutions.into_iter().skip(1).enumerate() - { - let title = format!("bloom texture[{i}]"); - let label = Some(title.as_str()); - let texture = create_texture( - runtime.as_ref(), - width, - height, - label, - wgpu::TextureUsages::empty(), - ); - textures.push(texture); - } - textures -} - -fn create_bindgroup( - device: &wgpu::Device, - layout: &wgpu::BindGroupLayout, - buffer: &wgpu::Buffer, - tex: &Texture, -) -> wgpu::BindGroup { - let label = Some("bloom"); - device.create_bind_group(&wgpu::BindGroupDescriptor { - label, - layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(buffer.as_entire_buffer_binding()), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::TextureView(&tex.view), - }, - wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::Sampler(&tex.sampler), - }, - ], - }) -} - -fn create_bindgroups( - device: &wgpu::Device, - pipeline: &wgpu::RenderPipeline, - buffer: &wgpu::Buffer, - textures: &[Texture], -) -> Vec { - let layout = pipeline.get_bind_group_layout(0); - textures - .iter() - .map(|tex| create_bindgroup(device, &layout, buffer, tex)) - .collect() -} - -fn create_mix_pipeline(device: &wgpu::Device) -> wgpu::RenderPipeline { - let label = Some("bloom mix"); - let bindgroup_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label, - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 3, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 4, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - }); - let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label, - bind_group_layouts: &[Some(&bindgroup_layout)], - immediate_size: 0, - }); - let vertex_module = crate::linkage::bloom_vertex::linkage(device); - let fragment_module = crate::linkage::bloom_mix_fragment::linkage(device); - device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - multiview_mask: None, - label, - layout: Some(&layout), - vertex: wgpu::VertexState { - module: &vertex_module.module, - entry_point: Some(vertex_module.entry_point), - buffers: &[], - compilation_options: Default::default(), - }, - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - unclipped_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - fragment: Some(wgpu::FragmentState { - module: &fragment_module.module, - entry_point: Some(fragment_module.entry_point), - targets: &[Some(wgpu::ColorTargetState { - format: wgpu::TextureFormat::Rgba16Float, - blend: Some(wgpu::BlendState::ALPHA_BLENDING), - write_mask: wgpu::ColorWrites::all(), - })], - compilation_options: Default::default(), - }), - cache: None, - }) -} - -fn create_mix_bindgroup( - device: &wgpu::Device, - pipeline: &wgpu::RenderPipeline, - slab_buffer: &wgpu::Buffer, - hdr_texture: &Texture, - bloom_texture: &Texture, -) -> wgpu::BindGroup { - device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("bloom mix"), - layout: &pipeline.get_bind_group_layout(0), - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(slab_buffer.as_entire_buffer_binding()), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::TextureView(&hdr_texture.view), - }, - wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::Sampler(&hdr_texture.sampler), - }, - wgpu::BindGroupEntry { - binding: 3, - resource: wgpu::BindingResource::TextureView(&bloom_texture.view), - }, - wgpu::BindGroupEntry { - binding: 4, - resource: wgpu::BindingResource::Sampler(&bloom_texture.sampler), - }, - ], - }) -} - -/// Performs a "physically based" bloom effect on a texture. CPU only. -/// -/// Contains pipelines, down/upsampling textures, a buffer -/// to communicate configuration to the shaders, and bindgroups. -/// -/// Clones of [`Bloom`] all point to the same resources. -#[derive(Clone)] -pub struct Bloom { - slab: SlabAllocator, - slab_buffer: SlabBuffer, - - downsample_pixel_sizes: HybridArray, - downsample_pipeline: Arc, - - upsample_filter_radius: Hybrid, - upsample_pipeline: Arc, - - textures: Arc>>, - bindgroups: Arc>>, - hdr_texture_downsample_bindgroup: Arc>, - - mix_pipeline: Arc, - mix_bindgroup: Arc>, - mix_texture: Arc>, - mix_strength: Hybrid, -} - -impl Bloom { - pub fn new(runtime: impl AsRef, hdr_texture: &Texture) -> Self { - let runtime = runtime.as_ref(); - let resolution = UVec2::new(hdr_texture.width(), hdr_texture.height()); - - let slab = SlabAllocator::new(runtime, "bloom-slab", wgpu::BufferUsages::empty()); - let downsample_pixel_sizes = slab.new_array( - config_resolutions(resolution).map(|r| 1.0 / Vec2::new(r.x as f32, r.y as f32)), - ); - let upsample_filter_radius = - slab.new_value(1.0 / Vec2::new(resolution.x as f32, resolution.y as f32)); - let mix_strength = slab.new_value(0.04f32); - let slab_buffer = slab.commit(); - - let downsample_pipeline = Arc::new(create_bloom_downsample_pipeline(&runtime.device)); - let upsample_pipeline = Arc::new(create_bloom_upsample_pipeline(&runtime.device)); - let mix_pipeline = Arc::new(create_mix_pipeline(&runtime.device)); - - let hdr_texture_downsample_bindgroup = create_bindgroup( - &runtime.device, - &downsample_pipeline.get_bind_group_layout(0), - &slab_buffer, - hdr_texture, - ); - let mix_texture = create_texture( - runtime, - resolution.x, - resolution.y, - Some("bloom mix"), - wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::COPY_DST, - ); - - let textures = create_textures(runtime, resolution); - let bindgroups = create_bindgroups( - &runtime.device, - &downsample_pipeline, - &slab_buffer, - &textures, - ); - - let mix_bindgroup = create_mix_bindgroup( - &runtime.device, - &mix_pipeline, - &slab_buffer, - hdr_texture, - &textures[0], - ); - - Self { - slab, - slab_buffer, - downsample_pixel_sizes, - downsample_pipeline, - upsample_filter_radius, - upsample_pipeline, - textures: Arc::new(RwLock::new(textures)), - bindgroups: Arc::new(RwLock::new(bindgroups)), - hdr_texture_downsample_bindgroup: Arc::new(RwLock::new( - hdr_texture_downsample_bindgroup, - )), - mix_pipeline, - mix_texture: Arc::new(RwLock::new(mix_texture)), - mix_bindgroup: Arc::new(RwLock::new(mix_bindgroup)), - mix_strength, - } - } - - pub(crate) fn slab_allocator(&self) -> &SlabAllocator { - &self.slab - } - - pub fn set_mix_strength(&self, strength: f32) { - self.mix_strength.set(strength); - } - - pub fn get_mix_strength(&self) -> f32 { - self.mix_strength.get() - } - - /// Set the filter radius in pixels. - pub fn set_filter_radius(&self, filter_radius: f32) { - let size = self.get_size(); - let filter_radius = Vec2::new(filter_radius / size.x as f32, filter_radius / size.y as f32); - self.upsample_filter_radius.set(filter_radius); - } - - pub fn get_filter_radius(&self) -> Vec2 { - self.upsample_filter_radius.get() - } - - pub fn get_size(&self) -> UVec2 { - let mix_texture = self.get_mix_texture(); - UVec2::new(mix_texture.width(), mix_texture.height()) - } - - /// Recreates this bloom using the new HDR texture. - pub fn set_hdr_texture(&self, runtime: impl AsRef, hdr_texture: &Texture) { - // UNWRAP: panic on purpose (here and on till the end of this fn) - let slab_buffer = self.slab.get_buffer().unwrap(); - let resolution = UVec2::new(hdr_texture.width(), hdr_texture.height()); - let runtime = runtime.as_ref(); - let textures = create_textures(runtime, resolution); - - *self.bindgroups.write().expect("bloom bindgroups write") = create_bindgroups( - &runtime.device, - &self.downsample_pipeline, - &slab_buffer, - &textures, - ); - *self - .hdr_texture_downsample_bindgroup - .write() - .expect("bloom hdr downsample bindgroup write") = create_bindgroup( - &runtime.device, - &self.downsample_pipeline.get_bind_group_layout(0), - &slab_buffer, - hdr_texture, - ); - *self.mix_texture.write().expect("bloom mix_texture write") = create_texture( - runtime, - resolution.x, - resolution.y, - Some("bloom mix"), - wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::COPY_DST, - ); - *self - .mix_bindgroup - .write() - .expect("bloom mix_bindgroup write") = create_mix_bindgroup( - &runtime.device, - &self.mix_pipeline, - &slab_buffer, - hdr_texture, - &textures[0], - ); - *self.textures.write().expect("bloom textures write") = textures; - } - - /// Returns a clone of the current mix texture. - /// - /// The mix texture is the result of mixing the bloom by the hdr using the - /// mix strength. - pub fn get_mix_texture(&self) -> Texture { - // UNWRAP: not safe but we want to panic - self.mix_texture - .read() - .expect("bloom mix_texture read") - .clone() - } - - pub(crate) fn render_downsamples(&self, device: &wgpu::Device, queue: &wgpu::Queue) { - struct DownsampleItem<'a> { - view: &'a wgpu::TextureView, - bindgroup: &'a wgpu::BindGroup, - pixel_size: Id, - } - // Get all the bindgroups (which are what we're reading from), - // starting with the hdr frame. - // Since `bindgroups` are one element greater (we pushed - // `hdr_texture_bindgroup` to the front) the last bindgroup will - // not be used, which is good - we don't need to read from the - // smallest texture during downsampling. UNWRAP: not safe but we - // want to panic - let textures_guard = self.textures.read().expect("bloom textures read"); - let hdr_texture_downsample_bindgroup_guard = self - .hdr_texture_downsample_bindgroup - .read() - .expect("bloom hdr downsample bindgroup read"); - let hdr_texture_downsample_bindgroup: &wgpu::BindGroup = - &hdr_texture_downsample_bindgroup_guard; - let bindgroups_guard = self.bindgroups.read().expect("bloom bindgroups read"); - let bindgroups = - std::iter::once(hdr_texture_downsample_bindgroup).chain(bindgroups_guard.iter()); - let items = textures_guard - .iter() - .zip(bindgroups) - .zip(self.downsample_pixel_sizes.array().iter()) - .map(|((tex, bindgroup), pixel_size)| DownsampleItem { - view: &tex.view, - bindgroup, - pixel_size, - }); - for ( - i, - DownsampleItem { - view, - bindgroup, - pixel_size, - }, - ) in items.enumerate() - { - let title = format!("bloom downsample {i}"); - let label = Some(title.as_str()); - let mut encoder = - device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - multiview_mask: None, - label, - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), - store: wgpu::StoreOp::Store, - }, - depth_slice: None, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - }); - render_pass.set_pipeline(&self.downsample_pipeline); - render_pass.set_bind_group(0, Some(bindgroup), &[]); - let id = pixel_size.into(); - render_pass.draw(0..6, id..id + 1); - } - queue.submit(std::iter::once(encoder.finish())); - } - } - - fn render_upsamples(&self, device: &wgpu::Device, queue: &wgpu::Queue) { - struct UpsampleItem<'a> { - view: &'a wgpu::TextureView, - bindgroup: &'a wgpu::BindGroup, - } - // Get all the bindgroups (which are what we're reading from), - // starting with the last mip. - // UNWRAP: not safe but we want to panic - let bindgroups_guard = self.bindgroups.read().expect("bloom bindgroups read"); - let bindgroups = bindgroups_guard.iter().rev(); - // Get all the texture views (which are what we're writing to), - // starting with the second-to-last mip. - let textures_guard = self.textures.read().expect("bloom textures read"); - let views = textures_guard.iter().rev().skip(1).map(|t| &t.view); - let items = bindgroups - .zip(views) - .map(|(bindgroup, view)| UpsampleItem { view, bindgroup }); - for (i, UpsampleItem { view, bindgroup }) in items.enumerate() { - let title = format!("bloom upsample {}", textures_guard.len() - i - 1); - let label = Some(title.as_str()); - let mut encoder = - device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - multiview_mask: None, - label, - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Load, - store: wgpu::StoreOp::Store, - }, - depth_slice: None, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - }); - render_pass.set_pipeline(&self.upsample_pipeline); - render_pass.set_bind_group(0, Some(bindgroup), &[]); - let id = self.upsample_filter_radius.id().into(); - render_pass.draw(0..6, id..id + 1); - } - queue.submit(std::iter::once(encoder.finish())); - } - } - - fn render_mix(&self, device: &wgpu::Device, queue: &wgpu::Queue) { - let label = Some("bloom mix"); - // UNWRAP: not safe but we want to panic - let mix_texture = self.mix_texture.read().expect("bloom mix_texture read"); - let mix_bindgroup = self.mix_bindgroup.read().expect("bloom mix_bindgroup read"); - let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - multiview_mask: None, - label, - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &mix_texture.view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), - store: wgpu::StoreOp::Store, - }, - depth_slice: None, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - }); - render_pass.set_pipeline(&self.mix_pipeline); - render_pass.set_bind_group(0, Some(mix_bindgroup.deref()), &[]); - let id = self.mix_strength.id().into(); - render_pass.draw(0..6, id..id + 1); - } - - queue.submit(std::iter::once(encoder.finish())); - } - - pub fn bloom(&self, device: &wgpu::Device, queue: &wgpu::Queue) { - self.slab.commit(); - assert!( - self.slab_buffer.is_valid(), - "bloom slab buffer should never resize" - ); - self.render_downsamples(device, queue); - self.render_upsamples(device, queue); - self.render_mix(device, queue); - } -} - -#[cfg(test)] -mod test { - use glam::Vec3; - - use crate::{context::Context, test::BlockOnFuture}; - - use super::*; - - #[test] - fn bloom_texture_sizes_sanity() { - let sizes = config_resolutions(UVec2::new(1024, 800)).collect::>(); - assert_eq!( - vec![ - UVec2::new(1024, 800), - UVec2::new(512, 400), - UVec2::new(256, 200), - UVec2::new(128, 100), - UVec2::new(64, 50), - UVec2::new(32, 25), - UVec2::new(16, 12), - UVec2::new(8, 6), - UVec2::new(4, 3), - UVec2::new(2, 1), - ], - sizes - ); - let pixel_sizes = config_resolutions(UVec2::new(1024, 800)) - .map(|r| 1.0 / Vec2::new(r.x as f32, r.y as f32)) - .collect::>(); - assert_eq!( - vec![ - Vec2::new(0.0009765625, 0.00125), - Vec2::new(0.001953125, 0.0025), - Vec2::new(0.00390625, 0.005), - Vec2::new(0.0078125, 0.01), - Vec2::new(0.015625, 0.02), - Vec2::new(0.03125, 0.04), - Vec2::new(0.0625, 0.083333336), - Vec2::new(0.125, 0.16666667), - Vec2::new(0.25, 0.33333334), - Vec2::new(0.5, 1.0) - ], - pixel_sizes - ); - } - - #[test] - fn bloom_sanity() { - let width = 256; - let height = 128; - let ctx = Context::headless(width, height).block(); - let stage = ctx.new_stage().with_bloom(false); - let projection = crate::camera::perspective(width as f32, height as f32); - let view = crate::camera::look_at(Vec3::new(0.0, 2.0, 18.0), Vec3::ZERO, Vec3::Y); - let _camera = stage - .new_camera() - .with_projection_and_view(projection, view); - let skybox = stage - .new_skybox_from_path("../../img/hdr/night.hdr") - .unwrap(); - stage.use_skybox(&skybox); - let ibl = stage.new_ibl(&skybox); - stage.use_ibl(&ibl); - - let _doc = stage - .load_gltf_document_from_path("../../gltf/EmissiveStrengthTest.glb") - .unwrap(); - - let frame = ctx.get_next_frame().unwrap(); - stage.render(&frame.view()); - let img = frame.read_image().block().unwrap(); - img_diff::assert_img_eq("bloom/without.png", img); - frame.present(); - - // now render the whole thing with default values - stage.set_has_bloom(true); - stage.set_bloom_mix_strength(0.1); - stage.set_bloom_filter_radius(2.0); - let frame = ctx.get_next_frame().unwrap(); - stage.render(&frame.view()); - let img = frame.read_image().block().unwrap(); - img_diff::assert_img_eq("bloom/with.png", img); - } -} diff --git a/crates/renderling/src/bloom/shader.rs b/crates/renderling/src/bloom/shader.rs deleted file mode 100644 index af5d199f..00000000 --- a/crates/renderling/src/bloom/shader.rs +++ /dev/null @@ -1,182 +0,0 @@ -use crabslab::{Id, Slab}; -use glam::{Vec2, Vec4, Vec4Swizzles}; -use spirv_std::{image::Image2d, spirv, Sampler}; - -/// Bloom vertex shader. -/// -/// This is a pass-through vertex shader to facilitate a bloom effect. -#[spirv(vertex)] -pub fn bloom_vertex( - #[spirv(vertex_index)] vertex_index: u32, - #[spirv(instance_index)] in_id: u32, - out_uv: &mut Vec2, - #[spirv(flat)] out_id: &mut u32, - #[spirv(position)] out_clip_pos: &mut Vec4, -) { - let i = (vertex_index % 6) as usize; - *out_uv = crate::math::UV_COORD_QUAD_CCW[i]; - *out_clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i]; - *out_id = in_id; -} - -/// Bloom downsampling shader. -/// -/// Performs successive downsampling from a source texture. -/// -/// As taken from Call Of Duty method - presented at ACM Siggraph 2014. -/// -/// This particular method was designed to eliminate -/// "pulsating artifacts and temporal stability issues". -#[spirv(fragment)] -pub fn bloom_downsample_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - // Remember to add bilinear minification filter for this texture! - // Remember to use a floating-point texture format (for HDR)! - // Remember to use edge clamping for this texture! - #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - in_uv: Vec2, - #[spirv(flat)] in_pixel_size_id: Id, - // frag_color - downsample: &mut Vec4, -) { - use glam::Vec3; - - let Vec2 { x, y } = slab.read(in_pixel_size_id); - - // Take 13 samples around current texel: - // a - b - c - // - j - k - - // d - e - f - // - l - m - - // g - h - i - // === ('e' is the current texel) === - let a = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y + 2.0 * y)); - let b = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y + 2.0 * y)); - let c = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y + 2.0 * y)); - - let d = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y)); - let e = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y)); - let f = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y)); - - let g = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y - 2.0 * y)); - let h = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y - 2.0 * y)); - let i = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y - 2.0 * y)); - - let j = texture.sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y + y)); - let k = texture.sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y + y)); - let l = texture.sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y - y)); - let m = texture.sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y - y)); - - // Apply weighted distribution: - // 0.5 + 0.125 + 0.125 + 0.125 + 0.125 = 1 - // a,b,d,e * 0.125 - // b,c,e,f * 0.125 - // d,e,g,h * 0.125 - // e,f,h,i * 0.125 - // j,k,l,m * 0.5 - // This shows 5 square areas that are being sampled. But some of them - // overlap, so to have an energy preserving downsample we need to make - // some adjustments. The weights are the distributed so that the sum of - // j,k,l,m (e.g.) contribute 0.5 to the final color output. The code - // below is written to effectively yield this sum. We get: - // 0.125*5 + 0.03125*4 + 0.0625*4 = 1 - let f1 = 0.125; - let f2 = 0.0625; - let f3 = 0.03125; - let center = e * f1; - let inner = (j + k + l + m) * f1; - let outer = (b + d + h + f) * f2; - let furthest = (a + c + g + i) * f3; - let min = Vec3::splat(f32::EPSILON).extend(1.0); - *downsample = (center + inner + outer + furthest).max(min); -} - -/// Bloom upsampling shader. -/// -/// This shader performs successive upsampling on a source texture. -/// -/// Taken from Call Of Duty method, presented at ACM Siggraph 2014. -#[spirv(fragment)] -pub fn bloom_upsample_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - // Remember to add bilinear minification filter for this texture! - // Remember to use a floating-point texture format (for HDR)! - // Remember to use edge clamping for this texture! - #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - in_uv: Vec2, - #[spirv(flat)] filter_radius_id: Id, - // frag_color - upsample: &mut Vec4, -) { - // The filter kernel is applied with a radius, specified in texture - // coordinates, so that the radius will vary across mip resolutions. - let Vec2 { x, y } = slab.read(filter_radius_id); - - // Take 9 samples around current texel: - // a - b - c - // d - e - f - // g - h - i - // === ('e' is the current texel) === - let a = texture - .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y + y)) - .xyz(); - let b = texture - .sample(*sampler, Vec2::new(in_uv.x, in_uv.y + y)) - .xyz(); - let c = texture - .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y + y)) - .xyz(); - - let d = texture - .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y)) - .xyz(); - let e = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y)).xyz(); - let f = texture - .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y)) - .xyz(); - - let g = texture - .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y - y)) - .xyz(); - let h = texture - .sample(*sampler, Vec2::new(in_uv.x, in_uv.y - y)) - .xyz(); - let i = texture - .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y - y)) - .xyz(); - - // Apply weighted distribution, by using a 3x3 tent filter: - // 1 | 1 2 1 | - // -- * | 2 4 2 | - // 16 | 1 2 1 | - let mut sample = e * 4.0; - sample += (b + d + f + h) * 2.0; - sample += a + c + g + i; - sample *= 1.0 / 16.0; - *upsample = sample.extend(0.5); -} - -#[spirv(fragment)] -#[allow(clippy::too_many_arguments)] -/// Bloom "mix" shader. -/// -/// This is the final step in applying bloom in which the computed bloom is -/// mixed with the source texture according to a strength factor. -pub fn bloom_mix_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - #[spirv(descriptor_set = 0, binding = 1)] hdr_texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] hdr_sampler: &Sampler, - #[spirv(descriptor_set = 0, binding = 3)] bloom_texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 4)] bloom_sampler: &Sampler, - in_uv: Vec2, - #[spirv(flat)] in_bloom_strength_id: Id, - frag_color: &mut Vec4, -) { - let bloom_strength = slab.read(in_bloom_strength_id); - let hdr = hdr_texture.sample(*hdr_sampler, in_uv).xyz(); - let bloom = bloom_texture.sample(*bloom_sampler, in_uv).xyz(); - let color = hdr.lerp(bloom, bloom_strength); - *frag_color = color.extend(1.0) -} diff --git a/crates/renderling/src/bvol.rs b/crates/renderling/src/bvol.rs index 40f580da..14fa5742 100644 --- a/crates/renderling/src/bvol.rs +++ b/crates/renderling/src/bvol.rs @@ -187,13 +187,14 @@ impl Aabb { let positions = crate::math::convex_mesh([p0, p1, p2, p3, p4, p5, p6, p7]); positions - .chunks_exact(3) + .as_chunks::<3>() + .0 + .iter() .flat_map(|chunk| match chunk { [a, b, c] => { let n = crate::math::triangle_face_normal(*a, *b, *c); [(*a, n), (*b, n), (*c, n)] } - _ => unreachable!(), }) .collect() } @@ -299,13 +300,14 @@ impl Frustum { let p6 = frb; let p7 = flb; crate::math::convex_mesh([p0, p1, p2, p3, p4, p5, p6, p7]) - .chunks_exact(3) + .as_chunks::<3>() + .0 + .iter() .flat_map(|chunk| match chunk { [a, b, c] => { let n = crate::math::triangle_face_normal(*a, *b, *c); [(*a, n), (*b, n), (*c, n)] } - _ => unreachable!(), }) .collect() } @@ -404,13 +406,14 @@ impl BoundingBox { // Attach per-triangle face normals. let vertices: Vec<(Vec3, Vec3)> = positions - .chunks_exact(3) + .as_chunks::<3>() + .0 + .iter() .flat_map(|chunk| match chunk { [a, b, c] => { let n = crate::math::triangle_face_normal(*a, *b, *c); [(*a, n), (*b, n), (*c, n)] } - _ => unreachable!(), }) .collect(); @@ -747,7 +750,7 @@ mod test { let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); let img = frame.read_image().block().unwrap(); - img_diff::save(&format!("bvol/ortho_lighting_{label}.png"), img.clone()); + img_diff::save(format!("bvol/ortho_lighting_{label}.png"), img.clone()); let bright = img .pixels() .filter(|p| p.0[0] > 10 || p.0[1] > 10 || p.0[2] > 10) diff --git a/crates/renderling/src/compositor.rs b/crates/renderling/src/compositor.rs index 34d10e07..d8f87b14 100644 --- a/crates/renderling/src/compositor.rs +++ b/crates/renderling/src/compositor.rs @@ -3,39 +3,45 @@ //! This is used by the `renderling-ui` crate to overlay MSAA-resolved UI //! content onto a 3D scene without overwriting existing framebuffer content. -use glam::{Vec2, Vec4}; -use spirv_std::{image::Image2d, spirv, Sampler}; +#[wgsl_rs::wgsl] +pub mod shader { + //! Kernels for compositor for alpha-blending a source texture onto a target + //! framebuffer. + use crate::shader::constants::*; + use wgsl_rs::std::*; -/// Fullscreen quad vertex shader for compositing. -/// -/// Generates 6 vertices (two triangles) covering the full clip-space quad -/// and passes through UV coordinates for texture sampling. -#[spirv(vertex)] -pub fn compositor_vertex( - #[spirv(vertex_index)] vertex_id: u32, - out_uv: &mut Vec2, - #[spirv(position)] out_pos: &mut Vec4, -) { - let i = vertex_id as usize; - *out_uv = crate::math::UV_COORD_QUAD_CCW[i]; - *out_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i]; -} + pub struct CompositorInterStage { + #[location(0)] + uv: Vec2f, + #[builtin(position)] + #[allow(dead_code)] + clip_pos: Vec4f, + } + /// Fullscreen quad vertex shader for compositing. + /// + /// Generates 6 vertices (two triangles) covering the full clip-space quad + /// and passes through UV coordinates for texture sampling. + #[vertex] + pub fn compositor_vertex(#[builtin(vertex_index)] vertex_id: u32) -> CompositorInterStage { + let i = vertex_id as usize; + CompositorInterStage { + uv: UV_COORD_QUAD_CCW[i], + clip_pos: CLIP_SPACE_COORD_QUAD_CCW[i], + } + } + + texture!(group(0), binding(0), TEXTURE: Texture2D); + sampler!(group(0), binding(1), SAMPLER: Sampler); -/// Passthrough fragment shader for compositing. -/// -/// Samples the source texture at the given UV and outputs the color. -/// Alpha blending is handled by the pipeline's blend state, not the shader. -#[spirv(fragment)] -pub fn compositor_fragment( - #[spirv(descriptor_set = 0, binding = 0)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 1)] sampler: &Sampler, - in_uv: Vec2, - frag_color: &mut Vec4, -) { - *frag_color = texture.sample(*sampler, in_uv); + /// Passthrough fragment shader for compositing. + /// + /// Samples the source texture at the given UV and outputs the color. + /// Alpha blending is handled by the pipeline's blend state, not the shader. + #[fragment] + pub fn compositor_fragment(input: CompositorInterStage) -> Vec4f { + texture_sample(TEXTURE, SAMPLER, input.uv) + } } -#[cfg(not(target_arch = "spirv"))] mod cpu; -#[cfg(not(target_arch = "spirv"))] pub use cpu::*; diff --git a/crates/renderling/src/compositor/cpu.rs b/crates/renderling/src/compositor/cpu.rs index b04c65bb..c24b5f10 100644 --- a/crates/renderling/src/compositor/cpu.rs +++ b/crates/renderling/src/compositor/cpu.rs @@ -1,4 +1,9 @@ //! CPU-side compositor for alpha-blending a source texture onto a target. +use std::sync::{Arc, RwLock}; + +use wgsl_rs_linkage_wgpu::{analyze_wgsl_module, WgpuLinkage}; + +use super::shader::WGSL_SOURCE; /// Alpha-blends a source texture onto a target framebuffer using a /// fullscreen quad. @@ -14,64 +19,25 @@ /// ``` pub struct Compositor { pipeline: wgpu::RenderPipeline, - bindgroup_layout: wgpu::BindGroupLayout, sampler: wgpu::Sampler, + linkage: Arc>, } impl Compositor { /// Create a new compositor targeting the given texture format. pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self { - let sampler = device.create_sampler(&wgpu::SamplerDescriptor { - label: Some("compositor"), - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - ..Default::default() - }); - - let bindgroup_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("compositor"), - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - }); - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("compositor"), - bind_group_layouts: &[Some(&bindgroup_layout)], - immediate_size: 0, - }); - - let vertex = crate::linkage::compositor_vertex::linkage(device); - let fragment = crate::linkage::compositor_fragment::linkage(device); + let mut linkage = analyze_wgsl_module(&WGSL_SOURCE).expect("compositor wgsl analysis"); + let wgsl_module = linkage.shader_module(device); + let pipeline_layout = linkage.pipeline_layout(device, Some("compositor")); let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { multiview_mask: None, label: Some("compositor"), layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &vertex.module, - entry_point: Some(vertex.entry_point), - compilation_options: wgpu::PipelineCompilationOptions::default(), - buffers: &[], - }, + vertex: linkage + .vertex_entry("compositor_vertex") + .expect("compositor_vertex entry present") + .vertex_state(&wgsl_module), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, @@ -84,8 +50,8 @@ impl Compositor { depth_stencil: None, multisample: wgpu::MultisampleState::default(), fragment: Some(wgpu::FragmentState { - module: &fragment.module, - entry_point: Some(fragment.entry_point), + module: &wgsl_module, + entry_point: Some("compositor_fragment"), compilation_options: wgpu::PipelineCompilationOptions::default(), targets: &[Some(wgpu::ColorTargetState { format, @@ -96,10 +62,20 @@ impl Compositor { cache: None, }); + let sampler = device.create_sampler(&wgpu::SamplerDescriptor { + label: Some("compositor"), + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + ..Default::default() + }); + Self { pipeline, - bindgroup_layout, sampler, + linkage: Arc::new(RwLock::new(linkage)), } } @@ -115,20 +91,19 @@ impl Compositor { source: &wgpu::TextureView, target: &wgpu::TextureView, ) { - let bindgroup = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("compositor"), - layout: &self.bindgroup_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(source), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&self.sampler), - }, - ], - }); + let bindgroup = { + let mut linkage = self.linkage.write().expect("compositor linkage write"); + linkage + .create_bind_group_named( + 0, + device, + &[ + ("TEXTURE", wgpu::BindingResource::TextureView(source)), + ("SAMPLER", wgpu::BindingResource::Sampler(&self.sampler)), + ], + ) + .expect("compositor bind group") + }; let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("compositor"), diff --git a/crates/renderling/src/context.rs b/crates/renderling/src/context.rs index ee0b0985..c3dccb75 100644 --- a/crates/renderling/src/context.rs +++ b/crates/renderling/src/context.rs @@ -395,6 +395,14 @@ impl Context { } } + /// Temporary method to convert the internally stored Rust-GPU craballoc + /// WgpuRuntime into a wgsl-rs craballoc WgpuRuntime. + // TODO: Remove this after the wgsl-rs port is done. + pub(crate) fn wgsl_rs_runtime(&self) -> craballoc_wgsl::runtime::WgpuRuntime { + let WgpuRuntime { device, queue } = self.runtime.clone(); + craballoc_wgsl::runtime::WgpuRuntime { device, queue } + } + /// Attempts to create a new headless `Context` with the specified width, /// height, and backends. pub async fn try_new_headless( diff --git a/crates/renderling/src/gltf.rs b/crates/renderling/src/gltf.rs index b7406146..11e8c07a 100644 --- a/crates/renderling/src/gltf.rs +++ b/crates/renderling/src/gltf.rs @@ -278,6 +278,7 @@ impl Material { builder.set_emissive_tex_coord(emissive_tex.tex_coord()); } } + builder.set_emissive_factor(Vec3::from(material.emissive_factor())); builder.set_emissive_strength_multiplier(material.emissive_strength().unwrap_or(1.0)); }; Ok(builder) @@ -1236,7 +1237,7 @@ where Ct: IsContainer = Array>, { pub fn renderlets_iter(&self) -> impl Iterator { - self.primitives.iter().flat_map(|(_, rs)| rs.iter()) + self.primitives.values().flat_map(|rs| rs.iter()) } fn collect_nodes_recursive<'a>(&'a self, node_index: usize, nodes: &mut Vec<&'a GltfNode>) { diff --git a/crates/renderling/src/internal/cpu.rs b/crates/renderling/src/internal/cpu.rs index 50539374..18bb4e9b 100644 --- a/crates/renderling/src/internal/cpu.rs +++ b/crates/renderling/src/internal/cpu.rs @@ -88,12 +88,12 @@ pub fn new_instance(backends: Option) -> wgpu::Instance { ); // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU let backends = backends.unwrap_or(wgpu::Backends::PRIMARY); - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + + + wgpu::Instance::new(wgpu::InstanceDescriptor { backends, ..wgpu::InstanceDescriptor::new_without_display_handle() - }); - - instance + }) } /// Create a new suite of `wgpu` machinery using a window or canvas. diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 29fb2438..0613d412 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -238,6 +238,8 @@ pub mod tutorial; pub mod types; pub mod ui_slab; +pub mod shader; + pub extern crate glam; // TODO: document the crate's feature flags here. diff --git a/crates/renderling/src/linkage.rs b/crates/renderling/src/linkage.rs index ca1b3ef5..193fb820 100644 --- a/crates/renderling/src/linkage.rs +++ b/crates/renderling/src/linkage.rs @@ -9,14 +9,8 @@ use std::sync::Arc; pub mod atlas_blit_fragment; pub mod atlas_blit_vertex; -pub mod bloom_downsample_fragment; -pub mod bloom_mix_fragment; -pub mod bloom_upsample_fragment; -pub mod bloom_vertex; pub mod brdf_lut_convolution_fragment; pub mod brdf_lut_convolution_vertex; -pub mod compositor_fragment; -pub mod compositor_vertex; pub mod compute_copy_depth_to_pyramid; pub mod compute_copy_depth_to_pyramid_multisampled; pub mod compute_culling; @@ -43,8 +37,6 @@ pub mod skybox_cubemap_fragment; pub mod skybox_cubemap_vertex; pub mod skybox_equirectangular_fragment; pub mod skybox_vertex; -pub mod tonemapping_fragment; -pub mod tonemapping_vertex; // 2D/UI shaders pub mod ui_fragment; diff --git a/crates/renderling/src/linkage/bloom_downsample_fragment.rs b/crates/renderling/src/linkage/bloom_downsample_fragment.rs deleted file mode 100644 index 6960adc6..00000000 --- a/crates/renderling/src/linkage/bloom_downsample_fragment.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![allow(dead_code)] -//! Automatically generated by Renderling's `build.rs`. -use crate::linkage::ShaderLinkage; -#[cfg(not(target_arch = "wasm32"))] -mod target { - pub const ENTRY_POINT: &str = "bloom::shader::bloom_downsample_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-shader-bloom_downsample_fragment.spv") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!( - "creating native linkage for {}", - "bloom_downsample_fragment" - ); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -#[cfg(target_arch = "wasm32")] -mod target { - pub const ENTRY_POINT: &str = "bloomshaderbloom_downsample_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-shader-bloom_downsample_fragment.wgsl") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "bloom_downsample_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -pub fn linkage(device: &wgpu::Device) -> ShaderLinkage { - target::linkage(device) -} diff --git a/crates/renderling/src/linkage/bloom_mix_fragment.rs b/crates/renderling/src/linkage/bloom_mix_fragment.rs deleted file mode 100644 index fe362a45..00000000 --- a/crates/renderling/src/linkage/bloom_mix_fragment.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![allow(dead_code)] -//! Automatically generated by Renderling's `build.rs`. -use crate::linkage::ShaderLinkage; -#[cfg(not(target_arch = "wasm32"))] -mod target { - pub const ENTRY_POINT: &str = "bloom::shader::bloom_mix_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-shader-bloom_mix_fragment.spv") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "bloom_mix_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -#[cfg(target_arch = "wasm32")] -mod target { - pub const ENTRY_POINT: &str = "bloomshaderbloom_mix_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-shader-bloom_mix_fragment.wgsl") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "bloom_mix_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -pub fn linkage(device: &wgpu::Device) -> ShaderLinkage { - target::linkage(device) -} diff --git a/crates/renderling/src/linkage/bloom_upsample_fragment.rs b/crates/renderling/src/linkage/bloom_upsample_fragment.rs deleted file mode 100644 index 74fcc4b8..00000000 --- a/crates/renderling/src/linkage/bloom_upsample_fragment.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![allow(dead_code)] -//! Automatically generated by Renderling's `build.rs`. -use crate::linkage::ShaderLinkage; -#[cfg(not(target_arch = "wasm32"))] -mod target { - pub const ENTRY_POINT: &str = "bloom::shader::bloom_upsample_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-shader-bloom_upsample_fragment.spv") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "bloom_upsample_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -#[cfg(target_arch = "wasm32")] -mod target { - pub const ENTRY_POINT: &str = "bloomshaderbloom_upsample_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-shader-bloom_upsample_fragment.wgsl") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "bloom_upsample_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -pub fn linkage(device: &wgpu::Device) -> ShaderLinkage { - target::linkage(device) -} diff --git a/crates/renderling/src/linkage/bloom_vertex.rs b/crates/renderling/src/linkage/bloom_vertex.rs deleted file mode 100644 index 532f4dcd..00000000 --- a/crates/renderling/src/linkage/bloom_vertex.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![allow(dead_code)] -//! Automatically generated by Renderling's `build.rs`. -use crate::linkage::ShaderLinkage; -#[cfg(not(target_arch = "wasm32"))] -mod target { - pub const ENTRY_POINT: &str = "bloom::shader::bloom_vertex"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-shader-bloom_vertex.spv") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "bloom_vertex"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -#[cfg(target_arch = "wasm32")] -mod target { - pub const ENTRY_POINT: &str = "bloomshaderbloom_vertex"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-shader-bloom_vertex.wgsl") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "bloom_vertex"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -pub fn linkage(device: &wgpu::Device) -> ShaderLinkage { - target::linkage(device) -} diff --git a/crates/renderling/src/linkage/compositor_fragment.rs b/crates/renderling/src/linkage/compositor_fragment.rs deleted file mode 100644 index 095d2690..00000000 --- a/crates/renderling/src/linkage/compositor_fragment.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![allow(dead_code)] -//! Automatically generated by Renderling's `build.rs`. -use crate::linkage::ShaderLinkage; -#[cfg(not(target_arch = "wasm32"))] -mod target { - pub const ENTRY_POINT: &str = "compositor::compositor_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/compositor-compositor_fragment.spv") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "compositor_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -#[cfg(target_arch = "wasm32")] -mod target { - pub const ENTRY_POINT: &str = "compositorcompositor_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/compositor-compositor_fragment.wgsl") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "compositor_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -pub fn linkage(device: &wgpu::Device) -> ShaderLinkage { - target::linkage(device) -} diff --git a/crates/renderling/src/linkage/compositor_vertex.rs b/crates/renderling/src/linkage/compositor_vertex.rs deleted file mode 100644 index e1d399d1..00000000 --- a/crates/renderling/src/linkage/compositor_vertex.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![allow(dead_code)] -//! Automatically generated by Renderling's `build.rs`. -use crate::linkage::ShaderLinkage; -#[cfg(not(target_arch = "wasm32"))] -mod target { - pub const ENTRY_POINT: &str = "compositor::compositor_vertex"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/compositor-compositor_vertex.spv") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "compositor_vertex"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -#[cfg(target_arch = "wasm32")] -mod target { - pub const ENTRY_POINT: &str = "compositorcompositor_vertex"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/compositor-compositor_vertex.wgsl") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "compositor_vertex"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -pub fn linkage(device: &wgpu::Device) -> ShaderLinkage { - target::linkage(device) -} diff --git a/crates/renderling/src/linkage/tonemapping_fragment.rs b/crates/renderling/src/linkage/tonemapping_fragment.rs deleted file mode 100644 index 396ca926..00000000 --- a/crates/renderling/src/linkage/tonemapping_fragment.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![allow(dead_code)] -//! Automatically generated by Renderling's `build.rs`. -use crate::linkage::ShaderLinkage; -#[cfg(not(target_arch = "wasm32"))] -mod target { - pub const ENTRY_POINT: &str = "tonemapping::tonemapping_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/tonemapping-tonemapping_fragment.spv") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "tonemapping_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -#[cfg(target_arch = "wasm32")] -mod target { - pub const ENTRY_POINT: &str = "tonemappingtonemapping_fragment"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/tonemapping-tonemapping_fragment.wgsl") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "tonemapping_fragment"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -pub fn linkage(device: &wgpu::Device) -> ShaderLinkage { - target::linkage(device) -} diff --git a/crates/renderling/src/linkage/tonemapping_vertex.rs b/crates/renderling/src/linkage/tonemapping_vertex.rs deleted file mode 100644 index 0ac39bb4..00000000 --- a/crates/renderling/src/linkage/tonemapping_vertex.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![allow(dead_code)] -//! Automatically generated by Renderling's `build.rs`. -use crate::linkage::ShaderLinkage; -#[cfg(not(target_arch = "wasm32"))] -mod target { - pub const ENTRY_POINT: &str = "tonemapping::tonemapping_vertex"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/tonemapping-tonemapping_vertex.spv") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "tonemapping_vertex"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -#[cfg(target_arch = "wasm32")] -mod target { - pub const ENTRY_POINT: &str = "tonemappingtonemapping_vertex"; - pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/tonemapping-tonemapping_vertex.wgsl") - } - pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "tonemapping_vertex"); - super::ShaderLinkage { - entry_point: ENTRY_POINT, - module: device.create_shader_module(descriptor()).into(), - } - } -} -pub fn linkage(device: &wgpu::Device) -> ShaderLinkage { - target::linkage(device) -} diff --git a/crates/renderling/src/math.rs b/crates/renderling/src/math.rs index 6dca4181..06649aab 100644 --- a/crates/renderling/src/math.rs +++ b/crates/renderling/src/math.rs @@ -635,7 +635,9 @@ pub const UNIT_INDICES: [usize; 36] = [ #[cfg(not(target_arch = "spirv"))] pub fn unit_cube() -> Vec<(Vec3, Vec3)> { UNIT_INDICES - .chunks_exact(3) + .as_chunks::<3>() + .0 + .iter() .flat_map(|chunk| match chunk { [a, b, c] => { let a = UNIT_POINTS[*a]; @@ -644,7 +646,6 @@ pub fn unit_cube() -> Vec<(Vec3, Vec3)> { let n = triangle_face_normal(a, b, c); [(a, n), (b, n), (c, n)] } - _ => unreachable!(), }) .collect::>() } diff --git a/crates/renderling/src/pbr/brdf/cpu.rs b/crates/renderling/src/pbr/brdf/cpu.rs index e7fd096f..2a04c64c 100644 --- a/crates/renderling/src/pbr/brdf/cpu.rs +++ b/crates/renderling/src/pbr/brdf/cpu.rs @@ -130,10 +130,11 @@ mod test { .collect(); assert_eq!(512 * 512 * 2, pixels.len()); let pixels: Vec = pixels - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .flat_map(|pixel| match pixel { [r, g] => [*r, *g, 0.0, 1.0], - _ => unreachable!(), }) .collect(); diff --git a/crates/renderling/src/shader.rs b/crates/renderling/src/shader.rs new file mode 100644 index 00000000..36f94db5 --- /dev/null +++ b/crates/renderling/src/shader.rs @@ -0,0 +1,36 @@ +//! WGSL shader helpers. + +#[wgsl_rs::wgsl] +pub mod constants { + //! Common constants. + + use wgsl_rs::std::*; + + pub const TOP_LEFT_2D: Vec2f = vec2f(0.0, 0.0); + pub const TOP_RIGHT_2D: Vec2f = vec2f(1.0, 0.0); + pub const BOTTOM_LEFT_2D: Vec2f = vec2f(0.0, 1.0); + pub const BOTTOM_RIGHT_2D: Vec2f = vec2f(1.0, 1.0); + + pub const UV_COORD_QUAD_CCW: [Vec2f; 6] = [ + BOTTOM_LEFT_2D, + BOTTOM_RIGHT_2D, + TOP_RIGHT_2D, + TOP_RIGHT_2D, + TOP_LEFT_2D, + BOTTOM_LEFT_2D, + ]; + + pub const CLIP_SPACE_COORD_QUAD_CCW_TL: Vec4f = vec4f(-1.0, 1.0, 0.5, 1.0); + pub const CLIP_SPACE_COORD_QUAD_CCW_BL: Vec4f = vec4f(-1.0, -1.0, 0.5, 1.0); + pub const CLIP_SPACE_COORD_QUAD_CCW_TR: Vec4f = vec4f(1.0, 1.0, 0.5, 1.0); + pub const CLIP_SPACE_COORD_QUAD_CCW_BR: Vec4f = vec4f(1.0, -1.0, 0.5, 1.0); + + pub const CLIP_SPACE_COORD_QUAD_CCW: [Vec4f; 6] = [ + CLIP_SPACE_COORD_QUAD_CCW_BL, + CLIP_SPACE_COORD_QUAD_CCW_BR, + CLIP_SPACE_COORD_QUAD_CCW_TR, + CLIP_SPACE_COORD_QUAD_CCW_TR, + CLIP_SPACE_COORD_QUAD_CCW_TL, + CLIP_SPACE_COORD_QUAD_CCW_BL, + ]; +} diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 6a63ea11..7dd33108 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -14,7 +14,7 @@ use crate::gltf::GltfDocument; use crate::{ atlas::{AtlasError, AtlasImage, AtlasImageError, AtlasTexture}, bindgroup::ManagedBindGroup, - bloom::Bloom, + bloom::wgsl::Bloom, camera::{shader::CameraDescriptor, Camera}, debug::DebugOverlay, draw::DrawCalls, @@ -31,7 +31,7 @@ use crate::{ primitive::Primitive, skybox::{Skybox, SkyboxRenderPipeline}, texture::{DepthTexture, Texture}, - tonemapping::Tonemapping, + tonemapping::wgsl::Tonemapping, transform::{NestedTransform, Transform}, }; @@ -414,8 +414,8 @@ pub struct Stage { pub(crate) clear_depth_attachments: Arc, pub(crate) bloom: Bloom, - pub(crate) tonemapping: Tonemapping, + pub(crate) debug_overlay: DebugOverlay, pub(crate) background_color: Arc>, @@ -940,6 +940,14 @@ impl Stage { self.as_ref() } + /// Temporary method to convert the internally stored Rust-GPU craballoc + /// WgpuRuntime into a wgsl-rs craballoc WgpuRuntime. + // TODO: Remove this after the wgsl-rs port is done. + pub(crate) fn wgsl_rs_runtime(&self) -> craballoc_wgsl::runtime::WgpuRuntime { + let WgpuRuntime { device, queue } = self.runtime().clone(); + craballoc_wgsl::runtime::WgpuRuntime { device, queue } + } + pub fn device(&self) -> &wgpu::Device { &self.runtime().device } @@ -966,8 +974,8 @@ impl Stage { let num_u32s = self.geometry.slab_allocator().len() + self.lighting.slab_allocator().len() + self.materials.slab_allocator().len() - + self.bloom.slab_allocator().len() - + self.tonemapping.slab_allocator().len() + + self.bloom.arena().capacity() as usize + + self.tonemapping.arena().length() as usize + self .draw_calls .read() @@ -1201,9 +1209,12 @@ impl Stage { let msaa_render_target = Default::default(); // UNWRAP: safe because no other references at this point (created // above^) - let bloom = Bloom::new(ctx, &hdr_texture.read().expect("hdr_texture read")); + let bloom = Bloom::new( + ctx.wgsl_rs_runtime(), + &hdr_texture.read().expect("hdr_texture read"), + ); let tonemapping = Tonemapping::new( - runtime, + ctx.wgsl_rs_runtime(), ctx.get_render_target().format().add_srgb_suffix(), &bloom.get_mix_texture(), ); @@ -1504,9 +1515,9 @@ impl Stage { sample_count, Some("stage-depth"), ); - self.bloom.set_hdr_texture(self.runtime(), &hdr_texture); - self.tonemapping - .set_hdr_texture(self.device(), &hdr_texture); + self.bloom + .set_hdr_texture(self.wgsl_rs_runtime(), &hdr_texture); + self.tonemapping.set_hdr_texture(&hdr_texture); *self.hdr_texture.write().expect("hdr_texture write") = hdr_texture; let _ = self @@ -1688,7 +1699,7 @@ impl Stage { // then render bloom if self.has_bloom.load(Ordering::Relaxed) { - self.bloom.bloom(self.device(), self.queue()); + self.bloom.bloom(self.wgsl_rs_runtime()); } else { // copy the input hdr texture to the bloom mix texture let mut encoder = @@ -1720,7 +1731,7 @@ impl Stage { } // then render tonemapping - self.tonemapping.render(self.device(), self.queue(), view); + self.tonemapping.render(self.wgsl_rs_runtime(), view); // then render the debug overlay if self.has_debug_overlay.load(Ordering::Relaxed) { diff --git a/crates/renderling/src/texture.rs b/crates/renderling/src/texture.rs index c0433b7c..1449cfbd 100644 --- a/crates/renderling/src/texture.rs +++ b/crates/renderling/src/texture.rs @@ -284,6 +284,82 @@ impl Texture { } } + /// Create a new texture. + #[allow(clippy::too_many_arguments)] + pub fn new_with_wgsl( + runtime: impl AsRef, + label: Option<&str>, + usage: Option, + sampler: Option, + format: wgpu::TextureFormat, + color_channels: u32, + color_channel_bytes: u32, + width: u32, + height: u32, + mip_level_count: u32, + data: &[u8], + ) -> Self { + let runtime = runtime.as_ref(); + let device = &runtime.device; + let queue = &runtime.queue; + let mip_level_count = 1.max(mip_level_count); + let size = wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }; + + let texture = device.create_texture(&wgpu::TextureDescriptor { + label, + size, + mip_level_count, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format, + usage: usage + .unwrap_or(wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST), + view_formats: &[], + }); + + if !data.is_empty() { + queue.write_texture( + wgpu::TexelCopyTextureInfo { + texture: &texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + aspect: wgpu::TextureAspect::All, + }, + data, + wgpu::TexelCopyBufferLayout { + offset: 0, + bytes_per_row: Some(color_channels * color_channel_bytes * width), + rows_per_image: None, + }, + size, + ); + } + + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + let sampler = sampler.unwrap_or_else(|| { + device.create_sampler(&wgpu::SamplerDescriptor { + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::MipmapFilterMode::Linear, + ..Default::default() + }) + }); + + Texture { + texture: Arc::new(texture), + view: Arc::new(view), + sampler: Arc::new(sampler), + id: get_next_texture_id(), + } + } + /// Create a new texture. /// /// This defaults the format to `Rgba8UnormSrgb` and assumes a pixel is 1 diff --git a/crates/renderling/src/tonemapping.rs b/crates/renderling/src/tonemapping.rs index 71fe7424..26ff6025 100644 --- a/crates/renderling/src/tonemapping.rs +++ b/crates/renderling/src/tonemapping.rs @@ -4,162 +4,506 @@ //! * //! * -use crabslab::{Slab, SlabItem}; -use glam::{mat3, Mat3, Vec2, Vec3, Vec4, Vec4Swizzles}; -use spirv_std::{image::Image2d, spirv, Sampler}; - -#[cfg(not(target_arch = "spirv"))] -mod cpu; -#[cfg(not(target_arch = "spirv"))] -pub use cpu::*; - -const GAMMA: f32 = 2.2; -const INV_GAMMA: f32 = 1.0 / GAMMA; - -/// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT -const ACESINPUT_MAT: Mat3 = mat3( - Vec3::new(0.59719, 0.07600, 0.02840), - Vec3::new(0.35458, 0.90834, 0.13383), - Vec3::new(0.04823, 0.01566, 0.83777), -); - -/// ODT_SAT => XYZ => D60_2_D65 => sRGB -const ACESOUTPUT_MAT: Mat3 = mat3( - Vec3::new(1.60475, -0.10208, -0.00327), - Vec3::new(-0.53108, 1.10813, -0.07276), - Vec3::new(-0.07367, -0.00605, 1.07602), -); - -/// Linear to sRGB approximation. -/// See -pub fn linear_to_srgb(color: Vec3) -> Vec3 { - color.powf(INV_GAMMA) -} +#[wgsl_rs::wgsl(extensions = [crabslab_wgsl::SlabItemExt])] +pub mod shader { + //! Tonemapping shader module. + use crabslab_wgsl::*; + use wgsl_rs::std::*; -/// sRGB to linear approximation. -/// See -pub fn srgb_to_linear(srgb_in: Vec3) -> Vec3 { - srgb_in.powf(GAMMA) -} + const GAMMA: f32 = 2.2; + const INV_GAMMA: f32 = 1.0 / GAMMA; -/// sRGB to linear approximation. -/// See -pub fn srgba_to_linear(srgb_in: Vec4) -> Vec4 { - srgb_to_linear(srgb_in.xyz()).extend(srgb_in.w) -} + /// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT + const ACESINPUT_MAT: Mat3f = mat3x3f( + vec3f(0.59719, 0.07600, 0.02840), + vec3f(0.35458, 0.90834, 0.13383), + vec3f(0.04823, 0.01566, 0.83777), + ); -/// ACES tone map (faster approximation) -/// see: -pub fn tone_map_aces_narkowicz(color: Vec3) -> Vec3 { - const A: f32 = 2.51; - const B: f32 = 0.03; - const C: f32 = 2.43; - const D: f32 = 0.59; - const E: f32 = 0.14; - let c = (color * (A * color + B)) / (color * (C * color + D) + E); - c.clamp(Vec3::ZERO, Vec3::ONE) -} + /// ODT_SAT => XYZ => D60_2_D65 => sRGB + const ACESOUTPUT_MAT: Mat3f = mat3x3f( + vec3f(1.60475, -0.10208, -0.00327), + vec3f(-0.53108, 1.10813, -0.07276), + vec3f(-0.07367, -0.00605, 1.07602), + ); -/// ACES filmic tone map approximation -/// see -fn rrt_and_odtfit(color: Vec3) -> Vec3 { - let a: Vec3 = color * (color + 0.0245786) - 0.000090537; - let b: Vec3 = color * (0.983729 * color + 0.432951) + 0.238081; - a / b -} + /// Linear to sRGB approximation. + /// See + pub fn linear_to_srgb(color: Vec3f) -> Vec3f { + let inv_gamma = vec3f(INV_GAMMA, INV_GAMMA, INV_GAMMA); + pow(color, inv_gamma) + } -pub fn tone_map_aces_hill(mut color: Vec3) -> Vec3 { - color = ACESINPUT_MAT * color; - // Apply RRT and ODT - color = rrt_and_odtfit(color); - color = ACESOUTPUT_MAT * color; - // Clamp to [0, 1] - color = color.clamp(Vec3::ZERO, Vec3::ONE); + /// sRGB to linear approximation. + /// See + pub fn srgb_to_linear(srgb_in: Vec3f) -> Vec3f { + let gamma = vec3f(GAMMA, GAMMA, GAMMA); + pow(srgb_in, gamma) + } - color -} + /// sRGB to linear approximation. + /// See + pub fn srgba_to_linear(srgb_in: Vec4f) -> Vec4f { + let lin = srgb_to_linear(srgb_in.xyz()); + vec4f(lin.x, lin.y, lin.z, srgb_in.w) + } -pub fn tone_map_reinhard(color: Vec3) -> Vec3 { - color / (color + Vec3::ONE) -} + /// ACES tone map (faster approximation) + /// see: + pub fn tone_map_aces_narkowicz(color: Vec3f) -> Vec3f { + const A: f32 = 2.51; + const B: f32 = 0.03; + const C: f32 = 2.43; + const D: f32 = 0.59; + const E: f32 = 0.14; + let c = (color * (A * color + B)) / (color * (C * color + D) + E); + clamp(c, Vec3f::ZERO, Vec3f::ONE) + } -#[repr(transparent)] -#[derive(Clone, Copy, Default, PartialEq, Eq, SlabItem, core::fmt::Debug)] -pub struct Tonemap(u32); + /// ACES filmic tone map approximation + /// see + pub fn rrt_and_odtfit(color: Vec3f) -> Vec3f { + let a: Vec3f = color * (color + 0.0245786) - 0.000090537; + let b: Vec3f = color * (0.983729 * color + 0.432951) + 0.238081; + a / b + } -impl Tonemap { - pub const NONE: Self = Tonemap(0); - pub const ACES_NARKOWICZ: Self = Tonemap(1); - pub const ACES_HILL: Self = Tonemap(2); - pub const ACES_HILL_EXPOSURE_BOOST: Self = Tonemap(3); - pub const REINHARD: Self = Tonemap(4); -} + pub fn tone_map_aces_hill(color_in: Vec3f) -> Vec3f { + let mut color = color_in; + color = ACESINPUT_MAT * color; + // Apply RRT and ODT + color = rrt_and_odtfit(color); + color = ACESOUTPUT_MAT * color; + // Clamp to [0, 1] + clamp(color, Vec3f::ZERO, Vec3f::ONE) + } -#[repr(C)] -#[derive(Clone, Copy, PartialEq, SlabItem)] -pub struct TonemapConstants { - pub tonemap: Tonemap, - pub exposure: f32, -} + pub fn tone_map_reinhard(color: Vec3f) -> Vec3f { + color / (color + Vec3f::ONE) + } + + #[derive(Clone, Copy, Default, PartialEq, Eq, Wgsl, SlabItem, core::fmt::Debug)] + #[repr(u32)] + pub enum Tonemap { + #[default] + None, + AcesNarkowicz, + AcesHill, + AcesHillExposureBoost, + Reinhard, + } -impl Default for TonemapConstants { - fn default() -> Self { - Self { - tonemap: Tonemap::NONE, - exposure: 1.0, + #[derive(Clone, Copy, PartialEq, Wgsl, SlabItem)] + pub struct TonemapConstants { + pub tonemap: Tonemap, + pub exposure: f32, + } + + impl Default for TonemapConstants { + fn default() -> Self { + Self { + tonemap: Tonemap::None, + exposure: 1.0, + } } } -} -pub fn tonemap(mut color: Vec4, slab: &[u32]) -> Vec4 { - let constants = slab.read::(0u32.into()); - color *= constants.exposure; - - match constants.tonemap { - Tonemap::ACES_NARKOWICZ => tone_map_aces_narkowicz(color.xyz()).extend(color.w), - Tonemap::ACES_HILL => tone_map_aces_hill(color.xyz()).extend(color.w), - Tonemap::ACES_HILL_EXPOSURE_BOOST => { - // boost exposure as discussed in https://github.com/mrdoob/three.js/pull/19621 - // this factor is based on the exposure correction of Krzysztof - // Narkowicz in his implemetation of ACES tone mapping - tone_map_aces_hill(color.xyz() / 0.6).extend(color.w) + storage!(group(0), binding(0), SLAB: RuntimeArray); + texture!(group(0), binding(1), TEXTURE: Texture2D); + sampler!(group(0), binding(2), SAMPLER: Sampler); + + pub fn tonemap(color_in: Vec4f) -> Vec4f { + let constants: TonemapConstants; + slab_read!(TonemapConstants, get!(SLAB), 0u32, constants); + + let mut color = color_in; + color *= constants.exposure; + + #[allow(clippy::needless_late_init)] + let toned: Vec3f; + #[wgsl_allow(non_literal_match_statement_patterns)] + match constants.tonemap { + Tonemap::AcesNarkowicz => { + toned = tone_map_aces_narkowicz(color.xyz()); + } + Tonemap::AcesHill => { + toned = tone_map_aces_hill(color.xyz()); + } + Tonemap::AcesHillExposureBoost => { + // boost exposure as discussed in https://github.com/mrdoob/three.js/pull/19621 + // this factor is based on the exposure correction of Krzysztof + // Narkowicz in his implemetation of ACES tone mapping + toned = tone_map_aces_hill(color.xyz() / 0.6); + } + Tonemap::Reinhard => { + // Use Reinhard tone mapping + toned = tone_map_reinhard(color.xyz()); + } + _ => { + toned = color.xyz(); + } } - Tonemap::REINHARD => { - // Use Reinhard tone mapping - tone_map_reinhard(color.xyz()).extend(color.w) + vec4f(toned.x, toned.y, toned.z, color.w) + } + + const TL_POS: Vec2f = vec2f(-1.0, 1.0); + const TR_POS: Vec2f = vec2f(1.0, 1.0); + const BL_POS: Vec2f = vec2f(-1.0, -1.0); + const BR_POS: Vec2f = vec2f(1.0, -1.0); + + const TL_UV: Vec2f = vec2f(0.0, 0.0); + const TR_UV: Vec2f = vec2f(1.0, 0.0); + const BL_UV: Vec2f = vec2f(0.0, 1.0); + const BR_UV: Vec2f = vec2f(1.0, 1.0); + + const QUAD_2D_POS: [Vec2f; 6] = [TL_POS, BL_POS, BR_POS, TL_POS, BR_POS, TR_POS]; + const QUAD_2D_UV: [Vec2f; 6] = [TL_UV, BL_UV, BR_UV, TL_UV, BR_UV, TR_UV]; + + pub struct TonemappingInterStage { + #[location(0)] + uv: Vec2f, + #[builtin(position)] + #[allow(dead_code)] + clip_pos: Vec4f, + } + + #[vertex] + pub fn tonemapping_vertex(#[builtin(vertex_index)] vertex_id: u32) -> TonemappingInterStage { + let pos = QUAD_2D_POS[vertex_id as usize]; + TonemappingInterStage { + uv: QUAD_2D_UV[vertex_id as usize], + clip_pos: vec4f(pos.x, pos.y, 0.0, 1.0), } - _ => color, + } + + #[fragment] + pub fn tonemapping_fragment(input: TonemappingInterStage) -> Vec4f { + let color = texture_sample(TEXTURE, SAMPLER, input.uv); + tonemap(color) } } -const QUAD_2D_POINTS: [(Vec2, Vec2); 6] = { - let tl = (Vec2::new(-1.0, 1.0), Vec2::new(0.0, 0.0)); - let tr = (Vec2::new(1.0, 1.0), Vec2::new(1.0, 0.0)); - let bl = (Vec2::new(-1.0, -1.0), Vec2::new(0.0, 1.0)); - let br = (Vec2::new(1.0, -1.0), Vec2::new(1.0, 1.0)); - [tl, bl, br, tl, br, tr] -}; - -#[spirv(vertex)] -pub fn tonemapping_vertex( - #[spirv(vertex_index)] vertex_id: u32, - out_uv: &mut glam::Vec2, - #[spirv(position)] gl_pos: &mut glam::Vec4, -) { - let (pos, uv) = QUAD_2D_POINTS[vertex_id as usize]; - *out_uv = uv; - *gl_pos = pos.extend(0.0).extend(1.0); +pub mod wgsl { + //! CPU side + //! + //! The wgsl-rs backed tonemapping runner: drop-in counterpart of the + //! legacy CPU-side `Tonemapping`, built on the craballoc_wgsl runtime + //! and the ported WGSL module. + use std::sync::{Arc, RwLock}; + + use craballoc_wgsl::{ + arena::{Arena, Value}, + runtime::WgpuRuntime, + }; + use wgsl_rs_linkage_wgpu::{analyze_wgsl_module, WgpuLinkage}; + + use crate::texture::Texture; + + use super::shader::{TonemapConstants, WGSL_SOURCE}; + + /// Conducts HDR tone mapping with the wgsl-rs shader module. + /// + /// Writes the HDR surface texture to the (most likely) sRGB window + /// surface. Clones of [`Tonemapping`] all reference the same internal + /// data. + #[derive(Clone)] + pub struct Tonemapping { + arena: Arena, + config: Value, + hdr_texture: Arc>, + pipeline: Arc, + linkage: Arc>, + } + + impl Tonemapping { + pub fn new( + runtime: impl AsRef, + frame_texture_format: wgpu::TextureFormat, + hdr_texture: &Texture, + ) -> Self { + let runtime = runtime.as_ref(); + let arena = Arena::new(runtime, "tonemapping-slab", None); + // The WGSL module reads the constants from slab offset zero, so + // the config must be the first value in the arena. + let config = arena.new_value(TonemapConstants::default()); + + let mut linkage = analyze_wgsl_module(&WGSL_SOURCE).expect("tonemapping wgsl analysis"); + let wgsl_module = linkage.shader_module(&runtime.device); + let pipeline_layout = linkage.pipeline_layout(&runtime.device, Some("tonemapping")); + + let pipeline = runtime + .device + .create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("tonemapping"), + layout: Some(&pipeline_layout), + vertex: linkage + .vertex_entry("tonemapping_vertex") + .expect("tonemapping_vertex entry present") + .vertex_state(&wgsl_module), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: Some(wgpu::Face::Back), + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + fragment: Some(wgpu::FragmentState { + module: &wgsl_module, + entry_point: Some("tonemapping_fragment"), + targets: &[Some(wgpu::ColorTargetState { + format: frame_texture_format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::ALL, + })], + compilation_options: Default::default(), + }), + multisample: wgpu::MultisampleState::default(), + multiview_mask: None, + cache: None, + }); + + Self { + arena, + config, + hdr_texture: Arc::new(RwLock::new(hdr_texture.clone())), + pipeline: Arc::new(pipeline), + linkage: Arc::new(RwLock::new(linkage)), + } + } + + pub(crate) fn arena(&self) -> &Arena { + &self.arena + } + + pub fn set_hdr_texture(&self, hdr_texture: &Texture) { + // The bind group is rebuilt on the next render against the + // latest committed slab buffer, so only the texture changes here. + *self + .hdr_texture + .write() + .expect("tonemapping hdr_texture write") = hdr_texture.clone(); + } + + pub fn get_tonemapping_config(&self) -> TonemapConstants { + self.config.get() + } + + pub fn set_tonemapping_config(&self, config: TonemapConstants) { + self.config.set(config); + } + + /// Uploads any config mutations and renders the tonemapping pass on + /// top of `view` (load-op Load, matching the legacy pass). The bind + /// group is rebuilt each render against the latest committed slab + /// buffer, so config mutations and buffer growth are both handled. + pub fn render(&self, runtime: impl AsRef, view: &wgpu::TextureView) { + let runtime = runtime.as_ref(); + let label = Some("tonemapping render"); + let slab_buffer = self.arena.commit(); + let hdr = self.hdr_texture.read().expect("tonemapping hdr read"); + let mut linkage = self.linkage.write().expect("tonemapping linkage write"); + let bind_group = linkage + .create_bind_group_named( + 0, + &runtime.device, + &[ + ( + "SLAB", + wgpu::BindingResource::Buffer(wgpu::BufferBinding { + buffer: &slab_buffer, + offset: 0, + size: None, + }), + ), + ("TEXTURE", wgpu::BindingResource::TextureView(&hdr.view)), + ("SAMPLER", wgpu::BindingResource::Sampler(&hdr.sampler)), + ], + ) + .expect("tonemapping bind group"); + drop(linkage); + + let mut encoder = runtime + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label, + multiview_mask: None, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }, + depth_slice: None, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }); + render_pass.set_pipeline(&self.pipeline); + render_pass.set_bind_group(0, &bind_group, &[]); + render_pass.draw(0..6, 0..1); + } + + runtime.queue.submit(std::iter::once(encoder.finish())); + } + } } -#[spirv(fragment)] -pub fn tonemapping_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - in_uv: glam::Vec2, - output: &mut glam::Vec4, -) { - let color: Vec4 = texture.sample(*sampler, in_uv); - let color = tonemap(color, slab); - *output = color; +#[cfg(test)] +mod test { + use super::{ + shader::{Tonemap, TonemapConstants}, + wgsl, + }; + use crate::{context::Context, test::BlockOnFuture}; + use glam::Vec4; + + /// The A/B golden test: procedurally generate an HDR image, render it + /// through the legacy Tonemapping once per tonemap method (saving each + /// result as a golden EXR), then render through the wgsl-rs Tonemapping + /// on the same input and compare each result against its golden. + #[test] + fn golden_per_variant() { + use crate::texture::Texture; + use craballoc_wgsl::runtime::WgpuRuntime; + + let width = 128u32; + let height = 64u32; + let ctx = Context::headless(width, height).block(); + + // Procedural HDR image: a red gradient into HDR range, a vertical + // green gradient, and a 40-nit blue blob - covering dark, mid, and + // bright regions of every curve. + let device = ctx.get_device(); + let queue = ctx.get_queue(); + let hdr_texture = Texture::create_hdr_texture(device, width, height, 1); + let mut texels = vec![0u16; (width * height * 4) as usize]; + for y in 0..height { + for x in 0..width { + let i = (y * width + x) as usize; + let dx = x as f32 - width as f32 * 0.5; + let dy = y as f32 - height as f32 * 0.5; + let in_blob = dx * dx + dy * dy < 12.0 * 12.0; + let px = [ + x as f32 / width as f32 * 2.0, + y as f32 / height as f32, + if in_blob { 40.0 } else { 0.05 }, + 1.0, + ]; + for (slot, val) in px.iter().enumerate() { + texels[i * 4 + slot] = half::f16::from_f32(*val).to_bits(); + } + } + } + queue.write_texture( + wgpu::TexelCopyTextureInfo { + texture: &hdr_texture.texture, + mip_level: 0, + origin: Default::default(), + aspect: wgpu::TextureAspect::All, + }, + bytemuck::cast_slice(&texels), + wgpu::TexelCopyBufferLayout { + offset: 0, + bytes_per_row: Some(width * 4 * 2), + rows_per_image: Some(height), + }, + wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }, + ); + + let frame_format = wgpu::TextureFormat::Rgba16Float; + + let wgsl_runtime = WgpuRuntime { + device: ctx.runtime().device.clone(), + queue: ctx.runtime().queue.clone(), + }; + let new = wgsl::Tonemapping::new(&wgsl_runtime, frame_format, &hdr_texture); + + // Reads back an RGBA16Float target as an f32 image. + // Wraps the raw target and reads it back with the crate's helper. + let read_f16_target = |texture: &wgpu::Texture| { + Texture::from_wgpu_tex(device, texture.clone(), None, None) + .read_hdr_image(ctx.runtime()) + .block() + .expect("hdr readback ok") + }; + + let variants = [ + (Tonemap::None, "none"), + (Tonemap::AcesNarkowicz, "aces_narkowicz"), + (Tonemap::AcesHill, "aces_hill"), + (Tonemap::AcesHillExposureBoost, "aces_hill_exposure_boost"), + (Tonemap::Reinhard, "reinhard"), + ]; + + let golden_dir = renderling_build::test_img_dir().join("tonemapping"); + + for (variant, name) in variants { + // Render once through the wgsl-rs implementation. + new.set_tonemapping_config(TonemapConstants { + tonemap: variant, + exposure: 1.0, + }); + let output = device.create_texture(&wgpu::TextureDescriptor { + label: Some(format!("tonemapping-new-{name}").as_str()), + size: wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: frame_format, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, + view_formats: &[], + }); + let output_view = output.create_view(&wgpu::TextureViewDescriptor::default()); + new.render(&wgsl_runtime, &output_view); + let new_img = read_f16_target(&output); + img_diff::save(format!("tonemapping/{name}_new.exr"), new_img.clone()); + + // Load the golden back from disk and compare per pixel. Both + // renders are GPU executions of the same math, so the deltas + // should be tiny relative differences from backend float paths. + let golden = image::open(golden_dir.join(format!("{name}.exr"))) + .unwrap() + .into_rgba32f(); + let mut failures = 0; + for (i, golden_px) in golden.pixels().enumerate() { + let expected = Vec4::from(golden_px.0); + let got = Vec4::from( + new_img + .get_pixel((i % width as usize) as u32, (i / width as usize) as u32) + .0, + ); + let delta = (got - expected).abs().max_element(); + let scale = got.length().max(expected.length()).max(1.0); + if delta > 2e-3 * scale { + failures += 1; + if failures <= 4 { + let x = (i % width as usize) as u32; + let y = (i / width as usize) as u32; + println!( + "{name} gpu({x},{y}): {got:?} vs golden {expected:?} (delta {delta})" + ); + } + } + } + assert_eq!( + failures, 0, + "{name}: {failures} pixels differ beyond tolerance" + ); + } + } } diff --git a/crates/renderling/src/tonemapping/cpu.rs b/crates/renderling/src/tonemapping/cpu.rs deleted file mode 100644 index b9cb2ab0..00000000 --- a/crates/renderling/src/tonemapping/cpu.rs +++ /dev/null @@ -1,223 +0,0 @@ -//! Tonemapping. -use core::ops::Deref; -use craballoc::{ - prelude::{Hybrid, SlabAllocator}, - runtime::WgpuRuntime, -}; -use std::sync::{Arc, RwLock}; - -use crate::texture::Texture; - -use super::TonemapConstants; - -pub fn bindgroup_layout(device: &wgpu::Device, label: Option<&str>) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label, - entries: &[ - // slab - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - // hdr texture - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - // hdr sampler - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - }) -} - -pub fn create_bindgroup( - device: &wgpu::Device, - label: Option<&str>, - hdr_texture: &Texture, - slab_buffer: &wgpu::Buffer, -) -> wgpu::BindGroup { - device.create_bind_group(&wgpu::BindGroupDescriptor { - label, - layout: &bindgroup_layout(device, label), - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { - buffer: slab_buffer, - offset: 0, - size: None, - }), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::TextureView(&hdr_texture.view), - }, - wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::Sampler(&hdr_texture.sampler), - }, - ], - }) -} - -/// Conducts HDR tone mapping. -/// -/// Writes the HDR surface texture to the (most likely) sRGB window surface. -/// -/// Clones of [`Tonemapping`] all reference the same internal data. -/// -/// ## Note -/// Only available on CPU. Not Available in shaders. -#[derive(Clone)] -pub struct Tonemapping { - slab: SlabAllocator, - config: Hybrid, - hdr_texture: Arc>, - bindgroup: Arc>, - pipeline: Arc, -} - -impl Tonemapping { - pub fn new( - runtime: &WgpuRuntime, - frame_texture_format: wgpu::TextureFormat, - hdr_texture: &Texture, - ) -> Self { - let slab = SlabAllocator::new(runtime, "tonemapping-slab", wgpu::BufferUsages::empty()); - let config = slab.new_value(TonemapConstants::default()); - - let label = Some("tonemapping"); - let slab_buffer = slab.commit(); - let bindgroup = Arc::new(RwLock::new(create_bindgroup( - &runtime.device, - label, - hdr_texture, - &slab_buffer, - ))); - - let device = &runtime.device; - let vertex_linkage = crate::linkage::tonemapping_vertex::linkage(device); - let fragment_linkage = crate::linkage::tonemapping_fragment::linkage(device); - let hdr_layout = bindgroup_layout(device, label); - let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label, - bind_group_layouts: &[Some(&hdr_layout)], - immediate_size: 0, - }); - let pipeline = Arc::new( - device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - multiview_mask: None, - label, - layout: Some(&layout), - vertex: wgpu::VertexState { - module: &vertex_linkage.module, - entry_point: Some(vertex_linkage.entry_point), - buffers: &[], - compilation_options: Default::default(), - }, - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: Some(wgpu::Face::Back), - unclipped_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - fragment: Some(wgpu::FragmentState { - module: &fragment_linkage.module, - entry_point: Some(fragment_linkage.entry_point), - targets: &[Some(wgpu::ColorTargetState { - format: frame_texture_format, - blend: Some(wgpu::BlendState::ALPHA_BLENDING), - write_mask: wgpu::ColorWrites::ALL, - })], - compilation_options: Default::default(), - }), - multisample: wgpu::MultisampleState::default(), - cache: None, - }), - ); - Self { - slab, - config, - hdr_texture: Arc::new(RwLock::new(hdr_texture.clone())), - bindgroup, - pipeline, - } - } - - pub(crate) fn slab_allocator(&self) -> &SlabAllocator { - &self.slab - } - - pub fn set_hdr_texture(&self, device: &wgpu::Device, hdr_texture: &Texture) { - // UNWRAP: safe because the buffer is created in `Self::new` and - // guaranteed to exist - let slab_buffer = self.slab.get_buffer().unwrap(); - let bindgroup = create_bindgroup(device, Some("tonemapping"), hdr_texture, &slab_buffer); - // UNWRAP: not safe but we want to panic - *self.bindgroup.write().expect("tonemapping bindgroup write") = bindgroup; - *self - .hdr_texture - .write() - .expect("tonemapping hdr_texture write") = hdr_texture.clone(); - } - - pub fn get_tonemapping_config(&self) -> TonemapConstants { - self.config.get() - } - - pub fn set_tonemapping_config(&self, config: TonemapConstants) { - self.config.set(config); - } - - pub fn render(&self, device: &wgpu::Device, queue: &wgpu::Queue, view: &wgpu::TextureView) { - let label = Some("tonemapping render"); - assert!(!self.slab.commit().is_new_this_commit()); - - // UNWRAP: not safe but we want to panic - let bindgroup = self.bindgroup.read().expect("tonemapping bindgroup read"); - let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - multiview_mask: None, - label, - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Load, - store: wgpu::StoreOp::Store, - }, - depth_slice: None, - })], - depth_stencil_attachment: None, - ..Default::default() - }); - render_pass.set_pipeline(&self.pipeline); - render_pass.set_bind_group(0, Some(bindgroup.deref()), &[]); - let id = self.config.id().into(); - render_pass.draw(0..6, id..id + 1); - drop(render_pass); - - queue.submit(std::iter::once(encoder.finish())); - } -} diff --git a/manual/src/assets/debug/albedo.png b/manual/src/assets/debug/albedo.png index 9d122e8c..1dfa0e82 100644 Binary files a/manual/src/assets/debug/albedo.png and b/manual/src/assets/debug/albedo.png differ diff --git a/manual/src/assets/debug/none.png b/manual/src/assets/debug/none.png index 23b5be61..94da39b9 100644 Binary files a/manual/src/assets/debug/none.png and b/manual/src/assets/debug/none.png differ diff --git a/manual/src/assets/debug/normals.png b/manual/src/assets/debug/normals.png index 823c3a1b..188dbb64 100644 Binary files a/manual/src/assets/debug/normals.png and b/manual/src/assets/debug/normals.png differ diff --git a/manual/src/assets/debug/uv-coords.png b/manual/src/assets/debug/uv-coords.png index a968d315..418930f6 100644 Binary files a/manual/src/assets/debug/uv-coords.png and b/manual/src/assets/debug/uv-coords.png differ diff --git a/manual/src/assets/gltf-example-unlit.png b/manual/src/assets/gltf-example-unlit.png index 04c26d2a..c1f7611b 100644 Binary files a/manual/src/assets/gltf-example-unlit.png and b/manual/src/assets/gltf-example-unlit.png differ diff --git a/manual/src/assets/lighting/directional.png b/manual/src/assets/lighting/directional.png index 4f4c3b3c..041b8e04 100644 Binary files a/manual/src/assets/lighting/directional.png and b/manual/src/assets/lighting/directional.png differ diff --git a/manual/src/assets/lighting/ibl-analytical-mixed.png b/manual/src/assets/lighting/ibl-analytical-mixed.png index e7e24fce..b939ab7c 100644 Binary files a/manual/src/assets/lighting/ibl-analytical-mixed.png and b/manual/src/assets/lighting/ibl-analytical-mixed.png differ diff --git a/manual/src/assets/lighting/ibl.png b/manual/src/assets/lighting/ibl.png index fbe5c4ce..4c484802 100644 Binary files a/manual/src/assets/lighting/ibl.png and b/manual/src/assets/lighting/ibl.png differ diff --git a/manual/src/assets/lighting/no-lights.png b/manual/src/assets/lighting/no-lights.png index 7617f3fe..0dbb79dc 100644 Binary files a/manual/src/assets/lighting/no-lights.png and b/manual/src/assets/lighting/no-lights.png differ diff --git a/manual/src/assets/lighting/point.png b/manual/src/assets/lighting/point.png index 7ac4afe1..5bb56112 100644 Binary files a/manual/src/assets/lighting/point.png and b/manual/src/assets/lighting/point.png differ diff --git a/manual/src/assets/lighting/shadow-none.png b/manual/src/assets/lighting/shadow-none.png index 6efdd6fe..128851f3 100644 Binary files a/manual/src/assets/lighting/shadow-none.png and b/manual/src/assets/lighting/shadow-none.png differ diff --git a/manual/src/assets/lighting/shadow.png b/manual/src/assets/lighting/shadow.png index 23b5be61..94da39b9 100644 Binary files a/manual/src/assets/lighting/shadow.png and b/manual/src/assets/lighting/shadow.png differ diff --git a/manual/src/assets/lighting/spot.png b/manual/src/assets/lighting/spot.png index 8817fab4..e01ee28c 100644 Binary files a/manual/src/assets/lighting/spot.png and b/manual/src/assets/lighting/spot.png differ diff --git a/manual/src/assets/material/albedo-texture.png b/manual/src/assets/material/albedo-texture.png index 4e30dbbf..a31c7645 100644 Binary files a/manual/src/assets/material/albedo-texture.png and b/manual/src/assets/material/albedo-texture.png differ diff --git a/manual/src/assets/material/albedo-updated.png b/manual/src/assets/material/albedo-updated.png index adc10f74..d2aba9a0 100644 Binary files a/manual/src/assets/material/albedo-updated.png and b/manual/src/assets/material/albedo-updated.png differ diff --git a/manual/src/assets/material/emissive.png b/manual/src/assets/material/emissive.png index e055cc50..1dceabe2 100644 Binary files a/manual/src/assets/material/emissive.png and b/manual/src/assets/material/emissive.png differ diff --git a/manual/src/assets/material/normal-map.png b/manual/src/assets/material/normal-map.png index 5c473014..a6939216 100644 Binary files a/manual/src/assets/material/normal-map.png and b/manual/src/assets/material/normal-map.png differ diff --git a/manual/src/assets/material/pbr-rough.png b/manual/src/assets/material/pbr-rough.png index d6f370b6..22964f94 100644 Binary files a/manual/src/assets/material/pbr-rough.png and b/manual/src/assets/material/pbr-rough.png differ diff --git a/manual/src/assets/material/pbr.png b/manual/src/assets/material/pbr.png index d38ebe9e..b353c2c0 100644 Binary files a/manual/src/assets/material/pbr.png and b/manual/src/assets/material/pbr.png differ diff --git a/manual/src/assets/performance/culling.png b/manual/src/assets/performance/culling.png index c5fbd61a..d9656c38 100644 Binary files a/manual/src/assets/performance/culling.png and b/manual/src/assets/performance/culling.png differ diff --git a/manual/src/assets/performance/msaa-4.png b/manual/src/assets/performance/msaa-4.png index af698bbd..62e923f0 100644 Binary files a/manual/src/assets/performance/msaa-4.png and b/manual/src/assets/performance/msaa-4.png differ diff --git a/manual/src/assets/performance/occlusion.png b/manual/src/assets/performance/occlusion.png index c5fbd61a..d9656c38 100644 Binary files a/manual/src/assets/performance/occlusion.png and b/manual/src/assets/performance/occlusion.png differ diff --git a/manual/src/assets/postprocessing/bloom-none.png b/manual/src/assets/postprocessing/bloom-none.png index a013f328..b86542c8 100644 Binary files a/manual/src/assets/postprocessing/bloom-none.png and b/manual/src/assets/postprocessing/bloom-none.png differ diff --git a/manual/src/assets/postprocessing/bloom.png b/manual/src/assets/postprocessing/bloom.png index 6d30e34b..8e831f36 100644 Binary files a/manual/src/assets/postprocessing/bloom.png and b/manual/src/assets/postprocessing/bloom.png differ diff --git a/manual/src/assets/postprocessing/exposure.png b/manual/src/assets/postprocessing/exposure.png index 069dd570..90055400 100644 Binary files a/manual/src/assets/postprocessing/exposure.png and b/manual/src/assets/postprocessing/exposure.png differ diff --git a/manual/src/assets/postprocessing/tonemap-aces.png b/manual/src/assets/postprocessing/tonemap-aces.png index c9efc676..9ffe8c2f 100644 Binary files a/manual/src/assets/postprocessing/tonemap-aces.png and b/manual/src/assets/postprocessing/tonemap-aces.png differ diff --git a/manual/src/assets/scene/hierarchy.png b/manual/src/assets/scene/hierarchy.png index e2700442..b32fcdae 100644 Binary files a/manual/src/assets/scene/hierarchy.png and b/manual/src/assets/scene/hierarchy.png differ diff --git a/manual/src/assets/scene/moved-child.png b/manual/src/assets/scene/moved-child.png index 17015dc0..a9ce4741 100644 Binary files a/manual/src/assets/scene/moved-child.png and b/manual/src/assets/scene/moved-child.png differ diff --git a/manual/src/assets/scene/moved-parent.png b/manual/src/assets/scene/moved-parent.png index 3d341dca..5aa0fa67 100644 Binary files a/manual/src/assets/scene/moved-parent.png and b/manual/src/assets/scene/moved-parent.png differ diff --git a/manual/src/assets/skybox.png b/manual/src/assets/skybox.png index 4081a39a..ce08c149 100644 Binary files a/manual/src/assets/skybox.png and b/manual/src/assets/skybox.png differ diff --git a/manual/src/assets/stage-example.png b/manual/src/assets/stage-example.png index 98ef0adf..7769d0f8 100644 Binary files a/manual/src/assets/stage-example.png and b/manual/src/assets/stage-example.png differ diff --git a/test_img/bloom/result.exr b/test_img/bloom/result.exr new file mode 100644 index 00000000..d7469633 Binary files /dev/null and b/test_img/bloom/result.exr differ diff --git a/test_img/tonemapping/aces_hill.exr b/test_img/tonemapping/aces_hill.exr new file mode 100644 index 00000000..f9bccadf Binary files /dev/null and b/test_img/tonemapping/aces_hill.exr differ diff --git a/test_img/tonemapping/aces_hill_exposure_boost.exr b/test_img/tonemapping/aces_hill_exposure_boost.exr new file mode 100644 index 00000000..f3736c93 Binary files /dev/null and b/test_img/tonemapping/aces_hill_exposure_boost.exr differ diff --git a/test_img/tonemapping/aces_narkowicz.exr b/test_img/tonemapping/aces_narkowicz.exr new file mode 100644 index 00000000..bfe7e82d Binary files /dev/null and b/test_img/tonemapping/aces_narkowicz.exr differ diff --git a/test_img/tonemapping/none.exr b/test_img/tonemapping/none.exr new file mode 100644 index 00000000..81798699 Binary files /dev/null and b/test_img/tonemapping/none.exr differ diff --git a/test_img/tonemapping/reinhard.exr b/test_img/tonemapping/reinhard.exr new file mode 100644 index 00000000..cb25a87e Binary files /dev/null and b/test_img/tonemapping/reinhard.exr differ