From 7adb747625000fbb634cfaaa7929c0a528b8fded Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Sat, 1 Aug 2026 15:48:54 -0400 Subject: [PATCH] Add a color coordinate to the chaos game All shader-related code has been removed; GPU entry points will be added once there's a better understanding of how the API should work. --- Cargo.lock | 690 +------------------------------ Cargo.toml | 3 +- enkou-shaders-tests/Cargo.toml | 18 - enkou-shaders-tests/build.rs | 25 -- enkou-shaders-tests/src/lib.rs | 67 --- enkou-shaders/examples/gasket.rs | 79 ++-- enkou-shaders/src/chaos_game.rs | 55 +-- enkou-shaders/src/lib.rs | 2 - enkou-shaders/src/rng.rs | 55 --- enkou-shaders/src/transform.rs | 53 ++- 10 files changed, 99 insertions(+), 948 deletions(-) delete mode 100644 enkou-shaders-tests/Cargo.toml delete mode 100644 enkou-shaders-tests/build.rs delete mode 100644 enkou-shaders-tests/src/lib.rs delete mode 100644 enkou-shaders/src/rng.rs diff --git a/Cargo.lock b/Cargo.lock index 48923e5..81eb3f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,9 +130,6 @@ name = "bitflags" version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" -dependencies = [ - "serde_core", -] [[package]] name = "bitstream-io" @@ -181,68 +178,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" -[[package]] -name = "camino" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce8d3bd5823c7504d3f579f13e7b2f3da252fcb938c594d5680ee508bf846f" -dependencies = [ - "serde_core", -] - -[[package]] -name = "cargo-gpu-install" -version = "0.10.0-alpha.1" -source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=67f1ff2#67f1ff27272a1dff82776a5ad7388c738e0b31be" -dependencies = [ - "anyhow", - "cargo_metadata", - "directories", - "log", - "serde", - "spirv-builder", -] - -[[package]] -name = "cargo-platform" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-util-schemas" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc1a6f7b5651af85774ae5a34b4e8be397d9cf4bc063b7e6dbd99a841837830" -dependencies = [ - "semver", - "serde", - "serde-untagged", - "serde-value", - "thiserror", - "toml", - "unicode-xid", - "url", -] - -[[package]] -name = "cargo_metadata" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868" -dependencies = [ - "camino", - "cargo-platform", - "cargo-util-schemas", - "semver", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "cc" version = "1.2.65" @@ -307,38 +242,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" -[[package]] -name = "directories" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys", -] - -[[package]] -name = "displaydoc" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "either" version = "1.16.0" @@ -360,15 +263,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "enkou-shaders-tests" -version = "0.1.0" -dependencies = [ - "anyhow", - "cargo-gpu-install", - "rspirv 0.13.0+sdk-1.4.341.0", -] - [[package]] name = "equator" version = "0.4.2" @@ -389,23 +283,6 @@ dependencies = [ "syn", ] -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "erased-serde" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" -dependencies = [ - "serde", - "serde_core", - "typeid", -] - [[package]] name = "errno" version = "0.3.14" @@ -467,26 +344,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "getrandom" version = "0.3.4" @@ -530,115 +387,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "hashbrown" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "icu_collections" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" -dependencies = [ - "displaydoc", - "potential_utf", - "utf8_iter", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" - -[[package]] -name = "icu_properties" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" - -[[package]] -name = "icu_provider" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - [[package]] name = "image" version = "0.25.10" @@ -678,16 +426,6 @@ version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7" -[[package]] -name = "indexmap" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" -dependencies = [ - "equivalent", - "hashbrown", -] - [[package]] name = "interpolate_name" version = "0.2.4" @@ -708,19 +446,13 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - [[package]] name = "jobserver" version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.4", + "getrandom", "libc", ] @@ -752,27 +484,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" -[[package]] -name = "libredox" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" -dependencies = [ - "libc", -] - [[package]] name = "linux-raw-sys" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" -[[package]] -name = "litemap" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" - [[package]] name = "log" version = "0.4.32" @@ -910,21 +627,6 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - [[package]] name = "paste" version = "1.0.15" @@ -937,12 +639,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - [[package]] name = "png" version = "0.18.1" @@ -956,15 +652,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "potential_utf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" -dependencies = [ - "zerovec", -] - [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1073,7 +760,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.4", + "getrandom", ] [[package]] @@ -1140,12 +827,6 @@ dependencies = [ "rgb", ] -[[package]] -name = "raw-string" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" - [[package]] name = "rayon" version = "1.12.0" @@ -1166,62 +847,12 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror", -] - [[package]] name = "rgb" version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" -[[package]] -name = "rspirv" -version = "0.12.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d" -dependencies = [ - "rustc-hash", - "spirv 0.3.0+sdk-1.3.268.0", -] - -[[package]] -name = "rspirv" -version = "0.13.0+sdk-1.4.341.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091dca2e1d6fd3098417b5ec88e77e80d1ba5945750943419dc976858082c296" -dependencies = [ - "rustc-hash", - "spirv 0.4.0+sdk-1.4.341.0", -] - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_codegen_spirv-types" -version = "0.10.0-alpha.1" -source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=67f1ff2#67f1ff27272a1dff82776a5ad7388c738e0b31be" -dependencies = [ - "rspirv 0.12.0+sdk-1.3.268.0", - "semver", - "serde", - "serde_json", - "spirv 0.3.0+sdk-1.3.268.0", - "thiserror", -] - [[package]] name = "rustix" version = "1.1.4" @@ -1241,90 +872,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" -dependencies = [ - "serde", - "serde_core", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde-untagged" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" -dependencies = [ - "erased-serde", - "serde", - "serde_core", - "typeid", -] - -[[package]] -name = "serde-value" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" -dependencies = [ - "ordered-float", - "serde", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - [[package]] name = "shlex" version = "2.0.1" @@ -1352,41 +899,6 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" -[[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" -dependencies = [ - "bitflags 2.13.0", - "serde", -] - -[[package]] -name = "spirv" -version = "0.4.0+sdk-1.4.341.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" -dependencies = [ - "bitflags 2.13.0", -] - -[[package]] -name = "spirv-builder" -version = "0.10.0-alpha.1" -source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=67f1ff2#67f1ff27272a1dff82776a5ad7388c738e0b31be" -dependencies = [ - "cargo_metadata", - "log", - "memchr", - "raw-string", - "rustc_codegen_spirv-types", - "semver", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "spirv-std" version = "0.10.0-alpha.1" @@ -1433,17 +945,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tempfile" version = "3.27.0" @@ -1451,7 +952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom", "once_cell", "rustix", "windows-sys", @@ -1491,93 +992,12 @@ dependencies = [ "zune-jpeg", ] -[[package]] -name = "tinystr" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "toml_write", - "winnow", -] - -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "v_frame" version = "0.3.9" @@ -1589,12 +1009,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - [[package]] name = "wasip2" version = "1.0.4+wasi-0.2.12" @@ -1670,56 +1084,18 @@ dependencies = [ "windows-link", ] -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" -dependencies = [ - "memchr", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "writeable" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" - [[package]] name = "y4m" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" -[[package]] -name = "yoke" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "zerocopy" version = "0.8.52" @@ -1740,66 +1116,6 @@ dependencies = [ "syn", ] -[[package]] -name = "zerofrom" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerotrie" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - [[package]] name = "zune-core" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index b5fdf79..33232ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ "enkou-shaders", - "enkou-shaders-tests", ] resolver = "3" @@ -13,6 +12,7 @@ license = "MIT" repository = "" [workspace.lints.rust] +missing_docs = { level = "warn" } unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spirv"))'] } [workspace.dependencies] @@ -26,5 +26,4 @@ image = { version = "0.25.10", default-features = false, features = ["default-fo libm = "0.2.16" rand = { version = "0.10.1", default-features = false } rand_xoshiro = "0.8.1" -rspirv = "0.13.0" tempfile = "3.27.0" diff --git a/enkou-shaders-tests/Cargo.toml b/enkou-shaders-tests/Cargo.toml deleted file mode 100644 index 1627234..0000000 --- a/enkou-shaders-tests/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "enkou-shaders-tests" -publish = false -version.workspace = true -authors.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true - -[lints] -workspace = true - -[dependencies] -rspirv.workspace = true - -[build-dependencies] -anyhow.workspace = true -cargo-gpu-install.workspace = true diff --git a/enkou-shaders-tests/build.rs b/enkou-shaders-tests/build.rs deleted file mode 100644 index 117b150..0000000 --- a/enkou-shaders-tests/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -use cargo_gpu_install::install::Install; -use cargo_gpu_install::spirv_builder::{Capability, ShaderPanicStrategy, SpirvMetadata}; -use std::path::PathBuf; - -pub fn main() -> anyhow::Result<()> { - let manifest_dir = env!("CARGO_MANIFEST_DIR"); - let crate_path = [manifest_dir, "..", "enkou-shaders"] - .iter() - .copied() - .collect::(); - - let install = Install::from_shader_crate(crate_path.clone()) - .within_build_script() - .run()?; - let mut builder = install.to_spirv_builder(crate_path, "spirv-unknown-vulkan1.3"); - builder.build_script.defaults = true; - builder.shader_panic_strategy = ShaderPanicStrategy::SilentExit; - builder.spirv_metadata = SpirvMetadata::Full; - builder.capabilities = vec![Capability::Int8, Capability::Int16, Capability::Int64]; - - let compile_result = builder.build()?; - let spv_path = compile_result.module.unwrap_single(); - println!("cargo::rustc-env=SHADER_SPV_PATH={}", spv_path.display()); - Ok(()) -} diff --git a/enkou-shaders-tests/src/lib.rs b/enkou-shaders-tests/src/lib.rs deleted file mode 100644 index 7aa1873..0000000 --- a/enkou-shaders-tests/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -#[cfg(test)] -mod test { - use rspirv::binary::parse_bytes; - use rspirv::dr::{Module, Operand}; - use rspirv::spirv::ExecutionModel; - use std::sync::OnceLock; - - static SHADER_MODULE: OnceLock = OnceLock::new(); - - fn shader() -> &'static Module { - SHADER_MODULE.get_or_init(|| { - let shader_bytes = include_bytes!(env!("SHADER_SPV_PATH")); - - let mut loader = rspirv::dr::Loader::new(); - parse_bytes(shader_bytes, &mut loader).expect("Unable to parse shader"); - - loader.module() - }) - } - - fn has_entry_point(execution_model: ExecutionModel, name: &str) -> bool { - for entry_point in shader().entry_points.iter() { - let operands: Vec = entry_point - .operands - .iter() - .filter(|op| matches!(op, Operand::ExecutionModel(_) | Operand::LiteralString(_))) - .cloned() - .collect(); - - assert_eq!(operands.len(), 2); - match &operands[0] { - Operand::ExecutionModel(actual) => { - if execution_model != *actual { - continue; - } - } - op => panic!("Unexpected operand; {}", op), - } - - match &operands[1] { - Operand::LiteralString(actual) => { - if name != actual { - continue; - } - } - op => panic!("Unexpected operand; {}", op), - } - - return true; - } - - false - } - - #[test] - pub fn has_entry_main_chaos_game() { - assert!(has_entry_point( - ExecutionModel::GLCompute, - "main_chaos_game" - )) - } - - #[test] - pub fn has_entry_main_camera() { - assert!(has_entry_point(ExecutionModel::GLCompute, "main_camera")) - } -} diff --git a/enkou-shaders/examples/gasket.rs b/enkou-shaders/examples/gasket.rs index 9c3bbe2..461096c 100644 --- a/enkou-shaders/examples/gasket.rs +++ b/enkou-shaders/examples/gasket.rs @@ -1,55 +1,51 @@ +//! # Sierpinski Gasket +//! +//! The Sierpinski Gasket is a simple iterated function system (IFS) that demonstrates +//! the basic principles of using the "chaos game" to generate images. Using a set of three +//! transforms, generate new points in the function system using the chaos game, +//! then plot those points and display the resulting image. use anyhow::{Context, Result}; use enkou_shaders::Coefficients2; use enkou_shaders::camera::Camera; -use enkou_shaders::camera::entry::main_camera; -use enkou_shaders::chaos_game::entry::main_chaos_game; +use enkou_shaders::chaos_game::ChaosGame; use enkou_shaders::transform::Transform; use enkou_shaders::variation::Variation; -use glam::{Affine2, IVec2, UVec2, Vec2, uvec2}; +use glam::{Affine2, UVec2, Vec2, uvec2}; use image::{GrayImage, Luma}; +use rand::SeedableRng; +use rand_xoshiro::Xoshiro256StarStar; use std::mem; use std::process::Command; use tempfile::NamedTempFile; -const ITERATIONS_DISCARD: u32 = 20; -const ITERATIONS: u32 = 50_000; +const ITERATIONS_DISCARD: usize = 20; const IMAGE_DIMENSION: UVec2 = uvec2(600, 600); +const IMAGE_QUALITY: f32 = 1.0; +/// Build and display a simple fractal - the Sierpinski Gasket pub fn main() -> Result<()> { + let mut rng = Xoshiro256StarStar::from_seed([4u8; 32]); + let transforms = [ { // F_0: (x / 2, y / 2) let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.0); - Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) + Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1), 0.0, 0.5) }, { // F_1: ((x + 1) / 2, y / 2) let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.5, 0.0, 0.5, 0.0); - Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) + Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1), 0.5, 0.5) }, { // F_2: (x / 2, (y + 1) / 2) let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.5); - Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1)) + Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1), 1.0, 0.5) }, ]; - let weights = [1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0]; - let variations = [Variation::IDENTITY]; - let mut output_points_ifs = Vec::new(); - output_points_ifs.resize(ITERATIONS as usize, Vec2::ZERO); - - main_chaos_game( - ITERATIONS_DISCARD, - &[4u8; 32], - &transforms, - &weights, - &variations, - &mut output_points_ifs, - ); - // The gasket is defined on the range [0, 1] for both X and Y let camera = Camera::new( IMAGE_DIMENSION, @@ -59,33 +55,28 @@ pub fn main() -> Result<()> { IMAGE_DIMENSION.as_vec2(), ); - let mut output_points_pixel = Vec::new(); - output_points_pixel.resize(ITERATIONS as usize, IVec2::ZERO); - - main_camera(&camera, &output_points_ifs, &mut output_points_pixel); - let mut image = GrayImage::new(IMAGE_DIMENSION.x, IMAGE_DIMENSION.y); - let dimensions = image.dimensions(); - output_points_pixel - .iter() - .skip_while(|p| { - p.x < 0 || (p.x as u32) > dimensions.0 || p.y < 0 || (p.y as u32) > dimensions.1 - }) - .map(|p| (p.x as u32, p.y as u32)) - .for_each(|(x, y)| image.put_pixel(x, y, Luma([255u8]))); + let chaos_game = ChaosGame::new(&mut rng, &transforms, &weights, &variations); + + let iterations = (IMAGE_DIMENSION.element_product() as f32 * IMAGE_QUALITY) as usize; + chaos_game + .skip(ITERATIONS_DISCARD) + .take(iterations) + .for_each(|(ifs_point, _)| { + if let Some(pixel_point) = camera.transform_point_to_image(ifs_point) { + image.put_pixel(pixel_point.x, pixel_point.y, Luma([255u8])); + } + }); let temp = NamedTempFile::with_suffix(".png").context("Unable to create file for image")?; image.save(temp.path()).context("Unable to save image")?; - let open_program: &str = cfg_select! { - unix => "xdg-open", - _ => panic!("No available program to open images") - }; - - Command::new(open_program) - .arg(temp.path()) - .spawn()? - .wait()?; + let mut command = cfg_select! { + unix => Command::new("xdg-open").arg(temp.path()).spawn(), + windows => Command::new("PowerShell").arg("-Command").arg(format!("start {}", temp.path().display())).spawn(), + _ => Err(anyhow::anyhow!("No available program to open images"))? + }?; + command.wait()?; // In case the image viewer forks and gives control back prior to reading the file, // drop it and don't run the destructor diff --git a/enkou-shaders/src/chaos_game.rs b/enkou-shaders/src/chaos_game.rs index 8ac3858..456462d 100644 --- a/enkou-shaders/src/chaos_game.rs +++ b/enkou-shaders/src/chaos_game.rs @@ -36,11 +36,12 @@ impl Distribution for BiUnit { /// * `weights` - Weights are assumed to be normalized; adding all elements together should return the value 1 pub fn step_chaos_game( point: Vec2, + color: f32, rng: &mut R, transforms: &[Transform], weights: &[f32], variations: &[Variation], -) -> (Vec2, u32) { +) -> (Vec2, f32) { let mut choice_weight = rng.sample::(StandardUniform); let mut transform_index: u32 = 0; @@ -53,9 +54,10 @@ pub fn step_chaos_game( transform_index += 1; } + let transform = &transforms[transform_index as usize]; ( - transforms[transform_index as usize].transform_point(rng, variations, point), - transform_index, + transform.transform_point(rng, variations, point), + transform.transform_color(color), ) } @@ -65,6 +67,7 @@ pub fn step_chaos_game( /// New points in the chaos game are produced by iterating on the chaos game. pub struct ChaosGame<'a, R: Rng> { current_point: Vec2, + current_color: f32, rng: &'a mut R, transforms: &'a [Transform], weights: &'a [f32], @@ -80,8 +83,10 @@ impl<'a, R: Rng> ChaosGame<'a, R> { variations: &'a [Variation], ) -> Self { let current_point = vec2(rng.sample(BiUnit), rng.sample(BiUnit)); + let current_color = rng.sample(StandardUniform); ChaosGame { current_point, + current_color, rng, transforms, weights, @@ -91,54 +96,20 @@ impl<'a, R: Rng> ChaosGame<'a, R> { } impl<'a, R: Rng> Iterator for ChaosGame<'a, R> { - type Item = Vec2; + type Item = (Vec2, f32); fn next(&mut self) -> Option { - let (next_point, _) = step_chaos_game( + let (next_point, next_color) = step_chaos_game( self.current_point, + self.current_color, self.rng, self.transforms, self.weights, self.variations, ); self.current_point = next_point; + self.current_color = next_color; - Some(next_point) - } -} - -/// Shader entry point for running the chaos game to produce new IFS coordinates -pub mod entry { - use crate::chaos_game::ChaosGame; - use crate::rng::xoshiro256starstar_from_seed; - use crate::transform::Transform; - use crate::variation::Variation; - use glam::Vec2; - use spirv_std::spirv; - - /// Given a set of fractal flame parameters, generate new IFS coordinates - /// and store them in the output array. - #[spirv(compute(entry_point_name = "main_chaos_game", threads(1)))] - pub fn main_chaos_game( - #[spirv(spec_constant(id = 1, default = 20))] iteration_discard: u32, - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] rng_seed: &[u8], - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] transforms: &[Transform], - #[spirv(storage_buffer, descriptor_set = 0, binding = 2)] weights: &[f32], - #[spirv(storage_buffer, descriptor_set = 0, binding = 3)] variations: &[Variation], - #[spirv(storage_buffer, descriptor_set = 1, binding = 0)] output: &mut [Vec2], - ) { - let mut rng_seed_actual = [0u8; 32]; - (0..32).for_each(|i| rng_seed_actual[i] = rng_seed[i]); - - let mut rng = xoshiro256starstar_from_seed(rng_seed_actual); - let mut chaos_game = ChaosGame::new(&mut rng, transforms, weights, variations); - - for _ in 0..iteration_discard { - chaos_game.next().unwrap(); - } - - for i in 0..output.len() { - output[i] = chaos_game.next().unwrap(); - } + Some((next_point, next_color)) } } diff --git a/enkou-shaders/src/lib.rs b/enkou-shaders/src/lib.rs index 0cb9009..0e485ae 100644 --- a/enkou-shaders/src/lib.rs +++ b/enkou-shaders/src/lib.rs @@ -1,11 +1,9 @@ //! # Enkou #![no_std] -#![deny(missing_docs)] #![allow(clippy::needless_range_loop)] // SPIR-V backend has issues with iteration over items pub mod camera; pub mod chaos_game; -mod rng; pub mod transform; pub mod variation; diff --git a/enkou-shaders/src/rng.rs b/enkou-shaders/src/rng.rs deleted file mode 100644 index 2169847..0000000 --- a/enkou-shaders/src/rng.rs +++ /dev/null @@ -1,55 +0,0 @@ -use rand::SeedableRng; -use rand_xoshiro::Xoshiro256StarStar; - -/// Convert an RNG state buffer to an instance of [`Xoshiro256StarStar`]. -/// -/// While [`SeedableRng::from_seed`] is an infallible function, -/// it relies on some methods that can't be compiled by the SPIR-V -/// backend (specifically, formatting functions in the core crate). -/// -/// In practice, the xoshiro RNG state is entirely defined by its seed, -/// so this function does the work of [`SeedableRng::from_seed`] by -/// transmuting the seed value to an RNG instance. -/// -/// This function assumes a properly-initialized state array; -/// output may silently degenerate if the initial state is all zeros, -/// so this module is private to the crate. -pub(crate) fn xoshiro256starstar_from_seed( - rng_state: ::Seed, -) -> Xoshiro256StarStar { - let mut rng_state_actual = [0u64; 4]; - - // NOTE: Bit shifting is bad, but we don't have great alternatives: - // - `chunks_exact` has issues with pointer casting - // - `u64::from_le_bytes` has issues with `OpBitcast` in SPIR-V validation - for i in 0..rng_state_actual.len() { - for j in 0..size_of::() { - rng_state_actual[i] |= (rng_state[i * size_of::() + j] as u64) << (j * 8); - } - } - - unsafe { core::mem::transmute(rng_state_actual) } -} - -#[cfg(test)] -mod test { - use crate::rng::xoshiro256starstar_from_seed; - use core::iter::zip; - use rand::{RngExt, SeedableRng}; - use rand_xoshiro::Xoshiro256StarStar; - - #[test] - fn match_seeded() { - let mut seed: ::Seed = [0u8; 32]; - for i in 0..seed.len() { - seed[i] = i as u8; - } - - let rng1 = Xoshiro256StarStar::from_seed(seed).random_iter::(); - let rng2 = xoshiro256starstar_from_seed(seed).random_iter::(); - - zip(rng1, rng2) - .take(100) - .for_each(|(rng1_value, rng2_value)| assert_eq!(rng1_value, rng2_value)); - } -} diff --git a/enkou-shaders/src/transform.rs b/enkou-shaders/src/transform.rs index 75d63bf..0cc3862 100644 --- a/enkou-shaders/src/transform.rs +++ b/enkou-shaders/src/transform.rs @@ -5,7 +5,7 @@ //! but produce more interesting images once we add variations. use crate::variation::Variation; use bytemuck::{Pod, Zeroable}; -use glam::{Affine2, UVec2, Vec2}; +use glam::{Affine2, FloatExt, UVec2, Vec2}; use rand::Rng; /// Affine transform for use in the [`chaos_game`](crate::chaos_game). @@ -15,15 +15,25 @@ pub struct Transform { coefficients: Affine2, coefficients_post: Affine2, variation_range: UVec2, + color: f32, + color_speed: f32, } impl Transform { /// Create a new transform from an affine transformation matrix - pub fn new(coefficients: Affine2, coefficients_post: Affine2, variation_range: UVec2) -> Self { + pub fn new( + coefficients: Affine2, + coefficients_post: Affine2, + variation_range: UVec2, + color: f32, + color_speed: f32, + ) -> Self { Transform { coefficients, coefficients_post, variation_range, + color, + color_speed, } } @@ -47,14 +57,20 @@ impl Transform { self.coefficients_post.transform_point2(point) } + + /// Apply this transform to a color in IFS coordinates, producing a new color + pub fn transform_color(&self, color: f32) -> f32 { + self.color.lerp(color, self.color_speed) + } } #[cfg(test)] mod test { - use crate::rng::xoshiro256starstar_from_seed; use crate::transform::Transform; use crate::variation::{Variation, VariationKind}; use glam::{Affine2, uvec2, vec2}; + use rand::SeedableRng; + use rand_xoshiro::Xoshiro256StarStar; #[test] fn transform_scaling() { @@ -63,9 +79,11 @@ mod test { Affine2::from_scale(scale_coefficients), Affine2::IDENTITY, uvec2(0, 1), + 0.0, + 0.0, ); - let mut rng = xoshiro256starstar_from_seed([0; 32]); + let mut rng = Xoshiro256StarStar::from_seed([0u8; 32]); let variations = [Variation::IDENTITY]; let point = vec2(1.0, 1.0); @@ -78,14 +96,17 @@ mod test { #[test] fn transform_scaling_post() { let scale_coefficients = vec2(2.0, 0.5); - let transform_pdj = Transform::new(Affine2::IDENTITY, Affine2::IDENTITY, uvec2(0, 1)); + let transform_pdj = + Transform::new(Affine2::IDENTITY, Affine2::IDENTITY, uvec2(0, 1), 0.0, 0.0); let transform_pdj_post = Transform::new( Affine2::IDENTITY, Affine2::from_scale(scale_coefficients), uvec2(0, 1), + 0.0, + 0.0, ); - let mut rng = xoshiro256starstar_from_seed([0; 32]); + let mut rng = Xoshiro256StarStar::from_seed([0; 32]); let variations = [Variation::new(VariationKind::Pdj, 1.0, [0.0f32; 4].into())]; let point = vec2(1.0, 1.0); @@ -94,4 +115,24 @@ mod test { assert_eq!(point_pdj * scale_coefficients, point_pdj_post); } + + #[test] + fn transform_color() { + let starting_color = 0.0; + let transform_color = 1.0; + let transform_speed = 0.5; + + let transform = Transform::new( + Affine2::IDENTITY, + Affine2::IDENTITY, + uvec2(0, 1), + starting_color, + transform_speed, + ); + + assert_eq!( + transform.transform_color(starting_color), + starting_color * (1.0 - transform_speed) + transform_color * transform_speed + ); + } }