diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..974402df9230d204de5b35a6797d21ee7d1936ff 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,8 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +correctness/frame.rgb filter=lfs diff=lfs merge=lfs -text +correctness/host/quality_samples/0000-encoder.f32 filter=lfs diff=lfs merge=lfs -text +correctness/host/quality_samples/0000-features.f32 filter=lfs diff=lfs merge=lfs -text +correctness/host/quality_samples/0000-patches.f32 filter=lfs diff=lfs merge=lfs -text +correctness/host/quality_samples/0000-reconstruction.f32 filter=lfs diff=lfs merge=lfs -text diff --git a/ARTIFACT_MANIFEST.json b/ARTIFACT_MANIFEST.json new file mode 100644 index 0000000000000000000000000000000000000000..c47f007cf3e00edf608ef8bb3d49885f7f86ae2f --- /dev/null +++ b/ARTIFACT_MANIFEST.json @@ -0,0 +1,1704 @@ +{ + "schema_version": 1, + "created_utc": "2026-08-02T04:18:09.5648993Z", + "selected_seed": 0, + "encoder_layers": 3, + "image_size": 224, + "files": [ + { + "path": "correctness/frame.rgb", + "bytes": 150528, + "sha256": "b89c2000b8877bce4649610e490579eef1ada5b29867f7a773d88450549ad1a8" + }, + { + "path": "correctness/host/quality.json", + "bytes": 1791, + "sha256": "c040d2f2770cf7a2356af63c27de38bb5bfdb475b703d8290e961d42ef1c92d2" + }, + { + "path": "correctness/host/quality_samples/0000-encoder.f32", + "bytes": 308736, + "sha256": "ca6b60574ccd26d8c6189c4c9a1ef143d60263c86bb6232d2a758552ed1db1e6" + }, + { + "path": "correctness/host/quality_samples/0000-features.f32", + "bytes": 301056, + "sha256": "899d9e027e9b63495e4aa09125872431611591d509d1f112c9decd4fbde8efca" + }, + { + "path": "correctness/host/quality_samples/0000-patches.f32", + "bytes": 602112, + "sha256": "222d3d93fbdcf3eca93ddec0a6d210384977bb48d17d5cf2da53d1d0175d92af" + }, + { + "path": "correctness/host/quality_samples/0000-reconstruction.f32", + "bytes": 602112, + "sha256": "81873eb7b3698e7205fcb26b4838c5730f6bc3abbfc6a0bcb8a6a8a484fb6deb" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/embeddings.bin", + "bytes": 308736, + "sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/features.bin", + "bytes": 308736, + "sha256": "47f7c2ffefe93f2cf6b855404cccc82c188b05f2f71ef8aefe927b26ad998603" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-attention.bin", + "bytes": 308736, + "sha256": "3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-attention-projected.bin", + "bytes": 308736, + "sha256": "79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-attention-scaled.bin", + "bytes": 308736, + "sha256": "60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-final-norm.bin", + "bytes": 308736, + "sha256": "63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-k.bin", + "bytes": 308736, + "sha256": "e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-k-rope.bin", + "bytes": 308736, + "sha256": "2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-mlp-activated.bin", + "bytes": 1234944, + "sha256": "152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-mlp-down.bin", + "bytes": 308736, + "sha256": "344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-mlp-scaled.bin", + "bytes": 308736, + "sha256": "4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-mlp-up.bin", + "bytes": 1234944, + "sha256": "4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-norm1.bin", + "bytes": 308736, + "sha256": "9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-norm2.bin", + "bytes": 308736, + "sha256": "222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-output.bin", + "bytes": 308736, + "sha256": "ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-q.bin", + "bytes": 308736, + "sha256": "d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-q-rope.bin", + "bytes": 308736, + "sha256": "9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-residual.bin", + "bytes": 308736, + "sha256": "62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/first-v.bin", + "bytes": 308736, + "sha256": "2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-embeddings.bin", + "bytes": 308736, + "sha256": "424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-features.bin", + "bytes": 308736, + "sha256": "f756676c12926a2a8be01c6d0bd6d56adbc1c6d249c457d7cc828f3bd519f697" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-attention.bin", + "bytes": 308736, + "sha256": "e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-attention-projected.bin", + "bytes": 308736, + "sha256": "ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-attention-scaled.bin", + "bytes": 308736, + "sha256": "2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-final-norm.bin", + "bytes": 308736, + "sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-k.bin", + "bytes": 308736, + "sha256": "01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-k-rope.bin", + "bytes": 308736, + "sha256": "cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-activated.bin", + "bytes": 1234944, + "sha256": "24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-down.bin", + "bytes": 308736, + "sha256": "a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-scaled.bin", + "bytes": 308736, + "sha256": "04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-up.bin", + "bytes": 1234944, + "sha256": "9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-norm1.bin", + "bytes": 308736, + "sha256": "f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-norm2.bin", + "bytes": 308736, + "sha256": "1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-output.bin", + "bytes": 308736, + "sha256": "c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-q.bin", + "bytes": 308736, + "sha256": "0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-q-rope.bin", + "bytes": 308736, + "sha256": "570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-residual.bin", + "bytes": 308736, + "sha256": "16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/meganeura-first-v.bin", + "bytes": 308736, + "sha256": "d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/pixel_values.bin", + "bytes": 602112, + "sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/reference.json", + "bytes": 792, + "sha256": "f7306c3e9c5256fc201a106554d105cae7e5c85a4e0ad9c4bcd8798543804e34" + }, + { + "path": "correctness/reference/dinovision-reference-final-0l/verification.json", + "bytes": 9716, + "sha256": "69ed9e478d432dbc0ccf4be92515883eb945710c209ace78ba66126b84769484" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/embeddings.bin", + "bytes": 308736, + "sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/features.bin", + "bytes": 308736, + "sha256": "caf5d0b7b085be6d9205a297e1ee4c16b594c857d335398b6e7c28481ae50448" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-attention.bin", + "bytes": 308736, + "sha256": "3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-attention-projected.bin", + "bytes": 308736, + "sha256": "79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-attention-scaled.bin", + "bytes": 308736, + "sha256": "60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-final-norm.bin", + "bytes": 308736, + "sha256": "63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-k.bin", + "bytes": 308736, + "sha256": "e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-k-rope.bin", + "bytes": 308736, + "sha256": "2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-mlp-activated.bin", + "bytes": 1234944, + "sha256": "152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-mlp-down.bin", + "bytes": 308736, + "sha256": "344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-mlp-scaled.bin", + "bytes": 308736, + "sha256": "4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-mlp-up.bin", + "bytes": 1234944, + "sha256": "4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-norm1.bin", + "bytes": 308736, + "sha256": "9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-norm2.bin", + "bytes": 308736, + "sha256": "222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-output.bin", + "bytes": 308736, + "sha256": "ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-q.bin", + "bytes": 308736, + "sha256": "d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-q-rope.bin", + "bytes": 308736, + "sha256": "9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-residual.bin", + "bytes": 308736, + "sha256": "62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/first-v.bin", + "bytes": 308736, + "sha256": "2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-embeddings.bin", + "bytes": 308736, + "sha256": "424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-features.bin", + "bytes": 308736, + "sha256": "29687eb03eb995951ed86dc15e25ac80ec7ea914194e7491923ea6f403f244a5" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-attention.bin", + "bytes": 308736, + "sha256": "e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-attention-projected.bin", + "bytes": 308736, + "sha256": "ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-attention-scaled.bin", + "bytes": 308736, + "sha256": "2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-final-norm.bin", + "bytes": 308736, + "sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-k.bin", + "bytes": 308736, + "sha256": "01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-k-rope.bin", + "bytes": 308736, + "sha256": "cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-activated.bin", + "bytes": 1234944, + "sha256": "24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-down.bin", + "bytes": 308736, + "sha256": "a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-scaled.bin", + "bytes": 308736, + "sha256": "04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-up.bin", + "bytes": 1234944, + "sha256": "9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-norm1.bin", + "bytes": 308736, + "sha256": "f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-norm2.bin", + "bytes": 308736, + "sha256": "1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-output.bin", + "bytes": 308736, + "sha256": "c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-q.bin", + "bytes": 308736, + "sha256": "0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-q-rope.bin", + "bytes": 308736, + "sha256": "570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-residual.bin", + "bytes": 308736, + "sha256": "16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/meganeura-first-v.bin", + "bytes": 308736, + "sha256": "d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/pixel_values.bin", + "bytes": 602112, + "sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/reference.json", + "bytes": 793, + "sha256": "d9a13c21c70a49efc76a9dcab1fc50f3dda5ddbaa486f43e3e2ec26c5cb5ba3c" + }, + { + "path": "correctness/reference/dinovision-reference-final-12l/verification.json", + "bytes": 9735, + "sha256": "fb3861ef746b894d354918e32e7a8f30ef61372ce8e7a4f157b73be435459a28" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/embeddings.bin", + "bytes": 308736, + "sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/features.bin", + "bytes": 308736, + "sha256": "2aa845bd42e136f1b35ad5096afea1e33004386879f3cf864a7a3e63c7d14160" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-attention.bin", + "bytes": 308736, + "sha256": "3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-attention-projected.bin", + "bytes": 308736, + "sha256": "79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-attention-scaled.bin", + "bytes": 308736, + "sha256": "60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-final-norm.bin", + "bytes": 308736, + "sha256": "63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-k.bin", + "bytes": 308736, + "sha256": "e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-k-rope.bin", + "bytes": 308736, + "sha256": "2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-mlp-activated.bin", + "bytes": 1234944, + "sha256": "152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-mlp-down.bin", + "bytes": 308736, + "sha256": "344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-mlp-scaled.bin", + "bytes": 308736, + "sha256": "4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-mlp-up.bin", + "bytes": 1234944, + "sha256": "4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-norm1.bin", + "bytes": 308736, + "sha256": "9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-norm2.bin", + "bytes": 308736, + "sha256": "222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-output.bin", + "bytes": 308736, + "sha256": "ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-q.bin", + "bytes": 308736, + "sha256": "d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-q-rope.bin", + "bytes": 308736, + "sha256": "9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-residual.bin", + "bytes": 308736, + "sha256": "62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/first-v.bin", + "bytes": 308736, + "sha256": "2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-embeddings.bin", + "bytes": 308736, + "sha256": "424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-features.bin", + "bytes": 308736, + "sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-attention.bin", + "bytes": 308736, + "sha256": "e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-attention-projected.bin", + "bytes": 308736, + "sha256": "ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-attention-scaled.bin", + "bytes": 308736, + "sha256": "2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-final-norm.bin", + "bytes": 308736, + "sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-k.bin", + "bytes": 308736, + "sha256": "01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-k-rope.bin", + "bytes": 308736, + "sha256": "cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-activated.bin", + "bytes": 1234944, + "sha256": "24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-down.bin", + "bytes": 308736, + "sha256": "a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-scaled.bin", + "bytes": 308736, + "sha256": "04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-up.bin", + "bytes": 1234944, + "sha256": "9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-norm1.bin", + "bytes": 308736, + "sha256": "f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-norm2.bin", + "bytes": 308736, + "sha256": "1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-output.bin", + "bytes": 308736, + "sha256": "c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-q.bin", + "bytes": 308736, + "sha256": "0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-q-rope.bin", + "bytes": 308736, + "sha256": "570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-residual.bin", + "bytes": 308736, + "sha256": "16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/meganeura-first-v.bin", + "bytes": 308736, + "sha256": "d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/pixel_values.bin", + "bytes": 602112, + "sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/reference.json", + "bytes": 792, + "sha256": "8adaf57b9e21f5e1c8760c21f868213157d8372e0ba5e3739a9fd0eaace96c01" + }, + { + "path": "correctness/reference/dinovision-reference-final-1l/verification.json", + "bytes": 9726, + "sha256": "0433671ead625d54224ed8bb57ec99fd3f0dc1829eac5c5974b7b0036242e745" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/embeddings.bin", + "bytes": 308736, + "sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/features.bin", + "bytes": 308736, + "sha256": "5a1e998a4ff5ee62f25af5e8c72ac27f1fa6648ee70c6bc8302027a1898efe11" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-attention.bin", + "bytes": 308736, + "sha256": "3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-attention-projected.bin", + "bytes": 308736, + "sha256": "79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-attention-scaled.bin", + "bytes": 308736, + "sha256": "60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-final-norm.bin", + "bytes": 308736, + "sha256": "63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-k.bin", + "bytes": 308736, + "sha256": "e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-k-rope.bin", + "bytes": 308736, + "sha256": "2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-mlp-activated.bin", + "bytes": 1234944, + "sha256": "152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-mlp-down.bin", + "bytes": 308736, + "sha256": "344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-mlp-scaled.bin", + "bytes": 308736, + "sha256": "4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-mlp-up.bin", + "bytes": 1234944, + "sha256": "4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-norm1.bin", + "bytes": 308736, + "sha256": "9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-norm2.bin", + "bytes": 308736, + "sha256": "222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-output.bin", + "bytes": 308736, + "sha256": "ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-q.bin", + "bytes": 308736, + "sha256": "d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-q-rope.bin", + "bytes": 308736, + "sha256": "9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-residual.bin", + "bytes": 308736, + "sha256": "62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/first-v.bin", + "bytes": 308736, + "sha256": "2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-embeddings.bin", + "bytes": 308736, + "sha256": "424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-features.bin", + "bytes": 308736, + "sha256": "c6342071d5079ef13381fb98937404f610b458b66936fd4d003ad4afb254811b" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-attention.bin", + "bytes": 308736, + "sha256": "e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-attention-projected.bin", + "bytes": 308736, + "sha256": "ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-attention-scaled.bin", + "bytes": 308736, + "sha256": "2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-final-norm.bin", + "bytes": 308736, + "sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-k.bin", + "bytes": 308736, + "sha256": "01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-k-rope.bin", + "bytes": 308736, + "sha256": "cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-activated.bin", + "bytes": 1234944, + "sha256": "24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-down.bin", + "bytes": 308736, + "sha256": "a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-scaled.bin", + "bytes": 308736, + "sha256": "04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-up.bin", + "bytes": 1234944, + "sha256": "9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-norm1.bin", + "bytes": 308736, + "sha256": "f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-norm2.bin", + "bytes": 308736, + "sha256": "1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-output.bin", + "bytes": 308736, + "sha256": "c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-q.bin", + "bytes": 308736, + "sha256": "0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-q-rope.bin", + "bytes": 308736, + "sha256": "570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-residual.bin", + "bytes": 308736, + "sha256": "16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/meganeura-first-v.bin", + "bytes": 308736, + "sha256": "d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/pixel_values.bin", + "bytes": 602112, + "sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/reference.json", + "bytes": 792, + "sha256": "e41899e3b0efc8f625cf85a00fd776fa56c9c0c27ad69eca0e3671153935296f" + }, + { + "path": "correctness/reference/dinovision-reference-final-3l/verification.json", + "bytes": 9731, + "sha256": "d4fcf8774a9d1db31ca6db5f59d13571d1a3c073c17d59e1a4df969d0ce2d66d" + }, + { + "path": "decoder.bin", + "bytes": 8050188, + "sha256": "d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c" + }, + { + "path": "decoder.safetensors", + "bytes": 8052700, + "sha256": "f287b5d1e4e14bed15e4883c3ea5b9f01d28e3123f3fb3308ace714e4b292123" + }, + { + "path": "DINOv3-LICENSE.md", + "bytes": 7503, + "sha256": "25d122eb8f5b880fd23c736fb6ea8018ee45c12237e00b8a86d14c653904999e" + }, + { + "path": "environment/android-build/android-build.json", + "bytes": 1999, + "sha256": "2c885e4aa06c42bc3033cd22d1dba491825b1c59a598cfbc015962f6d6ac82db" + }, + { + "path": "environment/android-build/apk-badging.txt", + "bytes": 1321, + "sha256": "f201346af57402252fc86a2aa0f96d1a05bea665a35d162cfa79af113714d862" + }, + { + "path": "environment/android-build/apk-build.stderr.log", + "bytes": 256, + "sha256": "6b933ec2f905aad57997f6516b3aa9613305eb7891e417dcc2b740088541979e" + }, + { + "path": "environment/android-build/apk-build.stdout.log", + "bytes": 703, + "sha256": "59269be892b423c60564e689facc842d97c281b328e7984491db4eab30a51e17" + }, + { + "path": "environment/android-build/native-build.stderr.log", + "bytes": 114, + "sha256": "88127fd3f4ed22b3c421284cfe740312ca575956f4a9498a08a37435256e5223" + }, + { + "path": "environment/android-build/native-build.stdout.log", + "bytes": 0, + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "path": "environment/publication-source/Cargo.lock", + "bytes": 148764, + "sha256": "d63a639b6af43b0fc1020ada5178902d30978ca51d555f2ea5417927582cbc49" + }, + { + "path": "environment/publication-source/cargo-tree.txt", + "bytes": 22285, + "sha256": "11dcf81c27b6c08381d55195ecf47c700401d4568214652a77fdcb990be42078" + }, + { + "path": "environment/publication-source/metadata.json", + "bytes": 28459, + "sha256": "79281c48c6009956a7de203f39b3983779f69c17c469ad2e3012202f58f3fa63" + }, + { + "path": "environment/publication-source/source-snapshot/.cargo/config.toml", + "bytes": 226, + "sha256": "e7bf454f82c0d679e1bafc31028f74b20994b063fa3e5e86e1339430b05cc47c" + }, + { + "path": "environment/publication-source/source-snapshot/.gitignore", + "bytes": 234, + "sha256": "0e02af3bcd20cfea482ea7d0460506aee7818b580aee468c0efcd40aadec8995" + }, + { + "path": "environment/publication-source/source-snapshot/android/Cargo.toml", + "bytes": 1630, + "sha256": "953097f02a122c40cc714c861862f4afc422e00ee99e46100c4cc6db5f254755" + }, + { + "path": "environment/publication-source/source-snapshot/android/src/lib.rs", + "bytes": 2474, + "sha256": "31baa9646d8af738ebef870bb964e9d033625fcb198d014526665698bc19f969" + }, + { + "path": "environment/publication-source/source-snapshot/android-xr/Cargo.toml", + "bytes": 2854, + "sha256": "1df860091562bb35a2432930acb801a68b9688563b2d450d40a74ea2dc6c3131" + }, + { + "path": "environment/publication-source/source-snapshot/android-xr/src/lib.rs", + "bytes": 35645, + "sha256": "6ba353c26a8b1bba037cc3c1fe5127047cdadbdf1bc51bc070664b4812a86e4b" + }, + { + "path": "environment/publication-source/source-snapshot/Cargo.lock", + "bytes": 148764, + "sha256": "d63a639b6af43b0fc1020ada5178902d30978ca51d555f2ea5417927582cbc49" + }, + { + "path": "environment/publication-source/source-snapshot/Cargo.toml", + "bytes": 2382, + "sha256": "4bc34588dca13c3430b2432b19b585c95e739b68e7f959abe8f280f35d79428c" + }, + { + "path": "environment/publication-source/source-snapshot/examples/bench.rs", + "bytes": 1803, + "sha256": "15577b6f3b2f3e1b28eaf228eb81897ceaa0c237181d24baa2a067de7819a0be" + }, + { + "path": "environment/publication-source/source-snapshot/examples/common/mod.rs", + "bytes": 9570, + "sha256": "97872bb9c929ec510f76cf04ed6643bb063f181d6e7181524b5d80c3d9cc8439" + }, + { + "path": "environment/publication-source/source-snapshot/examples/evaluate_decoder.rs", + "bytes": 19278, + "sha256": "3055791d64ebf488b4a4b837468b00ce49793eaa23a48d201692f7da9631656f" + }, + { + "path": "environment/publication-source/source-snapshot/examples/preview.rs", + "bytes": 5638, + "sha256": "f0beb2e9e0b2a1ddc2d681028a68843a6e570b2972a91b61c10b1d88f0e70c97" + }, + { + "path": "environment/publication-source/source-snapshot/examples/train_decoder.rs", + "bytes": 16740, + "sha256": "c8e28f2d8d78544a665ed6ad2ad620da07aa400aaadd0c8114004530286ae815" + }, + { + "path": "environment/publication-source/source-snapshot/examples/verify.rs", + "bytes": 25706, + "sha256": "e8ef67003e4e23f8c9acf25e6f2a3862c7f119fb993baddfc09f75d667dde850" + }, + { + "path": "environment/publication-source/source-snapshot/examples/viewer.rs", + "bytes": 10350, + "sha256": "b5d655c664f0d929c78d57d4daded61f0746ed885504b7a02b013f6389ab4df6" + }, + { + "path": "environment/publication-source/source-snapshot/experiments/AUDIT.md", + "bytes": 6017, + "sha256": "4216636a6cec96ff699d86d5d6e4cacf332898e39e60c57b7795c42b946950a1" + }, + { + "path": "environment/publication-source/source-snapshot/experiments/paper-section.tex", + "bytes": 5943, + "sha256": "362f8f17eed076a0d2a57ff96e46a07c21d9f5ed4409c686443ae866029ca35e" + }, + { + "path": "environment/publication-source/source-snapshot/experiments/README.md", + "bytes": 10625, + "sha256": "3b8148b63aaaefba589d148cc0bab20e7019720198e96f20db84a3a76b201f1e" + }, + { + "path": "environment/publication-source/source-snapshot/huggingface/DINOv3-LICENSE.md", + "bytes": 7503, + "sha256": "25d122eb8f5b880fd23c736fb6ea8018ee45c12237e00b8a86d14c653904999e" + }, + { + "path": "environment/publication-source/source-snapshot/huggingface/NOTICE.md", + "bytes": 883, + "sha256": "28b2cce3512b7c4d31d6ce435d338aeef9ee29839b198afbf414ec1c02ff3743" + }, + { + "path": "environment/publication-source/source-snapshot/huggingface/README.md", + "bytes": 6940, + "sha256": "c7a4aadf323f9794af72ea967b3b3307ebc08a7dfc5d6225f835613c840df117" + }, + { + "path": "environment/publication-source/source-snapshot/LICENSE", + "bytes": 1094, + "sha256": "602d42a30c16d186e3da4f12fc1eeab2dfc24a6e79da878c63a3ff234c0358e6" + }, + { + "path": "environment/publication-source/source-snapshot/README.md", + "bytes": 17245, + "sha256": "e71dc7dbef867dc9cf7e15bfc0fef603627dd8f855a9af3721f8bb14835638b0" + }, + { + "path": "environment/publication-source/source-snapshot/REPORT.md", + "bytes": 15303, + "sha256": "e0464e9c1a01897c3b1da64184828cf59c8f52166c900f7b3da79e83954e8c97" + }, + { + "path": "environment/publication-source/source-snapshot/src/bench.rs", + "bytes": 17407, + "sha256": "d8c11769ebb9182aaab718f1757e527f0502bb42cdd742577d0db7cebd8f4134" + }, + { + "path": "environment/publication-source/source-snapshot/src/camera.rs", + "bytes": 28374, + "sha256": "93472c94e6d8ce5122b4c7db2731106c7102593cbb4bf444e7bbe9e08aa7b086" + }, + { + "path": "environment/publication-source/source-snapshot/src/decoder.rs", + "bytes": 13220, + "sha256": "feee813cc1a8839d3ce374189e313d4f9c8ba5a087b0ab872fd570da156264b6" + }, + { + "path": "environment/publication-source/source-snapshot/src/dinov3.rs", + "bytes": 19624, + "sha256": "39d372288796a0f7c16bddc7776c14cb09e52bfa1bcfaff240cb576529633385" + }, + { + "path": "environment/publication-source/source-snapshot/src/inference.rs", + "bytes": 13643, + "sha256": "2c8205c9771cfd1848e49ff4eef40492d6c4860b88fdef1e6467d5b520f1b961" + }, + { + "path": "environment/publication-source/source-snapshot/src/lib.rs", + "bytes": 2547, + "sha256": "6b8ad76beffca29d94dcb5aa629f3f65c167c9c52fc8611e2ae48fb129a9cd64" + }, + { + "path": "environment/publication-source/source-snapshot/src/pca.rs", + "bytes": 15878, + "sha256": "252f09f61486e333e0df8ddf34b167ee4de0c2861a7d9169c007061884fa2405" + }, + { + "path": "environment/publication-source/source-snapshot/src/preprocess.rs", + "bytes": 7193, + "sha256": "69a13c6ee542763df8368839f6ae6ab9e082c3e25548b1f53219028c370561b5" + }, + { + "path": "environment/publication-source/source-snapshot/src/render.rs", + "bytes": 13166, + "sha256": "31a0393b5caffff5e248a6fff89988d6368cf0de553491d43574748b16c8a779" + }, + { + "path": "environment/publication-source/source-snapshot/src/shaders/grid_view.wgsl", + "bytes": 2490, + "sha256": "8406eba77ec27f055169edd00d540aeec18dd3c08733d8d9a7f0b2c479cb7869" + }, + { + "path": "environment/publication-source/source-snapshot/src/source.rs", + "bytes": 10284, + "sha256": "11b38e9a06a7090cf2a9864b65eb46c96e429dbdb008b17f104172f0ec5e751d" + }, + { + "path": "environment/publication-source/source-snapshot/src/weights.rs", + "bytes": 6404, + "sha256": "aa69dd605c691246fbe4cf00282aa25e0834681b713e47bfd6ef30369f98547f" + }, + { + "path": "environment/publication-source/source-snapshot/tests/dinov3_ops.rs", + "bytes": 4680, + "sha256": "1ff11a6db0cbccc422a0058a7a5d7e775dba357106cc3e8af3e23f315960387f" + }, + { + "path": "environment/publication-source/source-snapshot/tests/semantics.rs", + "bytes": 5790, + "sha256": "9cf2b851fd96adb9b754ebaeea315f6de02e7bf9f21d3d10b67fd376f28a80f1" + }, + { + "path": "environment/publication-source/source-snapshot/tests/threading.rs", + "bytes": 1352, + "sha256": "df85acc70c20081aa337d7c97f4df9c513c8fd4c42e2aa2d7e798688ce5e3333" + }, + { + "path": "environment/publication-source/source-snapshot/tools/build_android_artifacts.ps1", + "bytes": 4980, + "sha256": "97eedc24b8fc7e4baeb0faa0c023d57cda5d75d7ba9f9f1a04868d3563d8201b" + }, + { + "path": "environment/publication-source/source-snapshot/tools/collect_artifact_metadata.ps1", + "bytes": 6601, + "sha256": "4574dea9d7ec0a7f87d9439b7fbc03e78a3a407bbb3ec53edeca5c0b61853f95" + }, + { + "path": "environment/publication-source/source-snapshot/tools/compare_f32.py", + "bytes": 6380, + "sha256": "828f71146de6ac26aa40df27cec1170c0af4030c9d87cce87c5138c22d78e137" + }, + { + "path": "environment/publication-source/source-snapshot/tools/convert_decoder.py", + "bytes": 3286, + "sha256": "962853f90e35a726d2f69f0f6fba2da4071efc12e8c3f200f695178a0377b9b6" + }, + { + "path": "environment/publication-source/source-snapshot/tools/dump_reference.py", + "bytes": 9405, + "sha256": "81fc39d70a6c381c1e5f871563672ea96818ff88995472f6ddb68cf35734ef29" + }, + { + "path": "environment/publication-source/source-snapshot/tools/extract_json_records.py", + "bytes": 1927, + "sha256": "c5b8027cb6c8b1f57623c7543be0ce2925ad3e340c2a1bb510b3fa9f3c66cd3a" + }, + { + "path": "environment/publication-source/source-snapshot/tools/make_correctness_frame.py", + "bytes": 1302, + "sha256": "87aacc02d8ae4b875fc3d519cd02f487c4187ebbcb7a752bbfddaf2f1bec7a28" + }, + { + "path": "environment/publication-source/source-snapshot/tools/make_dataset_manifest.py", + "bytes": 4991, + "sha256": "d48f07f60af6c00edda4a8533e4ee5a265a924d2d6451898a8b0932e29343a11" + }, + { + "path": "environment/publication-source/source-snapshot/tools/pull_quest_artifacts.ps1", + "bytes": 3630, + "sha256": "ece78fdb0eba1dd8f9c260f32565dee481965c0c4803795ccfdb58d82f9c7438" + }, + { + "path": "environment/publication-source/source-snapshot/tools/run_cross_device_correctness.ps1", + "bytes": 8028, + "sha256": "114a673ab08ff8b5de534194d2efd19ff41ac6f3ff274ba70fa1f8532cef5195" + }, + { + "path": "environment/publication-source/source-snapshot/tools/run_decoder_matrix.ps1", + "bytes": 5352, + "sha256": "1f95ff681375b334dde39bab509c087321e6c531a9be04f47d65348dea9ccaef" + }, + { + "path": "environment/publication-source/source-snapshot/tools/run_quest_bench.ps1", + "bytes": 6501, + "sha256": "0b6966cbcd06109ddee85e5a0746468ffe3932cd3748c0b4b4743eb23e1b34cf" + }, + { + "path": "environment/publication-source/source-snapshot/tools/run_xr_sweep.ps1", + "bytes": 12220, + "sha256": "d7f07831ff8c4b237193809563f9c5296783c24d8ac97c333ab5f71bd49b0df1" + }, + { + "path": "environment/publication-source/source-snapshot/tools/stage_huggingface_artifact.ps1", + "bytes": 13033, + "sha256": "cdf19145fa5dc8b6c9fd387719855ebe354312add1b12f0aef77fc13db921069" + }, + { + "path": "environment/publication-source/source-snapshot/tools/summarize_bench.py", + "bytes": 5935, + "sha256": "94e4b431dad735c1233764018e43fafcfca194ccf75bfa6f14a159adeac17c12" + }, + { + "path": "environment/publication-source/source-snapshot/tools/summarize_dataset.py", + "bytes": 4905, + "sha256": "cc9e1d1f6c36a5e792194ca7d77ef14674d3eed591994070d6c277786f26d144" + }, + { + "path": "environment/publication-source/source-snapshot/tools/summarize_determinism.py", + "bytes": 3104, + "sha256": "65595ff079187c9e72fd80b0ad8dcbdca5368cda20d4fa4bf078b17eee80450a" + }, + { + "path": "environment/publication-source/source-snapshot/tools/summarize_quality.py", + "bytes": 8713, + "sha256": "4fa1965d098029b85e5224c44fcb209f9771734ef25d559a9807d77489f80f98" + }, + { + "path": "environment/publication-source/source-snapshot/tools/summarize_xr.py", + "bytes": 8249, + "sha256": "f78e44b7f1e81cb7b3d35e366b75fb464d6d76c84c23879e10f458794b4a640c" + }, + { + "path": "environment/publication-source/source-snapshot/tools/verify_huggingface_artifact.py", + "bytes": 19913, + "sha256": "2bd2b68f78040ec233763e44435e6f706a67886619be8992f2b3b0b3733fcb5e" + }, + { + "path": "environment/training-source/Cargo.lock", + "bytes": 148764, + "sha256": "d63a639b6af43b0fc1020ada5178902d30978ca51d555f2ea5417927582cbc49" + }, + { + "path": "environment/training-source/cargo-tree.txt", + "bytes": 22285, + "sha256": "11dcf81c27b6c08381d55195ecf47c700401d4568214652a77fdcb990be42078" + }, + { + "path": "environment/training-source/metadata.json", + "bytes": 27156, + "sha256": "bdd5419fbe7e857664429fe5ca671ef2292bd1a976338871b4e2b4abad355a5e" + }, + { + "path": "environment/training-source/source-snapshot/.cargo/config.toml", + "bytes": 226, + "sha256": "e7bf454f82c0d679e1bafc31028f74b20994b063fa3e5e86e1339430b05cc47c" + }, + { + "path": "environment/training-source/source-snapshot/.gitignore", + "bytes": 212, + "sha256": "5de7d69c3185414fd51c15aa33e4d104d6b7c1771431d97cae3920897b79a646" + }, + { + "path": "environment/training-source/source-snapshot/android/Cargo.toml", + "bytes": 1630, + "sha256": "953097f02a122c40cc714c861862f4afc422e00ee99e46100c4cc6db5f254755" + }, + { + "path": "environment/training-source/source-snapshot/android/src/lib.rs", + "bytes": 2474, + "sha256": "31baa9646d8af738ebef870bb964e9d033625fcb198d014526665698bc19f969" + }, + { + "path": "environment/training-source/source-snapshot/android-xr/Cargo.toml", + "bytes": 2854, + "sha256": "1df860091562bb35a2432930acb801a68b9688563b2d450d40a74ea2dc6c3131" + }, + { + "path": "environment/training-source/source-snapshot/android-xr/src/lib.rs", + "bytes": 36602, + "sha256": "dc39d9f6393482d325ec69fba83d0d846a76ddb8328164766d9445d74f981f52" + }, + { + "path": "environment/training-source/source-snapshot/Cargo.lock", + "bytes": 148764, + "sha256": "d63a639b6af43b0fc1020ada5178902d30978ca51d555f2ea5417927582cbc49" + }, + { + "path": "environment/training-source/source-snapshot/Cargo.toml", + "bytes": 2382, + "sha256": "4bc34588dca13c3430b2432b19b585c95e739b68e7f959abe8f280f35d79428c" + }, + { + "path": "environment/training-source/source-snapshot/examples/bench.rs", + "bytes": 1803, + "sha256": "15577b6f3b2f3e1b28eaf228eb81897ceaa0c237181d24baa2a067de7819a0be" + }, + { + "path": "environment/training-source/source-snapshot/examples/common/mod.rs", + "bytes": 9570, + "sha256": "97872bb9c929ec510f76cf04ed6643bb063f181d6e7181524b5d80c3d9cc8439" + }, + { + "path": "environment/training-source/source-snapshot/examples/evaluate_decoder.rs", + "bytes": 19279, + "sha256": "787b705331097ed8963a4d3569f94f72db0e3fb9fffd65ecc17488eb9f2cd1e5" + }, + { + "path": "environment/training-source/source-snapshot/examples/preview.rs", + "bytes": 5638, + "sha256": "f0beb2e9e0b2a1ddc2d681028a68843a6e570b2972a91b61c10b1d88f0e70c97" + }, + { + "path": "environment/training-source/source-snapshot/examples/train_decoder.rs", + "bytes": 16719, + "sha256": "cf9bb19634e9a08a6e98c8d536101095d841ed616b6272f0e013bfb5b86d7f10" + }, + { + "path": "environment/training-source/source-snapshot/examples/verify.rs", + "bytes": 22762, + "sha256": "241d70da7320526fa89fca9cb209cf839df398e051b9b26ccfe3ca5ca93073b7" + }, + { + "path": "environment/training-source/source-snapshot/examples/viewer.rs", + "bytes": 10350, + "sha256": "b5d655c664f0d929c78d57d4daded61f0746ed885504b7a02b013f6389ab4df6" + }, + { + "path": "environment/training-source/source-snapshot/experiments/AUDIT.md", + "bytes": 4945, + "sha256": "f3a2326e3e18e3937a074a4c69ec173ca911afbc1cc5064d87cec26d63108c2f" + }, + { + "path": "environment/training-source/source-snapshot/experiments/README.md", + "bytes": 7613, + "sha256": "dfd4018c60965d425a365a4886bf269daaf29801fcef68ed7c6cf960340b8b37" + }, + { + "path": "environment/training-source/source-snapshot/huggingface/DINOv3-LICENSE.md", + "bytes": 7503, + "sha256": "25d122eb8f5b880fd23c736fb6ea8018ee45c12237e00b8a86d14c653904999e" + }, + { + "path": "environment/training-source/source-snapshot/huggingface/NOTICE.md", + "bytes": 883, + "sha256": "28b2cce3512b7c4d31d6ce435d338aeef9ee29839b198afbf414ec1c02ff3743" + }, + { + "path": "environment/training-source/source-snapshot/huggingface/README.md", + "bytes": 5358, + "sha256": "1f03054b826a7136367452913a67e829473fc9fd9e69eb44248d1f09222ea571" + }, + { + "path": "environment/training-source/source-snapshot/LICENSE", + "bytes": 1094, + "sha256": "602d42a30c16d186e3da4f12fc1eeab2dfc24a6e79da878c63a3ff234c0358e6" + }, + { + "path": "environment/training-source/source-snapshot/README.md", + "bytes": 17245, + "sha256": "e71dc7dbef867dc9cf7e15bfc0fef603627dd8f855a9af3721f8bb14835638b0" + }, + { + "path": "environment/training-source/source-snapshot/REPORT.md", + "bytes": 12167, + "sha256": "1fa8109553226482eaa59eb080ba9cb2a5901106948cec6430381e10a1a4d149" + }, + { + "path": "environment/training-source/source-snapshot/src/bench.rs", + "bytes": 17678, + "sha256": "3bf99e83e2e8854730b34b5b0801172126c3f616371592d159b2ceb00405a35f" + }, + { + "path": "environment/training-source/source-snapshot/src/camera.rs", + "bytes": 28374, + "sha256": "93472c94e6d8ce5122b4c7db2731106c7102593cbb4bf444e7bbe9e08aa7b086" + }, + { + "path": "environment/training-source/source-snapshot/src/decoder.rs", + "bytes": 13220, + "sha256": "feee813cc1a8839d3ce374189e313d4f9c8ba5a087b0ab872fd570da156264b6" + }, + { + "path": "environment/training-source/source-snapshot/src/dinov3.rs", + "bytes": 20328, + "sha256": "09bcaad52dbeafe2992a1f7386d6444baae38a8f65a6f4c3a76266a0ec44145e" + }, + { + "path": "environment/training-source/source-snapshot/src/inference.rs", + "bytes": 13643, + "sha256": "2c8205c9771cfd1848e49ff4eef40492d6c4860b88fdef1e6467d5b520f1b961" + }, + { + "path": "environment/training-source/source-snapshot/src/lib.rs", + "bytes": 2547, + "sha256": "6b8ad76beffca29d94dcb5aa629f3f65c167c9c52fc8611e2ae48fb129a9cd64" + }, + { + "path": "environment/training-source/source-snapshot/src/pca.rs", + "bytes": 15878, + "sha256": "252f09f61486e333e0df8ddf34b167ee4de0c2861a7d9169c007061884fa2405" + }, + { + "path": "environment/training-source/source-snapshot/src/preprocess.rs", + "bytes": 7193, + "sha256": "69a13c6ee542763df8368839f6ae6ab9e082c3e25548b1f53219028c370561b5" + }, + { + "path": "environment/training-source/source-snapshot/src/render.rs", + "bytes": 13166, + "sha256": "31a0393b5caffff5e248a6fff89988d6368cf0de553491d43574748b16c8a779" + }, + { + "path": "environment/training-source/source-snapshot/src/shaders/grid_view.wgsl", + "bytes": 2490, + "sha256": "8406eba77ec27f055169edd00d540aeec18dd3c08733d8d9a7f0b2c479cb7869" + }, + { + "path": "environment/training-source/source-snapshot/src/source.rs", + "bytes": 10284, + "sha256": "11b38e9a06a7090cf2a9864b65eb46c96e429dbdb008b17f104172f0ec5e751d" + }, + { + "path": "environment/training-source/source-snapshot/src/weights.rs", + "bytes": 6404, + "sha256": "aa69dd605c691246fbe4cf00282aa25e0834681b713e47bfd6ef30369f98547f" + }, + { + "path": "environment/training-source/source-snapshot/tests/dinov3_ops.rs", + "bytes": 4680, + "sha256": "1ff11a6db0cbccc422a0058a7a5d7e775dba357106cc3e8af3e23f315960387f" + }, + { + "path": "environment/training-source/source-snapshot/tests/semantics.rs", + "bytes": 5790, + "sha256": "9cf2b851fd96adb9b754ebaeea315f6de02e7bf9f21d3d10b67fd376f28a80f1" + }, + { + "path": "environment/training-source/source-snapshot/tests/threading.rs", + "bytes": 1352, + "sha256": "df85acc70c20081aa337d7c97f4df9c513c8fd4c42e2aa2d7e798688ce5e3333" + }, + { + "path": "environment/training-source/source-snapshot/tools/build_android_artifacts.ps1", + "bytes": 4980, + "sha256": "97eedc24b8fc7e4baeb0faa0c023d57cda5d75d7ba9f9f1a04868d3563d8201b" + }, + { + "path": "environment/training-source/source-snapshot/tools/collect_artifact_metadata.ps1", + "bytes": 6601, + "sha256": "4574dea9d7ec0a7f87d9439b7fbc03e78a3a407bbb3ec53edeca5c0b61853f95" + }, + { + "path": "environment/training-source/source-snapshot/tools/compare_f32.py", + "bytes": 6380, + "sha256": "828f71146de6ac26aa40df27cec1170c0af4030c9d87cce87c5138c22d78e137" + }, + { + "path": "environment/training-source/source-snapshot/tools/convert_decoder.py", + "bytes": 3286, + "sha256": "962853f90e35a726d2f69f0f6fba2da4071efc12e8c3f200f695178a0377b9b6" + }, + { + "path": "environment/training-source/source-snapshot/tools/dump_reference.py", + "bytes": 9405, + "sha256": "81fc39d70a6c381c1e5f871563672ea96818ff88995472f6ddb68cf35734ef29" + }, + { + "path": "environment/training-source/source-snapshot/tools/extract_json_records.py", + "bytes": 1927, + "sha256": "c5b8027cb6c8b1f57623c7543be0ce2925ad3e340c2a1bb510b3fa9f3c66cd3a" + }, + { + "path": "environment/training-source/source-snapshot/tools/make_correctness_frame.py", + "bytes": 1302, + "sha256": "87aacc02d8ae4b875fc3d519cd02f487c4187ebbcb7a752bbfddaf2f1bec7a28" + }, + { + "path": "environment/training-source/source-snapshot/tools/make_dataset_manifest.py", + "bytes": 4991, + "sha256": "d48f07f60af6c00edda4a8533e4ee5a265a924d2d6451898a8b0932e29343a11" + }, + { + "path": "environment/training-source/source-snapshot/tools/pull_quest_artifacts.ps1", + "bytes": 3202, + "sha256": "eda42f889f2a884cf82eec03375608212a7f50f2c8c0fbc2a7de6529afba2626" + }, + { + "path": "environment/training-source/source-snapshot/tools/run_cross_device_correctness.ps1", + "bytes": 6833, + "sha256": "1eb0d95bac5b6808bdd982d2c7047a096442e8a8973ab516538fc746a42c9fff" + }, + { + "path": "environment/training-source/source-snapshot/tools/run_decoder_matrix.ps1", + "bytes": 5352, + "sha256": "1f95ff681375b334dde39bab509c087321e6c531a9be04f47d65348dea9ccaef" + }, + { + "path": "environment/training-source/source-snapshot/tools/run_quest_bench.ps1", + "bytes": 6501, + "sha256": "0b6966cbcd06109ddee85e5a0746468ffe3932cd3748c0b4b4743eb23e1b34cf" + }, + { + "path": "environment/training-source/source-snapshot/tools/run_xr_sweep.ps1", + "bytes": 10711, + "sha256": "73853e9647a029ef0ea7b0190eaa757ee96b10ea80110aa5b731280eb0eaf8a4" + }, + { + "path": "environment/training-source/source-snapshot/tools/stage_huggingface_artifact.ps1", + "bytes": 9571, + "sha256": "7bb2fa6c4716fdd183c57ef0da743a306ad1d383083093c009032d7859bf1b3e" + }, + { + "path": "environment/training-source/source-snapshot/tools/summarize_bench.py", + "bytes": 5935, + "sha256": "94e4b431dad735c1233764018e43fafcfca194ccf75bfa6f14a159adeac17c12" + }, + { + "path": "environment/training-source/source-snapshot/tools/summarize_dataset.py", + "bytes": 4905, + "sha256": "cc9e1d1f6c36a5e792194ca7d77ef14674d3eed591994070d6c277786f26d144" + }, + { + "path": "environment/training-source/source-snapshot/tools/summarize_quality.py", + "bytes": 8713, + "sha256": "4fa1965d098029b85e5224c44fcb209f9771734ef25d559a9807d77489f80f98" + }, + { + "path": "environment/training-source/source-snapshot/tools/summarize_xr.py", + "bytes": 8249, + "sha256": "f78e44b7f1e81cb7b3d35e366b75fb464d6d76c84c23879e10f458794b4a640c" + }, + { + "path": "manifests/correctness-224.json", + "bytes": 370, + "sha256": "94b10d1640c3e09b3eecec8abea64ec0cdd128032ad60a0e31d246ac932b178f" + }, + { + "path": "manifests/dataset-summary.json", + "bytes": 1581, + "sha256": "4ff2357e9125d604d99e25eaabb6c1487004a95979b901224c9e5d5d5c2e24c5" + }, + { + "path": "manifests/dataset-summary.md", + "bytes": 561, + "sha256": "52b0016a9754014032c785f2c23d705a1f1001a0a82bb7ff0fe3c84ce94c59b2" + }, + { + "path": "manifests/imagenette2-320.json", + "bytes": 3845327, + "sha256": "2071f89b2a7b077d7729641fc858e1225d057d11a797d16198c0d195d989bb89" + }, + { + "path": "NOTICE.md", + "bytes": 883, + "sha256": "28b2cce3512b7c4d31d6ce435d338aeef9ee29839b198afbf414ec1c02ff3743" + }, + { + "path": "quality/3l224-seed0.json", + "bytes": 1558199, + "sha256": "bd5d58f4710a44583d9f6282e324815eef331426b8a6b7f83f2c1bfd1989fb53" + }, + { + "path": "quality/3l224-seed1.json", + "bytes": 1558361, + "sha256": "e1f1aeb1b533cfecfeb57d79d2920d7dac7737fffad408038935febe80049a3d" + }, + { + "path": "quality/3l224-seed2.json", + "bytes": 1558299, + "sha256": "2155d1d230dca1a828b6588fa74c85506cf800bfbc954622ffdfe7720197937a" + }, + { + "path": "quality/summary.json", + "bytes": 4423, + "sha256": "06d34ea8eff9d0bf50dbae467891347d7032bcd85b5080b45d381bca02ba4350" + }, + { + "path": "quality/summary.md", + "bytes": 841, + "sha256": "619779b0ca59e82f961c99611c1200519371a7b1504ad08665db36120ab78c60" + }, + { + "path": "README.md", + "bytes": 6940, + "sha256": "c7a4aadf323f9794af72ea967b3b3307ebc08a7dfc5d6225f835613c840df117" + }, + { + "path": "replicates/3l224-seed0/decoder.bin", + "bytes": 8050188, + "sha256": "d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c" + }, + { + "path": "replicates/3l224-seed0/decoder.safetensors", + "bytes": 8052700, + "sha256": "f287b5d1e4e14bed15e4883c3ea5b9f01d28e3123f3fb3308ace714e4b292123" + }, + { + "path": "replicates/3l224-seed0/evaluation.stderr.log", + "bytes": 3242, + "sha256": "6ce6617fd3feae5a550fd1a7b5dd7edf2a8c271296b03c2a2eb554caa90fe629" + }, + { + "path": "replicates/3l224-seed0/evaluation.stdout.log", + "bytes": 292, + "sha256": "e9ba6deb0f30c47ae10a4d7571d55a2d49732dd49b8c5f54c4931b51b8f71a35" + }, + { + "path": "replicates/3l224-seed0/run-notes.json", + "bytes": 171, + "sha256": "940531455fb94831bc2691ae8110738b2293b3e5bf099a52c22c16984267e782" + }, + { + "path": "replicates/3l224-seed0/training.json", + "bytes": 1258, + "sha256": "bc5eed223d2b53886ec6de0966ed5c61cf61ddb7a771cb238246fa074fbd7306" + }, + { + "path": "replicates/3l224-seed0/training.stderr.log", + "bytes": 169492, + "sha256": "8dbb18d7c1dc4c8cc30b74689b6da39609a6719528a77abd911f7bd60c87b2dc" + }, + { + "path": "replicates/3l224-seed0/training.stdout.log", + "bytes": 366, + "sha256": "b1b89daefc3ded47c8c830ef07f8654df429f13c1013ee7516e33efad2329c11" + }, + { + "path": "replicates/3l224-seed1/decoder.bin", + "bytes": 8050188, + "sha256": "1dbc2b99603604814e5d6f99f3a5ed765863c3e2db5012fd95d8bc87954879a6" + }, + { + "path": "replicates/3l224-seed1/decoder.safetensors", + "bytes": 8052700, + "sha256": "1dcffb47b5c5ce5496286558600223f64a55512057e098c2bf0b3b9566c20700" + }, + { + "path": "replicates/3l224-seed1/evaluation.stderr.log", + "bytes": 3136, + "sha256": "3ef807cf96877d7e72ecefab30732675d5b3237728b871279b30bdc2ba723340" + }, + { + "path": "replicates/3l224-seed1/evaluation.stdout.log", + "bytes": 292, + "sha256": "186a5dfac4a286e2afdbcd920ace8a8ef42cc5fc97c7bee1fdc26a686dafd0cb" + }, + { + "path": "replicates/3l224-seed1/run-notes.json", + "bytes": 171, + "sha256": "940531455fb94831bc2691ae8110738b2293b3e5bf099a52c22c16984267e782" + }, + { + "path": "replicates/3l224-seed1/training.json", + "bytes": 1258, + "sha256": "d6aafde4237e5582de8a42184780be82f04e421ea67393ed2e6fce77493dadd0" + }, + { + "path": "replicates/3l224-seed1/training.stderr.log", + "bytes": 169494, + "sha256": "127aa130557aa9fe442f16d6e0239c022e741b74e135e6d9c034d76b78313149" + }, + { + "path": "replicates/3l224-seed1/training.stdout.log", + "bytes": 366, + "sha256": "6046c8d864a14c11cda29fbdb6a9038bc04b7fc35fe2956d654e0fe14424c653" + }, + { + "path": "replicates/3l224-seed2/decoder.bin", + "bytes": 8050188, + "sha256": "2085a6923760c0266c4f965db2014afd7cf4b7fcbde2c203d9e399c37fe2af67" + }, + { + "path": "replicates/3l224-seed2/decoder.safetensors", + "bytes": 8052700, + "sha256": "82d5178115a6251e69f72061d0ec5907c4968e89ee9f8d3fe53b32a26e9f7bfc" + }, + { + "path": "replicates/3l224-seed2/evaluation.stderr.log", + "bytes": 3136, + "sha256": "8f1b66f504df579523495391a43d1045eb35aae0899cdc1bba0705ebad230ff1" + }, + { + "path": "replicates/3l224-seed2/evaluation.stdout.log", + "bytes": 292, + "sha256": "c4ffca979ad80407d08856121950f9347ef7d9c1df1569eaec1d8ae1f67b0af1" + }, + { + "path": "replicates/3l224-seed2/run-notes.json", + "bytes": 289, + "sha256": "7181fa6dce7daa22fbb86d657f924d1ec307d4e4613a77a3fd2d0ba87e2e8846" + }, + { + "path": "replicates/3l224-seed2/training.json", + "bytes": 1258, + "sha256": "b38d16c0ee4d2b4e4d07c407af6e2dfc98308b91d14cd14dadac83cd9e02b02f" + }, + { + "path": "replicates/3l224-seed2/training.stderr.log", + "bytes": 169598, + "sha256": "8338b83a591e389b8864d6fac360509bb6b9a156282d38a99ace748fd2ac1d7c" + }, + { + "path": "replicates/3l224-seed2/training.stdout.log", + "bytes": 366, + "sha256": "e4e0066ca253d72dc754937cccc8b9eacd4485716ceee9ea4264ad17c36cf214" + }, + { + "path": "reproducibility/determinism.json", + "bytes": 1650, + "sha256": "a0681f63e8ac8a1140b98919371f600692917db87ac05e467378648b5415bd0e" + }, + { + "path": "reproducibility/runs/dinovision-determinism-a/training.json", + "bytes": 1242, + "sha256": "5c69394e4a3f8e7ce01efb591b850385bca602ff0fee2b931881336dfdf91885" + }, + { + "path": "reproducibility/runs/dinovision-determinism-b/training.json", + "bytes": 1251, + "sha256": "a4d4eac0314145ddfad16c7c3b9d63a0e3690a0613cbc97f1a874178a1ae79c0" + }, + { + "path": "training.json", + "bytes": 1258, + "sha256": "bc5eed223d2b53886ec6de0966ed5c61cf61ddb7a771cb238246fa074fbd7306" + } + ] +} diff --git a/DINOv3-LICENSE.md b/DINOv3-LICENSE.md new file mode 100644 index 0000000000000000000000000000000000000000..f531b1e6b5ab2318957bbf8ad1bda9f800a23e17 --- /dev/null +++ b/DINOv3-LICENSE.md @@ -0,0 +1,66 @@ +# DINOv3 License + +*Last Updated: August 19, 2025* + +**“Agreement”** means the terms and conditions for use, reproduction, distribution and modification of the DINO Materials set forth herein. + +**“DINO Materials”** means, collectively, Documentation and the models, software and algorithms, including machine-learning model code, trained model weights, inference-enabling code, training-enabling code, fine-tuning enabling code, and other elements of the foregoing distributed by Meta and made available under this Agreement. + +**“Documentation”** means the specifications, manuals and documentation accompanying +DINO Materials distributed by Meta. + +**“Licensee”** or **“you”** means you, or your employer or any other person or entity (if you are entering into this Agreement on such person or entity’s behalf), of the age required under applicable laws, rules or regulations to provide legal consent and that has legal authority to bind your employer or such other person or entity if you are entering in this Agreement on their behalf. + +**“Meta”** or **“we”** means Meta Platforms Ireland Limited (if you are located in or, if you are an entity, your principal place of business is in the EEA or Switzerland) or Meta Platforms, Inc. (if you are located outside of the EEA or Switzerland). + +**“Sanctions”** means any economic or trade sanctions or restrictions administered or enforced by the United States (including the Office of Foreign Assets Control of the U.S. Department of the Treasury (“OFAC”), the U.S. Department of State and the U.S. Department of Commerce), the United Nations, the European Union, or the United Kingdom. + +**“Trade Controls”** means any of the following: Sanctions and applicable export and import controls. + +By clicking “I Accept” below or by using or distributing any portion or element of the DINO Materials, you agree to be bound by this Agreement. + +## 1. License Rights and Redistribution. + +a. Grant of Rights. You are granted a non-exclusive, worldwide, non-transferable and royalty-free limited license under Meta’s intellectual property or other rights owned by Meta embodied in the DINO Materials to use, reproduce, distribute, copy, create derivative works of, and make modifications to the DINO Materials. + +b. Redistribution and Use. + +i. Distribution of DINO Materials, and any derivative works thereof, are subject to the terms of this Agreement. If you distribute or make the DINO Materials, or any derivative works thereof, available to a third party, you may only do so under the terms of this Agreement and you shall provide a copy of this Agreement with any such DINO Materials. + +ii. If you submit for publication the results of research you perform on, using, or otherwise in connection with DINO Materials, you must acknowledge the use of DINO Materials in your publication. + +iii. Your use of the DINO Materials must comply with applicable laws and regulations, including Trade Control Laws and applicable privacy and data protection laws. + +iv. Your use of the DINO Materials will not involve or encourage others to reverse engineer, decompile or discover the underlying components of the DINO Materials. + +v. You are not the target of Trade Controls and your use of DINO Materials must comply with Trade Controls. You agree not to use, or permit others to use, DINO Materials for any activities subject to the International Traffic in Arms Regulations (ITAR) or end uses prohibited by Trade Controls, including those related to military or warfare purposes, nuclear industries or applications, espionage, or the development or use of guns or illegal weapons. + +## 2. User Support. + +Your use of the DINO Materials is done at your own discretion; Meta does not process any information nor provide any service in relation to such use. Meta is under no obligation to provide any support services for the DINO Materials. Any support provided is “as is”, “with all faults”, and without warranty of any kind. + +## 3. Disclaimer of Warranty. + +UNLESS REQUIRED BY APPLICABLE LAW, THE DINO MATERIALS AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED ON AN “AS IS” BASIS, WITHOUT WARRANTIES OF ANY KIND, AND META DISCLAIMS ALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE DINO MATERIALS AND ASSUME ANY RISKS ASSOCIATED WITH YOUR USE OF THE DINO MATERIALS AND ANY OUTPUT AND RESULTS. + +## 4. Limitation of Liability. + +IN NO EVENT WILL META OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, FOR ANY LOST PROFITS OR ANY DIRECT OR INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF META OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING. + +## 5. Intellectual Property. + +a. Subject to Meta’s ownership of DINO Materials and derivatives made by or for Meta, with respect to any derivative works and modifications of the DINO Materials that are made by you, as between you and Meta, you are and will be the owner of such derivative works and modifications. + +b. If you institute litigation or other proceedings against Meta or any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the DINO Materials, outputs or results, or any portion of any of the foregoing, constitutes infringement of intellectual property or other rights owned or licensable by you, then any licenses granted to you under this Agreement shall terminate as of the date such litigation or claim is filed or instituted. You will indemnify and hold harmless Meta from and against any claim by any third party arising out of or related to your use or distribution of the DINO Materials. + +## 6. Term and Termination. + +The term of this Agreement will commence upon your acceptance of this Agreement or access to the DINO Materials and will continue in full force and effect until terminated in accordance with the terms and conditions herein. Meta may terminate this Agreement if you are in breach of any term or condition of this Agreement. Upon termination of this Agreement, you shall delete and cease use of the DINO Materials. Sections 3, 4 and 7 shall survive the termination of this Agreement. + +## 7. Governing Law and Jurisdiction. + +This Agreement will be governed and construed under the laws of the State of California without regard to choice of law principles, and the UN Convention on Contracts for the International Sale of Goods does not apply to this Agreement. The courts of California shall have exclusive jurisdiction of any dispute arising out of this Agreement. + +## 8. Modifications and Amendments. + +Meta may modify this Agreement from time to time; provided that they are similar in spirit to the current version of the Agreement, but may differ in detail to address new problems or concerns. All such changes will be effective immediately. Your continued use of the DINO Materials after any modification to this Agreement constitutes your agreement to such modification. Except as provided in this Agreement, no modification or addition to any provision of this Agreement will be binding unless it is in writing and signed by an authorized representative of both you and Meta. diff --git a/correctness/frame.rgb b/correctness/frame.rgb new file mode 100644 index 0000000000000000000000000000000000000000..3c3c4c2ec5380c5e68978dea8ff3608c66fee84e --- /dev/null +++ b/correctness/frame.rgb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b89c2000b8877bce4649610e490579eef1ada5b29867f7a773d88450549ad1a8 +size 150528 diff --git a/correctness/host/quality.json b/correctness/host/quality.json new file mode 100644 index 0000000000000000000000000000000000000000..77f1422dd9c1b90e82fc669b51eafb99b603df76 --- /dev/null +++ b/correctness/host/quality.json @@ -0,0 +1,56 @@ +{ + "schema_version": 1, + "created_unix_seconds": 1785642778, + "dataset_name": "dinovision-correctness-224", + "manifest": "C:/tmp/dinovision-correctness/manifests/correctness-224.json", + "manifest_sha256": "94b10d1640c3e09b3eecec8abea64ec0cdd128032ad60a0e31d246ac932b178f", + "split": "test", + "image_size": 224, + "encoder_layers": 3, + "model": "C:/tmp/dinovision-assets/model.safetensors", + "model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d", + "decoder": "C:/tmp/dinovision-runs-corrected-v2/3l224-seed0/decoder.bin", + "decoder_sha256": "d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c", + "elapsed_seconds": 0.0803737, + "summary": { + "count": 1, + "global_psnr_db": 15.31123604981094, + "psnr_db": { + "mean": 15.31123604981094, + "median": 15.31123604981094, + "p25": 15.31123604981094, + "p75": 15.31123604981094, + "min": 15.31123604981094, + "max": 15.31123604981094 + }, + "ssim": { + "mean": 0.6935712951367996, + "median": 0.6935712951367996, + "p25": 0.6935712951367996, + "p75": 0.6935712951367996, + "min": 0.6935712951367996, + "max": 0.6935712951367996 + }, + "mae": { + "mean": 0.11556125122496931, + "median": 0.11556125122496931, + "p25": 0.11556125122496931, + "p75": 0.11556125122496931, + "min": 0.11556125122496931, + "max": 0.11556125122496931 + } + }, + "images": [ + { + "path": "input/frame.rgb", + "source": "synthetic", + "group": "fixed-frame", + "sha256": "b89c2000b8877bce4649610e490579eef1ada5b29867f7a773d88450549ad1a8", + "pixels": 50176, + "mse": 0.02943583738294543, + "mae": 0.11556125122496931, + "psnr_db": 15.31123604981094, + "ssim": 0.6935712951367996 + } + ] +} \ No newline at end of file diff --git a/correctness/host/quality_samples/0000-encoder.f32 b/correctness/host/quality_samples/0000-encoder.f32 new file mode 100644 index 0000000000000000000000000000000000000000..f48d021ba0407bc8656901be1c49f3f1cec27911 --- /dev/null +++ b/correctness/host/quality_samples/0000-encoder.f32 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca6b60574ccd26d8c6189c4c9a1ef143d60263c86bb6232d2a758552ed1db1e6 +size 308736 diff --git a/correctness/host/quality_samples/0000-features.f32 b/correctness/host/quality_samples/0000-features.f32 new file mode 100644 index 0000000000000000000000000000000000000000..618a618386a91118b13de355ecb09e76de6a81b9 --- /dev/null +++ b/correctness/host/quality_samples/0000-features.f32 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:899d9e027e9b63495e4aa09125872431611591d509d1f112c9decd4fbde8efca +size 301056 diff --git a/correctness/host/quality_samples/0000-patches.f32 b/correctness/host/quality_samples/0000-patches.f32 new file mode 100644 index 0000000000000000000000000000000000000000..6d9565a10d36b2e22c8e07d174a913d45a922750 --- /dev/null +++ b/correctness/host/quality_samples/0000-patches.f32 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:222d3d93fbdcf3eca93ddec0a6d210384977bb48d17d5cf2da53d1d0175d92af +size 602112 diff --git a/correctness/host/quality_samples/0000-reconstruction.f32 b/correctness/host/quality_samples/0000-reconstruction.f32 new file mode 100644 index 0000000000000000000000000000000000000000..522b4d0b7d8c0e25c0b642e373e5384864099a11 --- /dev/null +++ b/correctness/host/quality_samples/0000-reconstruction.f32 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81873eb7b3698e7205fcb26b4838c5730f6bc3abbfc6a0bcb8a6a8a484fb6deb +size 602112 diff --git a/correctness/reference/dinovision-reference-final-0l/embeddings.bin b/correctness/reference/dinovision-reference-final-0l/embeddings.bin new file mode 100644 index 0000000000000000000000000000000000000000..9be47ad6bb50191c631037cb973ea58b995befcc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/embeddings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/features.bin b/correctness/reference/dinovision-reference-final-0l/features.bin new file mode 100644 index 0000000000000000000000000000000000000000..934a48101ae5660654648fc04724424989702b03 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/features.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47f7c2ffefe93f2cf6b855404cccc82c188b05f2f71ef8aefe927b26ad998603 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-attention-projected.bin b/correctness/reference/dinovision-reference-final-0l/first-attention-projected.bin new file mode 100644 index 0000000000000000000000000000000000000000..00222b68eaa6812dce7ce4e7ef0934d92e5ba149 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-attention-projected.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-attention-scaled.bin b/correctness/reference/dinovision-reference-final-0l/first-attention-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..91fd08af65199a91d65271f9b4ac96a3f384c1a5 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-attention-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-attention.bin b/correctness/reference/dinovision-reference-final-0l/first-attention.bin new file mode 100644 index 0000000000000000000000000000000000000000..ee42a8955b2a56aee7cc56440c64bc8f346e37f9 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-attention.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-final-norm.bin b/correctness/reference/dinovision-reference-final-0l/first-final-norm.bin new file mode 100644 index 0000000000000000000000000000000000000000..0761ace3c4707290af099ca88793dfb7dc2b1fb9 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-final-norm.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-k-rope.bin b/correctness/reference/dinovision-reference-final-0l/first-k-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..fe66d075bda3eec47a34c584b91d7d3889d751ae --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-k-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-k.bin b/correctness/reference/dinovision-reference-final-0l/first-k.bin new file mode 100644 index 0000000000000000000000000000000000000000..bd9807b28ade3eda02432470e0c3c5ca83669a78 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-mlp-activated.bin b/correctness/reference/dinovision-reference-final-0l/first-mlp-activated.bin new file mode 100644 index 0000000000000000000000000000000000000000..4075727f7d658748c77b021eb7c2af209a16d8b5 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-mlp-activated.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-0l/first-mlp-down.bin b/correctness/reference/dinovision-reference-final-0l/first-mlp-down.bin new file mode 100644 index 0000000000000000000000000000000000000000..024b8051ca620dab8a10a9975a8a4e14524cef0c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-mlp-down.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-mlp-scaled.bin b/correctness/reference/dinovision-reference-final-0l/first-mlp-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..d2bea8b086e73b8c970891d1d67bae80f175d639 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-mlp-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-mlp-up.bin b/correctness/reference/dinovision-reference-final-0l/first-mlp-up.bin new file mode 100644 index 0000000000000000000000000000000000000000..976f41fd36c4644c8d2e598196b6a6abcfe4ff94 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-mlp-up.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-0l/first-norm1.bin b/correctness/reference/dinovision-reference-final-0l/first-norm1.bin new file mode 100644 index 0000000000000000000000000000000000000000..866ed665d10c59c7549764f3a4fda4eb07889d7e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-norm1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-norm2.bin b/correctness/reference/dinovision-reference-final-0l/first-norm2.bin new file mode 100644 index 0000000000000000000000000000000000000000..b2ca5531fd82d48bbd6cf78e803aea2d92b0044e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-norm2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-output.bin b/correctness/reference/dinovision-reference-final-0l/first-output.bin new file mode 100644 index 0000000000000000000000000000000000000000..2563fa6735b4505a6132b7ec63ce8ad09f723e7c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-output.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-q-rope.bin b/correctness/reference/dinovision-reference-final-0l/first-q-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..ed86bd6cd2164760171dd7f02dea49414417514d --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-q-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-q.bin b/correctness/reference/dinovision-reference-final-0l/first-q.bin new file mode 100644 index 0000000000000000000000000000000000000000..2e9970c972e7756a32ca80439765913b951df837 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-q.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-residual.bin b/correctness/reference/dinovision-reference-final-0l/first-residual.bin new file mode 100644 index 0000000000000000000000000000000000000000..239119b409129e60f229d0a6fdb43f14d8c6e92c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-residual.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/first-v.bin b/correctness/reference/dinovision-reference-final-0l/first-v.bin new file mode 100644 index 0000000000000000000000000000000000000000..6810a875c8abaaf9c900ba269c176ee30d015043 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/first-v.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-embeddings.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-embeddings.bin new file mode 100644 index 0000000000000000000000000000000000000000..61cc9bf17a375eabe3f88e6e121ea5e82a3e1284 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-embeddings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-features.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-features.bin new file mode 100644 index 0000000000000000000000000000000000000000..0644656ebd49b7eeca31e4d82399f14cea21aece --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-features.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f756676c12926a2a8be01c6d0bd6d56adbc1c6d249c457d7cc828f3bd519f697 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention-projected.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention-projected.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f015cded49311b49c249c9230a7290ac6258150 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention-projected.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention-scaled.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..2d61e867226f62c4b2f64eda39200ed8468a6c50 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention.bin new file mode 100644 index 0000000000000000000000000000000000000000..97c25fa0bd5f8e32a3b45359c2aa77f019346be1 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-attention.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-final-norm.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-final-norm.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f3875c3735dc7893a58227c1b8029050821cfcd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-final-norm.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-k-rope.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-k-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..bd8e5d94f3afb899206eb49b8f519fd8c2488ebc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-k-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-k.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-k.bin new file mode 100644 index 0000000000000000000000000000000000000000..55981e3636e02b1766993da333eddc1ff5420dbc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-activated.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-activated.bin new file mode 100644 index 0000000000000000000000000000000000000000..4a1663292516e4686e33a0599d9408f63815f502 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-activated.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-down.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-down.bin new file mode 100644 index 0000000000000000000000000000000000000000..2498fa4b48d7235766a29d7d70429b73f92bc969 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-down.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-scaled.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..591b7fc30b7da004c3ffb2a56b2bd9dde26d4426 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-up.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-up.bin new file mode 100644 index 0000000000000000000000000000000000000000..aa7178a85165134a8d313fdc47fea71fca108d05 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-mlp-up.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-norm1.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-norm1.bin new file mode 100644 index 0000000000000000000000000000000000000000..0331d83e4c4e4abcc4078d78493424148eb3e85c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-norm1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-norm2.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-norm2.bin new file mode 100644 index 0000000000000000000000000000000000000000..3dbceeab521dc85dfad75cc44c1307e66f725c26 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-norm2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-output.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-output.bin new file mode 100644 index 0000000000000000000000000000000000000000..7044208943125eee462578752d6108c11e54c55b --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-output.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-q-rope.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-q-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..97555f24e5c5b8546a4573ec573e9d6ac3a1c462 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-q-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-q.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-q.bin new file mode 100644 index 0000000000000000000000000000000000000000..e278bcb6c726521384423da63aacaf7c155a7eaa --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-q.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-residual.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-residual.bin new file mode 100644 index 0000000000000000000000000000000000000000..3d8f3fbb3a06b8ecdc688370a595143510ca20e0 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-residual.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/meganeura-first-v.bin b/correctness/reference/dinovision-reference-final-0l/meganeura-first-v.bin new file mode 100644 index 0000000000000000000000000000000000000000..a9adabf9c2f88dc36bda1d2b30d833572d6aecbd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/meganeura-first-v.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-0l/pixel_values.bin b/correctness/reference/dinovision-reference-final-0l/pixel_values.bin new file mode 100644 index 0000000000000000000000000000000000000000..072f56d70835ec2384a675496a111b2c08d7fa46 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/pixel_values.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde +size 602112 diff --git a/correctness/reference/dinovision-reference-final-0l/reference.json b/correctness/reference/dinovision-reference-final-0l/reference.json new file mode 100644 index 0000000000000000000000000000000000000000..a242da10036c5eea1df20e86e84529b671c63f5f --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/reference.json @@ -0,0 +1,17 @@ +{ + "schema_version": 1, + "base_model": "facebook/dinov3-vits16-pretrain-lvd1689m", + "model_source": "C:\\tmp\\dinovision-assets", + "image_size": 224, + "encoder_layers": 0, + "tokens": 201, + "hidden_size": 384, + "torch_version": "2.13.0+cpu", + "transformers_version": "5.14.1", + "numpy_version": "2.5.1", + "pixel_values_sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde", + "embeddings_sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee", + "features_sha256": "47f7c2ffefe93f2cf6b855404cccc82c188b05f2f71ef8aefe927b26ad998603", + "exported_model_sha256": "39a37931d12a036fee34b564f474d65240527656217bced6c609c75adae0ac3d", + "source_model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d" +} diff --git a/correctness/reference/dinovision-reference-final-0l/verification.json b/correctness/reference/dinovision-reference-final-0l/verification.json new file mode 100644 index 0000000000000000000000000000000000000000..48abb2fad1361b540b1c1d64148fa82e3c20b84f --- /dev/null +++ b/correctness/reference/dinovision-reference-final-0l/verification.json @@ -0,0 +1,233 @@ +{ + "schema_version": 1, + "image_size": 224, + "encoder_layers": 0, + "model_sha256": "39a37931d12a036fee34b564f474d65240527656217bced6c609c75adae0ac3d", + "source_model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d", + "pixel_values_sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde", + "reference_features_sha256": "47f7c2ffefe93f2cf6b855404cccc82c188b05f2f71ef8aefe927b26ad998603", + "meganeura_features_sha256": "f756676c12926a2a8be01c6d0bd6d56adbc1c6d249c457d7cc828f3bd519f697", + "elements": 77184, + "relative_l2": 5.535775069547819e-7, + "max_absolute_error": 0.00004196167, + "worst_absolute_token": 64, + "cls_cosine": 1.0, + "worst_patch_cosine": 1.0, + "stages": [ + { + "name": "embeddings", + "reference_file": "embeddings.bin", + "meganeura_file": "meganeura-embeddings.bin", + "elements": 77184, + "reference_sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee", + "meganeura_sha256": "424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66", + "relative_l2": 8.344785450785781e-7, + "max_absolute_error": 0.000032424927, + "cosine": 1.0 + }, + { + "name": "first norm1", + "reference_file": "first-norm1.bin", + "meganeura_file": "meganeura-first-norm1.bin", + "elements": 77184, + "reference_sha256": "9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68", + "meganeura_sha256": "f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf", + "relative_l2": 3.2224150941862483e-7, + "max_absolute_error": 0.00004863739, + "cosine": 1.0 + }, + { + "name": "first Q", + "reference_file": "first-q.bin", + "meganeura_file": "meganeura-first-q.bin", + "elements": 77184, + "reference_sha256": "d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441", + "meganeura_sha256": "0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6", + "relative_l2": 3.071679931085431e-7, + "max_absolute_error": 0.0013427734, + "cosine": 1.0 + }, + { + "name": "first K", + "reference_file": "first-k.bin", + "meganeura_file": "meganeura-first-k.bin", + "elements": 77184, + "reference_sha256": "e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c", + "meganeura_sha256": "01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9", + "relative_l2": 3.072096576447463e-7, + "max_absolute_error": 0.0007324219, + "cosine": 1.0 + }, + { + "name": "first V", + "reference_file": "first-v.bin", + "meganeura_file": "meganeura-first-v.bin", + "elements": 77184, + "reference_sha256": "2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38", + "meganeura_sha256": "d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92", + "relative_l2": 3.723951616632015e-7, + "max_absolute_error": 0.000091552734, + "cosine": 1.0 + }, + { + "name": "first Q RoPE", + "reference_file": "first-q-rope.bin", + "meganeura_file": "meganeura-first-q-rope.bin", + "elements": 77184, + "reference_sha256": "9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502", + "meganeura_sha256": "570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19", + "relative_l2": 3.1018054339116394e-7, + "max_absolute_error": 0.0014648438, + "cosine": 1.0 + }, + { + "name": "first K RoPE", + "reference_file": "first-k-rope.bin", + "meganeura_file": "meganeura-first-k-rope.bin", + "elements": 77184, + "reference_sha256": "2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f", + "meganeura_sha256": "cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267", + "relative_l2": 3.1089024427713095e-7, + "max_absolute_error": 0.0007324219, + "cosine": 1.0 + }, + { + "name": "first attention", + "reference_file": "first-attention.bin", + "meganeura_file": "meganeura-first-attention.bin", + "elements": 77184, + "reference_sha256": "3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884", + "meganeura_sha256": "e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7", + "relative_l2": 0.005852490342268343, + "max_absolute_error": 3.7177415, + "cosine": 0.9999829 + }, + { + "name": "attention projected", + "reference_file": "first-attention-projected.bin", + "meganeura_file": "meganeura-first-attention-projected.bin", + "elements": 77184, + "reference_sha256": "79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d", + "meganeura_sha256": "ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0", + "relative_l2": 0.008695364007431688, + "max_absolute_error": 2.2218108, + "cosine": 0.9999622 + }, + { + "name": "attention scaled", + "reference_file": "first-attention-scaled.bin", + "meganeura_file": "meganeura-first-attention-scaled.bin", + "elements": 77184, + "reference_sha256": "60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f", + "meganeura_sha256": "2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f", + "relative_l2": 0.0007030390329494454, + "max_absolute_error": 0.09749603, + "cosine": 0.99999976 + }, + { + "name": "attention residual", + "reference_file": "first-residual.bin", + "meganeura_file": "meganeura-first-residual.bin", + "elements": 77184, + "reference_sha256": "62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6", + "meganeura_sha256": "16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f", + "relative_l2": 0.0005662438450659326, + "max_absolute_error": 0.09749222, + "cosine": 0.9999998 + }, + { + "name": "first norm2", + "reference_file": "first-norm2.bin", + "meganeura_file": "meganeura-first-norm2.bin", + "elements": 77184, + "reference_sha256": "222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012", + "meganeura_sha256": "1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a", + "relative_l2": 0.0012286038444027736, + "max_absolute_error": 0.091413856, + "cosine": 0.9999992 + }, + { + "name": "first MLP up", + "reference_file": "first-mlp-up.bin", + "meganeura_file": "meganeura-first-mlp-up.bin", + "elements": 308736, + "reference_sha256": "4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812", + "meganeura_sha256": "9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71", + "relative_l2": 0.0011424722841056115, + "max_absolute_error": 0.1488514, + "cosine": 0.99999934 + }, + { + "name": "first MLP GELU", + "reference_file": "first-mlp-activated.bin", + "meganeura_file": "meganeura-first-mlp-activated.bin", + "elements": 308736, + "reference_sha256": "152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899", + "meganeura_sha256": "24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228", + "relative_l2": 0.0013806594583536597, + "max_absolute_error": 0.11534512, + "cosine": 0.99999905 + }, + { + "name": "first MLP down", + "reference_file": "first-mlp-down.bin", + "meganeura_file": "meganeura-first-mlp-down.bin", + "elements": 77184, + "reference_sha256": "344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132", + "meganeura_sha256": "a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c", + "relative_l2": 0.0009130983652202729, + "max_absolute_error": 0.354644, + "cosine": 0.9999996 + }, + { + "name": "first MLP scaled", + "reference_file": "first-mlp-scaled.bin", + "meganeura_file": "meganeura-first-mlp-scaled.bin", + "elements": 77184, + "reference_sha256": "4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4", + "meganeura_sha256": "04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77", + "relative_l2": 0.0008284863371853334, + "max_absolute_error": 0.11327553, + "cosine": 0.99999964 + }, + { + "name": "first output", + "reference_file": "first-output.bin", + "meganeura_file": "meganeura-first-output.bin", + "elements": 77184, + "reference_sha256": "ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747", + "meganeura_sha256": "c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283", + "relative_l2": 0.0007489798020562046, + "max_absolute_error": 0.03207016, + "cosine": 0.99999976 + }, + { + "name": "first final norm", + "reference_file": "first-final-norm.bin", + "meganeura_file": "meganeura-first-final-norm.bin", + "elements": 77184, + "reference_sha256": "63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940", + "meganeura_sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766", + "relative_l2": 0.0007806123774764947, + "max_absolute_error": 0.062523246, + "cosine": 0.9999997 + }, + { + "name": "full encoder output", + "reference_file": "features.bin", + "meganeura_file": "meganeura-features.bin", + "elements": 77184, + "reference_sha256": "47f7c2ffefe93f2cf6b855404cccc82c188b05f2f71ef8aefe927b26ad998603", + "meganeura_sha256": "f756676c12926a2a8be01c6d0bd6d56adbc1c6d249c457d7cc828f3bd519f697", + "relative_l2": 5.535775069547819e-7, + "max_absolute_error": 0.00004196167, + "cosine": 1.0 + } + ], + "thresholds": { + "max_relative_l2": 0.01, + "min_cls_cosine": 0.999, + "min_patch_cosine": 0.999 + }, + "passed": true +} \ No newline at end of file diff --git a/correctness/reference/dinovision-reference-final-12l/embeddings.bin b/correctness/reference/dinovision-reference-final-12l/embeddings.bin new file mode 100644 index 0000000000000000000000000000000000000000..9be47ad6bb50191c631037cb973ea58b995befcc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/embeddings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/features.bin b/correctness/reference/dinovision-reference-final-12l/features.bin new file mode 100644 index 0000000000000000000000000000000000000000..e88f774fbb5597971dfc086c2721f4a19427c2c2 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/features.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:caf5d0b7b085be6d9205a297e1ee4c16b594c857d335398b6e7c28481ae50448 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-attention-projected.bin b/correctness/reference/dinovision-reference-final-12l/first-attention-projected.bin new file mode 100644 index 0000000000000000000000000000000000000000..00222b68eaa6812dce7ce4e7ef0934d92e5ba149 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-attention-projected.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-attention-scaled.bin b/correctness/reference/dinovision-reference-final-12l/first-attention-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..91fd08af65199a91d65271f9b4ac96a3f384c1a5 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-attention-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-attention.bin b/correctness/reference/dinovision-reference-final-12l/first-attention.bin new file mode 100644 index 0000000000000000000000000000000000000000..ee42a8955b2a56aee7cc56440c64bc8f346e37f9 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-attention.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-final-norm.bin b/correctness/reference/dinovision-reference-final-12l/first-final-norm.bin new file mode 100644 index 0000000000000000000000000000000000000000..0761ace3c4707290af099ca88793dfb7dc2b1fb9 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-final-norm.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-k-rope.bin b/correctness/reference/dinovision-reference-final-12l/first-k-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..fe66d075bda3eec47a34c584b91d7d3889d751ae --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-k-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-k.bin b/correctness/reference/dinovision-reference-final-12l/first-k.bin new file mode 100644 index 0000000000000000000000000000000000000000..bd9807b28ade3eda02432470e0c3c5ca83669a78 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-mlp-activated.bin b/correctness/reference/dinovision-reference-final-12l/first-mlp-activated.bin new file mode 100644 index 0000000000000000000000000000000000000000..4075727f7d658748c77b021eb7c2af209a16d8b5 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-mlp-activated.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-12l/first-mlp-down.bin b/correctness/reference/dinovision-reference-final-12l/first-mlp-down.bin new file mode 100644 index 0000000000000000000000000000000000000000..024b8051ca620dab8a10a9975a8a4e14524cef0c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-mlp-down.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-mlp-scaled.bin b/correctness/reference/dinovision-reference-final-12l/first-mlp-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..d2bea8b086e73b8c970891d1d67bae80f175d639 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-mlp-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-mlp-up.bin b/correctness/reference/dinovision-reference-final-12l/first-mlp-up.bin new file mode 100644 index 0000000000000000000000000000000000000000..976f41fd36c4644c8d2e598196b6a6abcfe4ff94 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-mlp-up.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-12l/first-norm1.bin b/correctness/reference/dinovision-reference-final-12l/first-norm1.bin new file mode 100644 index 0000000000000000000000000000000000000000..866ed665d10c59c7549764f3a4fda4eb07889d7e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-norm1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-norm2.bin b/correctness/reference/dinovision-reference-final-12l/first-norm2.bin new file mode 100644 index 0000000000000000000000000000000000000000..b2ca5531fd82d48bbd6cf78e803aea2d92b0044e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-norm2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-output.bin b/correctness/reference/dinovision-reference-final-12l/first-output.bin new file mode 100644 index 0000000000000000000000000000000000000000..2563fa6735b4505a6132b7ec63ce8ad09f723e7c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-output.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-q-rope.bin b/correctness/reference/dinovision-reference-final-12l/first-q-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..ed86bd6cd2164760171dd7f02dea49414417514d --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-q-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-q.bin b/correctness/reference/dinovision-reference-final-12l/first-q.bin new file mode 100644 index 0000000000000000000000000000000000000000..2e9970c972e7756a32ca80439765913b951df837 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-q.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-residual.bin b/correctness/reference/dinovision-reference-final-12l/first-residual.bin new file mode 100644 index 0000000000000000000000000000000000000000..239119b409129e60f229d0a6fdb43f14d8c6e92c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-residual.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/first-v.bin b/correctness/reference/dinovision-reference-final-12l/first-v.bin new file mode 100644 index 0000000000000000000000000000000000000000..6810a875c8abaaf9c900ba269c176ee30d015043 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/first-v.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-embeddings.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-embeddings.bin new file mode 100644 index 0000000000000000000000000000000000000000..61cc9bf17a375eabe3f88e6e121ea5e82a3e1284 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-embeddings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-features.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-features.bin new file mode 100644 index 0000000000000000000000000000000000000000..13170613084f62bc06474a9ef580444ee4ed7dbc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-features.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29687eb03eb995951ed86dc15e25ac80ec7ea914194e7491923ea6f403f244a5 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention-projected.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention-projected.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f015cded49311b49c249c9230a7290ac6258150 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention-projected.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention-scaled.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..2d61e867226f62c4b2f64eda39200ed8468a6c50 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention.bin new file mode 100644 index 0000000000000000000000000000000000000000..97c25fa0bd5f8e32a3b45359c2aa77f019346be1 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-attention.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-final-norm.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-final-norm.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f3875c3735dc7893a58227c1b8029050821cfcd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-final-norm.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-k-rope.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-k-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..bd8e5d94f3afb899206eb49b8f519fd8c2488ebc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-k-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-k.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-k.bin new file mode 100644 index 0000000000000000000000000000000000000000..55981e3636e02b1766993da333eddc1ff5420dbc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-activated.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-activated.bin new file mode 100644 index 0000000000000000000000000000000000000000..4a1663292516e4686e33a0599d9408f63815f502 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-activated.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-down.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-down.bin new file mode 100644 index 0000000000000000000000000000000000000000..2498fa4b48d7235766a29d7d70429b73f92bc969 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-down.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-scaled.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..591b7fc30b7da004c3ffb2a56b2bd9dde26d4426 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-up.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-up.bin new file mode 100644 index 0000000000000000000000000000000000000000..aa7178a85165134a8d313fdc47fea71fca108d05 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-mlp-up.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-norm1.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-norm1.bin new file mode 100644 index 0000000000000000000000000000000000000000..0331d83e4c4e4abcc4078d78493424148eb3e85c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-norm1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-norm2.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-norm2.bin new file mode 100644 index 0000000000000000000000000000000000000000..3dbceeab521dc85dfad75cc44c1307e66f725c26 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-norm2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-output.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-output.bin new file mode 100644 index 0000000000000000000000000000000000000000..7044208943125eee462578752d6108c11e54c55b --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-output.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-q-rope.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-q-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..97555f24e5c5b8546a4573ec573e9d6ac3a1c462 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-q-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-q.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-q.bin new file mode 100644 index 0000000000000000000000000000000000000000..e278bcb6c726521384423da63aacaf7c155a7eaa --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-q.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-residual.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-residual.bin new file mode 100644 index 0000000000000000000000000000000000000000..3d8f3fbb3a06b8ecdc688370a595143510ca20e0 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-residual.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/meganeura-first-v.bin b/correctness/reference/dinovision-reference-final-12l/meganeura-first-v.bin new file mode 100644 index 0000000000000000000000000000000000000000..a9adabf9c2f88dc36bda1d2b30d833572d6aecbd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/meganeura-first-v.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-12l/pixel_values.bin b/correctness/reference/dinovision-reference-final-12l/pixel_values.bin new file mode 100644 index 0000000000000000000000000000000000000000..072f56d70835ec2384a675496a111b2c08d7fa46 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/pixel_values.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde +size 602112 diff --git a/correctness/reference/dinovision-reference-final-12l/reference.json b/correctness/reference/dinovision-reference-final-12l/reference.json new file mode 100644 index 0000000000000000000000000000000000000000..40da45fa2faa0452269c3893bcd732d06cc61b03 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/reference.json @@ -0,0 +1,17 @@ +{ + "schema_version": 1, + "base_model": "facebook/dinov3-vits16-pretrain-lvd1689m", + "model_source": "C:\\tmp\\dinovision-assets", + "image_size": 224, + "encoder_layers": 12, + "tokens": 201, + "hidden_size": 384, + "torch_version": "2.13.0+cpu", + "transformers_version": "5.14.1", + "numpy_version": "2.5.1", + "pixel_values_sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde", + "embeddings_sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee", + "features_sha256": "caf5d0b7b085be6d9205a297e1ee4c16b594c857d335398b6e7c28481ae50448", + "exported_model_sha256": "39a37931d12a036fee34b564f474d65240527656217bced6c609c75adae0ac3d", + "source_model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d" +} diff --git a/correctness/reference/dinovision-reference-final-12l/verification.json b/correctness/reference/dinovision-reference-final-12l/verification.json new file mode 100644 index 0000000000000000000000000000000000000000..b343f0607448c01c58d5c2cc1c8613431774320a --- /dev/null +++ b/correctness/reference/dinovision-reference-final-12l/verification.json @@ -0,0 +1,233 @@ +{ + "schema_version": 1, + "image_size": 224, + "encoder_layers": 12, + "model_sha256": "39a37931d12a036fee34b564f474d65240527656217bced6c609c75adae0ac3d", + "source_model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d", + "pixel_values_sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde", + "reference_features_sha256": "caf5d0b7b085be6d9205a297e1ee4c16b594c857d335398b6e7c28481ae50448", + "meganeura_features_sha256": "29687eb03eb995951ed86dc15e25ac80ec7ea914194e7491923ea6f403f244a5", + "elements": 77184, + "relative_l2": 0.002253213523752634, + "max_absolute_error": 0.006783724, + "worst_absolute_token": 128, + "cls_cosine": 0.9999975, + "worst_patch_cosine": 0.99999523, + "stages": [ + { + "name": "embeddings", + "reference_file": "embeddings.bin", + "meganeura_file": "meganeura-embeddings.bin", + "elements": 77184, + "reference_sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee", + "meganeura_sha256": "424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66", + "relative_l2": 8.344785450785781e-7, + "max_absolute_error": 0.000032424927, + "cosine": 1.0 + }, + { + "name": "first norm1", + "reference_file": "first-norm1.bin", + "meganeura_file": "meganeura-first-norm1.bin", + "elements": 77184, + "reference_sha256": "9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68", + "meganeura_sha256": "f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf", + "relative_l2": 3.2224150941862483e-7, + "max_absolute_error": 0.00004863739, + "cosine": 1.0 + }, + { + "name": "first Q", + "reference_file": "first-q.bin", + "meganeura_file": "meganeura-first-q.bin", + "elements": 77184, + "reference_sha256": "d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441", + "meganeura_sha256": "0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6", + "relative_l2": 3.071679931085431e-7, + "max_absolute_error": 0.0013427734, + "cosine": 1.0 + }, + { + "name": "first K", + "reference_file": "first-k.bin", + "meganeura_file": "meganeura-first-k.bin", + "elements": 77184, + "reference_sha256": "e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c", + "meganeura_sha256": "01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9", + "relative_l2": 3.072096576447463e-7, + "max_absolute_error": 0.0007324219, + "cosine": 1.0 + }, + { + "name": "first V", + "reference_file": "first-v.bin", + "meganeura_file": "meganeura-first-v.bin", + "elements": 77184, + "reference_sha256": "2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38", + "meganeura_sha256": "d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92", + "relative_l2": 3.723951616632015e-7, + "max_absolute_error": 0.000091552734, + "cosine": 1.0 + }, + { + "name": "first Q RoPE", + "reference_file": "first-q-rope.bin", + "meganeura_file": "meganeura-first-q-rope.bin", + "elements": 77184, + "reference_sha256": "9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502", + "meganeura_sha256": "570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19", + "relative_l2": 3.1018054339116394e-7, + "max_absolute_error": 0.0014648438, + "cosine": 1.0 + }, + { + "name": "first K RoPE", + "reference_file": "first-k-rope.bin", + "meganeura_file": "meganeura-first-k-rope.bin", + "elements": 77184, + "reference_sha256": "2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f", + "meganeura_sha256": "cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267", + "relative_l2": 3.1089024427713095e-7, + "max_absolute_error": 0.0007324219, + "cosine": 1.0 + }, + { + "name": "first attention", + "reference_file": "first-attention.bin", + "meganeura_file": "meganeura-first-attention.bin", + "elements": 77184, + "reference_sha256": "3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884", + "meganeura_sha256": "e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7", + "relative_l2": 0.005852490342268343, + "max_absolute_error": 3.7177415, + "cosine": 0.9999829 + }, + { + "name": "attention projected", + "reference_file": "first-attention-projected.bin", + "meganeura_file": "meganeura-first-attention-projected.bin", + "elements": 77184, + "reference_sha256": "79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d", + "meganeura_sha256": "ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0", + "relative_l2": 0.008695364007431688, + "max_absolute_error": 2.2218108, + "cosine": 0.9999622 + }, + { + "name": "attention scaled", + "reference_file": "first-attention-scaled.bin", + "meganeura_file": "meganeura-first-attention-scaled.bin", + "elements": 77184, + "reference_sha256": "60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f", + "meganeura_sha256": "2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f", + "relative_l2": 0.0007030390329494454, + "max_absolute_error": 0.09749603, + "cosine": 0.99999976 + }, + { + "name": "attention residual", + "reference_file": "first-residual.bin", + "meganeura_file": "meganeura-first-residual.bin", + "elements": 77184, + "reference_sha256": "62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6", + "meganeura_sha256": "16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f", + "relative_l2": 0.0005662438450659326, + "max_absolute_error": 0.09749222, + "cosine": 0.9999998 + }, + { + "name": "first norm2", + "reference_file": "first-norm2.bin", + "meganeura_file": "meganeura-first-norm2.bin", + "elements": 77184, + "reference_sha256": "222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012", + "meganeura_sha256": "1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a", + "relative_l2": 0.0012286038444027736, + "max_absolute_error": 0.091413856, + "cosine": 0.9999992 + }, + { + "name": "first MLP up", + "reference_file": "first-mlp-up.bin", + "meganeura_file": "meganeura-first-mlp-up.bin", + "elements": 308736, + "reference_sha256": "4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812", + "meganeura_sha256": "9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71", + "relative_l2": 0.0011424722841056115, + "max_absolute_error": 0.1488514, + "cosine": 0.99999934 + }, + { + "name": "first MLP GELU", + "reference_file": "first-mlp-activated.bin", + "meganeura_file": "meganeura-first-mlp-activated.bin", + "elements": 308736, + "reference_sha256": "152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899", + "meganeura_sha256": "24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228", + "relative_l2": 0.0013806594583536597, + "max_absolute_error": 0.11534512, + "cosine": 0.99999905 + }, + { + "name": "first MLP down", + "reference_file": "first-mlp-down.bin", + "meganeura_file": "meganeura-first-mlp-down.bin", + "elements": 77184, + "reference_sha256": "344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132", + "meganeura_sha256": "a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c", + "relative_l2": 0.0009130983652202729, + "max_absolute_error": 0.354644, + "cosine": 0.9999996 + }, + { + "name": "first MLP scaled", + "reference_file": "first-mlp-scaled.bin", + "meganeura_file": "meganeura-first-mlp-scaled.bin", + "elements": 77184, + "reference_sha256": "4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4", + "meganeura_sha256": "04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77", + "relative_l2": 0.0008284863371853334, + "max_absolute_error": 0.11327553, + "cosine": 0.99999964 + }, + { + "name": "first output", + "reference_file": "first-output.bin", + "meganeura_file": "meganeura-first-output.bin", + "elements": 77184, + "reference_sha256": "ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747", + "meganeura_sha256": "c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283", + "relative_l2": 0.0007489798020562046, + "max_absolute_error": 0.03207016, + "cosine": 0.99999976 + }, + { + "name": "first final norm", + "reference_file": "first-final-norm.bin", + "meganeura_file": "meganeura-first-final-norm.bin", + "elements": 77184, + "reference_sha256": "63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940", + "meganeura_sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766", + "relative_l2": 0.0007806123774764947, + "max_absolute_error": 0.062523246, + "cosine": 0.9999997 + }, + { + "name": "full encoder output", + "reference_file": "features.bin", + "meganeura_file": "meganeura-features.bin", + "elements": 77184, + "reference_sha256": "caf5d0b7b085be6d9205a297e1ee4c16b594c857d335398b6e7c28481ae50448", + "meganeura_sha256": "29687eb03eb995951ed86dc15e25ac80ec7ea914194e7491923ea6f403f244a5", + "relative_l2": 0.0022532135237321137, + "max_absolute_error": 0.006783724, + "cosine": 0.99999744 + } + ], + "thresholds": { + "max_relative_l2": 0.01, + "min_cls_cosine": 0.999, + "min_patch_cosine": 0.999 + }, + "passed": true +} \ No newline at end of file diff --git a/correctness/reference/dinovision-reference-final-1l/embeddings.bin b/correctness/reference/dinovision-reference-final-1l/embeddings.bin new file mode 100644 index 0000000000000000000000000000000000000000..9be47ad6bb50191c631037cb973ea58b995befcc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/embeddings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/features.bin b/correctness/reference/dinovision-reference-final-1l/features.bin new file mode 100644 index 0000000000000000000000000000000000000000..8fe2c311db87773f55836967c047d3326272b7b2 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/features.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2aa845bd42e136f1b35ad5096afea1e33004386879f3cf864a7a3e63c7d14160 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-attention-projected.bin b/correctness/reference/dinovision-reference-final-1l/first-attention-projected.bin new file mode 100644 index 0000000000000000000000000000000000000000..00222b68eaa6812dce7ce4e7ef0934d92e5ba149 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-attention-projected.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-attention-scaled.bin b/correctness/reference/dinovision-reference-final-1l/first-attention-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..91fd08af65199a91d65271f9b4ac96a3f384c1a5 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-attention-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-attention.bin b/correctness/reference/dinovision-reference-final-1l/first-attention.bin new file mode 100644 index 0000000000000000000000000000000000000000..ee42a8955b2a56aee7cc56440c64bc8f346e37f9 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-attention.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-final-norm.bin b/correctness/reference/dinovision-reference-final-1l/first-final-norm.bin new file mode 100644 index 0000000000000000000000000000000000000000..0761ace3c4707290af099ca88793dfb7dc2b1fb9 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-final-norm.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-k-rope.bin b/correctness/reference/dinovision-reference-final-1l/first-k-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..fe66d075bda3eec47a34c584b91d7d3889d751ae --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-k-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-k.bin b/correctness/reference/dinovision-reference-final-1l/first-k.bin new file mode 100644 index 0000000000000000000000000000000000000000..bd9807b28ade3eda02432470e0c3c5ca83669a78 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-mlp-activated.bin b/correctness/reference/dinovision-reference-final-1l/first-mlp-activated.bin new file mode 100644 index 0000000000000000000000000000000000000000..4075727f7d658748c77b021eb7c2af209a16d8b5 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-mlp-activated.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-1l/first-mlp-down.bin b/correctness/reference/dinovision-reference-final-1l/first-mlp-down.bin new file mode 100644 index 0000000000000000000000000000000000000000..024b8051ca620dab8a10a9975a8a4e14524cef0c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-mlp-down.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-mlp-scaled.bin b/correctness/reference/dinovision-reference-final-1l/first-mlp-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..d2bea8b086e73b8c970891d1d67bae80f175d639 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-mlp-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-mlp-up.bin b/correctness/reference/dinovision-reference-final-1l/first-mlp-up.bin new file mode 100644 index 0000000000000000000000000000000000000000..976f41fd36c4644c8d2e598196b6a6abcfe4ff94 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-mlp-up.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-1l/first-norm1.bin b/correctness/reference/dinovision-reference-final-1l/first-norm1.bin new file mode 100644 index 0000000000000000000000000000000000000000..866ed665d10c59c7549764f3a4fda4eb07889d7e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-norm1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-norm2.bin b/correctness/reference/dinovision-reference-final-1l/first-norm2.bin new file mode 100644 index 0000000000000000000000000000000000000000..b2ca5531fd82d48bbd6cf78e803aea2d92b0044e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-norm2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-output.bin b/correctness/reference/dinovision-reference-final-1l/first-output.bin new file mode 100644 index 0000000000000000000000000000000000000000..2563fa6735b4505a6132b7ec63ce8ad09f723e7c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-output.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-q-rope.bin b/correctness/reference/dinovision-reference-final-1l/first-q-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..ed86bd6cd2164760171dd7f02dea49414417514d --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-q-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-q.bin b/correctness/reference/dinovision-reference-final-1l/first-q.bin new file mode 100644 index 0000000000000000000000000000000000000000..2e9970c972e7756a32ca80439765913b951df837 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-q.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-residual.bin b/correctness/reference/dinovision-reference-final-1l/first-residual.bin new file mode 100644 index 0000000000000000000000000000000000000000..239119b409129e60f229d0a6fdb43f14d8c6e92c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-residual.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/first-v.bin b/correctness/reference/dinovision-reference-final-1l/first-v.bin new file mode 100644 index 0000000000000000000000000000000000000000..6810a875c8abaaf9c900ba269c176ee30d015043 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/first-v.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-embeddings.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-embeddings.bin new file mode 100644 index 0000000000000000000000000000000000000000..61cc9bf17a375eabe3f88e6e121ea5e82a3e1284 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-embeddings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-features.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-features.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f3875c3735dc7893a58227c1b8029050821cfcd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-features.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention-projected.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention-projected.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f015cded49311b49c249c9230a7290ac6258150 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention-projected.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention-scaled.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..2d61e867226f62c4b2f64eda39200ed8468a6c50 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention.bin new file mode 100644 index 0000000000000000000000000000000000000000..97c25fa0bd5f8e32a3b45359c2aa77f019346be1 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-attention.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-final-norm.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-final-norm.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f3875c3735dc7893a58227c1b8029050821cfcd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-final-norm.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-k-rope.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-k-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..bd8e5d94f3afb899206eb49b8f519fd8c2488ebc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-k-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-k.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-k.bin new file mode 100644 index 0000000000000000000000000000000000000000..55981e3636e02b1766993da333eddc1ff5420dbc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-activated.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-activated.bin new file mode 100644 index 0000000000000000000000000000000000000000..4a1663292516e4686e33a0599d9408f63815f502 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-activated.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-down.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-down.bin new file mode 100644 index 0000000000000000000000000000000000000000..2498fa4b48d7235766a29d7d70429b73f92bc969 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-down.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-scaled.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..591b7fc30b7da004c3ffb2a56b2bd9dde26d4426 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-up.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-up.bin new file mode 100644 index 0000000000000000000000000000000000000000..aa7178a85165134a8d313fdc47fea71fca108d05 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-mlp-up.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-norm1.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-norm1.bin new file mode 100644 index 0000000000000000000000000000000000000000..0331d83e4c4e4abcc4078d78493424148eb3e85c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-norm1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-norm2.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-norm2.bin new file mode 100644 index 0000000000000000000000000000000000000000..3dbceeab521dc85dfad75cc44c1307e66f725c26 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-norm2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-output.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-output.bin new file mode 100644 index 0000000000000000000000000000000000000000..7044208943125eee462578752d6108c11e54c55b --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-output.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-q-rope.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-q-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..97555f24e5c5b8546a4573ec573e9d6ac3a1c462 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-q-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-q.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-q.bin new file mode 100644 index 0000000000000000000000000000000000000000..e278bcb6c726521384423da63aacaf7c155a7eaa --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-q.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-residual.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-residual.bin new file mode 100644 index 0000000000000000000000000000000000000000..3d8f3fbb3a06b8ecdc688370a595143510ca20e0 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-residual.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/meganeura-first-v.bin b/correctness/reference/dinovision-reference-final-1l/meganeura-first-v.bin new file mode 100644 index 0000000000000000000000000000000000000000..a9adabf9c2f88dc36bda1d2b30d833572d6aecbd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/meganeura-first-v.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-1l/pixel_values.bin b/correctness/reference/dinovision-reference-final-1l/pixel_values.bin new file mode 100644 index 0000000000000000000000000000000000000000..072f56d70835ec2384a675496a111b2c08d7fa46 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/pixel_values.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde +size 602112 diff --git a/correctness/reference/dinovision-reference-final-1l/reference.json b/correctness/reference/dinovision-reference-final-1l/reference.json new file mode 100644 index 0000000000000000000000000000000000000000..18d23bd6bd72e7774a1a8b97eddec0dcb944f270 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/reference.json @@ -0,0 +1,17 @@ +{ + "schema_version": 1, + "base_model": "facebook/dinov3-vits16-pretrain-lvd1689m", + "model_source": "C:\\tmp\\dinovision-assets", + "image_size": 224, + "encoder_layers": 1, + "tokens": 201, + "hidden_size": 384, + "torch_version": "2.13.0+cpu", + "transformers_version": "5.14.1", + "numpy_version": "2.5.1", + "pixel_values_sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde", + "embeddings_sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee", + "features_sha256": "2aa845bd42e136f1b35ad5096afea1e33004386879f3cf864a7a3e63c7d14160", + "exported_model_sha256": "39a37931d12a036fee34b564f474d65240527656217bced6c609c75adae0ac3d", + "source_model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d" +} diff --git a/correctness/reference/dinovision-reference-final-1l/verification.json b/correctness/reference/dinovision-reference-final-1l/verification.json new file mode 100644 index 0000000000000000000000000000000000000000..bd1040e295315acd92e4ec08751d511056308c2e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-1l/verification.json @@ -0,0 +1,233 @@ +{ + "schema_version": 1, + "image_size": 224, + "encoder_layers": 1, + "model_sha256": "39a37931d12a036fee34b564f474d65240527656217bced6c609c75adae0ac3d", + "source_model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d", + "pixel_values_sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde", + "reference_features_sha256": "2aa845bd42e136f1b35ad5096afea1e33004386879f3cf864a7a3e63c7d14160", + "meganeura_features_sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766", + "elements": 77184, + "relative_l2": 0.0007806134116510104, + "max_absolute_error": 0.062523246, + "worst_absolute_token": 156, + "cls_cosine": 1.0, + "worst_patch_cosine": 0.9999894, + "stages": [ + { + "name": "embeddings", + "reference_file": "embeddings.bin", + "meganeura_file": "meganeura-embeddings.bin", + "elements": 77184, + "reference_sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee", + "meganeura_sha256": "424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66", + "relative_l2": 8.344785450785781e-7, + "max_absolute_error": 0.000032424927, + "cosine": 1.0 + }, + { + "name": "first norm1", + "reference_file": "first-norm1.bin", + "meganeura_file": "meganeura-first-norm1.bin", + "elements": 77184, + "reference_sha256": "9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68", + "meganeura_sha256": "f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf", + "relative_l2": 3.2224150941862483e-7, + "max_absolute_error": 0.00004863739, + "cosine": 1.0 + }, + { + "name": "first Q", + "reference_file": "first-q.bin", + "meganeura_file": "meganeura-first-q.bin", + "elements": 77184, + "reference_sha256": "d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441", + "meganeura_sha256": "0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6", + "relative_l2": 3.071679931085431e-7, + "max_absolute_error": 0.0013427734, + "cosine": 1.0 + }, + { + "name": "first K", + "reference_file": "first-k.bin", + "meganeura_file": "meganeura-first-k.bin", + "elements": 77184, + "reference_sha256": "e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c", + "meganeura_sha256": "01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9", + "relative_l2": 3.072096576447463e-7, + "max_absolute_error": 0.0007324219, + "cosine": 1.0 + }, + { + "name": "first V", + "reference_file": "first-v.bin", + "meganeura_file": "meganeura-first-v.bin", + "elements": 77184, + "reference_sha256": "2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38", + "meganeura_sha256": "d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92", + "relative_l2": 3.723951616632015e-7, + "max_absolute_error": 0.000091552734, + "cosine": 1.0 + }, + { + "name": "first Q RoPE", + "reference_file": "first-q-rope.bin", + "meganeura_file": "meganeura-first-q-rope.bin", + "elements": 77184, + "reference_sha256": "9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502", + "meganeura_sha256": "570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19", + "relative_l2": 3.1018054339116394e-7, + "max_absolute_error": 0.0014648438, + "cosine": 1.0 + }, + { + "name": "first K RoPE", + "reference_file": "first-k-rope.bin", + "meganeura_file": "meganeura-first-k-rope.bin", + "elements": 77184, + "reference_sha256": "2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f", + "meganeura_sha256": "cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267", + "relative_l2": 3.1089024427713095e-7, + "max_absolute_error": 0.0007324219, + "cosine": 1.0 + }, + { + "name": "first attention", + "reference_file": "first-attention.bin", + "meganeura_file": "meganeura-first-attention.bin", + "elements": 77184, + "reference_sha256": "3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884", + "meganeura_sha256": "e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7", + "relative_l2": 0.005852490342268343, + "max_absolute_error": 3.7177415, + "cosine": 0.9999829 + }, + { + "name": "attention projected", + "reference_file": "first-attention-projected.bin", + "meganeura_file": "meganeura-first-attention-projected.bin", + "elements": 77184, + "reference_sha256": "79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d", + "meganeura_sha256": "ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0", + "relative_l2": 0.008695364007431688, + "max_absolute_error": 2.2218108, + "cosine": 0.9999622 + }, + { + "name": "attention scaled", + "reference_file": "first-attention-scaled.bin", + "meganeura_file": "meganeura-first-attention-scaled.bin", + "elements": 77184, + "reference_sha256": "60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f", + "meganeura_sha256": "2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f", + "relative_l2": 0.0007030390329494454, + "max_absolute_error": 0.09749603, + "cosine": 0.99999976 + }, + { + "name": "attention residual", + "reference_file": "first-residual.bin", + "meganeura_file": "meganeura-first-residual.bin", + "elements": 77184, + "reference_sha256": "62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6", + "meganeura_sha256": "16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f", + "relative_l2": 0.0005662438450659326, + "max_absolute_error": 0.09749222, + "cosine": 0.9999998 + }, + { + "name": "first norm2", + "reference_file": "first-norm2.bin", + "meganeura_file": "meganeura-first-norm2.bin", + "elements": 77184, + "reference_sha256": "222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012", + "meganeura_sha256": "1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a", + "relative_l2": 0.0012286038444027736, + "max_absolute_error": 0.091413856, + "cosine": 0.9999992 + }, + { + "name": "first MLP up", + "reference_file": "first-mlp-up.bin", + "meganeura_file": "meganeura-first-mlp-up.bin", + "elements": 308736, + "reference_sha256": "4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812", + "meganeura_sha256": "9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71", + "relative_l2": 0.0011424722841056115, + "max_absolute_error": 0.1488514, + "cosine": 0.99999934 + }, + { + "name": "first MLP GELU", + "reference_file": "first-mlp-activated.bin", + "meganeura_file": "meganeura-first-mlp-activated.bin", + "elements": 308736, + "reference_sha256": "152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899", + "meganeura_sha256": "24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228", + "relative_l2": 0.0013806594583536597, + "max_absolute_error": 0.11534512, + "cosine": 0.99999905 + }, + { + "name": "first MLP down", + "reference_file": "first-mlp-down.bin", + "meganeura_file": "meganeura-first-mlp-down.bin", + "elements": 77184, + "reference_sha256": "344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132", + "meganeura_sha256": "a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c", + "relative_l2": 0.0009130983652202729, + "max_absolute_error": 0.354644, + "cosine": 0.9999996 + }, + { + "name": "first MLP scaled", + "reference_file": "first-mlp-scaled.bin", + "meganeura_file": "meganeura-first-mlp-scaled.bin", + "elements": 77184, + "reference_sha256": "4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4", + "meganeura_sha256": "04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77", + "relative_l2": 0.0008284863371853334, + "max_absolute_error": 0.11327553, + "cosine": 0.99999964 + }, + { + "name": "first output", + "reference_file": "first-output.bin", + "meganeura_file": "meganeura-first-output.bin", + "elements": 77184, + "reference_sha256": "ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747", + "meganeura_sha256": "c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283", + "relative_l2": 0.0007489798020562046, + "max_absolute_error": 0.03207016, + "cosine": 0.99999976 + }, + { + "name": "first final norm", + "reference_file": "first-final-norm.bin", + "meganeura_file": "meganeura-first-final-norm.bin", + "elements": 77184, + "reference_sha256": "63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940", + "meganeura_sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766", + "relative_l2": 0.0007806123774764947, + "max_absolute_error": 0.062523246, + "cosine": 0.9999997 + }, + { + "name": "full encoder output", + "reference_file": "features.bin", + "meganeura_file": "meganeura-features.bin", + "elements": 77184, + "reference_sha256": "2aa845bd42e136f1b35ad5096afea1e33004386879f3cf864a7a3e63c7d14160", + "meganeura_sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766", + "relative_l2": 0.000780613411650114, + "max_absolute_error": 0.062523246, + "cosine": 0.9999997 + } + ], + "thresholds": { + "max_relative_l2": 0.01, + "min_cls_cosine": 0.999, + "min_patch_cosine": 0.999 + }, + "passed": true +} \ No newline at end of file diff --git a/correctness/reference/dinovision-reference-final-3l/embeddings.bin b/correctness/reference/dinovision-reference-final-3l/embeddings.bin new file mode 100644 index 0000000000000000000000000000000000000000..9be47ad6bb50191c631037cb973ea58b995befcc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/embeddings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/features.bin b/correctness/reference/dinovision-reference-final-3l/features.bin new file mode 100644 index 0000000000000000000000000000000000000000..9138cf873e2d65cef1ed872978511345518d7a7b --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/features.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a1e998a4ff5ee62f25af5e8c72ac27f1fa6648ee70c6bc8302027a1898efe11 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-attention-projected.bin b/correctness/reference/dinovision-reference-final-3l/first-attention-projected.bin new file mode 100644 index 0000000000000000000000000000000000000000..00222b68eaa6812dce7ce4e7ef0934d92e5ba149 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-attention-projected.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-attention-scaled.bin b/correctness/reference/dinovision-reference-final-3l/first-attention-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..91fd08af65199a91d65271f9b4ac96a3f384c1a5 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-attention-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-attention.bin b/correctness/reference/dinovision-reference-final-3l/first-attention.bin new file mode 100644 index 0000000000000000000000000000000000000000..ee42a8955b2a56aee7cc56440c64bc8f346e37f9 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-attention.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-final-norm.bin b/correctness/reference/dinovision-reference-final-3l/first-final-norm.bin new file mode 100644 index 0000000000000000000000000000000000000000..0761ace3c4707290af099ca88793dfb7dc2b1fb9 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-final-norm.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-k-rope.bin b/correctness/reference/dinovision-reference-final-3l/first-k-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..fe66d075bda3eec47a34c584b91d7d3889d751ae --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-k-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-k.bin b/correctness/reference/dinovision-reference-final-3l/first-k.bin new file mode 100644 index 0000000000000000000000000000000000000000..bd9807b28ade3eda02432470e0c3c5ca83669a78 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-mlp-activated.bin b/correctness/reference/dinovision-reference-final-3l/first-mlp-activated.bin new file mode 100644 index 0000000000000000000000000000000000000000..4075727f7d658748c77b021eb7c2af209a16d8b5 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-mlp-activated.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-3l/first-mlp-down.bin b/correctness/reference/dinovision-reference-final-3l/first-mlp-down.bin new file mode 100644 index 0000000000000000000000000000000000000000..024b8051ca620dab8a10a9975a8a4e14524cef0c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-mlp-down.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-mlp-scaled.bin b/correctness/reference/dinovision-reference-final-3l/first-mlp-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..d2bea8b086e73b8c970891d1d67bae80f175d639 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-mlp-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-mlp-up.bin b/correctness/reference/dinovision-reference-final-3l/first-mlp-up.bin new file mode 100644 index 0000000000000000000000000000000000000000..976f41fd36c4644c8d2e598196b6a6abcfe4ff94 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-mlp-up.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-3l/first-norm1.bin b/correctness/reference/dinovision-reference-final-3l/first-norm1.bin new file mode 100644 index 0000000000000000000000000000000000000000..866ed665d10c59c7549764f3a4fda4eb07889d7e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-norm1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-norm2.bin b/correctness/reference/dinovision-reference-final-3l/first-norm2.bin new file mode 100644 index 0000000000000000000000000000000000000000..b2ca5531fd82d48bbd6cf78e803aea2d92b0044e --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-norm2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-output.bin b/correctness/reference/dinovision-reference-final-3l/first-output.bin new file mode 100644 index 0000000000000000000000000000000000000000..2563fa6735b4505a6132b7ec63ce8ad09f723e7c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-output.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-q-rope.bin b/correctness/reference/dinovision-reference-final-3l/first-q-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..ed86bd6cd2164760171dd7f02dea49414417514d --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-q-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-q.bin b/correctness/reference/dinovision-reference-final-3l/first-q.bin new file mode 100644 index 0000000000000000000000000000000000000000..2e9970c972e7756a32ca80439765913b951df837 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-q.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-residual.bin b/correctness/reference/dinovision-reference-final-3l/first-residual.bin new file mode 100644 index 0000000000000000000000000000000000000000..239119b409129e60f229d0a6fdb43f14d8c6e92c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-residual.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/first-v.bin b/correctness/reference/dinovision-reference-final-3l/first-v.bin new file mode 100644 index 0000000000000000000000000000000000000000..6810a875c8abaaf9c900ba269c176ee30d015043 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/first-v.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-embeddings.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-embeddings.bin new file mode 100644 index 0000000000000000000000000000000000000000..61cc9bf17a375eabe3f88e6e121ea5e82a3e1284 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-embeddings.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-features.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-features.bin new file mode 100644 index 0000000000000000000000000000000000000000..45be809f2c15b432f79d42c7cf30ddf6682e9b23 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-features.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6342071d5079ef13381fb98937404f610b458b66936fd4d003ad4afb254811b +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention-projected.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention-projected.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f015cded49311b49c249c9230a7290ac6258150 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention-projected.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention-scaled.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..2d61e867226f62c4b2f64eda39200ed8468a6c50 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention.bin new file mode 100644 index 0000000000000000000000000000000000000000..97c25fa0bd5f8e32a3b45359c2aa77f019346be1 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-attention.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-final-norm.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-final-norm.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f3875c3735dc7893a58227c1b8029050821cfcd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-final-norm.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-k-rope.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-k-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..bd8e5d94f3afb899206eb49b8f519fd8c2488ebc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-k-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-k.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-k.bin new file mode 100644 index 0000000000000000000000000000000000000000..55981e3636e02b1766993da333eddc1ff5420dbc --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-activated.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-activated.bin new file mode 100644 index 0000000000000000000000000000000000000000..4a1663292516e4686e33a0599d9408f63815f502 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-activated.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-down.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-down.bin new file mode 100644 index 0000000000000000000000000000000000000000..2498fa4b48d7235766a29d7d70429b73f92bc969 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-down.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-scaled.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-scaled.bin new file mode 100644 index 0000000000000000000000000000000000000000..591b7fc30b7da004c3ffb2a56b2bd9dde26d4426 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-scaled.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-up.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-up.bin new file mode 100644 index 0000000000000000000000000000000000000000..aa7178a85165134a8d313fdc47fea71fca108d05 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-mlp-up.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71 +size 1234944 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-norm1.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-norm1.bin new file mode 100644 index 0000000000000000000000000000000000000000..0331d83e4c4e4abcc4078d78493424148eb3e85c --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-norm1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-norm2.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-norm2.bin new file mode 100644 index 0000000000000000000000000000000000000000..3dbceeab521dc85dfad75cc44c1307e66f725c26 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-norm2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-output.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-output.bin new file mode 100644 index 0000000000000000000000000000000000000000..7044208943125eee462578752d6108c11e54c55b --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-output.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-q-rope.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-q-rope.bin new file mode 100644 index 0000000000000000000000000000000000000000..97555f24e5c5b8546a4573ec573e9d6ac3a1c462 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-q-rope.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-q.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-q.bin new file mode 100644 index 0000000000000000000000000000000000000000..e278bcb6c726521384423da63aacaf7c155a7eaa --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-q.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-residual.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-residual.bin new file mode 100644 index 0000000000000000000000000000000000000000..3d8f3fbb3a06b8ecdc688370a595143510ca20e0 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-residual.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/meganeura-first-v.bin b/correctness/reference/dinovision-reference-final-3l/meganeura-first-v.bin new file mode 100644 index 0000000000000000000000000000000000000000..a9adabf9c2f88dc36bda1d2b30d833572d6aecbd --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/meganeura-first-v.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92 +size 308736 diff --git a/correctness/reference/dinovision-reference-final-3l/pixel_values.bin b/correctness/reference/dinovision-reference-final-3l/pixel_values.bin new file mode 100644 index 0000000000000000000000000000000000000000..072f56d70835ec2384a675496a111b2c08d7fa46 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/pixel_values.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde +size 602112 diff --git a/correctness/reference/dinovision-reference-final-3l/reference.json b/correctness/reference/dinovision-reference-final-3l/reference.json new file mode 100644 index 0000000000000000000000000000000000000000..5be40a1a25832825a649d05cbdd22225afa06a34 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/reference.json @@ -0,0 +1,17 @@ +{ + "schema_version": 1, + "base_model": "facebook/dinov3-vits16-pretrain-lvd1689m", + "model_source": "C:\\tmp\\dinovision-assets", + "image_size": 224, + "encoder_layers": 3, + "tokens": 201, + "hidden_size": 384, + "torch_version": "2.13.0+cpu", + "transformers_version": "5.14.1", + "numpy_version": "2.5.1", + "pixel_values_sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde", + "embeddings_sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee", + "features_sha256": "5a1e998a4ff5ee62f25af5e8c72ac27f1fa6648ee70c6bc8302027a1898efe11", + "exported_model_sha256": "39a37931d12a036fee34b564f474d65240527656217bced6c609c75adae0ac3d", + "source_model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d" +} diff --git a/correctness/reference/dinovision-reference-final-3l/verification.json b/correctness/reference/dinovision-reference-final-3l/verification.json new file mode 100644 index 0000000000000000000000000000000000000000..4c78e7b8457cf47e151ec99627e370b4e8dbe1b3 --- /dev/null +++ b/correctness/reference/dinovision-reference-final-3l/verification.json @@ -0,0 +1,233 @@ +{ + "schema_version": 1, + "image_size": 224, + "encoder_layers": 3, + "model_sha256": "39a37931d12a036fee34b564f474d65240527656217bced6c609c75adae0ac3d", + "source_model_sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d", + "pixel_values_sha256": "1272edacdbc33744773de3683a7c9416bb2a9041c659e26ce79868579d2d3fde", + "reference_features_sha256": "5a1e998a4ff5ee62f25af5e8c72ac27f1fa6648ee70c6bc8302027a1898efe11", + "meganeura_features_sha256": "c6342071d5079ef13381fb98937404f610b458b66936fd4d003ad4afb254811b", + "elements": 77184, + "relative_l2": 0.001403442372470342, + "max_absolute_error": 0.054070473, + "worst_absolute_token": 5, + "cls_cosine": 0.9999995, + "worst_patch_cosine": 0.9999949, + "stages": [ + { + "name": "embeddings", + "reference_file": "embeddings.bin", + "meganeura_file": "meganeura-embeddings.bin", + "elements": 77184, + "reference_sha256": "fe5651d49406b4f8a761864067427a8ee5ecfb607097ce8dfc5f38491a4fd4ee", + "meganeura_sha256": "424f0c4f40f6519c4843f800a51837733d6b01f3ce4d56f898f3cca6946ded66", + "relative_l2": 8.344785450785781e-7, + "max_absolute_error": 0.000032424927, + "cosine": 1.0 + }, + { + "name": "first norm1", + "reference_file": "first-norm1.bin", + "meganeura_file": "meganeura-first-norm1.bin", + "elements": 77184, + "reference_sha256": "9a9d0aab2f5bbb1882e0db6398484fa4131f15e7e09f7a43f1654313514b4d68", + "meganeura_sha256": "f223ba160448dc4d58843925115835394af84702fa2ad4a2c0c670e1dac0dccf", + "relative_l2": 3.2224150941862483e-7, + "max_absolute_error": 0.00004863739, + "cosine": 1.0 + }, + { + "name": "first Q", + "reference_file": "first-q.bin", + "meganeura_file": "meganeura-first-q.bin", + "elements": 77184, + "reference_sha256": "d18ddc2d246d3ba21cd80781537f46104e4df4181e3b967c4e79ef2d55eee441", + "meganeura_sha256": "0be67ffff816875b5a063babf46986b46a7013ecb514ed8889f655b36b6229f6", + "relative_l2": 3.071679931085431e-7, + "max_absolute_error": 0.0013427734, + "cosine": 1.0 + }, + { + "name": "first K", + "reference_file": "first-k.bin", + "meganeura_file": "meganeura-first-k.bin", + "elements": 77184, + "reference_sha256": "e0cb2a0b19a5ae34bf42582584819e44a77d4196e947a63ed25a9caee4f5fe8c", + "meganeura_sha256": "01bf7bfdd01b97e06e491182d2ed14d8ea3d5910027977df77a3346b75e27ed9", + "relative_l2": 3.072096576447463e-7, + "max_absolute_error": 0.0007324219, + "cosine": 1.0 + }, + { + "name": "first V", + "reference_file": "first-v.bin", + "meganeura_file": "meganeura-first-v.bin", + "elements": 77184, + "reference_sha256": "2e37843f061b3db75ef08b54b995f4c1162f8ff1524c5087c3cb415e8fd79f38", + "meganeura_sha256": "d2af52954a22a4ff610abb63a077746a617717237994b41203c46173fd089c92", + "relative_l2": 3.723951616632015e-7, + "max_absolute_error": 0.000091552734, + "cosine": 1.0 + }, + { + "name": "first Q RoPE", + "reference_file": "first-q-rope.bin", + "meganeura_file": "meganeura-first-q-rope.bin", + "elements": 77184, + "reference_sha256": "9e77fe5da33371027e96a331079e5258cbe04dee803014b24157b5c32be75502", + "meganeura_sha256": "570070490ad36aab9e32ffa956443dcaebf17c9ec80d16764f94cff9228d7f19", + "relative_l2": 3.1018054339116394e-7, + "max_absolute_error": 0.0014648438, + "cosine": 1.0 + }, + { + "name": "first K RoPE", + "reference_file": "first-k-rope.bin", + "meganeura_file": "meganeura-first-k-rope.bin", + "elements": 77184, + "reference_sha256": "2d5c557ea824e759a4f5cd2d7afe4aee50619ecd56de17e1e755380690366f5f", + "meganeura_sha256": "cc9940fa72a0e6cb68966ec5ef332ceb4b6cfe6b23d08ffcd8ccd9f7caad2267", + "relative_l2": 3.1089024427713095e-7, + "max_absolute_error": 0.0007324219, + "cosine": 1.0 + }, + { + "name": "first attention", + "reference_file": "first-attention.bin", + "meganeura_file": "meganeura-first-attention.bin", + "elements": 77184, + "reference_sha256": "3e7b4c1a9cbd0517fb4ab6c799f08306de60787b742762baf625b55369090884", + "meganeura_sha256": "e8fc081e7fc3abcda08a13a3cfdd996a85f44332a024a15c00bea8c6778b0ca7", + "relative_l2": 0.005852490342268343, + "max_absolute_error": 3.7177415, + "cosine": 0.9999829 + }, + { + "name": "attention projected", + "reference_file": "first-attention-projected.bin", + "meganeura_file": "meganeura-first-attention-projected.bin", + "elements": 77184, + "reference_sha256": "79be0576f601855a10a961d82de9c7b36339478bdd57bd93bf8ea5430008d15d", + "meganeura_sha256": "ede3361c2c37ae2323ff72e990bf71a01a3ac8c0aa328fa1f206035342d53cf0", + "relative_l2": 0.008695364007431688, + "max_absolute_error": 2.2218108, + "cosine": 0.9999622 + }, + { + "name": "attention scaled", + "reference_file": "first-attention-scaled.bin", + "meganeura_file": "meganeura-first-attention-scaled.bin", + "elements": 77184, + "reference_sha256": "60887a49dbb6cb85d7d5f3d2e14c681878d053bda0800a8fa9530a9761bb624f", + "meganeura_sha256": "2ab4ec93c7afa6eda112cac4e75b339e3094706d87641059ae03e6a3a6219d8f", + "relative_l2": 0.0007030390329494454, + "max_absolute_error": 0.09749603, + "cosine": 0.99999976 + }, + { + "name": "attention residual", + "reference_file": "first-residual.bin", + "meganeura_file": "meganeura-first-residual.bin", + "elements": 77184, + "reference_sha256": "62417f6a624416cc844959a07482fdc29b0fd1d23c73cce7ba135662c56840d6", + "meganeura_sha256": "16b80fe63ce7026b8e21bbd4ef0c7a2013f3a80a8c22f08c47404849b83bf53f", + "relative_l2": 0.0005662438450659326, + "max_absolute_error": 0.09749222, + "cosine": 0.9999998 + }, + { + "name": "first norm2", + "reference_file": "first-norm2.bin", + "meganeura_file": "meganeura-first-norm2.bin", + "elements": 77184, + "reference_sha256": "222759f6e32c10b0bdc11427ec7a74a2e4408f48b74c55de9b308a4b43958012", + "meganeura_sha256": "1b35028e7deb034b22fa5507f026ef1aab4a5f5bda9a54393c6f07fb3b79938a", + "relative_l2": 0.0012286038444027736, + "max_absolute_error": 0.091413856, + "cosine": 0.9999992 + }, + { + "name": "first MLP up", + "reference_file": "first-mlp-up.bin", + "meganeura_file": "meganeura-first-mlp-up.bin", + "elements": 308736, + "reference_sha256": "4e91bd9d37811c62fe8a651d9bca7150790e7e874da5af446812177638d7f812", + "meganeura_sha256": "9678668e36392544b4bb20dad798c5ffa4a59c405ed562c7e1ca967da5513b71", + "relative_l2": 0.0011424722841056115, + "max_absolute_error": 0.1488514, + "cosine": 0.99999934 + }, + { + "name": "first MLP GELU", + "reference_file": "first-mlp-activated.bin", + "meganeura_file": "meganeura-first-mlp-activated.bin", + "elements": 308736, + "reference_sha256": "152bf201ed4d59552b25cfe7a5c5d2b14017753703912b67d922319e2e28e899", + "meganeura_sha256": "24cf846a20b0bdfd01d043778e50640937dce89232327463528fef80be146228", + "relative_l2": 0.0013806594583536597, + "max_absolute_error": 0.11534512, + "cosine": 0.99999905 + }, + { + "name": "first MLP down", + "reference_file": "first-mlp-down.bin", + "meganeura_file": "meganeura-first-mlp-down.bin", + "elements": 77184, + "reference_sha256": "344346f7470f0574d5d4dbc88cf4fa12a550217ed47150738f26f5c3054f3132", + "meganeura_sha256": "a9ca855e3d32ed07c14e4df1f81fe087b5494b6b02492f7458022fcec0002e9c", + "relative_l2": 0.0009130983652202729, + "max_absolute_error": 0.354644, + "cosine": 0.9999996 + }, + { + "name": "first MLP scaled", + "reference_file": "first-mlp-scaled.bin", + "meganeura_file": "meganeura-first-mlp-scaled.bin", + "elements": 77184, + "reference_sha256": "4341c097688ea66bef8d40c61775f1b98dfa3a4646c83d9cd601e08927d96dc4", + "meganeura_sha256": "04765e0d7419f7b0feeb575cce2817044322fd9f89a10b0c0bb7a383909cac77", + "relative_l2": 0.0008284863371853334, + "max_absolute_error": 0.11327553, + "cosine": 0.99999964 + }, + { + "name": "first output", + "reference_file": "first-output.bin", + "meganeura_file": "meganeura-first-output.bin", + "elements": 77184, + "reference_sha256": "ed13583e37de038c5417506431d8367b318271b3005746f11229799436f37747", + "meganeura_sha256": "c42bfeb296577d5f567d26ce932f4134443877899f637ab1d4c8165665846283", + "relative_l2": 0.0007489798020562046, + "max_absolute_error": 0.03207016, + "cosine": 0.99999976 + }, + { + "name": "first final norm", + "reference_file": "first-final-norm.bin", + "meganeura_file": "meganeura-first-final-norm.bin", + "elements": 77184, + "reference_sha256": "63d29c82e2e617284eeee39a40d044a1f5ba14348fefc7b83843cb4759ac9940", + "meganeura_sha256": "4b67d559cb4d194caf35f4612037ad1ab127ff78fdc525276acc7b561fac0766", + "relative_l2": 0.0007806123774764947, + "max_absolute_error": 0.062523246, + "cosine": 0.9999997 + }, + { + "name": "full encoder output", + "reference_file": "features.bin", + "meganeura_file": "meganeura-features.bin", + "elements": 77184, + "reference_sha256": "5a1e998a4ff5ee62f25af5e8c72ac27f1fa6648ee70c6bc8302027a1898efe11", + "meganeura_sha256": "c6342071d5079ef13381fb98937404f610b458b66936fd4d003ad4afb254811b", + "relative_l2": 0.0014034423724708772, + "max_absolute_error": 0.054070473, + "cosine": 0.99999905 + } + ], + "thresholds": { + "max_relative_l2": 0.01, + "min_cls_cosine": 0.999, + "min_patch_cosine": 0.999 + }, + "passed": true +} \ No newline at end of file diff --git a/decoder.bin b/decoder.bin new file mode 100644 index 0000000000000000000000000000000000000000..a9f9a42629e2c378d865113a9bdf9b1994aa04ac --- /dev/null +++ b/decoder.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c +size 8050188 diff --git a/decoder.safetensors b/decoder.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..c981320b74596f4ac2467fbdc5d45da34e218bc8 --- /dev/null +++ b/decoder.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f287b5d1e4e14bed15e4883c3ea5b9f01d28e3123f3fb3308ace714e4b292123 +size 8052700 diff --git a/environment/android-build/android-build.json b/environment/android-build/android-build.json new file mode 100644 index 0000000000000000000000000000000000000000..ddc2bda35eec4cd54feaf6a476066aff3e05b510 --- /dev/null +++ b/environment/android-build/android-build.json @@ -0,0 +1,31 @@ +{ + "schema_version": 1, + "completed_utc": "2026-08-02T04:10:15.3911769Z", + "target": "aarch64-linux-android", + "android_api": 34, + "android_sdk": "C:\\Users\\kvark\\AppData\\Local\\Android\\Sdk", + "ndk": "C:\\Users\\kvark\\AppData\\Local\\Android\\Sdk\\ndk\\27.0.12077973", + "ndk_source_properties": "Pkg.Desc = Android NDK\nPkg.Revision = 27.0.12077973\nPkg.BaseRevision = 27.0.12077973\nPkg.ReleaseName = r27", + "rustc": "rustc 1.95.0 (59807616e 2026-04-14)\nbinary: rustc\ncommit-hash: 59807616e1fa2540724bfbac14d7976d7e4a3860\ncommit-date: 2026-04-14\nhost: x86_64-pc-windows-msvc\nrelease: 1.95.0\nLLVM version: 22.1.2", + "cargo": "cargo 1.95.0 (f2d3ce0bd 2026-03-21)\nrelease: 1.95.0\ncommit-hash: f2d3ce0bd7f24a49f8f72d9000448f8838c4e850\ncommit-date: 2026-03-21\nhost: x86_64-pc-windows-msvc\nlibgit2: 1.9.2 (sys:0.20.4 vendored)\nlibcurl: 8.15.0-DEV (sys:0.4.83+curl-8.15.0 vendored ssl:Schannel)\nos: Windows 10.0.26200 (Windows 11 Core) [64-bit]", + "cargo_apk_sha256": "2fb19b6e6c93d3a0acf67a5efaa972556f02644831b8e114fb5c0dfaef7743c7", + "package": "rust.dinovision_xr", + "activity": "android.app.NativeActivity", + "artifacts": [ + { + "name": "bench", + "bytes": 13056136, + "sha256": "abc5e83478346fe2ea38d8ee8a0edc3cebf3c4967e454ce83db663dc1c9c1d3c" + }, + { + "name": "evaluate_decoder", + "bytes": 14174872, + "sha256": "2f1ffaf7573bfe0c03ce4760fc36898afd70c282aeed2dc3a738a3e9478db9b2" + }, + { + "name": "dinovision_xr.apk", + "bytes": 6185480, + "sha256": "6f57f0ceb378e87b0d1a147f1e839b179c8f68e540621c460db9ff87bec049b9" + } + ] +} diff --git a/environment/android-build/apk-badging.txt b/environment/android-build/apk-badging.txt new file mode 100644 index 0000000000000000000000000000000000000000..42582ce1eb2968e55f63624640327f68c9a74142 --- /dev/null +++ b/environment/android-build/apk-badging.txt @@ -0,0 +1,23 @@ +package: name='rust.dinovision_xr' versionCode='16777472' versionName='0.1.0' platformBuildVersionName='14' platformBuildVersionCode='34' compileSdkVersion='34' compileSdkVersionCodename='14' +sdkVersion:'34' +targetSdkVersion:'34' +uses-permission: name='com.oculus.permission.HAND_TRACKING' +uses-permission: name='horizonos.permission.HEADSET_CAMERA' +uses-permission: name='android.permission.CAMERA' +application: label='' icon='' +launchable-activity: name='android.app.NativeActivity' label='DinoVision' icon='' +feature-group: label='' + uses-feature-not-required: name='android.hardware.camera2.any' + uses-feature-not-required: name='oculus.software.handtracking' + uses-feature: name='android.hardware.camera' + uses-implied-feature: name='android.hardware.camera' reason='requested android.permission.CAMERA permission' + uses-feature: name='android.hardware.faketouch' + uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps' + uses-feature: name='android.hardware.screen.landscape' + uses-implied-feature: name='android.hardware.screen.landscape' reason='one or more activities have specified a landscape orientation' +main +supports-screens: 'small' 'normal' 'large' 'xlarge' +supports-any-density: 'true' +locales: +densities: +native-code: 'arm64-v8a' diff --git a/environment/android-build/apk-build.stderr.log b/environment/android-build/apk-build.stderr.log new file mode 100644 index 0000000000000000000000000000000000000000..dd22cd5a1991710cdde4c91e4e37a39ee50c8e48 --- /dev/null +++ b/environment/android-build/apk-build.stderr.log @@ -0,0 +1,2 @@ +Warning: Environment variable ANDROID_SDK_ROOT is deprecated (https://developer.android.com/studio/command-line/variables#envar). It will be used until it is unset and replaced by ANDROID_HOME. + Finished `release` profile [optimized] target(s) in 0.47s diff --git a/environment/android-build/apk-build.stdout.log b/environment/android-build/apk-build.stdout.log new file mode 100644 index 0000000000000000000000000000000000000000..beb5083433a2cd371579dbb7e4c7a08ddb878f33 --- /dev/null +++ b/environment/android-build/apk-build.stdout.log @@ -0,0 +1,11 @@ +Using package `dinovision-xr` in `C:\Code\dinovision\android-xr\Cargo.toml` + 'lib/arm64-v8a/libc++_shared.so'... + 'lib/arm64-v8a/libdinovision_xr.so'... + 'lib/arm64-v8a/libopenxr_loader.so'... +Verifying alignment of C:\Code\dinovision\target\release\apk\dinovision_xr.apk (4)... + 49 AndroidManifest.xml (OK - compressed) + 1246 lib/arm64-v8a/libc++_shared.so (OK - compressed) + 1689952 lib/arm64-v8a/libdinovision_xr.so (OK - compressed) + 5716054 lib/arm64-v8a/libopenxr_loader.so (OK - compressed) +Verification succesful +Signing `C:\Code\dinovision\target\release\apk\dinovision_xr.apk` with keystore `C:\Code\dinovision\android-xr\../../blade/examples-android/keystore/debug.keystore` diff --git a/environment/android-build/native-build.stderr.log b/environment/android-build/native-build.stderr.log new file mode 100644 index 0000000000000000000000000000000000000000..e3489b44e4a2596e77a6eab5259d0378205944a7 --- /dev/null +++ b/environment/android-build/native-build.stderr.log @@ -0,0 +1,2 @@ + Compiling dinovision v0.1.0 (C:\Code\dinovision) + Finished `release` profile [optimized] target(s) in 2.30s diff --git a/environment/android-build/native-build.stdout.log b/environment/android-build/native-build.stdout.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/environment/publication-source/Cargo.lock b/environment/publication-source/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..d977280a171f65aa0327b289cceed2c4f2d7c8f7 --- /dev/null +++ b/environment/publication-source/Cargo.lock @@ -0,0 +1,6011 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-activity" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" +dependencies = [ + "android-properties", + "bitflags 2.13.1", + "cc", + "jni", + "libc", + "log", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "num_enum 0.7.6", + "thiserror 2.0.19", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" +dependencies = [ + "android_log-sys", + "env_filter 0.1.4", + "log", +] + +[[package]] +name = "annotate-snippets" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +dependencies = [ + "anstyle", + "unicode-width", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "arc-swap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "ash-window" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52bca67b61cb81e5553babde81b8211f713cb6db79766f80168f3e5f40ea6c82" +dependencies = [ + "ash", + "raw-window-handle 0.6.2", + "raw-window-metal", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.4", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.4", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.4", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "annotate-snippets", + "bitflags 2.13.1", + "cexpr", + "clang-sys", + "itertools", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.3", + "shlex 1.3.0", + "syn 2.0.119", +] + +[[package]] +name = "bit-set" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2f926cc3060f09db9ebc5b52823d85268d24bb917e472c0c4bea35780a7d" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blade-graphics" +version = "0.8.4" +source = "git+https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac" +dependencies = [ + "ash", + "ash-window", + "bitflags 2.13.1", + "bytemuck", + "codespan-reporting", + "glow", + "gpu-alloc", + "gpu-alloc-ash", + "hidden-trait", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "mint", + "naga", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", + "objc2-ui-kit 0.3.2", + "once_cell", + "openxr", + "raw-window-handle 0.6.2", + "slab", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "blade-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27142319e2f4c264581067eaccb9f80acccdde60d8b4bf57cc50cd3152f109ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.4", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.13.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex 2.0.1", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-expr" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb693542bcafa528e198be0ebd9d3632ca5b7c93dbe7237460e199910835997c" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "num-traits", +] + +[[package]] +name = "clang-sys" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation", + "core-graphics-types", + "libc", + "objc", +] + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "cookie-factory" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dashmap" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.19", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dinovision" +version = "0.1.0" +dependencies = [ + "blade-graphics", + "blade-macros", + "bytemuck", + "env_logger", + "half", + "image", + "log", + "meganeura", + "serde", + "serde_json", + "sha2", + "winit", + "xcap", +] + +[[package]] +name = "dinovision-android" +version = "0.1.0" +dependencies = [ + "android-activity", + "android_logger", + "dinovision", + "log", +] + +[[package]] +name = "dinovision-xr" +version = "0.1.0" +dependencies = [ + "android-activity", + "android_logger", + "blade-graphics", + "dinovision", + "log", + "ndk-glue", + "openxr", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +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 0.61.2", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "dot-generator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aaac7ada45f71873ebce336491d1c1bc4a7c8042c7cea978168ad59e805b871" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "dot-structures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cfcded997a93eb31edd639361fa33fd229a8784e953b37d71035fe3890b7b" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "drm" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 0.38.44", +] + +[[package]] +name = "drm" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a41816e58f47f49acfd956651055ddcf137c4882c2098c30c448817af21183a" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "bytemuck_derive", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 1.1.4", +] + +[[package]] +name = "drm-ffi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690" +dependencies = [ + "drm-sys", + "rustix 1.1.4", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8e1361066d91f5ffccff060a3c3be9c3ecde15be2959c1937595f7a82a9f8" +dependencies = [ + "libc", + "linux-raw-sys 0.9.4", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "egglog" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2e053dcef2cd92b0dee0acfad08d83a98c1c1e55b4c55b8eefa2c0e3f4d055" +dependencies = [ + "chrono", + "clap", + "csv", + "dyn-clone", + "egglog-add-primitive", + "egglog-ast", + "egglog-bridge", + "egglog-core-relations", + "egglog-numeric-id", + "egglog-reports", + "egraph-serialize", + "env_logger", + "hashbrown 0.16.1", + "im-rc", + "indexmap", + "log", + "mimalloc", + "num", + "ordered-float", + "rayon", + "rustc-hash 2.1.3", + "serde_json", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-add-primitive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea7ffb4d889c382918cfa139256f2a4d3f46de6e08d9c071e33543393bd3663" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "egglog-ast" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c67f2aa84cdabd48b266cff0ad4bc6d4cb4386ca51d8c8d93e089f182bc162b" +dependencies = [ + "ordered-float", +] + +[[package]] +name = "egglog-bridge" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaf9e5c5f59f5edb456367dd1e7e30fe5ecfd5b434954ec7ad2d90b3169d9a2f" +dependencies = [ + "anyhow", + "dyn-clone", + "egglog-core-relations", + "egglog-numeric-id", + "egglog-reports", + "egglog-union-find", + "hashbrown 0.16.1", + "indexmap", + "log", + "num-rational", + "once_cell", + "ordered-float", + "petgraph", + "rayon", + "smallvec", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-concurrency" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5cf71f21545d7b14aceb21e51fdc16b1077e5063df03d57253fc13f098ea2cd" +dependencies = [ + "arc-swap", + "egglog-numeric-id", + "rayon", + "smallvec", +] + +[[package]] +name = "egglog-core-relations" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d477debbbe77c0fb24df98c37560cce6b8dcd8d05918a009926204cbf13c73" +dependencies = [ + "anyhow", + "bumpalo", + "crossbeam", + "crossbeam-queue", + "dashmap", + "dyn-clone", + "egglog-concurrency", + "egglog-numeric-id", + "egglog-reports", + "egglog-union-find", + "fixedbitset", + "hashbrown 0.16.1", + "indexmap", + "log", + "num", + "once_cell", + "petgraph", + "rand 0.9.5", + "rayon", + "rustc-hash 2.1.3", + "smallvec", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-numeric-id" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b207a4ee3241bc8c84bb314d8c6802fa4974c4742a9b1af5e7646ec6ddb5ae5" +dependencies = [ + "rayon", +] + +[[package]] +name = "egglog-reports" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a58e0caea9c3d0fe0486245784f579645576f3b4a8be97fb5828655b281208" +dependencies = [ + "clap", + "hashbrown 0.16.1", + "indexmap", + "rustc-hash 2.1.3", + "serde", + "serde_json", + "web-time", +] + +[[package]] +name = "egglog-union-find" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175f8e99129dcdac7f96b12cc4703c4145bb74a1a53accc46073a19ace10b9f9" +dependencies = [ + "crossbeam", + "egglog-concurrency", + "egglog-numeric-id", +] + +[[package]] +name = "egraph-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0977732fb537ace6f8c15ce160ebdda78b6502b4866d3b904e4fe752e2be4702" +dependencies = [ + "graphviz-rust", + "indexmap", + "once_cell", + "ordered-float", + "serde", + "serde_json", +] + +[[package]] +name = "either" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_filter" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" +dependencies = [ + "anstream", + "anstyle", + "env_filter 2.0.0", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" + +[[package]] +name = "futures-io" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "futures-sink" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" + +[[package]] +name = "futures-task" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" + +[[package]] +name = "futures-util" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gbm" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a" +dependencies = [ + "bitflags 2.13.1", + "drm 0.14.1", + "drm-fourcc", + "gbm-sys", + "libc", + "wayland-backend", + "wayland-server", +] + +[[package]] +name = "gbm-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13a5f2acc785d8fb6bf6b7ab6bfb0ef5dad4f4d97e8e70bb8e470722312f76f" +dependencies = [ + "libc", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasm-bindgen", +] + +[[package]] +name = "gl" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45cf04b2726f02df5508c6de726acdc90cdf97ac771a9a0ffd8ba10a6e696bf9" +dependencies = [ + "bitflags 2.13.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-ash" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643756f08ef6def813c776199e4766596395a4c6530373c9a4374a64de2f53a1" +dependencies = [ + "ash", + "gpu-alloc-types", + "tinyvec", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bbed164dd10ed526c2e4fe3e721ca4a71c61730e5aafac6844b417b3227058" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "graphviz-rust" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee83cefff83c5dd5f34c603145f4e8d478e70cc17873049b6a36eeaf37b250a" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "into-attr-derive", + "pest", + "pest_derive", + "rand 0.9.5", + "tempfile", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hf-hub" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "629d8f3bbeda9d148036d6b0de0a3ab947abd08ce90626327fc3547a49d59d97" +dependencies = [ + "dirs", + "http", + "indicatif", + "libc", + "log", + "rand 0.9.5", + "reqwest", + "serde", + "serde_json", + "thiserror 2.0.19", + "ureq", + "windows-sys 0.60.2", +] + +[[package]] +name = "hidden-trait" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ed9e850438ac849bec07e7d09fbe9309cbd396a5988c30b010580ce08860df" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "http" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 1.0.9", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[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 = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[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 = "im-rc" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + +[[package]] +name = "into-attr" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b48c537e49a709e678caec3753a7dba6854661a1eaa27675024283b3f8b376" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "into-attr-derive" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecac7c1ae6cd2c6a3a64d1061a8bdc7f52ff62c26a831a2301e54c1b5d70d5b1" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jiff" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +dependencies = [ + "defmt", +] + +[[package]] +name = "jiff-static" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.19", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" +dependencies = [ + "cc", +] + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "bitflags 2.13.1", + "libc", + "plain", + "redox_syscall 0.9.1", +] + +[[package]] +name = "libspa" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2909f3be29d674e7f10604aff18d1bbe1bb03c4cd61c8a8ba19c0b1d162f7d4e" +dependencies = [ + "bitflags 2.13.1", + "cc", + "cookie-factory", + "libc", + "libspa-sys", + "nom 8.0.0", + "rustix 1.1.4", + "system-deps", +] + +[[package]] +name = "libspa-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69ad52764fca54818486f3cf75afec844d1f1a1568c24dcee25d41b1ab007dda" +dependencies = [ + "bindgen", + "cc", + "system-deps", +] + +[[package]] +name = "libwayshot-xcap" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8a46e4d016ef464e386e4970f5415fe0939c2d63abe0c2f539c05ef88c5fe5" +dependencies = [ + "drm 0.15.0", + "gbm", + "gl", + "image", + "khronos-egl", + "memmap2", + "rustix 1.1.4", + "thiserror 2.0.19", + "tracing", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-wlr", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[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 = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "meganeura" +version = "0.2.0" +dependencies = [ + "blade-graphics", + "blade-macros", + "bytemuck", + "egglog", + "flate2", + "half", + "hf-hub", + "log", + "naga", + "oxionnx-core", + "oxionnx-proto", + "ron", + "safetensors", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mimalloc" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + +[[package]] +name = "mio" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +dependencies = [ + "libc", + "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 = "naga" +version = "29.0.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb#78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.13.1", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror 2.0.19", + "unicode-ident", +] + +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags 1.3.2", + "jni-sys 0.3.1", + "ndk-sys 0.4.1+23.1.7779620", + "num_enum 0.5.11", + "raw-window-handle 0.5.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.13.1", + "jni-sys 0.3.1", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum 0.7.6", + "raw-window-handle 0.6.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-glue" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" +dependencies = [ + "libc", + "log", + "ndk 0.7.0", + "ndk-context", + "ndk-macro", + "ndk-sys 0.4.1+23.1.7779620", + "once_cell", + "parking_lot", +] + +[[package]] +name = "ndk-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive 0.7.6", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", + "objc2-cloud-kit 0.3.2", + "objc2-core-data 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-av-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478ae33fcac9df0a18db8302387c666b8ef08a3e2d62b510ca4fc278a384b6c0" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "objc2 0.6.4", + "objc2-avf-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-image-io", + "objc2-media-toolbox", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-avf-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be" +dependencies = [ + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2" +dependencies = [ + "dispatch2", + "objc2 0.6.4", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-core-audio-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "libc", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "libc", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-io-surface", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-media" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ec576860167a15dd9fce7fbee7512beb4e31f532159d3482d1f9c6caedf31d" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "objc2 0.6.4", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-video", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-image-io" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b0446e98cf4a784cc7a0177715ff317eeaa8463841c616cfc78aa4f953c4ea" +dependencies = [ + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-media-toolbox" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd9fdde720df3da7046bb9097811000c1e7ab5cd579fa89d96b27d56781fb30" +dependencies = [ + "objc2 0.6.4", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-media", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit 0.2.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "openxr" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2d6934d2508f94fd4cbda6c2a326f111f60ce59fd9136df6d478564397dd40" +dependencies = [ + "libc", + "libloading", + "ndk-context", + "openxr-sys", +] + +[[package]] +name = "openxr-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f10e7e38c47f2175fc39363713b656db899fa0b4a14341029702cbdfa6f44d05" +dependencies = [ + "libc", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "orbclient" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" +dependencies = [ + "libc", + "libredox", +] + +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", + "rand 0.8.7", + "serde", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "oxionnx-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e993c5ce626b2ba751efa1c0c1e6b95c7dacc092174363a2aa6f55f3feee7c7f" +dependencies = [ + "half", + "hashbrown 0.17.1", +] + +[[package]] +name = "oxionnx-proto" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e80cf809f319ae19ef5e80a8b50a0afc2859da77cb182646d31633f75615ff" +dependencies = [ + "half", + "oxionnx-core", + "thiserror 2.0.19", + "tracing", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df728be843c7070fab6ab7c328c4e9e9d78e23bf749c0669c86ee7ebfa050a2" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2dd6fc3b26b3462ee188aac870f5a41d398f1cd5e2408d16531bd71c9591fd" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a7a9205cfb6f596a9e8b689c0a15f9ceb7a1aafae7aaf788150ac65b29975b6" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pest_meta" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85abd351c0de1e8384fc791a0737111a350394937e92b956b743dac12429f57c" +dependencies = [ + "pest", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", + "serde", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pipewire" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8585aba8a52ad74ccc633b8e293c1dc4277976bd5d510b925533f34fd6685f38" +dependencies = [ + "bitflags 2.13.1", + "libc", + "libspa", + "libspa-sys", + "pipewire-sys", + "rustix 1.1.4", +] + +[[package]] +name = "pipewire-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2089f245b548723e60325773c27f586b7a2372c79ea941b246cd0d654706adc" +dependencies = [ + "bindgen", + "libspa-sys", + "system-deps", +] + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "portable-atomic" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.13+spec-1.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.3", + "rustls", + "socket2", + "thiserror 2.0.19", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" +dependencies = [ + "bytes", + "getrandom 0.4.3", + "lru-slab", + "rand 0.10.2", + "rand_pcg", + "ring", + "rustc-hash 2.1.3", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.19", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.61.2", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +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.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +dependencies = [ + "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "serde", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e8caa82e31bb98fee12fa8f051c94a6aa36b07cddb03f0d4fc558988360ff1" +dependencies = [ + "cocoa", + "core-graphics", + "objc", + "raw-window-handle 0.6.2", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "redox_syscall" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07507be7b4a5f9f26eeb41eeaebb1f5a7ff29dfb29739facc21d35bf8b11c21e" +dependencies = [ + "bitflags 2.13.1", +] + +[[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 2.0.19", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots 1.0.9", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.13.1", + "serde", + "serde_derive", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "safetensors" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44560c11236a6130a46ce36c836a62936dc81ebf8c36a37947423571be0e55b6" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +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 = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.13.1", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "socks" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" +dependencies = [ + "byteorder", + "libc", + "winapi", +] + +[[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.1", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "system-deps" +version = "7.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +dependencies = [ + "thiserror-impl 2.0.19", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "1.1.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.4", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime 0.6.11", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.13+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.4", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.13.1", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "socks", + "url", + "webpki-roots 0.26.11", +] + +[[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 = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wayland-backend" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016ccf01d1c58b6f8999612813e17c9b2390f7d70671428869913310f83f54b8" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073" +dependencies = [ + "bitflags 2.13.1", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.13.1", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0" +dependencies = [ + "proc-macro2", + "quick-xml 0.41.0", + "quote", +] + +[[package]] +name = "wayland-server" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde9c29be0f723a573977de51ee455bf3dfa03652730a74f9dd3b337e374d75" +dependencies = [ + "bitflags 2.13.1", + "downcast-rs", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "libc", + "log", + "memoffset", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.9", +] + +[[package]] +name = "webpki-roots" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[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.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winit" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.13.1", + "block2 0.5.1", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk 0.9.0", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit 0.2.2", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle 0.6.2", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +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 = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 1.1.4", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcap" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b31c7f57ddfb14983525d9149eaed160de7d3973aaa546f3e19eb3394122b6b" +dependencies = [ + "dispatch2", + "image", + "libwayshot-xcap", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-av-foundation", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-media", + "objc2-core-video", + "objc2-foundation 0.3.2", + "percent-encoding", + "pipewire", + "rand 0.10.2", + "scopeguard", + "serde", + "thiserror 2.0.19", + "url", + "widestring", + "windows", + "xcb", + "zbus", +] + +[[package]] +name = "xcb" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4c580d8205abb0a5cf4eb7e927bd664e425b6c3263f9c5310583da96970cf6" +dependencies = [ + "bitflags 1.3.2", + "libc", + "quick-xml 0.30.0", +] + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.13.1", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[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 2.0.119", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe18fb60dc696039e738717b76eaea21e7a4489bbb1885020b43c94236d7e98a" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix 1.1.4", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow 1.0.4", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe96480bed92df2b442a1a30df364e12d08eed03aeb061f2b8dc6afb2be91119" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e" +dependencies = [ + "serde", + "winnow 1.0.4", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[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 2.0.119", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + +[[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 2.0.119", +] + +[[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.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] + +[[package]] +name = "zvariant" +version = "5.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee2a0bcd2a907786a456fff45aaaaf54c9ba5f50b71ae9ec1a4edd200c94911" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow 1.0.4", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a708216a18780796770bfe3f4739c7c83a3e8f789b755534bbbc06e4e23e12" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.119", + "winnow 1.0.4", +] diff --git a/environment/publication-source/cargo-tree.txt b/environment/publication-source/cargo-tree.txt new file mode 100644 index 0000000000000000000000000000000000000000..650b01df5dbdf6355abf48d37c149a7dd4b06379 --- /dev/null +++ b/environment/publication-source/cargo-tree.txt @@ -0,0 +1,450 @@ +dinovision v0.1.0 (C:\Code\dinovision) +├── blade-graphics v0.8.4 (https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6) +│ ├── ash v0.38.0+1.3.281 +│ │ └── libloading v0.8.9 +│ │ └── windows-link v0.2.1 +│ ├── ash-window v0.13.0 +│ │ ├── ash v0.38.0+1.3.281 (*) +│ │ └── raw-window-handle v0.6.2 +│ ├── bitflags v2.13.1 +│ │ └── serde_core v1.0.229 +│ ├── bytemuck v1.25.2 +│ │ └── bytemuck_derive v1.11.0 (proc-macro) +│ │ ├── proc-macro2 v1.0.107 +│ │ │ └── unicode-ident v1.0.24 +│ │ ├── quote v1.0.47 +│ │ │ └── proc-macro2 v1.0.107 (*) +│ │ └── syn v2.0.119 +│ │ ├── proc-macro2 v1.0.107 (*) +│ │ ├── quote v1.0.47 (*) +│ │ └── unicode-ident v1.0.24 +│ ├── codespan-reporting v0.13.1 +│ │ ├── termcolor v1.4.1 +│ │ │ └── winapi-util v0.1.11 +│ │ │ └── windows-sys v0.61.2 +│ │ │ └── windows-link v0.2.1 +│ │ └── unicode-width v0.2.2 +│ ├── gpu-alloc v0.6.2 +│ │ ├── bitflags v2.13.1 (*) +│ │ └── gpu-alloc-types v0.3.1 +│ │ └── bitflags v2.13.1 (*) +│ ├── gpu-alloc-ash v0.7.1 +│ │ ├── ash v0.38.0+1.3.281 (*) +│ │ ├── gpu-alloc-types v0.3.1 (*) +│ │ └── tinyvec v1.12.0 +│ │ └── tinyvec_macros v0.1.1 +│ ├── hidden-trait v0.1.2 (proc-macro) +│ │ ├── proc-macro2 v1.0.107 (*) +│ │ ├── quote v1.0.47 (*) +│ │ └── syn v1.0.109 +│ │ ├── proc-macro2 v1.0.107 (*) +│ │ ├── quote v1.0.47 (*) +│ │ └── unicode-ident v1.0.24 +│ ├── log v0.4.33 +│ ├── mint v0.5.9 +│ ├── naga v29.0.0 (https://github.com/gfx-rs/wgpu?rev=78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb#78b4dfd0) +│ │ ├── arrayvec v0.7.8 +│ │ ├── bit-set v0.10.0 +│ │ │ └── bit-vec v0.9.1 +│ │ ├── bitflags v2.13.1 (*) +│ │ ├── cfg-if v1.0.4 +│ │ ├── codespan-reporting v0.13.1 (*) +│ │ ├── half v2.7.1 +│ │ │ ├── cfg-if v1.0.4 +│ │ │ ├── num-traits v0.2.19 +│ │ │ │ └── libm v0.2.16 +│ │ │ │ [build-dependencies] +│ │ │ │ └── autocfg v1.5.1 +│ │ │ └── zerocopy v0.8.55 +│ │ │ └── zerocopy-derive v0.8.55 (proc-macro) +│ │ │ ├── proc-macro2 v1.0.107 (*) +│ │ │ ├── quote v1.0.47 (*) +│ │ │ └── syn v2.0.119 (*) +│ │ ├── hashbrown v0.16.1 +│ │ │ ├── allocator-api2 v0.2.21 +│ │ │ ├── equivalent v1.0.2 +│ │ │ ├── foldhash v0.2.0 +│ │ │ └── serde_core v1.0.229 +│ │ ├── indexmap v2.14.0 +│ │ │ ├── equivalent v1.0.2 +│ │ │ ├── hashbrown v0.17.1 +│ │ │ │ ├── allocator-api2 v0.2.21 +│ │ │ │ ├── equivalent v1.0.2 +│ │ │ │ └── foldhash v0.2.0 +│ │ │ └── serde_core v1.0.229 +│ │ ├── libm v0.2.16 +│ │ ├── log v0.4.33 +│ │ ├── num-traits v0.2.19 (*) +│ │ ├── once_cell v1.21.4 +│ │ ├── rustc-hash v1.1.0 +│ │ ├── spirv v0.4.0+sdk-1.4.341.0 +│ │ │ └── bitflags v2.13.1 (*) +│ │ ├── thiserror v2.0.19 +│ │ │ └── thiserror-impl v2.0.19 (proc-macro) +│ │ │ ├── proc-macro2 v1.0.107 (*) +│ │ │ ├── quote v1.0.47 (*) +│ │ │ └── syn v3.0.3 +│ │ │ ├── proc-macro2 v1.0.107 (*) +│ │ │ ├── quote v1.0.47 (*) +│ │ │ └── unicode-ident v1.0.24 +│ │ └── unicode-ident v1.0.24 +│ │ [build-dependencies] +│ │ └── cfg_aliases v0.2.2 +│ ├── once_cell v1.21.4 +│ ├── openxr v0.19.0 +│ │ ├── libc v0.2.189 +│ │ ├── libloading v0.8.9 (*) +│ │ └── openxr-sys v0.11.0 +│ │ └── libc v0.2.189 +│ ├── raw-window-handle v0.6.2 +│ └── slab v0.4.12 +├── blade-macros v0.3.0 (proc-macro) +│ ├── proc-macro2 v1.0.107 (*) +│ ├── quote v1.0.47 (*) +│ └── syn v2.0.119 (*) +├── bytemuck v1.25.2 (*) +├── half v2.7.1 (*) +├── log v0.4.33 +└── meganeura v0.2.0 (C:\Code\meganeura) + ├── blade-graphics v0.8.4 (https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6) (*) + ├── blade-macros v0.3.0 (proc-macro) (*) + ├── bytemuck v1.25.2 (*) + ├── egglog v2.0.0 + │ ├── clap v4.6.4 + │ │ ├── clap_builder v4.6.2 + │ │ │ ├── anstream v1.0.0 + │ │ │ │ ├── anstyle v1.0.14 + │ │ │ │ ├── anstyle-parse v1.0.0 + │ │ │ │ │ └── utf8parse v0.2.2 + │ │ │ │ ├── anstyle-query v1.1.5 + │ │ │ │ │ └── windows-sys v0.61.2 (*) + │ │ │ │ ├── anstyle-wincon v3.0.11 + │ │ │ │ │ ├── anstyle v1.0.14 + │ │ │ │ │ ├── once_cell_polyfill v1.70.2 + │ │ │ │ │ └── windows-sys v0.61.2 (*) + │ │ │ │ ├── colorchoice v1.0.5 + │ │ │ │ ├── is_terminal_polyfill v1.70.2 + │ │ │ │ └── utf8parse v0.2.2 + │ │ │ ├── anstyle v1.0.14 + │ │ │ ├── clap_lex v1.1.0 + │ │ │ └── strsim v0.11.1 + │ │ └── clap_derive v4.6.4 (proc-macro) + │ │ ├── heck v0.5.0 + │ │ ├── proc-macro2 v1.0.107 (*) + │ │ ├── quote v1.0.47 (*) + │ │ └── syn v3.0.3 (*) + │ ├── csv v1.4.0 + │ │ ├── csv-core v0.1.13 + │ │ │ └── memchr v2.8.3 + │ │ ├── itoa v1.0.18 + │ │ ├── ryu v1.0.23 + │ │ └── serde_core v1.0.229 + │ ├── dyn-clone v1.0.20 + │ ├── egglog-add-primitive v2.0.0 (proc-macro) + │ │ ├── quote v1.0.47 (*) + │ │ └── syn v2.0.119 (*) + │ ├── egglog-ast v2.0.0 + │ │ └── ordered-float v5.3.0 + │ │ ├── num-traits v0.2.19 (*) + │ │ └── serde v1.0.229 + │ │ ├── serde_core v1.0.229 + │ │ └── serde_derive v1.0.229 (proc-macro) + │ │ ├── proc-macro2 v1.0.107 (*) + │ │ ├── quote v1.0.47 (*) + │ │ └── syn v3.0.3 (*) + │ ├── egglog-bridge v2.0.0 + │ │ ├── anyhow v1.0.104 + │ │ ├── dyn-clone v1.0.20 + │ │ ├── egglog-core-relations v2.0.0 + │ │ │ ├── anyhow v1.0.104 + │ │ │ ├── bumpalo v3.20.3 + │ │ │ ├── crossbeam v0.8.4 + │ │ │ │ ├── crossbeam-channel v0.5.16 + │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ ├── crossbeam-deque v0.8.7 + │ │ │ │ │ ├── crossbeam-epoch v0.9.20 + │ │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ ├── crossbeam-epoch v0.9.20 (*) + │ │ │ │ ├── crossbeam-queue v0.3.13 + │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ ├── crossbeam-queue v0.3.13 (*) + │ │ │ ├── dashmap v6.2.1 + │ │ │ │ ├── cfg-if v1.0.4 + │ │ │ │ ├── crossbeam-utils v0.8.22 + │ │ │ │ ├── hashbrown v0.14.5 + │ │ │ │ ├── lock_api v0.4.14 + │ │ │ │ │ └── scopeguard v1.2.0 + │ │ │ │ ├── once_cell v1.21.4 + │ │ │ │ └── parking_lot_core v0.9.12 + │ │ │ │ ├── cfg-if v1.0.4 + │ │ │ │ ├── smallvec v1.15.2 + │ │ │ │ └── windows-link v0.2.1 + │ │ │ ├── dyn-clone v1.0.20 + │ │ │ ├── egglog-concurrency v2.0.0 + │ │ │ │ ├── arc-swap v1.9.2 + │ │ │ │ │ └── rustversion v1.0.23 (proc-macro) + │ │ │ │ ├── egglog-numeric-id v2.0.0 + │ │ │ │ │ └── rayon v1.12.0 + │ │ │ │ │ ├── either v1.17.0 + │ │ │ │ │ └── rayon-core v1.13.0 + │ │ │ │ │ ├── crossbeam-deque v0.8.7 (*) + │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ ├── rayon v1.12.0 (*) + │ │ │ │ └── smallvec v1.15.2 + │ │ │ ├── egglog-numeric-id v2.0.0 (*) + │ │ │ ├── egglog-reports v2.0.0 + │ │ │ │ ├── clap v4.6.4 (*) + │ │ │ │ ├── hashbrown v0.16.1 (*) + │ │ │ │ ├── indexmap v2.14.0 (*) + │ │ │ │ ├── rustc-hash v2.1.3 + │ │ │ │ ├── serde v1.0.229 (*) + │ │ │ │ ├── serde_json v1.0.151 + │ │ │ │ │ ├── indexmap v2.14.0 (*) + │ │ │ │ │ ├── itoa v1.0.18 + │ │ │ │ │ ├── memchr v2.8.3 + │ │ │ │ │ ├── serde_core v1.0.229 + │ │ │ │ │ └── zmij v1.0.23 + │ │ │ │ └── web-time v1.1.0 + │ │ │ ├── egglog-union-find v2.0.0 + │ │ │ │ ├── crossbeam v0.8.4 (*) + │ │ │ │ ├── egglog-concurrency v2.0.0 (*) + │ │ │ │ └── egglog-numeric-id v2.0.0 (*) + │ │ │ ├── fixedbitset v0.5.7 + │ │ │ ├── hashbrown v0.16.1 (*) + │ │ │ ├── indexmap v2.14.0 (*) + │ │ │ ├── log v0.4.33 + │ │ │ ├── num v0.4.3 + │ │ │ │ ├── num-bigint v0.4.8 + │ │ │ │ │ ├── num-integer v0.1.46 + │ │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ ├── num-complex v0.4.6 + │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ ├── num-integer v0.1.46 (*) + │ │ │ │ ├── num-iter v0.1.46 + │ │ │ │ │ ├── num-integer v0.1.46 (*) + │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ ├── num-rational v0.4.2 + │ │ │ │ │ ├── num-bigint v0.4.8 (*) + │ │ │ │ │ ├── num-integer v0.1.46 (*) + │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ ├── once_cell v1.21.4 + │ │ │ ├── petgraph v0.8.3 + │ │ │ │ ├── fixedbitset v0.5.7 + │ │ │ │ ├── hashbrown v0.15.5 + │ │ │ │ │ └── foldhash v0.1.5 + │ │ │ │ └── indexmap v2.14.0 (*) + │ │ │ ├── rand v0.9.5 + │ │ │ │ ├── rand_chacha v0.9.0 + │ │ │ │ │ ├── ppv-lite86 v0.2.21 + │ │ │ │ │ │ └── zerocopy v0.8.55 (*) + │ │ │ │ │ └── rand_core v0.9.5 + │ │ │ │ │ └── getrandom v0.3.4 + │ │ │ │ │ └── cfg-if v1.0.4 + │ │ │ │ └── rand_core v0.9.5 (*) + │ │ │ ├── rayon v1.12.0 (*) + │ │ │ ├── rustc-hash v2.1.3 + │ │ │ ├── smallvec v1.15.2 + │ │ │ ├── thiserror v2.0.19 (*) + │ │ │ └── web-time v1.1.0 + │ │ ├── egglog-numeric-id v2.0.0 (*) + │ │ ├── egglog-reports v2.0.0 (*) + │ │ ├── egglog-union-find v2.0.0 (*) + │ │ ├── hashbrown v0.16.1 (*) + │ │ ├── indexmap v2.14.0 (*) + │ │ ├── log v0.4.33 + │ │ ├── num-rational v0.4.2 (*) + │ │ ├── once_cell v1.21.4 + │ │ ├── ordered-float v5.3.0 (*) + │ │ ├── petgraph v0.8.3 (*) + │ │ ├── rayon v1.12.0 (*) + │ │ ├── smallvec v1.15.2 + │ │ ├── thiserror v2.0.19 (*) + │ │ └── web-time v1.1.0 + │ ├── egglog-core-relations v2.0.0 (*) + │ ├── egglog-numeric-id v2.0.0 (*) + │ ├── egglog-reports v2.0.0 (*) + │ ├── egraph-serialize v0.3.0 + │ │ ├── graphviz-rust v0.9.8 + │ │ │ ├── dot-generator v0.2.0 + │ │ │ │ └── dot-structures v0.1.2 + │ │ │ ├── dot-structures v0.1.2 + │ │ │ ├── into-attr v0.1.1 + │ │ │ │ └── dot-structures v0.1.2 + │ │ │ ├── into-attr-derive v0.2.1 (proc-macro) + │ │ │ │ ├── dot-generator v0.2.0 (*) + │ │ │ │ ├── dot-structures v0.1.2 + │ │ │ │ ├── into-attr v0.1.1 (*) + │ │ │ │ ├── quote v1.0.47 (*) + │ │ │ │ └── syn v1.0.109 (*) + │ │ │ ├── pest v2.8.8 + │ │ │ │ ├── memchr v2.8.3 + │ │ │ │ └── ucd-trie v0.1.7 + │ │ │ ├── pest_derive v2.8.8 (proc-macro) + │ │ │ │ ├── pest v2.8.8 (*) + │ │ │ │ └── pest_generator v2.8.8 + │ │ │ │ ├── pest v2.8.8 (*) + │ │ │ │ ├── pest_meta v2.8.8 + │ │ │ │ │ └── pest v2.8.8 (*) + │ │ │ │ ├── proc-macro2 v1.0.107 (*) + │ │ │ │ ├── quote v1.0.47 (*) + │ │ │ │ └── syn v2.0.119 (*) + │ │ │ ├── rand v0.9.5 (*) + │ │ │ └── tempfile v3.27.0 + │ │ │ ├── fastrand v2.5.0 + │ │ │ ├── getrandom v0.4.3 + │ │ │ │ └── cfg-if v1.0.4 + │ │ │ ├── once_cell v1.21.4 + │ │ │ └── windows-sys v0.61.2 (*) + │ │ ├── indexmap v2.14.0 (*) + │ │ ├── once_cell v1.21.4 + │ │ ├── ordered-float v5.3.0 (*) + │ │ ├── serde v1.0.229 (*) + │ │ └── serde_json v1.0.151 (*) + │ ├── env_logger v0.11.11 + │ │ ├── anstream v1.0.0 (*) + │ │ ├── anstyle v1.0.14 + │ │ ├── env_filter v2.0.0 + │ │ │ ├── log v0.4.33 + │ │ │ └── regex v1.13.1 + │ │ │ ├── aho-corasick v1.1.4 + │ │ │ │ └── memchr v2.8.3 + │ │ │ ├── memchr v2.8.3 + │ │ │ ├── regex-automata v0.4.16 + │ │ │ │ ├── aho-corasick v1.1.4 (*) + │ │ │ │ ├── memchr v2.8.3 + │ │ │ │ └── regex-syntax v0.8.11 + │ │ │ └── regex-syntax v0.8.11 + │ │ ├── jiff v0.2.35 + │ │ │ └── jiff-core v0.1.0 + │ │ └── log v0.4.33 + │ ├── hashbrown v0.16.1 (*) + │ ├── im-rc v15.1.0 + │ │ ├── bitmaps v2.1.0 + │ │ │ └── typenum v1.20.1 + │ │ ├── rand_core v0.6.4 + │ │ ├── rand_xoshiro v0.6.0 + │ │ │ └── rand_core v0.6.4 + │ │ ├── sized-chunks v0.6.5 + │ │ │ ├── bitmaps v2.1.0 (*) + │ │ │ └── typenum v1.20.1 + │ │ └── typenum v1.20.1 + │ │ [build-dependencies] + │ │ └── version_check v0.9.5 + │ ├── indexmap v2.14.0 (*) + │ ├── log v0.4.33 + │ ├── mimalloc v0.1.52 + │ │ └── libmimalloc-sys v0.1.49 + │ │ [build-dependencies] + │ │ └── cc v1.4.0 + │ │ ├── find-msvc-tools v0.1.9 + │ │ └── shlex v2.0.1 + │ ├── num v0.4.3 (*) + │ ├── ordered-float v5.3.0 (*) + │ ├── rayon v1.12.0 (*) + │ ├── rustc-hash v2.1.3 + │ ├── serde_json v1.0.151 (*) + │ ├── thiserror v2.0.19 (*) + │ └── web-time v1.1.0 + │ [build-dependencies] + │ └── chrono v0.4.45 + │ └── num-traits v0.2.19 + │ [build-dependencies] + │ └── autocfg v1.5.1 + ├── flate2 v1.1.9 + │ ├── crc32fast v1.5.0 + │ │ └── cfg-if v1.0.4 + │ └── miniz_oxide v0.8.9 + │ ├── adler2 v2.0.1 + │ └── simd-adler32 v0.3.10 + ├── half v2.7.1 (*) + ├── log v0.4.33 + ├── naga v29.0.0 (https://github.com/gfx-rs/wgpu?rev=78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb#78b4dfd0) (*) + ├── oxionnx-core v0.1.4 + │ ├── half v2.7.1 (*) + │ └── hashbrown v0.17.1 (*) + ├── oxionnx-proto v0.1.4 + │ ├── half v2.7.1 (*) + │ ├── oxionnx-core v0.1.4 (*) + │ ├── thiserror v2.0.19 (*) + │ └── tracing v0.1.44 + │ ├── pin-project-lite v0.2.17 + │ ├── tracing-attributes v0.1.31 (proc-macro) + │ │ ├── proc-macro2 v1.0.107 (*) + │ │ ├── quote v1.0.47 (*) + │ │ └── syn v2.0.119 (*) + │ └── tracing-core v0.1.36 + │ └── once_cell v1.21.4 + ├── ron v0.8.1 + │ ├── base64 v0.21.7 + │ ├── bitflags v2.13.1 (*) + │ ├── serde v1.0.229 (*) + │ └── serde_derive v1.0.229 (proc-macro) (*) + ├── safetensors v0.4.5 + │ ├── serde v1.0.229 (*) + │ └── serde_json v1.0.151 (*) + ├── serde v1.0.229 (*) + ├── serde_json v1.0.151 (*) + ├── tracing v0.1.44 (*) + └── tracing-subscriber v0.3.23 + ├── nu-ansi-term v0.50.3 + │ └── windows-sys v0.61.2 (*) + ├── sharded-slab v0.1.7 + │ └── lazy_static v1.5.0 + ├── smallvec v1.15.2 + ├── thread_local v1.1.10 + │ └── cfg-if v1.0.4 + ├── tracing-core v0.1.36 (*) + └── tracing-log v0.2.0 + ├── log v0.4.33 + ├── once_cell v1.21.4 + └── tracing-core v0.1.36 (*) +[dev-dependencies] +├── env_logger v0.11.11 (*) +├── image v0.25.10 +│ ├── bytemuck v1.25.2 (*) +│ ├── byteorder-lite v0.1.0 +│ ├── moxcms v0.8.1 +│ │ ├── num-traits v0.2.19 (*) +│ │ └── pxfm v0.1.30 +│ ├── num-traits v0.2.19 (*) +│ ├── png v0.18.1 +│ │ ├── bitflags v2.13.1 (*) +│ │ ├── crc32fast v1.5.0 (*) +│ │ ├── fdeflate v0.3.7 +│ │ │ └── simd-adler32 v0.3.10 +│ │ ├── flate2 v1.1.9 (*) +│ │ └── miniz_oxide v0.8.9 (*) +│ ├── zune-core v0.5.1 +│ └── zune-jpeg v0.5.15 +│ └── zune-core v0.5.1 +├── serde v1.0.229 (*) +├── serde_json v1.0.151 (*) +├── sha2 v0.10.9 +│ ├── cfg-if v1.0.4 +│ ├── cpufeatures v0.2.17 +│ └── digest v0.10.7 +│ ├── block-buffer v0.10.4 +│ │ └── generic-array v0.14.7 +│ │ └── typenum v1.20.1 +│ │ [build-dependencies] +│ │ └── version_check v0.9.5 +│ └── crypto-common v0.1.7 +│ ├── generic-array v0.14.7 (*) +│ └── typenum v1.20.1 +└── winit v0.30.13 + ├── bitflags v2.13.1 (*) + ├── cursor-icon v1.2.0 + ├── dpi v0.1.2 + ├── raw-window-handle v0.6.2 + ├── smol_str v0.2.2 + ├── tracing v0.1.44 (*) + ├── unicode-segmentation v1.13.3 + └── windows-sys v0.52.0 + └── windows-targets v0.52.6 + └── windows_x86_64_msvc v0.52.6 + [build-dependencies] + └── cfg_aliases v0.2.2 diff --git a/environment/publication-source/metadata.json b/environment/publication-source/metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..e96e3652ff1f8c163050029ff9392befc309d545 --- /dev/null +++ b/environment/publication-source/metadata.json @@ -0,0 +1,402 @@ +{ + "schema_version": 1, + "collected_utc": "2026-08-02T04:17:52.5632093Z", + "dinovision": { + "path": "C:\\Code\\dinovision", + "revision": "66caef824dc53c96b60e1c7382f004300428079d", + "branch": "main", + "clean": false, + "status": [ + " M .cargo/config.toml", + " M .gitignore", + " M Cargo.lock", + " M Cargo.toml", + " M README.md", + " M REPORT.md", + " M android-xr/src/lib.rs", + " M android/src/lib.rs", + " M examples/bench.rs", + " M examples/train_decoder.rs", + " M examples/verify.rs", + " M src/bench.rs", + " M src/decoder.rs", + " M src/dinov3.rs", + " M tools/dump_reference.py", + "?? examples/common/", + "?? examples/evaluate_decoder.rs", + "?? experiments/", + "?? huggingface/", + "?? tests/dinov3_ops.rs", + "?? tools/build_android_artifacts.ps1", + "?? tools/collect_artifact_metadata.ps1", + "?? tools/compare_f32.py", + "?? tools/convert_decoder.py", + "?? tools/extract_json_records.py", + "?? tools/make_correctness_frame.py", + "?? tools/make_dataset_manifest.py", + "?? tools/pull_quest_artifacts.ps1", + "?? tools/run_cross_device_correctness.ps1", + "?? tools/run_decoder_matrix.ps1", + "?? tools/run_quest_bench.ps1", + "?? tools/run_xr_sweep.ps1", + "?? tools/stage_huggingface_artifact.ps1", + "?? tools/summarize_bench.py", + "?? tools/summarize_dataset.py", + "?? tools/summarize_determinism.py", + "?? tools/summarize_quality.py", + "?? tools/summarize_xr.py", + "?? tools/verify_huggingface_artifact.py" + ], + "source_files": [ + { + "path": "examples/common/mod.rs", + "bytes": 9570, + "sha256": "97872bb9c929ec510f76cf04ed6643bb063f181d6e7181524b5d80c3d9cc8439" + }, + { + "path": "examples/evaluate_decoder.rs", + "bytes": 19278, + "sha256": "3055791d64ebf488b4a4b837468b00ce49793eaa23a48d201692f7da9631656f" + }, + { + "path": "experiments/AUDIT.md", + "bytes": 6017, + "sha256": "4216636a6cec96ff699d86d5d6e4cacf332898e39e60c57b7795c42b946950a1" + }, + { + "path": "experiments/README.md", + "bytes": 10625, + "sha256": "3b8148b63aaaefba589d148cc0bab20e7019720198e96f20db84a3a76b201f1e" + }, + { + "path": "experiments/paper-section.tex", + "bytes": 5943, + "sha256": "362f8f17eed076a0d2a57ff96e46a07c21d9f5ed4409c686443ae866029ca35e" + }, + { + "path": "huggingface/DINOv3-LICENSE.md", + "bytes": 7503, + "sha256": "25d122eb8f5b880fd23c736fb6ea8018ee45c12237e00b8a86d14c653904999e" + }, + { + "path": "huggingface/NOTICE.md", + "bytes": 883, + "sha256": "28b2cce3512b7c4d31d6ce435d338aeef9ee29839b198afbf414ec1c02ff3743" + }, + { + "path": "huggingface/README.md", + "bytes": 6940, + "sha256": "c7a4aadf323f9794af72ea967b3b3307ebc08a7dfc5d6225f835613c840df117" + }, + { + "path": "tests/dinov3_ops.rs", + "bytes": 4680, + "sha256": "1ff11a6db0cbccc422a0058a7a5d7e775dba357106cc3e8af3e23f315960387f" + }, + { + "path": "tools/build_android_artifacts.ps1", + "bytes": 4980, + "sha256": "97eedc24b8fc7e4baeb0faa0c023d57cda5d75d7ba9f9f1a04868d3563d8201b" + }, + { + "path": "tools/collect_artifact_metadata.ps1", + "bytes": 6601, + "sha256": "4574dea9d7ec0a7f87d9439b7fbc03e78a3a407bbb3ec53edeca5c0b61853f95" + }, + { + "path": "tools/compare_f32.py", + "bytes": 6380, + "sha256": "828f71146de6ac26aa40df27cec1170c0af4030c9d87cce87c5138c22d78e137" + }, + { + "path": "tools/convert_decoder.py", + "bytes": 3286, + "sha256": "962853f90e35a726d2f69f0f6fba2da4071efc12e8c3f200f695178a0377b9b6" + }, + { + "path": "tools/extract_json_records.py", + "bytes": 1927, + "sha256": "c5b8027cb6c8b1f57623c7543be0ce2925ad3e340c2a1bb510b3fa9f3c66cd3a" + }, + { + "path": "tools/make_correctness_frame.py", + "bytes": 1302, + "sha256": "87aacc02d8ae4b875fc3d519cd02f487c4187ebbcb7a752bbfddaf2f1bec7a28" + }, + { + "path": "tools/make_dataset_manifest.py", + "bytes": 4991, + "sha256": "d48f07f60af6c00edda4a8533e4ee5a265a924d2d6451898a8b0932e29343a11" + }, + { + "path": "tools/pull_quest_artifacts.ps1", + "bytes": 3630, + "sha256": "ece78fdb0eba1dd8f9c260f32565dee481965c0c4803795ccfdb58d82f9c7438" + }, + { + "path": "tools/run_cross_device_correctness.ps1", + "bytes": 8028, + "sha256": "114a673ab08ff8b5de534194d2efd19ff41ac6f3ff274ba70fa1f8532cef5195" + }, + { + "path": "tools/run_decoder_matrix.ps1", + "bytes": 5352, + "sha256": "1f95ff681375b334dde39bab509c087321e6c531a9be04f47d65348dea9ccaef" + }, + { + "path": "tools/run_quest_bench.ps1", + "bytes": 6501, + "sha256": "0b6966cbcd06109ddee85e5a0746468ffe3932cd3748c0b4b4743eb23e1b34cf" + }, + { + "path": "tools/run_xr_sweep.ps1", + "bytes": 12220, + "sha256": "d7f07831ff8c4b237193809563f9c5296783c24d8ac97c333ab5f71bd49b0df1" + }, + { + "path": "tools/stage_huggingface_artifact.ps1", + "bytes": 13033, + "sha256": "cdf19145fa5dc8b6c9fd387719855ebe354312add1b12f0aef77fc13db921069" + }, + { + "path": "tools/summarize_bench.py", + "bytes": 5935, + "sha256": "94e4b431dad735c1233764018e43fafcfca194ccf75bfa6f14a159adeac17c12" + }, + { + "path": "tools/summarize_dataset.py", + "bytes": 4905, + "sha256": "cc9e1d1f6c36a5e792194ca7d77ef14674d3eed591994070d6c277786f26d144" + }, + { + "path": "tools/summarize_determinism.py", + "bytes": 3104, + "sha256": "65595ff079187c9e72fd80b0ad8dcbdca5368cda20d4fa4bf078b17eee80450a" + }, + { + "path": "tools/summarize_quality.py", + "bytes": 8713, + "sha256": "4fa1965d098029b85e5224c44fcb209f9771734ef25d559a9807d77489f80f98" + }, + { + "path": "tools/summarize_xr.py", + "bytes": 8249, + "sha256": "f78e44b7f1e81cb7b3d35e366b75fb464d6d76c84c23879e10f458794b4a640c" + }, + { + "path": "tools/verify_huggingface_artifact.py", + "bytes": 19913, + "sha256": "2bd2b68f78040ec233763e44435e6f706a67886619be8992f2b3b0b3733fcb5e" + }, + { + "path": ".cargo/config.toml", + "bytes": 226, + "sha256": "e7bf454f82c0d679e1bafc31028f74b20994b063fa3e5e86e1339430b05cc47c" + }, + { + "path": ".gitignore", + "bytes": 234, + "sha256": "0e02af3bcd20cfea482ea7d0460506aee7818b580aee468c0efcd40aadec8995" + }, + { + "path": "Cargo.lock", + "bytes": 148764, + "sha256": "d63a639b6af43b0fc1020ada5178902d30978ca51d555f2ea5417927582cbc49" + }, + { + "path": "Cargo.toml", + "bytes": 2382, + "sha256": "4bc34588dca13c3430b2432b19b585c95e739b68e7f959abe8f280f35d79428c" + }, + { + "path": "LICENSE", + "bytes": 1094, + "sha256": "602d42a30c16d186e3da4f12fc1eeab2dfc24a6e79da878c63a3ff234c0358e6" + }, + { + "path": "README.md", + "bytes": 17245, + "sha256": "e71dc7dbef867dc9cf7e15bfc0fef603627dd8f855a9af3721f8bb14835638b0" + }, + { + "path": "REPORT.md", + "bytes": 15303, + "sha256": "e0464e9c1a01897c3b1da64184828cf59c8f52166c900f7b3da79e83954e8c97" + }, + { + "path": "android-xr/Cargo.toml", + "bytes": 2854, + "sha256": "1df860091562bb35a2432930acb801a68b9688563b2d450d40a74ea2dc6c3131" + }, + { + "path": "android-xr/src/lib.rs", + "bytes": 35645, + "sha256": "6ba353c26a8b1bba037cc3c1fe5127047cdadbdf1bc51bc070664b4812a86e4b" + }, + { + "path": "android/Cargo.toml", + "bytes": 1630, + "sha256": "953097f02a122c40cc714c861862f4afc422e00ee99e46100c4cc6db5f254755" + }, + { + "path": "android/src/lib.rs", + "bytes": 2474, + "sha256": "31baa9646d8af738ebef870bb964e9d033625fcb198d014526665698bc19f969" + }, + { + "path": "examples/bench.rs", + "bytes": 1803, + "sha256": "15577b6f3b2f3e1b28eaf228eb81897ceaa0c237181d24baa2a067de7819a0be" + }, + { + "path": "examples/preview.rs", + "bytes": 5638, + "sha256": "f0beb2e9e0b2a1ddc2d681028a68843a6e570b2972a91b61c10b1d88f0e70c97" + }, + { + "path": "examples/train_decoder.rs", + "bytes": 16740, + "sha256": "c8e28f2d8d78544a665ed6ad2ad620da07aa400aaadd0c8114004530286ae815" + }, + { + "path": "examples/verify.rs", + "bytes": 25706, + "sha256": "e8ef67003e4e23f8c9acf25e6f2a3862c7f119fb993baddfc09f75d667dde850" + }, + { + "path": "examples/viewer.rs", + "bytes": 10350, + "sha256": "b5d655c664f0d929c78d57d4daded61f0746ed885504b7a02b013f6389ab4df6" + }, + { + "path": "src/bench.rs", + "bytes": 17407, + "sha256": "d8c11769ebb9182aaab718f1757e527f0502bb42cdd742577d0db7cebd8f4134" + }, + { + "path": "src/camera.rs", + "bytes": 28374, + "sha256": "93472c94e6d8ce5122b4c7db2731106c7102593cbb4bf444e7bbe9e08aa7b086" + }, + { + "path": "src/decoder.rs", + "bytes": 13220, + "sha256": "feee813cc1a8839d3ce374189e313d4f9c8ba5a087b0ab872fd570da156264b6" + }, + { + "path": "src/dinov3.rs", + "bytes": 19624, + "sha256": "39d372288796a0f7c16bddc7776c14cb09e52bfa1bcfaff240cb576529633385" + }, + { + "path": "src/inference.rs", + "bytes": 13643, + "sha256": "2c8205c9771cfd1848e49ff4eef40492d6c4860b88fdef1e6467d5b520f1b961" + }, + { + "path": "src/lib.rs", + "bytes": 2547, + "sha256": "6b8ad76beffca29d94dcb5aa629f3f65c167c9c52fc8611e2ae48fb129a9cd64" + }, + { + "path": "src/pca.rs", + "bytes": 15878, + "sha256": "252f09f61486e333e0df8ddf34b167ee4de0c2861a7d9169c007061884fa2405" + }, + { + "path": "src/preprocess.rs", + "bytes": 7193, + "sha256": "69a13c6ee542763df8368839f6ae6ab9e082c3e25548b1f53219028c370561b5" + }, + { + "path": "src/render.rs", + "bytes": 13166, + "sha256": "31a0393b5caffff5e248a6fff89988d6368cf0de553491d43574748b16c8a779" + }, + { + "path": "src/shaders/grid_view.wgsl", + "bytes": 2490, + "sha256": "8406eba77ec27f055169edd00d540aeec18dd3c08733d8d9a7f0b2c479cb7869" + }, + { + "path": "src/source.rs", + "bytes": 10284, + "sha256": "11b38e9a06a7090cf2a9864b65eb46c96e429dbdb008b17f104172f0ec5e751d" + }, + { + "path": "src/weights.rs", + "bytes": 6404, + "sha256": "aa69dd605c691246fbe4cf00282aa25e0834681b713e47bfd6ef30369f98547f" + }, + { + "path": "tests/semantics.rs", + "bytes": 5790, + "sha256": "9cf2b851fd96adb9b754ebaeea315f6de02e7bf9f21d3d10b67fd376f28a80f1" + }, + { + "path": "tests/threading.rs", + "bytes": 1352, + "sha256": "df85acc70c20081aa337d7c97f4df9c513c8fd4c42e2aa2d7e798688ce5e3333" + }, + { + "path": "tools/dump_reference.py", + "bytes": 9405, + "sha256": "81fc39d70a6c381c1e5f871563672ea96818ff88995472f6ddb68cf35734ef29" + } + ] + }, + "meganeura": { + "path": "C:\\Code\\meganeura", + "revision": "0c0192a9414de45148086af64f610684e7a98743", + "branch": "android-cross-compile", + "clean": true, + "status": [ + + ] + }, + "blade_checkout": { + "path": "C:\\Code\\blade", + "revision": "1aa9d04a192b095533b2e5441ec658b2bafe056d", + "branch": "command-encoder-send", + "clean": true, + "status": [ + + ] + }, + "resolved_packages": { + "meganeura": [ + { + "version": "0.2.0", + "source": null, + "manifest_path": "C:\\Code\\meganeura\\Cargo.toml" + } + ], + "blade-graphics": [ + { + "version": "0.8.4", + "source": "git+https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac", + "manifest_path": "C:\\Users\\kvark\\.cargo\\git\\checkouts\\blade-26bd638d88226de3\\ba0fb5a\\blade-graphics\\Cargo.toml" + } + ] + }, + "rustc": "rustc 1.95.0 (59807616e 2026-04-14)\nbinary: rustc\ncommit-hash: 59807616e1fa2540724bfbac14d7976d7e4a3860\ncommit-date: 2026-04-14\nhost: x86_64-pc-windows-msvc\nrelease: 1.95.0\nLLVM version: 22.1.2", + "cargo": "cargo 1.95.0 (f2d3ce0bd 2026-03-21)\nrelease: 1.95.0\ncommit-hash: f2d3ce0bd7f24a49f8f72d9000448f8838c4e850\ncommit-date: 2026-03-21\nhost: x86_64-pc-windows-msvc\nlibgit2: 1.9.2 (sys:0.20.4 vendored)\nlibcurl: 8.15.0-DEV (sys:0.4.83+curl-8.15.0 vendored ssl:Schannel)\nos: Windows 10.0.26200 (Windows 11 Core) [64-bit]", + "os": "Microsoft Windows NT 10.0.26200.0", + "android_ndks": [ + "23.2.8568313", + "27.0.12077973" + ], + "nvidia_smi": "NVIDIA GeForce RTX 3050, 591.86", + "adb": "Android Debug Bridge version 1.0.41\nVersion 35.0.2-12147458\nInstalled as C:\\Users\\kvark\\AppData\\Local\\Android\\Sdk\\platform-tools\\adb.exe\nRunning on Windows 10.0.26200", + "model": { + "path": "C:\\tmp\\dinovision-assets\\model.safetensors", + "bytes": 86406384, + "sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d" + }, + "decoder": { + "path": "C:\\tmp\\dinovision-runs-corrected-v2\\3l224-seed0\\decoder.bin", + "bytes": 8050188, + "sha256": "d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c" + }, + "quest_connected": false +} diff --git a/environment/publication-source/source-snapshot/.cargo/config.toml b/environment/publication-source/source-snapshot/.cargo/config.toml new file mode 100644 index 0000000000000000000000000000000000000000..91648b19c2c12ef74e184905d125184fee8eef87 --- /dev/null +++ b/environment/publication-source/source-snapshot/.cargo/config.toml @@ -0,0 +1,3 @@ +# Host-specific Android SDK/NDK paths do not belong in a reproducible source +# tree. `tools/build_android_artifacts.ps1` validates NDK r27 and injects the +# target linker and compiler environment for both Cargo and cargo-apk. diff --git a/environment/publication-source/source-snapshot/.gitignore b/environment/publication-source/source-snapshot/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..15f0208c08d30e206b64e1637ca65dbfc7b795a7 --- /dev/null +++ b/environment/publication-source/source-snapshot/.gitignore @@ -0,0 +1,13 @@ +/target +/artifacts + +# Reference dumps from tools/dump_reference.py — weights and tensor blobs, +# tens of megabytes, and regenerable. +/ref +*.safetensors +*.bin +__pycache__/ +*.py[cod] + +# Compiled meganeura execution plans +*.plan diff --git a/environment/publication-source/source-snapshot/Cargo.lock b/environment/publication-source/source-snapshot/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..d977280a171f65aa0327b289cceed2c4f2d7c8f7 --- /dev/null +++ b/environment/publication-source/source-snapshot/Cargo.lock @@ -0,0 +1,6011 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-activity" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" +dependencies = [ + "android-properties", + "bitflags 2.13.1", + "cc", + "jni", + "libc", + "log", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "num_enum 0.7.6", + "thiserror 2.0.19", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" +dependencies = [ + "android_log-sys", + "env_filter 0.1.4", + "log", +] + +[[package]] +name = "annotate-snippets" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +dependencies = [ + "anstyle", + "unicode-width", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "arc-swap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "ash-window" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52bca67b61cb81e5553babde81b8211f713cb6db79766f80168f3e5f40ea6c82" +dependencies = [ + "ash", + "raw-window-handle 0.6.2", + "raw-window-metal", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.4", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.4", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.4", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "annotate-snippets", + "bitflags 2.13.1", + "cexpr", + "clang-sys", + "itertools", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.3", + "shlex 1.3.0", + "syn 2.0.119", +] + +[[package]] +name = "bit-set" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2f926cc3060f09db9ebc5b52823d85268d24bb917e472c0c4bea35780a7d" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blade-graphics" +version = "0.8.4" +source = "git+https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac" +dependencies = [ + "ash", + "ash-window", + "bitflags 2.13.1", + "bytemuck", + "codespan-reporting", + "glow", + "gpu-alloc", + "gpu-alloc-ash", + "hidden-trait", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "mint", + "naga", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", + "objc2-ui-kit 0.3.2", + "once_cell", + "openxr", + "raw-window-handle 0.6.2", + "slab", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "blade-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27142319e2f4c264581067eaccb9f80acccdde60d8b4bf57cc50cd3152f109ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.4", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.13.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex 2.0.1", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-expr" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb693542bcafa528e198be0ebd9d3632ca5b7c93dbe7237460e199910835997c" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "num-traits", +] + +[[package]] +name = "clang-sys" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation", + "core-graphics-types", + "libc", + "objc", +] + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "cookie-factory" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dashmap" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.19", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dinovision" +version = "0.1.0" +dependencies = [ + "blade-graphics", + "blade-macros", + "bytemuck", + "env_logger", + "half", + "image", + "log", + "meganeura", + "serde", + "serde_json", + "sha2", + "winit", + "xcap", +] + +[[package]] +name = "dinovision-android" +version = "0.1.0" +dependencies = [ + "android-activity", + "android_logger", + "dinovision", + "log", +] + +[[package]] +name = "dinovision-xr" +version = "0.1.0" +dependencies = [ + "android-activity", + "android_logger", + "blade-graphics", + "dinovision", + "log", + "ndk-glue", + "openxr", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +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 0.61.2", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "dot-generator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aaac7ada45f71873ebce336491d1c1bc4a7c8042c7cea978168ad59e805b871" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "dot-structures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cfcded997a93eb31edd639361fa33fd229a8784e953b37d71035fe3890b7b" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "drm" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 0.38.44", +] + +[[package]] +name = "drm" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a41816e58f47f49acfd956651055ddcf137c4882c2098c30c448817af21183a" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "bytemuck_derive", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 1.1.4", +] + +[[package]] +name = "drm-ffi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690" +dependencies = [ + "drm-sys", + "rustix 1.1.4", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8e1361066d91f5ffccff060a3c3be9c3ecde15be2959c1937595f7a82a9f8" +dependencies = [ + "libc", + "linux-raw-sys 0.9.4", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "egglog" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2e053dcef2cd92b0dee0acfad08d83a98c1c1e55b4c55b8eefa2c0e3f4d055" +dependencies = [ + "chrono", + "clap", + "csv", + "dyn-clone", + "egglog-add-primitive", + "egglog-ast", + "egglog-bridge", + "egglog-core-relations", + "egglog-numeric-id", + "egglog-reports", + "egraph-serialize", + "env_logger", + "hashbrown 0.16.1", + "im-rc", + "indexmap", + "log", + "mimalloc", + "num", + "ordered-float", + "rayon", + "rustc-hash 2.1.3", + "serde_json", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-add-primitive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea7ffb4d889c382918cfa139256f2a4d3f46de6e08d9c071e33543393bd3663" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "egglog-ast" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c67f2aa84cdabd48b266cff0ad4bc6d4cb4386ca51d8c8d93e089f182bc162b" +dependencies = [ + "ordered-float", +] + +[[package]] +name = "egglog-bridge" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaf9e5c5f59f5edb456367dd1e7e30fe5ecfd5b434954ec7ad2d90b3169d9a2f" +dependencies = [ + "anyhow", + "dyn-clone", + "egglog-core-relations", + "egglog-numeric-id", + "egglog-reports", + "egglog-union-find", + "hashbrown 0.16.1", + "indexmap", + "log", + "num-rational", + "once_cell", + "ordered-float", + "petgraph", + "rayon", + "smallvec", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-concurrency" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5cf71f21545d7b14aceb21e51fdc16b1077e5063df03d57253fc13f098ea2cd" +dependencies = [ + "arc-swap", + "egglog-numeric-id", + "rayon", + "smallvec", +] + +[[package]] +name = "egglog-core-relations" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d477debbbe77c0fb24df98c37560cce6b8dcd8d05918a009926204cbf13c73" +dependencies = [ + "anyhow", + "bumpalo", + "crossbeam", + "crossbeam-queue", + "dashmap", + "dyn-clone", + "egglog-concurrency", + "egglog-numeric-id", + "egglog-reports", + "egglog-union-find", + "fixedbitset", + "hashbrown 0.16.1", + "indexmap", + "log", + "num", + "once_cell", + "petgraph", + "rand 0.9.5", + "rayon", + "rustc-hash 2.1.3", + "smallvec", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-numeric-id" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b207a4ee3241bc8c84bb314d8c6802fa4974c4742a9b1af5e7646ec6ddb5ae5" +dependencies = [ + "rayon", +] + +[[package]] +name = "egglog-reports" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a58e0caea9c3d0fe0486245784f579645576f3b4a8be97fb5828655b281208" +dependencies = [ + "clap", + "hashbrown 0.16.1", + "indexmap", + "rustc-hash 2.1.3", + "serde", + "serde_json", + "web-time", +] + +[[package]] +name = "egglog-union-find" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175f8e99129dcdac7f96b12cc4703c4145bb74a1a53accc46073a19ace10b9f9" +dependencies = [ + "crossbeam", + "egglog-concurrency", + "egglog-numeric-id", +] + +[[package]] +name = "egraph-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0977732fb537ace6f8c15ce160ebdda78b6502b4866d3b904e4fe752e2be4702" +dependencies = [ + "graphviz-rust", + "indexmap", + "once_cell", + "ordered-float", + "serde", + "serde_json", +] + +[[package]] +name = "either" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_filter" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" +dependencies = [ + "anstream", + "anstyle", + "env_filter 2.0.0", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" + +[[package]] +name = "futures-io" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "futures-sink" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" + +[[package]] +name = "futures-task" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" + +[[package]] +name = "futures-util" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gbm" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a" +dependencies = [ + "bitflags 2.13.1", + "drm 0.14.1", + "drm-fourcc", + "gbm-sys", + "libc", + "wayland-backend", + "wayland-server", +] + +[[package]] +name = "gbm-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13a5f2acc785d8fb6bf6b7ab6bfb0ef5dad4f4d97e8e70bb8e470722312f76f" +dependencies = [ + "libc", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasm-bindgen", +] + +[[package]] +name = "gl" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45cf04b2726f02df5508c6de726acdc90cdf97ac771a9a0ffd8ba10a6e696bf9" +dependencies = [ + "bitflags 2.13.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-ash" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643756f08ef6def813c776199e4766596395a4c6530373c9a4374a64de2f53a1" +dependencies = [ + "ash", + "gpu-alloc-types", + "tinyvec", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bbed164dd10ed526c2e4fe3e721ca4a71c61730e5aafac6844b417b3227058" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "graphviz-rust" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee83cefff83c5dd5f34c603145f4e8d478e70cc17873049b6a36eeaf37b250a" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "into-attr-derive", + "pest", + "pest_derive", + "rand 0.9.5", + "tempfile", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hf-hub" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "629d8f3bbeda9d148036d6b0de0a3ab947abd08ce90626327fc3547a49d59d97" +dependencies = [ + "dirs", + "http", + "indicatif", + "libc", + "log", + "rand 0.9.5", + "reqwest", + "serde", + "serde_json", + "thiserror 2.0.19", + "ureq", + "windows-sys 0.60.2", +] + +[[package]] +name = "hidden-trait" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ed9e850438ac849bec07e7d09fbe9309cbd396a5988c30b010580ce08860df" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "http" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 1.0.9", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[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 = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[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 = "im-rc" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + +[[package]] +name = "into-attr" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b48c537e49a709e678caec3753a7dba6854661a1eaa27675024283b3f8b376" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "into-attr-derive" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecac7c1ae6cd2c6a3a64d1061a8bdc7f52ff62c26a831a2301e54c1b5d70d5b1" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jiff" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +dependencies = [ + "defmt", +] + +[[package]] +name = "jiff-static" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.19", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" +dependencies = [ + "cc", +] + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "bitflags 2.13.1", + "libc", + "plain", + "redox_syscall 0.9.1", +] + +[[package]] +name = "libspa" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2909f3be29d674e7f10604aff18d1bbe1bb03c4cd61c8a8ba19c0b1d162f7d4e" +dependencies = [ + "bitflags 2.13.1", + "cc", + "cookie-factory", + "libc", + "libspa-sys", + "nom 8.0.0", + "rustix 1.1.4", + "system-deps", +] + +[[package]] +name = "libspa-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69ad52764fca54818486f3cf75afec844d1f1a1568c24dcee25d41b1ab007dda" +dependencies = [ + "bindgen", + "cc", + "system-deps", +] + +[[package]] +name = "libwayshot-xcap" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8a46e4d016ef464e386e4970f5415fe0939c2d63abe0c2f539c05ef88c5fe5" +dependencies = [ + "drm 0.15.0", + "gbm", + "gl", + "image", + "khronos-egl", + "memmap2", + "rustix 1.1.4", + "thiserror 2.0.19", + "tracing", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-wlr", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[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 = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "meganeura" +version = "0.2.0" +dependencies = [ + "blade-graphics", + "blade-macros", + "bytemuck", + "egglog", + "flate2", + "half", + "hf-hub", + "log", + "naga", + "oxionnx-core", + "oxionnx-proto", + "ron", + "safetensors", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mimalloc" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + +[[package]] +name = "mio" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +dependencies = [ + "libc", + "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 = "naga" +version = "29.0.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb#78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.13.1", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror 2.0.19", + "unicode-ident", +] + +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags 1.3.2", + "jni-sys 0.3.1", + "ndk-sys 0.4.1+23.1.7779620", + "num_enum 0.5.11", + "raw-window-handle 0.5.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.13.1", + "jni-sys 0.3.1", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum 0.7.6", + "raw-window-handle 0.6.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-glue" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" +dependencies = [ + "libc", + "log", + "ndk 0.7.0", + "ndk-context", + "ndk-macro", + "ndk-sys 0.4.1+23.1.7779620", + "once_cell", + "parking_lot", +] + +[[package]] +name = "ndk-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive 0.7.6", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", + "objc2-cloud-kit 0.3.2", + "objc2-core-data 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-av-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478ae33fcac9df0a18db8302387c666b8ef08a3e2d62b510ca4fc278a384b6c0" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "objc2 0.6.4", + "objc2-avf-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-image-io", + "objc2-media-toolbox", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-avf-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be" +dependencies = [ + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2" +dependencies = [ + "dispatch2", + "objc2 0.6.4", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-core-audio-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "libc", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "libc", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-io-surface", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-media" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ec576860167a15dd9fce7fbee7512beb4e31f532159d3482d1f9c6caedf31d" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "objc2 0.6.4", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-video", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-image-io" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b0446e98cf4a784cc7a0177715ff317eeaa8463841c616cfc78aa4f953c4ea" +dependencies = [ + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-media-toolbox" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd9fdde720df3da7046bb9097811000c1e7ab5cd579fa89d96b27d56781fb30" +dependencies = [ + "objc2 0.6.4", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-media", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit 0.2.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "openxr" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2d6934d2508f94fd4cbda6c2a326f111f60ce59fd9136df6d478564397dd40" +dependencies = [ + "libc", + "libloading", + "ndk-context", + "openxr-sys", +] + +[[package]] +name = "openxr-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f10e7e38c47f2175fc39363713b656db899fa0b4a14341029702cbdfa6f44d05" +dependencies = [ + "libc", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "orbclient" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" +dependencies = [ + "libc", + "libredox", +] + +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", + "rand 0.8.7", + "serde", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "oxionnx-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e993c5ce626b2ba751efa1c0c1e6b95c7dacc092174363a2aa6f55f3feee7c7f" +dependencies = [ + "half", + "hashbrown 0.17.1", +] + +[[package]] +name = "oxionnx-proto" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e80cf809f319ae19ef5e80a8b50a0afc2859da77cb182646d31633f75615ff" +dependencies = [ + "half", + "oxionnx-core", + "thiserror 2.0.19", + "tracing", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df728be843c7070fab6ab7c328c4e9e9d78e23bf749c0669c86ee7ebfa050a2" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2dd6fc3b26b3462ee188aac870f5a41d398f1cd5e2408d16531bd71c9591fd" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a7a9205cfb6f596a9e8b689c0a15f9ceb7a1aafae7aaf788150ac65b29975b6" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pest_meta" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85abd351c0de1e8384fc791a0737111a350394937e92b956b743dac12429f57c" +dependencies = [ + "pest", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", + "serde", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pipewire" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8585aba8a52ad74ccc633b8e293c1dc4277976bd5d510b925533f34fd6685f38" +dependencies = [ + "bitflags 2.13.1", + "libc", + "libspa", + "libspa-sys", + "pipewire-sys", + "rustix 1.1.4", +] + +[[package]] +name = "pipewire-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2089f245b548723e60325773c27f586b7a2372c79ea941b246cd0d654706adc" +dependencies = [ + "bindgen", + "libspa-sys", + "system-deps", +] + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "portable-atomic" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.13+spec-1.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.3", + "rustls", + "socket2", + "thiserror 2.0.19", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" +dependencies = [ + "bytes", + "getrandom 0.4.3", + "lru-slab", + "rand 0.10.2", + "rand_pcg", + "ring", + "rustc-hash 2.1.3", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.19", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.61.2", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +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.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +dependencies = [ + "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "serde", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e8caa82e31bb98fee12fa8f051c94a6aa36b07cddb03f0d4fc558988360ff1" +dependencies = [ + "cocoa", + "core-graphics", + "objc", + "raw-window-handle 0.6.2", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "redox_syscall" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07507be7b4a5f9f26eeb41eeaebb1f5a7ff29dfb29739facc21d35bf8b11c21e" +dependencies = [ + "bitflags 2.13.1", +] + +[[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 2.0.19", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots 1.0.9", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.13.1", + "serde", + "serde_derive", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "safetensors" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44560c11236a6130a46ce36c836a62936dc81ebf8c36a37947423571be0e55b6" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +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 = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.13.1", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "socks" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" +dependencies = [ + "byteorder", + "libc", + "winapi", +] + +[[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.1", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "system-deps" +version = "7.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +dependencies = [ + "thiserror-impl 2.0.19", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "1.1.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.4", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime 0.6.11", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.13+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.4", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.13.1", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "socks", + "url", + "webpki-roots 0.26.11", +] + +[[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 = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wayland-backend" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016ccf01d1c58b6f8999612813e17c9b2390f7d70671428869913310f83f54b8" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073" +dependencies = [ + "bitflags 2.13.1", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.13.1", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0" +dependencies = [ + "proc-macro2", + "quick-xml 0.41.0", + "quote", +] + +[[package]] +name = "wayland-server" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde9c29be0f723a573977de51ee455bf3dfa03652730a74f9dd3b337e374d75" +dependencies = [ + "bitflags 2.13.1", + "downcast-rs", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "libc", + "log", + "memoffset", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.9", +] + +[[package]] +name = "webpki-roots" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[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.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winit" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.13.1", + "block2 0.5.1", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk 0.9.0", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit 0.2.2", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle 0.6.2", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +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 = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 1.1.4", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcap" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b31c7f57ddfb14983525d9149eaed160de7d3973aaa546f3e19eb3394122b6b" +dependencies = [ + "dispatch2", + "image", + "libwayshot-xcap", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-av-foundation", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-media", + "objc2-core-video", + "objc2-foundation 0.3.2", + "percent-encoding", + "pipewire", + "rand 0.10.2", + "scopeguard", + "serde", + "thiserror 2.0.19", + "url", + "widestring", + "windows", + "xcb", + "zbus", +] + +[[package]] +name = "xcb" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4c580d8205abb0a5cf4eb7e927bd664e425b6c3263f9c5310583da96970cf6" +dependencies = [ + "bitflags 1.3.2", + "libc", + "quick-xml 0.30.0", +] + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.13.1", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[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 2.0.119", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe18fb60dc696039e738717b76eaea21e7a4489bbb1885020b43c94236d7e98a" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix 1.1.4", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow 1.0.4", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe96480bed92df2b442a1a30df364e12d08eed03aeb061f2b8dc6afb2be91119" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e" +dependencies = [ + "serde", + "winnow 1.0.4", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[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 2.0.119", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + +[[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 2.0.119", +] + +[[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.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] + +[[package]] +name = "zvariant" +version = "5.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee2a0bcd2a907786a456fff45aaaaf54c9ba5f50b71ae9ec1a4edd200c94911" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow 1.0.4", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a708216a18780796770bfe3f4739c7c83a3e8f789b755534bbbc06e4e23e12" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.119", + "winnow 1.0.4", +] diff --git a/environment/publication-source/source-snapshot/Cargo.toml b/environment/publication-source/source-snapshot/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..646d2e32e32606e5679e6ad6aa6753ea44cb192c --- /dev/null +++ b/environment/publication-source/source-snapshot/Cargo.toml @@ -0,0 +1,74 @@ +[package] +name = "dinovision" +version = "0.1.0" +edition = "2024" + +[workspace] +members = ["android", "android-xr"] + +[dependencies] +# Pinned to the exact blade-graphics revision meganeura depends on. Both +# crates must resolve to the *same* blade-graphics so the +# `Arc` we create for rendering is the same type +# meganeura's `SessionConfig::gpu` accepts. Bump both together. +blade-graphics = { version = "0.8.4", git = "https://github.com/kvark/blade", rev = "ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac" } +meganeura = { version = "0.2", default-features = false } +bytemuck = { version = "1", features = ["derive"] } +blade-macros = "0.3" +half = "2" +log = "0.4" + +# Desktop screen capture. Optional so the Android crate never sees it — +# it drags in a windowing stack that has no business on a headset. +xcap = { version = "0.9", optional = true } + +[dev-dependencies] +env_logger = "0.11" +image = { version = "0.25", default-features = false, features = ["png", "jpeg"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +sha2 = "0.10" + +# The viewer's windowing, kept off Android: winit drags in android-activity, +# which then fails to build for aarch64-linux-android when no backend +# feature is selected — and it has no business there anyway, since the +# on-device benchmark is a plain native binary and the XR app has its own +# activity. +[target.'cfg(not(target_os = "android"))'.dev-dependencies] +winit = "0.30" + +[features] +default = [] +# Desktop-only: lets the tools fetch weights straight from the Hub. The +# on-device crate never enables it. +hub = ["meganeura/hub"] +# Live screen capture as a `source::FrameSource`. +capture = ["dep:xcap"] + +# Tools live in examples/ rather than src/bin/ so they can use +# dev-dependencies, matching meganeura's own layout. +[[example]] +name = "bench" +path = "examples/bench.rs" + +[[example]] +name = "verify" +path = "examples/verify.rs" + +# Local checkout: the Android build fix (hf-hub behind a feature, +# tokenizers moved to dev-dependencies) is not upstream yet. +[patch.crates-io] +meganeura = { path = "../meganeura" } + +[[example]] +name = "preview" +path = "examples/preview.rs" + +[[example]] +name = "viewer" +path = "examples/viewer.rs" +required-features = ["capture"] + +[[example]] +name = "train_decoder" +path = "examples/train_decoder.rs" diff --git a/environment/publication-source/source-snapshot/LICENSE b/environment/publication-source/source-snapshot/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..b8600f37f580ab0ea4766922726a3f0a9c4cb953 --- /dev/null +++ b/environment/publication-source/source-snapshot/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Dzmitry Malyshau + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/environment/publication-source/source-snapshot/README.md b/environment/publication-source/source-snapshot/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b78e1ef3ef783f24ff9b66dc39956765d9c32af4 --- /dev/null +++ b/environment/publication-source/source-snapshot/README.md @@ -0,0 +1,363 @@ +# dinovision + +DINOv3 inference on Meta Quest, using [Blade](https://github.com/kvark/blade) +for graphics and [Meganeura](https://github.com/kvark/meganeura) for the +network. The camera image is encoded to DINOv3 patch features and those +features are turned back into something viewable, so the wearer sees the +world through a DINO roundtrip. + +Status: **the full stereo passthrough roundtrip is implemented.** The corrected +encoder and Meganeura-trained decoder pass host validation; fresh Quest +correctness and timing runs are tracked in `REPORT.md`. No historical device +number in Git history is paper evidence unless that report explicitly admits +it into the frozen artifact. + +**Meganeura does both halves.** The encoder is Meganeura inference; the +decoder was *trained* in Meganeura too — its autodiff builds the backward +pass (47 forward nodes → 122 with backward), its Adam runs the updates, and +`session.step()` does forward, backward, and optimizer in one GPU +submission. PyTorch is not used to train or export the decoder; it appears +only in the independent Hugging Face numerical-reference check. + +The test-pattern fallback remains available when camera permission or hardware +is absent, but it is not evidence for the passthrough result. + +## Layout + +| Path | What | +|---|---| +| `src/dinov3.rs` | The encoder as a meganeura graph, plus config and RoPE tables | +| `src/preprocess.rs` | Image → patch tensor, in the order the folded patch-embedding matmul needs | +| `src/weights.rs` | Binding a HuggingFace checkpoint to graph parameters | +| `src/pca.rs` | Features → RGB: on-device PCA fit, folded into the graph as one matmul | +| `src/inference.rs` | The worker thread that owns the session and publishes feature grids | +| `src/render.rs` | Full-screen view of the coloured grid | +| `src/source.rs` | Where frames come from: test pattern, screen capture, and the seam the Quest camera slots into | +| `src/bench.rs` | Throughput measurement, shared by desktop and device | +| `examples/viewer.rs` | Live windowed viewer over screen capture | +| `examples/preview.rs` | Runs the whole pipeline on desktop and writes a PNG | +| `examples/bench.rs` | Desktop benchmark runner | +| `examples/verify.rs` | Numerics comparison against the HuggingFace reference | +| `android/` | The headless benchmark APK | +| `android-xr/` | The XR application | +| `tools/dump_reference.py` | Produces the reference dump `verify` consumes | + +## Running + +**Live, in a window, no headset needed.** Screen capture through the same +pipeline the headset runs: + +```sh +cargo run --release --features capture --example viewer -- [model.safetensors] [monitor] +``` + +`R` refits the colour basis (worth doing after pointing it at something +new), `Esc` quits. The window title reports display and inference rates. + +This is the demo, and it is also how the passthrough-camera work gets +de-risked: capture loop, downscale, and asynchronous-frame structure are all +identical, so the Quest camera becomes one more `source::FrameSource` with +nothing around it changing. + +Run the whole pipeline on desktop and look at the result — inference +worker, PCA fit, colour projection, everything but OpenXR: + +```sh +cargo run --release --example preview -- preview.png [model.safetensors] +``` + +Without a checkpoint it uses synthetic weights. The colours are then +meaningless, but the *structure* is not: a ViT with random weights still +preserves patch identity, so the scene's layout must still show through. If +it comes out scrambled, patch extraction or token ordering is broken. + +Desktop benchmark: + +```sh +cargo run --release --example bench -- 20 +``` + +Weights. Accept Meta's DINOv3 License on the canonical gated repository, then +download the exact upstream checkpoint: + +```sh +hf download facebook/dinov3-vits16-pretrain-lvd1689m model.safetensors \ + --local-dir ref/ +``` + +The paper artifact records SHA-256 +`4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d`. + +Semantic check — that the features actually separate content: + +```sh +DINOVISION_WEIGHTS=model.safetensors cargo test --release --test semantics -- --nocapture +``` + +On a scene of four flat regions, every same-material patch pair must score +closer than every different-material pair (measured: worst within 0.984, +best across 0.959). This catches more than a numerical diff would: a +transposed projection, a mis-paired RoPE half, or a patch flattening in the +wrong channel order all leave magnitudes healthy while collapsing that +margin — and it needs no torch on the machine. + +A strict numerical comparison against HuggingFace is also available, if you +have `torch`/`transformers`: + +```sh +python tools/dump_reference.py --out ref/ +cargo run --release --example verify -- ref/ +``` + +On device. Needs `cargo-apk`, the `aarch64-linux-android` target, and +`ANDROID_HOME` / `ANDROID_NDK_HOME` set. + +**Benchmarking: skip the APK.** Vulkan compute works from a plain adb shell +binary — no activity, no window, no compositor, and the headset does not +even need to be awake. This is much faster to iterate on than an APK, and it +measures compute without the window system anywhere near it: + +```sh +cargo build --release --target aarch64-linux-android --example bench +adb shell mkdir -p /data/local/tmp/dinovision +adb push target/aarch64-linux-android/release/examples/bench /data/local/tmp/dinovision/ +adb shell "cd /data/local/tmp/dinovision && chmod 755 bench && RUST_LOG=info ./bench 5" +``` + +(On Git Bash, prefix with `MSYS_NO_PATHCONV=1` or `/data/...` gets rewritten +to `C:/data/...`.) + +The `android/` benchmark APK exists but is the wrong shape for Horizon OS — +see the note below. + +The XR application: + +```sh +# Optional: real weights, and a writable directory for the plan cache. +adb shell mkdir -p /data/local/tmp/dinovision +adb push ref/model.safetensors /data/local/tmp/dinovision/ + +cargo apk run --manifest-path android-xr/Cargo.toml --release --no-logcat +adb logcat -v time | grep -E "dinovision|RustStdoutStderr" +``` + +It falls back to synthetic weights if the checkpoint is absent, and logs +render and inference rates separately every five seconds. + +**The headset must be worn**, and awake is not enough. `adb shell am start` +silently caches the launch instead of running it: + +```text +Launch is blocked because: a Reprojected OS dialog is currently showing +``` + +That message is misleading. Check what is actually on top: + +```sh +adb shell dumpsys activity activities | grep topResumedActivity +``` + +`com.oculus.os.vrlockscreen/.SensorLockActivity` means the proximity sensor +has locked the headset because nobody is wearing it. `mWakefulness=Awake` +does not help, `wm dismiss-keyguard` does nothing, and there is no adb-side +override — only putting the headset on clears it. With `mWakefulness=Asleep` +the OpenXR session additionally never reaches `READY`. + +Two Horizon OS behaviours worth knowing, both learned the hard way: + +* A plain 2D activity that never creates a surface — a headless compute + benchmark, say — is killed by the volumetric window manager with + `Timeout while requesting window placement`. Use the native binary above + instead. +* Without a hand-tracking declaration, launches are blocked behind + `LaunchCheckControllerRequiredDialogActivity` when no controllers are on. + `android-xr/Cargo.toml` declares `oculus.software.handtracking` as + optional to avoid it. + +## Architecture notes + +### One shared GPU context + +The renderer and the network run on a **single** +`blade_graphics::Context`, created by `dinovision::init_context` and handed +to meganeura through `SessionConfig::gpu`. No external-memory interop is +involved: `Session::input_buffer` returns a `BufferPiece` that a render pass +can write to directly, and both sides share one device and queue. + +This is why the root `Cargo.toml` pins the *exact* blade-graphics revision +meganeura depends on. Two resolved copies of the crate would make the +`Arc` types incompatible, and the error would be a confusing type +mismatch rather than anything about versions. **Bump both together.** + +### Threading, and the constraint that shapes it + +The renderer runs free at the headset's refresh rate, always drawing the +most recent completed grid; inference runs on a worker thread and lands +whenever it lands. The display loop never waits synchronously for a model +result. + +`blade_graphics::Context` is `Send + Sync`, so an `Arc` can be +shared. `meganeura::Session` is **not** `Send`, so the worker receives the +context and builds its session *in place* rather than being handed one. +`tests/threading.rs` pins this down. + +The reason is narrower than it first appears, and fixable: the only +non-`Send` field anywhere in the chain is `ScratchBuffer::mapped`, a raw +pointer into a persistently mapped allocation. `Buffer` carries the same +kind of pointer and has `unsafe impl Send`/`Sync` already. Command buffers +are not thread-affine in Vulkan — the spec asks only that a command pool be +externally synchronized, which `&mut CommandEncoder` guarantees. A one-line +`unsafe impl Send for ScratchBuffer` in blade makes `Session` `Send` +(verified); the branch `command-encoder-send` carries it. The worker does +not need it, so it is not pulled in here. + +Threading decouples CPU orchestration, not GPU occupancy: both threads submit +to the same Vulkan queue, so a long compute submission can still delay a +render submission behind it. The audited live-worn sweep measures that +co-tenancy effect with each eye counted separately; pre-audit rates are not +retained here. + +The fix is now in meganeura: `Session::set_submission_chunks` spreads the +plan over several submissions so the renderer can interleave. The app +defaults to 12, roughly one per transformer layer. + +That boundary needs no extra synchronization, which is the whole risk of +the change and worth stating explicitly: blade closes every command buffer +with a conservative global memory barrier, opens each new one assuming an +unknown prior producer, and a Vulkan pipeline barrier's scopes cover +commands submitted to the same queue *before and after* it — not merely +those in one command buffer. `meganeura/tests/submission_chunks.rs` checks +a deep dependent chain over several steps and requires chunked output to +match the single-submission result **exactly**, at 2, 3, 5, and 16 chunks. +The isolated benchmark reports the throughput cost beside the live sweep. + +### The roundtrip + +`src/decoder.rs` reconstructs RGB from patch features — the thing the +project is named for. A plain convolutional upsampler, four ×2 stages from +`[384, 14, 14]` to `[3, 224, 224]`, about 1.3M parameters and ~0.9 GMAC, so +roughly a fifth of the encoder. No skip connections and nothing clever on +purpose: the question is what the *features* carry, and a decoder with its +own path to the input would answer a different one. + +```sh +cargo run --release --example train_decoder -- \ + \ + [steps] [images] [layers] [size] [seed] [output-dir] +cargo run --release --features capture --example viewer -- model.safetensors decoder.bin +``` + +**The training is Meganeura's own**, which is half the point of the +exercise: `train::build` with `Mode::Training` runs the autodiff that turns +47 forward nodes into a 122-node forward-plus-backward graph, `set_adam` +drives the optimizer, and each `session.step()` is forward, backward, and +parameter update in one submission. The same runtime that serves the model +on a headset trained the model on a desktop. + +Training precomputes features once per image rather than re-encoding every +step — the encoder is frozen, so running it in the loop would cost ~30× the +decoder's forward pass for no gradient — and caches targets as u8, because +as f32 they are 900 KB an image and a few thousand no longer fit in RAM. + +Expect softness. 14×14×384 is only about 2× the raw pixel count, and DINOv3 +features are trained for semantic invariance, which means colour and texture +detail are discarded *by design*. Layout and dominant colour come back well; +fine detail does not. That is the result, not a defect in the decoder. + +### Features to pixels + +The first display mode is the classic DINO visualization: project patch +features onto their top three principal components and read those off as +RGB. No trained decoder, one `[hidden, 3]` matmul, and semantically +meaningful — patches of the same object land on the same colour. + +The basis is fitted **on device** from a captured frame rather than shipped +as an asset, because feature statistics depend on what the camera is looking +at. It is folded into the graph as a parameter, so the per-frame readback is +`tokens × 3` floats (~3 KB) instead of `tokens × 384` (~300 KB), and +refitting is a `set_parameter` call rather than a graph rebuild. + +One case worth knowing about: when a component carries almost no variance — +a blank wall — normalizing it to full range would amplify numerical noise +into a psychedelic channel. Such components are mapped to flat mid-grey +instead. + +### Why the graph is hand-built + +`meganeura::load_onnx` recognizes `Add`, `Gemm`, `MatMul`, and `Relu` — not +close to enough for a ViT. Every op DINOv3 needs already exists in the IR, +so `src/dinov3.rs` transcribes +`transformers/models/dinov3_vit/modeling_dinov3_vit.py` directly, following +the pattern of meganeura's own `src/models/`. + +### The three things that make DINOv3 not a plain ViT + +1. **No learned position embedding.** Position enters only as 2D axial RoPE + on Q and K inside every layer. The `pos_embed_rescale` in the config is + applied under `if self.training` in the reference, so inference ignores + it. +2. **Prefix tokens.** A CLS token and 4 register tokens precede the patch + tokens, and RoPE deliberately skips them. Rather than split the token + dimension in the graph, the RoPE tables carry `(cos, sin) = (1, 0)` on + prefix rows, making the rotation an identity there. +3. **LayerScale.** Each residual branch is scaled by a learned hidden-channel + vector. Meganeura's broadcast operator is NCHW-flat, so the token-major + matrix is transposed to hidden-major layout before `mul_per_channel` and + transposed back afterward. Exact-shape tests pin this convention. + +Two conventions differ from the checkpoint and are fixed up in +`src/weights.rs`: `nn.Linear` stores `[out, in]` where meganeura's `matmul` +wants `[in, out]`, and the patch embedding is a 4D conv weight that gets +flattened and transposed. The checkpoint's `k_proj` genuinely has no bias +(`key_bias: false`). + +Patch flattening order is **channel-major** (`c * patch_size² + ky * +patch_size + kx`) because that is how PyTorch's `[out, 3, k, k]` conv weight +flattens. Getting it wrong still runs and produces confident nonsense, so +`src/preprocess.rs` pins it with tests. + +## Evidence status + +The original exploratory measurements are intentionally removed from this +README. An audit found that the encoder misapplied LayerScale after the first +token; the old decoder weights, reconstruction scores, and device timings are +therefore invalid. The corrected 1-, 3-, and 12-layer graphs pass an +independent Transformers comparison under predeclared numerical thresholds. + +See [REPORT.md](REPORT.md) for the paper-facing case study, +[experiments/AUDIT.md](experiments/AUDIT.md) for rejected evidence, and +[experiments/README.md](experiments/README.md) for the frozen protocol. Only +machine-readable results produced after the LayerScale correction are +admissible. + +## Local dependency revisions + +The workspace uses the sibling `../meganeura` checkout. Its Android branch +makes host-only Hub/tokenizer dependencies optional, adds Android +cross-compilation support, and exposes chunked plan submission so Blade +rendering can interleave with inference on a shared Vulkan queue. Artifact +metadata records both that checkout's full revision and the Blade revision +actually resolved by Cargo; the neighboring Blade working tree is not assumed +to be the selected dependency. + +These revisions must be frozen as clean commits before a paper artifact cites +them. Until then, `tools/collect_artifact_metadata.ps1` stores the dirty-tree +patch and hashes every tracked or untracked, non-ignored source file. + +## Android toolchain + +The camera path requires Android API 34 symbols and NDK r27. Paper builds set +both `ANDROID_NDK_ROOT` and the Android target linker to +`27.0.12077973`; NDK r23 is insufficient for the vendor-tag camera API. + +## Remaining paper run + +1. Complete three corrected decoder initializations on the frozen Imagenette + manifest and aggregate all 3,925 validation images per seed. +2. Compare one fixed public frame across the RTX host and Quest before + admitting device timing. +3. Run the isolated multi-process benchmark and live-worn chunk sweep with raw + samples and device-state snapshots. +4. Freeze source revisions and publish the corrected decoder artifacts and + audit records without the gated encoder, Imagenette images, or private + headset captures. diff --git a/environment/publication-source/source-snapshot/REPORT.md b/environment/publication-source/source-snapshot/REPORT.md new file mode 100644 index 0000000000000000000000000000000000000000..0a26a17411c88f8987f3ec60a22c9c005a8a85ff --- /dev/null +++ b/environment/publication-source/source-snapshot/REPORT.md @@ -0,0 +1,280 @@ +# DinoVision: host training and Android XR deployment with Meganeura + +## Merge recommendation + +**Status: not yet ready to merge into the Meganeura paper.** The experiment +now has a defensible claim and an audited protocol, and the corrected DINOv3 +encoder agrees with an independent Transformers implementation. The corrected +three-seed held-out decoder result is complete; fresh Quest correctness and +timing are the remaining experimental gate. No historical quality or +device-performance number from the previous version of this report should be +cited. + +The experiment is best used as a deployment case study, complementary to a +matched framework benchmark: + +> Meganeura trains an image decoder through its graph autodiff and Adam path +> on an NVIDIA host, then compiles the decoder's forward path, joined to a +> frozen DINOv3 encoder, through the same graph compiler and Vulkan runtime in +> an Android XR application sharing Blade's graphics context and queue. + +This demonstrates a useful span of the stack: transformer inference, +convolutional decoder training, parameter serialization, Android +cross-compilation, and compute/graphics co-tenancy. It does not establish +performance portability relative to PyTorch, capture-to-photon latency, +zero-copy camera integration, or a general image-generation result. + +## 1. System boundary + +DinoVision converts each passthrough frame to a 224 by 224 RGB image, runs the +first three layers of DINOv3 ViT-S/16, decodes the 14 by 14 patch-feature grid +back to RGB, and displays the reconstruction in both eyes. + +| Component | Training host | Android XR device | +|---|---|---| +| DINOv3 encoder | Frozen; run once per corpus image to cache features | Joined to the decoder in one inference graph | +| RGB decoder | Meganeura training graph, batch 8, autodiff and Adam | Same decoder builder and parameters, forward only, batch 1 | +| Compiler/runtime | Meganeura graph compiler and Vulkan runtime | Meganeura graph compiler and Vulkan runtime | +| GPU integration | Dedicated compute context | Blade graphics context and Vulkan queue shared with rendering | + +The wording “same graph” would be too strong. Training caches frozen encoder +features and optimizes a decoder-only batch graph. Deployment builds a +batch-one joined encoder/decoder graph. The decoder construction, learned +parameters, IR operators, compiler, and runtime are shared across the two +paths. + +The frozen encoder is the gated +`facebook/dinov3-vits16-pretrain-lvd1689m` checkpoint (SHA-256 +`4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d`). +At 224 pixels it produces 196 patch tokens plus one CLS and four register +tokens, each 384-dimensional. Only patch tokens enter the decoder. + +The decoder has 2,012,547 trainable parameters. Four stages successively +upsample 14 to 28, 56, 112, and 224 pixels while reducing channels from 384 +through 256, 128, 64, and 32. Each stage uses a 3 by 3 convolution, group +normalization, SiLU, and 2x upsampling; the first two stages include a second +blend convolution. A final 3 by 3 convolution and sigmoid produce RGB. Its +forward pass is 1.142 GMAC at 224 pixels. + +## 2. Correctness gate + +The first audit run found that the previous application was not executing the +intended transformer. DinoVision passed a `[tokens, hidden]` matrix to +Meganeura's NCHW-flat `mul_per_channel` operator as if it broadcast over the +trailing hidden dimension. Consequently, only the first token received the +intended learned LayerScale update; residual branches for later tokens were +effectively suppressed. Visually plausible reconstructions and a semantic +smoke test did not expose this error. + +The corrected graph transposes each residual branch to `[hidden, tokens]`, +flattens it for the NCHW operator, applies the learned hidden-coordinate gain +with all tokens as the spatial extent, reshapes, and transposes back. Exact +shape tests compare both attention and this LayerScale path against CPU +implementations. + +An independent reference run uses Torch 2.13.0+cpu and Transformers 5.14.1. +Both implementations consume the same normalized f32 pixel tensor and exact +checkpoint. The acceptance thresholds were relative output L2 at most 0.01, +CLS cosine above 0.999, and every patch-token cosine above 0.999. + +| Encoder depth | Relative L2 | CLS cosine | Worst patch cosine | Result | +|---:|---:|---:|---:|---| +| 1 layer | 0.000781 | 1.000000 | 0.999990 | pass | +| 3 layers (deployed) | 0.001403 | 1.000000 | 0.999995 | pass | +| 12 layers | 0.002253 | 0.999997 | 0.999996 | pass | + +At the first layer, embeddings, LayerNorm, Q/K/V projections, and RoPE match +to the displayed six decimal places. The attention output differs by 0.005852 +relative L2; learned LayerScale reduces the attention-residual difference to +0.000566. The final three-layer error is comfortably inside the declared +threshold. + +All decoder weights and device measurements produced before this correction +are invalid. They are excluded rather than “corrected” by reinterpretation. + +This failure also identifies a small Meganeura API-hardening opportunity. At +the frozen branch revision, `Graph::mul_per_channel` documents flat +`[N*C*H*W]` and `[N*C]` inputs but does not validate either shape, while the +compiler takes the dispatch length from `shape[0]`. A graph-construction +assertion for rank, `channels * spatial`, and gate length would have converted +this silent semantic error into an immediate diagnostic. The corrected +DinoVision graph obeys the documented contract; upstreaming that validation +would make the lesson reusable beyond this case study. + +## 3. Host training and held-out reconstruction + +The corrected experiment uses the public Imagenette-320 archive. Its archive +SHA-256 is +`569b4497c98db6dd29f335d1f109cf315fe127053cedf69010d047f0188e158c`. +An immutable manifest records every image path, byte count, SHA-256, source, +split, and leakage group; its SHA-256 is +`2071f89b2a7b077d7729641fc858e1225d057d11a797d16198c0d195d989bb89`. +The upstream train/validation boundary is preserved. + +Each run trains on the same class-interleaved prefix of 2,500 training images, +exactly 250 from each of Imagenette's ten classes, for 12,000 batch-8 updates. +The objective is mean absolute error. Adam uses +beta1 0.9, beta2 0.999, epsilon 1e-8, and a learning rate that decays linearly +from 0.002 to 0.0001 over the first 95% of updates, then remains at 0.0001. +Seeds 0, 1, and 2 independently control initialization and data order. The +selected deployment artifact is seed 0 by prior rule, not the best validation +seed. + +Every photograph is center-cropped to its largest square and resized to 224 +by 224 with a Catmull-Rom filter; there is no stochastic augmentation. The +encoder input uses ImageNet RGB mean `[0.485, 0.456, 0.406]` and standard +deviation `[0.229, 0.224, 0.225]`. The decoder target is the same resized RGB8 +image mapped to `[0,1]`, so preprocessing cannot create a train/evaluation +resolution mismatch. + +Evaluation verifies every input hash and processes all 3,925 held-out +validation images. It retains per-image MSE, MAE, PSNR, and RGB SSIM. RGB SSIM +uses an 11 by 11 Gaussian window with sigma 1.5 over the valid region. Global +PSNR is computed from aggregate squared error; seed dispersion is reported +across independently initialized decoders. + +Across the three initializations, global validation PSNR is +**21.86 +/- 0.11 dB** (mean +/- sample standard deviation). Each seed evaluates +all 3,925 images; the aggregate therefore covers 11,775 reconstruction +executions, although the same validation images are reused across seeds. + +| Seed | Global PSNR (dB) | Median-image PSNR (dB) | Median RGB SSIM | Median MAE | +|---:|---:|---:|---:|---:| +| 0 (deployment) | 21.7688 | 22.3603 | 0.6338 | 0.04729 | +| 1 | 21.9830 | 22.5714 | 0.6491 | 0.04598 | +| 2 | 21.8170 | 22.3911 | 0.6388 | 0.04700 | +| mean +/- sample SD | 21.86 +/- 0.11 | 22.44 +/- 0.11 | 0.6406 +/- 0.0078 | 0.0468 +/- 0.0007 | + +The selected seed-0 runtime decoder has SHA-256 +`d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c`; +its named SafeTensors representation has SHA-256 +`f287b5d1e4e14bed15e4883c3ea5b9f01d28e3123f3fb3308ace714e4b292123`. +Seed 1 scores highest, so retaining seed 0 demonstrably did not select the +best validation replicate. The machine-generated aggregate JSON has SHA-256 +`06d34ea8eff9d0bf50dbae467891347d7032bcd85b5080b45d381bca02ba4350`. + +A short determinism check repeated a fresh 20-update, 16-image training cell +twice with seed 20260801. Both executions produced byte-identical decoder +files (SHA-256 +`2959b06784576bb1bc495b4e0a0d2f4aeebb216d56f7fc078843df4b7ec12686`). +This exercises initialization, shuffle, encoder caching, optimization, and +serialization, but it is a reproducibility smoke test rather than a quality +or throughput result; the full 12,000-update matrix was not duplicated with +identical seeds. + +The former 20.94 dB claim was the mean PSNR of six training images selected +for a diagnostic strip and is not a generalization result. Pre-fix held-out +runs are also invalid because their encoder was wrong. + +Training wall times are retained diagnostically but excluded from performance +claims: the host clock and interactive workload were not controlled, and seed +2 includes a recorded host-suspension gap between steps 6,500 and 6,600. The +experiment demonstrates functional host training, not competitive training +throughput. + +## 4. Device experiment + +The deployment graph contains the corrected three-layer encoder, patch-token +to NCHW rearrangement, and decoder. Intermediate features remain on the GPU +inside this graph. The application creates one inference worker per eye; each +worker owns its Meganeura session. The render loop never waits for inference +and drops submissions while a worker is busy instead of queuing stale camera +frames. + +Both inference workers and Blade rendering submit to one Vulkan queue. The +Meganeura branch adds `Session::set_submission_chunks(n)`, allowing a long +plan to be split so rendering can interleave between compute submissions. +This is the main systems question for the live experiment: chunking trades +some isolated throughput for queue fairness under graphics co-tenancy. + +Fresh device results must satisfy two separate protocols: + +1. **Isolated native benchmark.** At least five untimed warmups, 20 retained + synchronized samples, median/IQR/min/max/raw samples, and three fresh + processes in one declared headset state. +2. **Live-worn XR sweep.** `submission_chunks = 1, 2, 4, 8, 12, 16` at a fixed + inference interval, retaining every application JSON window, each eye's + update rate, render-submission rate, worker wall latency, thermal/power + snapshots, display configuration, and runtime toggles. + +The host and Quest must also execute one fixed public RGB frame with identical +weights. Preprocessed patches, full encoder output, spatial decoder input, and +reconstruction are compared by relative L2, maximum absolute error, and +cosine similarity before any device timing is admitted. + +**Corrected Quest correctness and timing results are pending.** Historical +figures such as 125 ms, 12.5 Hz, the claimed 45% elementwise share, f16 +conclusions, and the 224-to-240 comparison must not appear in the paper unless +they are reproduced under the audited protocol on the corrected graph. + +The corrected source also cross-compiles successfully for +`aarch64-linux-android` at API 34. The checked release bundle contains the +native benchmark, fixed-input evaluator, and XR APK; `aapt` confirms package +`rust.dinovision_xr` and launch activity `android.app.NativeActivity`. +Cross-compilation is a build result, not evidence that the graph is correct or +fast on the Quest, so it does not relax the numerical and measurement gates. + +## 5. What the case study can support + +If the pending runs pass, DinoVision provides evidence for the following +Meganeura properties: + +- The graph IR expresses a ViT with patch projection, learned prefix tokens, + axial RoPE, multi-head attention, LayerNorm, GELU MLPs, LayerScale, and + residual connections, as well as a convolutional upsampling decoder. +- The training stack differentiates and optimizes the decoder with Adam on an + NVIDIA Vulkan device; no decoder is trained or imported through PyTorch. +- The same decoder definition and serialized parameters execute through the + inference compiler/runtime on an Android Adreno device. +- Meganeura sessions can share Blade's Vulkan context and queue inside a live + OpenXR application, and chunked plan submission exposes a runtime mechanism + for compute/graphics co-tenancy. +- The runtime cross-compiles without pulling host-only Hub/tokenizer + dependencies into Android. + +The strongest evidence is breadth and integration, not peak speed. This is an +application-level complement to controlled kernel or framework comparisons. + +## 6. Limitations + +- No matched PyTorch-on-Android baseline is included. The experiment does not + estimate speedup over another framework. +- Decoder quality is measured on held-out photographs. Until independent + headset capture sessions are grouped and held out, no quantitative + camera-domain quality claim is supported. +- DINOv3 is trained for semantic invariance, not invertibility. Reconstruction + quality is a probe of retained information, not a measure of DINOv3's + intended task quality. +- Camera conversion, CPU patchification, GPU upload, output readback, + smoothing, and renderer upload are not zero-copy. Worker wall time is not + capture-to-photon latency. +- Stereo comfort and perceived stability are single-user observations unless + instrumented or evaluated with multiple participants. +- The source revisions are not citable until DinoVision changes are committed + and the Meganeura Android branch is frozen or merged. The Blade checkout in + the neighboring repository is not necessarily the revision selected by + Cargo; artifact metadata records the resolved dependency instead. +- Debug-mode host tests pass their numerical assertions but the Khronos + validation layer emits two device-creation VUIDs from the resolved Blade + Vulkan setup (an extension dependency and a feature-chain dependency). The + release-mode reference verifier is quiet. This does not change the retained + tensors, but the current stack should not be described as validation-clean + until the Blade setup is corrected and the debug suite is rerun. + +## 7. Artifact and licensing + +`experiments/README.md` defines the complete protocol and +`experiments/AUDIT.md` records rejected evidence. Machine-readable training, +quality, correctness, benchmark, and environment records are generated by the +tools in `tools/`; summaries are derived from those records rather than +manually transcribed. + +The public Hugging Face repository will contain corrected decoder weights, +replicate metadata, held-out metrics, the public dataset manifest, and the +fixed correctness frame. It will not duplicate Meta's gated DINOv3 checkpoint, +Imagenette images, or private headset captures. + +DinoVision source code is MIT-licensed. The encoder is governed by Meta's +DINOv3 License. Decoder weights are treated conservatively as DINOv3-derived: +their distribution includes that agreement and a prominent “Built with +DINOv3” notice, and the Meganeura paper must acknowledge DINOv3. diff --git a/environment/publication-source/source-snapshot/android-xr/Cargo.toml b/environment/publication-source/source-snapshot/android-xr/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..9fcda6477acb8bdfff2e696b686aa5305e6173b8 --- /dev/null +++ b/environment/publication-source/source-snapshot/android-xr/Cargo.toml @@ -0,0 +1,83 @@ +[package] +name = "dinovision-xr" +version = "0.1.0" +publish = false +edition = "2024" + +[lib] +name = "dinovision_xr" +path = "src/lib.rs" +crate-type = ["cdylib"] + +[target.'cfg(target_os = "android")'.dependencies] +dinovision = { path = ".." } +blade-graphics = { version = "0.8.4", git = "https://github.com/kvark/blade", rev = "ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac" } +openxr = "0.19" +android-activity = { version = "0.6", features = ["native-activity"] } +android_logger = "0.14" +ndk-glue = "0.7" +log = "0.4" + +[package.metadata.android] +build_targets = ["aarch64-linux-android"] +# libopenxr_loader.so lives here; blade's examples ship the same set. +runtime_libs = "../../blade/examples-android/libs" +label = "DinoVision" + +[package.metadata.android.sdk] +# 34 is what Meta requires for the Passthrough Camera API, and NDK r27 is +# what has `ACameraManager_getTagFromName` for finding their vendor tags. +min_sdk_version = 34 +target_sdk_version = 34 + +[package.metadata.android.signing.release] +path = "../../blade/examples-android/keystore/debug.keystore" +keystore_password = "android" +key_alias = "androiddebugkey" +key_password = "android" + +# Without these, Horizon OS assumes controllers are mandatory and blocks +# launch behind a "controllers required" system dialog +# (LaunchCheckControllerRequiredDialogActivity). The app takes no input at +# all, so declaring optional hand tracking is the honest way to say so. +[[package.metadata.android.uses_feature]] +name = "oculus.software.handtracking" +required = false + +[[package.metadata.android.uses_permission]] +name = "com.oculus.permission.HAND_TRACKING" + +# Passthrough camera. Declaring these is necessary but not sufficient — +# HEADSET_CAMERA is a runtime permission, so it also has to be granted: +# adb shell pm grant rust.dinovision_xr horizonos.permission.HEADSET_CAMERA +[[package.metadata.android.uses_permission]] +name = "horizonos.permission.HEADSET_CAMERA" + +[[package.metadata.android.uses_permission]] +name = "android.permission.CAMERA" + +[[package.metadata.android.uses_feature]] +name = "android.hardware.camera2.any" +required = false + +[package.metadata.android.application] +label = "DinoVision" + +[[package.metadata.android.application.meta_data]] +name = "com.oculus.vr.focusaware" +value = "true" + +[package.metadata.android.application.activity] +label = "DinoVision" +theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" +config_changes = "density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode" +launch_mode = "singleTask" +orientation = "landscape" +resizeable_activity = false + +[[package.metadata.android.application.activity.intent_filter]] +actions = ["android.intent.action.MAIN"] +categories = [ + "com.oculus.intent.category.VR", + "android.intent.category.LAUNCHER", +] diff --git a/environment/publication-source/source-snapshot/android-xr/src/lib.rs b/environment/publication-source/source-snapshot/android-xr/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..247fba429bfe67ab5e6d296881e829fadda52607 --- /dev/null +++ b/environment/publication-source/source-snapshot/android-xr/src/lib.rs @@ -0,0 +1,879 @@ +//! The DinoVision XR application. +//! +//! Renders the DINO feature view to both eyes at the headset's refresh +//! rate, while inference runs on a worker thread at whatever rate it can +//! manage. The renderer never waits for the encoder: it draws the most +//! recent completed grid, so a long inference does not become a synchronous +//! render-frame wait. +//! +//! ```text +//! cargo apk run --manifest-path android-xr/Cargo.toml --release --no-logcat +//! adb logcat -v time | grep -E "dinovision|RustStdoutStderr" +//! ``` +//! +//! Frames come from the passthrough camera when it opens, and from +//! `dinovision::source::TestPattern` when it does not — a missing runtime +//! permission or an older Horizon OS should degrade to something visible +//! rather than a black screen. The camera needs a grant that the manifest +//! alone does not provide: +//! +//! ```text +//! adb shell pm grant rust.dinovision_xr horizonos.permission.HEADSET_CAMERA +//! ``` + +#![cfg(target_os = "android")] + +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; + +use blade_graphics as gpu; +use dinovision::dinov3::Config; +use dinovision::inference::{self, Weights, Worker}; +use dinovision::render::GridView; +use dinovision::source::{FrameSource, TestPattern}; +use log::{info, warn}; +use openxr as xr; + +const VIEW_TYPE: xr::ViewConfigurationType = xr::ViewConfigurationType::PRIMARY_STEREO; +const MAX_EYES: usize = 2; + +/// Where the app looks for weights pushed by `adb push`. +/// +/// Bundling 43 MB of f16 weights as an asset is the eventual answer; for +/// bring-up, a path outside the APK avoids a rebuild per weight change. +const WEIGHTS_PATH: &str = "/data/local/tmp/dinovision/model.safetensors"; + +/// Trained RGB decoder. When present the app shows a real reconstruction +/// instead of the PCA colouring — the roundtrip the project is for. +const DECODER_PATH: &str = "/data/local/tmp/dinovision/decoder.bin"; + +/// Encoder depth used with the decoder. +/// +/// The published decoder is trained against this depth and is not valid at +/// any other. Depth is an artifact property, not a runtime quality switch. +const RECONSTRUCTION_LAYERS: usize = 3; + +const CAPTURE_SIZE: (i32, i32) = (1280, 960); + +/// Show the camera frame directly instead of the DINO roundtrip, for +/// checking geometry independently of the model: +/// +/// ```text +/// adb shell touch /data/local/tmp/dinovision/raw_camera +/// ``` +const RAW_CAMERA_PATH: &str = "/data/local/tmp/dinovision/raw_camera"; + +/// Dump camera frames to disk for retraining, one raw RGB file each: +/// +/// ```text +/// adb shell "echo room-a-01 > /data/local/tmp/dinovision/capture" +/// # …wear the headset and look around… +/// adb pull /sdcard/Android/data/rust.dinovision_xr/files/captures/room-a-01 +/// ``` +/// +/// The decoder has only ever been trained on clean, well-lit colour +/// photographs, while these cameras produce noisy, wide-angle, nearly +/// monochrome frames. That mismatch is the most likely single cause of poor +/// reconstruction on the headset, and no amount of architecture work +/// addresses it — the model has to see the distribution it will be used on. +/// The flag is read from `/data/local/tmp` — apps may read there — but the +/// frames go to the app's own external directory. SELinux forbids an +/// `untrusted_app` writing to `shell_data_file` no matter how permissive +/// the mode bits look: +/// +/// ```text +/// avc: denied { write } … tcontext=u:object_r:shell_data_file +/// ``` +const CAPTURE_FLAG_PATH: &str = "/data/local/tmp/dinovision/capture"; +const CAPTURE_DIR_BASE: &str = "/sdcard/Android/data/rust.dinovision_xr/files/captures"; + +fn capture_directory() -> Option { + if !std::path::Path::new(CAPTURE_FLAG_PATH).exists() { + return None; + } + let requested = std::fs::read_to_string(CAPTURE_FLAG_PATH).unwrap_or_default(); + let requested = requested.trim(); + let session = if requested.is_empty() { + format!( + "session-{}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs() + ) + } else if requested + .chars() + .all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '_')) + { + requested.to_string() + } else { + warn!("invalid capture session {requested:?}; use only ASCII letters, digits, '-' and '_'"); + return None; + }; + let directory = format!("{CAPTURE_DIR_BASE}/{session}"); + if std::fs::read_dir(&directory) + .ok() + .and_then(|mut entries| entries.next()) + .is_some() + { + warn!("capture session directory is not empty; refusing to overwrite {directory}"); + return None; + } + match std::fs::create_dir_all(&directory) { + Ok(()) => { + info!("capturing session {session:?} to {directory}"); + Some(directory) + } + Err(error) => { + warn!("could not create capture session directory {directory}: {error}"); + None + } + } +} + +/// Frames to keep, and how many to skip between them. +/// +/// Consecutive frames of a barely-moving head are near-duplicates and teach +/// almost nothing, so sampling sparsely buys far more variety per byte. At +/// 224² RGB a frame is 150 KB, so this caps the dump around 225 MB. +const CAPTURE_LIMIT: usize = 1500; +const CAPTURE_STRIDE: u64 = 8; + +/// Run one camera and one roundtrip, shown to both eyes: +/// +/// ```text +/// adb shell touch /data/local/tmp/dinovision/mono +/// ``` +/// +/// Halves the work, since encoder and decoder both run once instead of +/// twice, and roughly doubles the update rate. The cost is that the right +/// eye sees the world from the left camera's position, so there is no +/// stereo depth — worth it when the question is latency rather than +/// whether the roundtrip fuses. +const MONO_PATH: &str = "/data/local/tmp/dinovision/mono"; + +/// How far each new result moves the displayed image. 1.0 shows the raw +/// result and flickers; lower is steadier but lags. At ~12 Hz inference, +/// 0.35 settles within a few frames while killing most of the jitter. +const SMOOTHING: f32 = 0.35; + +/// Optional override for the camera image's vertical half-angle, in +/// degrees. +/// +/// Unset — the normal case — the image simply spans each eye's field of +/// view, which is what passthrough itself does with these cameras. Only +/// worth setting if the camera turns out to see meaningfully more or less +/// than the display shows: +/// +/// ```text +/// adb shell "echo 40 > /data/local/tmp/dinovision/camera_half_fov_deg" +/// ``` +/// +/// The full frame is resampled rather than cropped, so the horizontal +/// extent follows from the sensor aspect: for a rectilinear lens the +/// tangents scale with the sensor dimensions, giving +/// `tan(hfov/2) = (w/h) · tan(vfov/2)`. +const HALF_FOV_PATH: &str = "/data/local/tmp/dinovision/camera_half_fov_deg"; + +fn read_half_fov() -> Option { + let deg = std::fs::read_to_string(HALF_FOV_PATH) + .ok() + .and_then(|s| s.trim().parse::().ok())?; + info!("camera half-FOV override: {deg} deg"); + Some(deg.to_radians()) +} + +/// Minimum gap between inference submissions, in milliseconds, read from a +/// pushed file so it can be changed without rebuilding: +/// +/// ```text +/// adb shell "echo 300 > /data/local/tmp/dinovision/inference_interval_ms" +/// ``` +/// +/// Inference and rendering share one Vulkan queue, so a long compute +/// submission delays the frame queued behind it. Left unthrottled the +/// worker resubmits the instant it finishes, so the GPU is never free and +/// the render loop is dragged down to the encoder's cadence. Raising this +/// trades feature-update rate for frame rate. A very large value disables +/// inference entirely, which is how the renderer's standalone cost is +/// measured. +const INTERVAL_PATH: &str = "/data/local/tmp/dinovision/inference_interval_ms"; + +/// How many submissions the encoder is split across, same override +/// mechanism as the interval. +const CHUNKS_PATH: &str = "/data/local/tmp/dinovision/submission_chunks"; + +/// Interactive default. The paper harness overrides this and sweeps every +/// declared chunk cell in a precommitted non-monotonic order. +const DEFAULT_CHUNKS: usize = 12; + +fn read_chunks() -> usize { + let n = std::fs::read_to_string(CHUNKS_PATH) + .ok() + .and_then(|s| s.trim().parse::().ok()) + .unwrap_or(DEFAULT_CHUNKS); + info!("submission chunks: {n}"); + n +} + +/// Conservative interactive default. Audited co-tenancy runs override it +/// explicitly and record the selected value in every JSON window. +const DEFAULT_INTERVAL_MS: u64 = 500; + +fn read_interval() -> Duration { + let ms = std::fs::read_to_string(INTERVAL_PATH) + .ok() + .and_then(|s| s.trim().parse::().ok()) + .unwrap_or(DEFAULT_INTERVAL_MS); + info!("inference interval: {ms} ms"); + Duration::from_millis(ms) +} + +/// One eye's chain: its own camera, its own encode, its own image. +/// +/// Kept entirely separate per eye because the experiment is whether the +/// roundtrip survives stereo fusion. Sharing anything — one camera shown +/// twice, or one encode reused — would answer a different and easier +/// question. +struct EyePipeline { + source: Box, + worker: Worker, + view: GridView, + /// Exponentially smoothed image, damping per-frame feature jitter. + smoothed: Vec, + last_shown: u64, + last_submit: Instant, + eye: dinovision::camera::Eye, + /// Head orientation when the in-flight frame was captured, and when + /// the frame currently on screen was. The difference between the + /// latter and the live pose is what keeps the image world-locked. + pending_orientation: Option<[f32; 4]>, + shown_orientation: Option<[f32; 4]>, +} + +struct App { + surface: gpu::XrSurface, + /// One per eye when both cameras open, otherwise a single shared chain + /// drawn to both. + eyes: Vec, + config: Config, + frames: u64, + last_report: Instant, + /// Completed results per eye pipeline in the current reporting window. + /// Keeping these separate avoids calling two asynchronous eye updates a + /// single "inference Hz" figure. + inference_counts: Vec, + /// Wall latency for every completed worker result in the current window. + inference_latencies_ms: Vec>, + /// Minimum gap between inference submissions. See [`INTERVAL_PATH`]. + interval: Duration, + submission_chunks: usize, + camera_active: bool, + /// Bypass inference and show the camera frame. See [`RAW_CAMERA_PATH`]. + raw_camera: bool, + raw_scratch: Vec, + /// Tangent of the image half-angle, per axis. See [`HALF_FOV_PATH`]. + camera_half_tan: Option<[f32; 2]>, + logged_fov: bool, + /// Frames written so far, and the counter that strides between them. + captured: usize, + capture_tick: u64, + capturing: bool, + capture_dir: Option, + /// Head orientation from the previous frame. Used when submitting, so + /// it is one frame stale — around 10 ms against the 100 ms the + /// inference itself takes, which is the lag that actually matters. + last_head: Option<[f32; 4]>, +} + +impl App { + fn new(context: &Arc, config: Config) -> Self { + let surface = context + .create_xr_surface() + .expect("unable to create XR surface"); + + // A trained decoder turns this into the actual roundtrip, at a + // shallower and much cheaper encoder depth. + let decoder_path = std::path::PathBuf::from(DECODER_PATH); + let (config, display, view_grid) = if decoder_path.exists() { + info!("reconstructing with {}", decoder_path.display()); + let config = config.with_layers(RECONSTRUCTION_LAYERS); + let grid = config.image_size; + ( + config, + inference::Display::Reconstruction(decoder_path), + grid, + ) + } else { + let grid = config.grid(); + (config, inference::Display::PcaColour, grid) + }; + // Raw camera frames are full resolution regardless of what the + // model would have produced. + let raw_camera = std::path::Path::new(RAW_CAMERA_PATH).exists(); + if raw_camera { + info!("raw camera mode — inference bypassed"); + } + let view_grid = if raw_camera { + config.image_size + } else { + view_grid + }; + + // Real weights if they have been pushed, synthetic otherwise, so + // the render path can be brought up before the checkpoint is on + // the device. + let weights_path = std::path::PathBuf::from(WEIGHTS_PATH); + let have_weights = weights_path.exists(); + if have_weights { + info!("using weights from {}", weights_path.display()); + } else { + warn!( + "no weights at {WEIGHTS_PATH} — running synthetic; \ + adb push the checkpoint there for real features" + ); + } + + // One chain per eye if both cameras open. Two encodes cost twice the + // GPU, which is the price of the question being asked: whether a + // reconstructed world still fuses into a single stereo percept. A + // single camera shown to both eyes cannot answer it — that is + // monocular, and would look flat and offset no matter how good the + // reconstruction is. + let chunks = read_chunks(); + let mono = std::path::Path::new(MONO_PATH).exists(); + if mono { + info!("monocular: one camera and one roundtrip for both eyes"); + } + let wanted: &[dinovision::camera::Eye] = if mono { + &[dinovision::camera::Eye::Left] + } else { + &[ + dinovision::camera::Eye::Left, + dinovision::camera::Eye::Right, + ] + }; + let mut sources: Vec<(dinovision::camera::Eye, Box)> = Vec::new(); + for &eye in wanted { + match dinovision::camera::PassthroughCamera::new(config.image_size, eye, CAPTURE_SIZE) { + Ok(camera) => { + info!("{eye:?} camera open"); + sources.push((eye, Box::new(camera))); + } + Err(e) => warn!("{eye:?} camera unavailable: {e}"), + } + } + if sources.is_empty() { + warn!( + "no camera opened; falling back to the test pattern. Grant it with: \ + adb shell pm grant rust.dinovision_xr horizonos.permission.HEADSET_CAMERA" + ); + sources.push(( + dinovision::camera::Eye::Left, + Box::new(TestPattern::new(config.image_size)), + )); + } + + let eyes: Vec = sources + .into_iter() + .map(|(eye, source)| EyePipeline { + source, + // No plan cache: two sessions would race on the same file. + worker: inference::spawn( + Arc::clone(context), + config.clone(), + if have_weights { + Weights::SafeTensors(weights_path.clone()) + } else { + Weights::Synthetic + }, + None, + chunks, + display.clone(), + ), + view: GridView::new(context, surface.format(), view_grid), + smoothed: Vec::new(), + last_shown: 0, + last_submit: Instant::now(), + eye, + pending_orientation: None, + shown_orientation: None, + }) + .collect(); + info!( + "{} eye pipeline(s) — {}", + eyes.len(), + if eyes.len() > 1 { + "stereo" + } else { + "monocular" + } + ); + let eye_count = eyes.len(); + let interval = read_interval(); + + let capture_dir = capture_directory(); + Self { + surface, + eyes, + config, + frames: 0, + last_report: Instant::now(), + inference_counts: vec![0; eye_count], + inference_latencies_ms: vec![Vec::new(); eye_count], + interval, + submission_chunks: chunks, + camera_active: true, + raw_camera, + raw_scratch: Vec::new(), + last_head: None, + captured: 0, + capture_tick: 0, + capturing: capture_dir.is_some(), + capture_dir, + camera_half_tan: read_half_fov().map(|v| { + let t = v.tan(); + let aspect = CAPTURE_SIZE.0 as f32 / CAPTURE_SIZE.1 as f32; + [t * aspect, t] + }), + logged_fov: false, + } + } + + /// Acquire or release the camera as focus comes and goes. + /// + /// Android hands the camera to the foreground app and takes it back + /// otherwise; holding it while backgrounded is what produced + /// `ACameraDevice` error 3. Releasing on the way out also means the + /// headset camera stops streaming to an app the wearer has navigated + /// away from, which is the behaviour anyone would expect of it. + fn set_camera_active(&mut self, active: bool) { + if active == self.camera_active { + return; + } + self.camera_active = active; + let size = self.config.image_size; + for pipeline in &mut self.eyes { + if active { + match dinovision::camera::PassthroughCamera::new(size, pipeline.eye, CAPTURE_SIZE) { + Ok(camera) => { + info!("{:?} camera reacquired on focus", pipeline.eye); + pipeline.source = Box::new(camera); + } + Err(e) => warn!("could not reacquire the {:?} camera: {e}", pipeline.eye), + } + } else { + // Dropping the camera closes the device and stops the stream. + info!("releasing the {:?} camera on focus loss", pipeline.eye); + pipeline.source = Box::new(TestPattern::new(size)); + } + } + } + + fn render(&mut self, context: &gpu::Context, encoder: &mut gpu::CommandEncoder) { + let interval = self.interval; + let raw = self.raw_camera; + let config = self.config.clone(); + let head = self.last_head; + + // Snapshot frames for retraining, from the first eye only — the two + // cameras see nearly the same scene, so the second would mostly + // duplicate the first. + if self.capturing && self.captured < CAPTURE_LIMIT { + self.capture_tick += 1; + if self.capture_tick.is_multiple_of(CAPTURE_STRIDE) + && let Some(pipeline) = self.eyes.first_mut() + && let Some(rgb) = pipeline.source.next_frame() + { + let path = format!( + "{}/{:05}.rgb", + self.capture_dir.as_deref().expect("capture directory"), + self.captured + ); + match std::fs::write(&path, rgb) { + Ok(()) => { + self.captured += 1; + if self.captured.is_multiple_of(100) { + info!("captured {} / {CAPTURE_LIMIT} frames", self.captured); + } + } + Err(e) => { + warn!("capture failed ({e}); stopping"); + self.capturing = false; + } + } + } + } + for (pipeline_index, pipeline) in self.eyes.iter_mut().enumerate() { + if raw { + // Straight to the display, no model in the way, for judging + // geometry and render submission rate separately from the + // network. Keep this before worker submission: "raw" must + // not leave hidden inference contending for the same queue. + if let Some(rgb) = pipeline.source.next_frame() { + self.raw_scratch.clear(); + self.raw_scratch + .extend(rgb.iter().map(|&b| b as f32 / 255.0)); + pipeline.view.upload(context, &self.raw_scratch); + } + continue; + } + + // Keep each worker fed. They report not-ready while busy, and + // frames offered meanwhile are dropped rather than queued — a + // queued frame would be stale by the time it ran. + if pipeline.worker.is_ready() + && pipeline.last_submit.elapsed() >= interval + && let Some(rgb) = pipeline.source.next_frame() + { + let patches = dinovision::preprocess::patches_from_rgb8(rgb, &config); + if pipeline.worker.submit(patches) { + pipeline.last_submit = Instant::now(); + // Remember where the head was pointing, so the result + // can be put back in the world where it was seen. + pipeline.pending_orientation = head; + } + } + + let generation = pipeline.worker.generation(); + if generation != pipeline.last_shown + && let Some(grid) = pipeline.worker.latest() + { + // Blend towards the new frame rather than snapping to it. + // DINO features are sensitive enough that sensor noise and + // auto-exposure make individual patches jump between + // consecutive frames, which reads as constant flickering + // even with the head still. + let new = grid.patch_rgb(); + if pipeline.smoothed.len() != new.len() { + pipeline.smoothed = new.to_vec(); + } else { + for (s, &n) in pipeline.smoothed.iter_mut().zip(new) { + *s += (n - *s) * SMOOTHING; + } + } + pipeline.view.upload(context, &pipeline.smoothed); + pipeline.last_shown = generation; + pipeline.shown_orientation = pipeline.pending_orientation; + self.inference_counts[pipeline_index] += 1; + self.inference_latencies_ms[pipeline_index].push(grid.latency_ms); + } + } + + let Some(frame) = self.surface.acquire_frame(context) else { + return; + }; + + encoder.start(); + encoder.init_texture(frame.texture()); + + let eyes = frame.xr_view_count().min(MAX_EYES as u32); + for eye in 0..eyes { + // Each eye's frustum is asymmetric and differs from the other's, + // so the overlay has to be placed per eye. Skipping this is what + // made the two views refuse to fuse. + let xr_view = frame.xr_view(eye); + let fov = [ + xr_view.fov.angle_left, + xr_view.fov.angle_right, + xr_view.fov.angle_up, + xr_view.fov.angle_down, + ]; + if !self.logged_fov { + info!( + "eye {eye} frustum: L {:.1} R {:.1} U {:.1} D {:.1} deg \ + (axis offset x {:.2} y {:.2})", + fov[0].to_degrees(), + fov[1].to_degrees(), + fov[2].to_degrees(), + fov[3].to_degrees(), + -(fov[1].tan() + fov[0].tan()) / (fov[1].tan() - fov[0].tan()), + -(fov[2].tan() + fov[3].tan()) / (fov[2].tan() - fov[3].tan()), + ); + if eye + 1 == eyes { + self.logged_fov = true; + } + } + let now = xr_view.pose.orientation; + if eye == 0 { + self.last_head = Some(now); + } + + // With two cameras each eye shows its own; with one, both show + // the same and the view is monocular. + let index = (eye as usize).min(self.eyes.len() - 1); + + // Put the image back where the head was pointing when the + // camera saw it, so it holds still in the world while the view + // sweeps across it. Without this the picture is glued to the + // screen and drags a tenth of a second behind every turn. + let centre = self.eyes[index] + .shown_orientation + .and_then(|then| dinovision::render::reprojection_offset(then, now)) + .unwrap_or([0.0, 0.0]); + self.eyes[index].view.set_transform( + context, + eye as usize, + // Same size as filling the buffer, but recentred on each + // eye's own axis. Still a 2D scale and offset; nothing is + // projected. + // + // The recentring is not optional, and this device says so + // with numbers. Its frusta are asymmetric and mirrored — + // left eye L -49.0 R +45.0, right eye L -45.0 R +49.0 — so + // an image filling the buffer has its centre at -2.0 deg in + // the left eye and +2.0 deg in the right. That is 4 deg of + // *divergence*, pulling the eyes apart, against a fusion + // limit of roughly 1 deg. It reads exactly as "the object + // is further left in my left eye" and it cannot converge. + match self.camera_half_tan { + Some(half_tan) => dinovision::render::EyeTransform::for_eye(fov, half_tan), + None => dinovision::render::EyeTransform::filling_at(fov, centre), + }, + ); + + let mut pass = encoder.render( + "eye", + gpu::RenderTargetSet { + colors: &[gpu::RenderTarget { + view: frame.xr_texture_view(eye), + // The view covers every pixel, so clearing would only + // be wasted bandwidth on a tiler. + init_op: gpu::InitOp::Clear(gpu::TextureColor::OpaqueBlack), + finish_op: gpu::FinishOp::Store, + }], + depth_stencil: None, + }, + ); + self.eyes[index].view.draw(&mut pass, eye as usize); + } + + encoder.present(frame); + let _sync_point = context.submit(encoder); + self.frames += 1; + + if self.last_report.elapsed() >= Duration::from_secs(5) { + let secs = self.last_report.elapsed().as_secs_f64(); + let render_hz = self.frames as f64 / secs; + let per_eye_hz: Vec = self + .inference_counts + .iter() + .map(|&count| count as f64 / secs) + .collect(); + // This is the lower eye update rate, not a synchronization claim: + // the two cameras and workers are currently independent. + let min_eye_hz = per_eye_hz.iter().copied().fold(f64::INFINITY, f64::min); + let latencies: Vec> = self + .eyes + .iter() + .map(|eye| eye.worker.latest().map(|grid| grid.latency_ms)) + .collect(); + info!( + "render {:.1} Hz | per-eye updates {:?} Hz | min-eye {:.1} Hz | worker latency {:?} ms", + render_hz, per_eye_hz, min_eye_hz, latencies, + ); + let counts_json = self + .inference_counts + .iter() + .map(u64::to_string) + .collect::>() + .join(","); + let rates_json = per_eye_hz + .iter() + .map(|value| format!("{value:.6}")) + .collect::>() + .join(","); + let latency_json = latencies + .iter() + .map(|value| value.map_or_else(|| "null".into(), |v| format!("{v:.6}"))) + .collect::>() + .join(","); + let latency_samples_json = self + .inference_latencies_ms + .iter() + .map(|samples| { + format!( + "[{}]", + samples + .iter() + .map(|value| format!("{value:.6}")) + .collect::>() + .join(",") + ) + }) + .collect::>() + .join(","); + info!( + "DINOVISION_APP_JSON {{\"schema_version\":1,\"kind\":\"dinovision_app_window\",\ + \"window_seconds\":{secs:.6},\"render_frames\":{},\"render_hz\":{render_hz:.6},\ + \"per_eye_update_counts\":[{counts_json}],\"per_eye_update_hz\":[{rates_json}],\ + \"min_eye_update_hz\":{min_eye_hz:.6},\"worker_latest_latency_ms\":[{latency_json}],\ + \"worker_latency_samples_ms\":[{latency_samples_json}],\"submission_chunks\":{},\ + \"inference_interval_ms\":{},\"raw_camera\":{}}}", + self.frames, + self.submission_chunks, + self.interval.as_millis(), + self.raw_camera, + ); + self.frames = 0; + self.inference_counts.fill(0); + self.inference_latencies_ms.iter_mut().for_each(Vec::clear); + self.last_report = Instant::now(); + } + } + + fn destroy(mut self, context: &gpu::Context) { + // Drop the workers first: each holds an `Arc` and must + // finish any in-flight submission before the surface goes away. + for pipeline in self.eyes.drain(..) { + drop(pipeline.worker); + pipeline.view.destroy(context); + } + context.destroy_xr_surface(&mut self.surface); + } +} + +fn spawn_event_pump() -> Arc { + let should_exit = Arc::new(AtomicBool::new(false)); + let flag = Arc::clone(&should_exit); + std::thread::spawn(move || { + while let Some(event) = ndk_glue::poll_events() { + if matches!(event, ndk_glue::Event::Destroy) { + flag.store(true, Ordering::Relaxed); + break; + } + } + }); + should_exit +} + +#[ndk_glue::main] +pub fn main() { + android_logger::init_once( + android_logger::Config::default() + .with_max_level(log::LevelFilter::Info) + .with_tag("dinovision"), + ); + std::panic::set_hook(Box::new(|info| log::error!("panic: {info}"))); + info!("=== dinovision starting ==="); + + let entry = unsafe { xr::Entry::load().expect("no OpenXR loader") }; + entry.initialize_android_loader().unwrap(); + + let available = entry.enumerate_extensions().unwrap(); + assert!( + available.khr_vulkan_enable2, + "runtime lacks XR_KHR_vulkan_enable2" + ); + let mut extensions = xr::ExtensionSet::default(); + extensions.khr_vulkan_enable2 = true; + extensions.khr_android_create_instance = true; + + let xr_instance = entry + .create_instance( + &xr::ApplicationInfo { + application_name: "DinoVision", + application_version: 0, + engine_name: "Blade", + engine_version: 0, + api_version: xr::Version::new(1, 0, 0), + }, + &extensions, + &[], + ) + .unwrap(); + let system = xr_instance + .system(xr::FormFactor::HEAD_MOUNTED_DISPLAY) + .unwrap(); + + // One context, shared by the renderer and by meganeura. This is the + // whole reason the crate pins meganeura's blade revision. + let context = Arc::new(unsafe { + gpu::Context::init(gpu::ContextDesc { + xr: Some(gpu::XrDesc { + instance: xr_instance.clone(), + system_id: system, + }), + ..Default::default() + }) + .expect("failed to initialize GPU context") + }); + let info = context.device_information(); + info!("GPU: {} ({})", info.device_name, info.driver_name); + + // The published decoder and correctness manifest are fixed at 224. + let config = Config::vits16().at_resolution(224); + + let mut encoder = context.create_command_encoder(gpu::CommandEncoderDesc { + name: "dinovision", + buffer_count: 2, + manual_barriers: false, + }); + + let mut app: Option = None; + let should_exit = spawn_event_pump(); + let mut events = xr::EventDataBuffer::new(); + + 'main: loop { + if should_exit.load(Ordering::Relaxed) { + break 'main; + } + + while let Some(event) = xr_instance.poll_event(&mut events).unwrap() { + use xr::Event::*; + match event { + SessionStateChanged(e) => { + info!("XR session state: {:?}", e.state()); + match e.state() { + xr::SessionState::READY => { + if app.is_none() { + app = Some(App::new(&context, config.clone())); + } + context.xr_session().unwrap().begin(VIEW_TYPE).unwrap(); + } + xr::SessionState::STOPPING => { + context.xr_session().unwrap().end().unwrap(); + if let Some(app) = app.take() { + app.destroy(&context); + } + } + // Release the camera the moment we stop being the + // focused app. Android revokes it from background + // apps anyway — that is what error code 3 was — and + // holding it is both rude to whatever wants it next + // and a privacy question, since a headset camera + // should not keep streaming to an app the wearer has + // navigated away from. + xr::SessionState::VISIBLE | xr::SessionState::SYNCHRONIZED => { + if let Some(app) = app.as_mut() { + app.set_camera_active(false); + } + } + xr::SessionState::FOCUSED => { + if let Some(app) = app.as_mut() { + app.set_camera_active(true); + } + } + xr::SessionState::EXITING | xr::SessionState::LOSS_PENDING => break 'main, + _ => {} + } + } + InstanceLossPending(_) => break 'main, + _ => {} + } + } + + match &mut app { + Some(app) => app.render(&context, &mut encoder), + // Not in session yet; idle rather than spin. + None => std::thread::sleep(Duration::from_millis(50)), + } + } + + if let Some(app) = app.take() { + app.destroy(&context); + } + context.destroy_command_encoder(&mut encoder); + info!("=== dinovision stopped ==="); +} diff --git a/environment/publication-source/source-snapshot/android/Cargo.toml b/environment/publication-source/source-snapshot/android/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..af16c0c81adb8e4d4f1d51d75e90d9a44d90c1be --- /dev/null +++ b/environment/publication-source/source-snapshot/android/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "dinovision-android" +version = "0.1.0" +publish = false +edition = "2024" + +[lib] +name = "dinobench" +path = "src/lib.rs" +crate-type = ["cdylib"] + +[target.'cfg(target_os = "android")'.dependencies] +dinovision = { path = ".." } +android-activity = { version = "0.6", features = ["native-activity"] } +android_logger = "0.14" +log = "0.4" + +[package.metadata.android] +build_targets = ["aarch64-linux-android"] +label = "DinoVision Bench" + +[package.metadata.android.sdk] +# API 30 matches the NDK clang wrapper configured in ../.cargo/config.toml. +# The passthrough-camera phase needs 34, and NDK r26+ to go with it. +min_sdk_version = 30 +target_sdk_version = 30 + +[package.metadata.android.signing.release] +path = "../../blade/examples-android/keystore/debug.keystore" +keystore_password = "android" +key_alias = "androiddebugkey" +key_password = "android" + +[package.metadata.android.application] +label = "DinoVision Bench" + +# Deliberately a plain 2D Android app, not a VR one: the benchmark answers +# a pure compute question, so there is no reason to drag OpenXR, a +# stereo swapchain, or the compositor into the measurement. It launches as +# a flat panel on the headset and logs to logcat. +[package.metadata.android.application.activity] +label = "DinoVision Bench" +config_changes = "density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode" +launch_mode = "singleTask" +orientation = "landscape" + +[[package.metadata.android.application.activity.intent_filter]] +actions = ["android.intent.action.MAIN"] +categories = ["android.intent.category.LAUNCHER"] diff --git a/environment/publication-source/source-snapshot/android/src/lib.rs b/environment/publication-source/source-snapshot/android/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d1b37df179f274a93e6af87c217b0ee05e30dadd --- /dev/null +++ b/environment/publication-source/source-snapshot/android/src/lib.rs @@ -0,0 +1,75 @@ +//! On-device benchmark entry point. +//! +//! A deliberately plain Android app: no OpenXR, no swapchain, no camera. +//! The only question it answers is how fast the Adreno runs a DINOv3 +//! forward pass under meganeura, and mixing in the XR compositor would +//! only add noise to that. +//! +//! ```text +//! cargo apk run --manifest-path android/Cargo.toml --release --no-logcat +//! adb logcat -v time | grep -E "dinovision|RustStdoutStderr" +//! ``` +//! +//! The run is one-shot: results go to logcat and the process stays alive so +//! the launcher does not report a crash. + +#![cfg(target_os = "android")] + +use android_activity::{AndroidApp, MainEvent, PollEvent}; + +#[unsafe(no_mangle)] +fn android_main(app: AndroidApp) { + android_logger::init_once( + android_logger::Config::default() + .with_max_level(log::LevelFilter::Info) + .with_tag("dinovision"), + ); + + // Vulkan initialization can fail on a device we have not accounted for; + // a panic here would be reported as an opaque crash, so log the reason. + std::panic::set_hook(Box::new(|info| { + log::error!("panic: {info}"); + })); + + log::info!("=== dinovision benchmark ==="); + match std::panic::catch_unwind(run) { + Ok(()) => log::info!("=== benchmark complete ==="), + Err(_) => log::error!("=== benchmark aborted ==="), + } + + // Stay responsive to the lifecycle instead of returning, which Android + // treats as the activity dying. + loop { + app.poll_events(Some(std::time::Duration::from_millis(500)), |event| { + if let PollEvent::Main(MainEvent::Destroy) = event { + std::process::exit(0); + } + }); + } +} + +fn run() { + let gpu = match dinovision::init_context(None) { + Ok(gpu) => gpu, + Err(e) => { + log::error!("GPU context init failed: {e:?}"); + return; + } + }; + + let iters = std::env::var("DINOVISION_ITERS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(20); + log::info!( + "timing protocol: {} warmups, {iters} retained samples", + std::env::var("DINOVISION_WARMUPS").unwrap_or_else(|_| "5".into()) + ); + let results = dinovision::bench::run_all(gpu, iters); + + log::info!("---- summary ----"); + for t in &results { + log::info!("{t}"); + log::info!("DINOVISION_BENCH_JSON {}", t.json_line()); + } +} diff --git a/environment/publication-source/source-snapshot/examples/bench.rs b/environment/publication-source/source-snapshot/examples/bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..466aeeafe2c220839eb244e3f7a8d99ce148627d --- /dev/null +++ b/environment/publication-source/source-snapshot/examples/bench.rs @@ -0,0 +1,44 @@ +//! Desktop benchmark runner. +//! +//! The same [`dinovision::bench`] code runs on the Quest through the +//! `android` crate; running it here first gives a reference point from a +//! GPU that *does* have cooperative matrix, which makes the Adreno numbers +//! interpretable rather than just small. +//! +//! ```text +//! cargo run --release --example bench -- [iters] +//! DINOVISION_BENCH=shapes cargo run --release --example bench -- [iters] +//! ``` +//! +//! With `DINOVISION_BENCH=shapes`, runs only the matmul shape sweep — the diagnostic for +//! what the register-tiled kernel is short of. It takes a couple of minutes +//! instead of the full suite's twenty, which matters when the target is a +//! headset on a flaky wireless adb link. + +fn main() { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + let iters = std::env::args() + .nth(1) + .and_then(|s| s.parse().ok()) + .unwrap_or(20); + // Selected by environment, not by argument: `std::env::args()` does not + // survive the trip to an adb shell on Horizon OS, and silently running + // the wrong benchmark is worse than an ugly interface. `RUST_LOG` + // already proves the environment arrives intact. + let shapes_only = std::env::var("DINOVISION_BENCH").as_deref() == Ok("shapes"); + + let gpu = dinovision::init_context(None).expect("failed to initialize GPU context"); + let results = if shapes_only { + dinovision::bench::describe_device(&gpu); + dinovision::bench::matmul_shapes(gpu, iters) + } else { + dinovision::bench::run_all(gpu, iters) + }; + + println!("\n{:-<80}", ""); + for t in &results { + println!("{t}"); + println!("DINOVISION_BENCH_JSON {}", t.json_line()); + } +} diff --git a/environment/publication-source/source-snapshot/examples/common/mod.rs b/environment/publication-source/source-snapshot/examples/common/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..e9e838047e5e58d9465d01023e05a3c33549611a --- /dev/null +++ b/environment/publication-source/source-snapshot/examples/common/mod.rs @@ -0,0 +1,310 @@ +//! Dataset handling shared by the decoder trainer and evaluator. + +#![allow(dead_code)] // Each example uses a different subset of these helpers. + +use std::collections::HashMap; +use std::io::Read; +use std::path::{Path, PathBuf}; + +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DatasetManifest { + pub schema_version: u32, + pub name: String, + /// Relative to the manifest file unless absolute. May be overridden by + /// `DINOVISION_DATA_ROOT` on another machine. + pub root: PathBuf, + pub images: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ManifestImage { + pub path: PathBuf, + pub split: String, + pub source: String, + /// Capture session, photo collection, or other leakage boundary. A group + /// must occur in exactly one split. + pub group: String, + pub sha256: String, + pub bytes: u64, +} + +pub struct LoadedManifest { + pub manifest: DatasetManifest, + pub root: PathBuf, +} + +pub fn load_manifest(path: &Path) -> Result> { + let bytes = std::fs::read(path)?; + let manifest: DatasetManifest = serde_json::from_slice(&bytes)?; + if manifest.schema_version != 1 { + return Err(format!( + "{} uses unsupported manifest schema {}", + path.display(), + manifest.schema_version + ) + .into()); + } + let root = match std::env::var_os("DINOVISION_DATA_ROOT") { + Some(value) => PathBuf::from(value), + None if manifest.root.is_absolute() => manifest.root.clone(), + None => path + .parent() + .unwrap_or_else(|| Path::new(".")) + .join(&manifest.root), + }; + + validate_manifest(&manifest)?; + Ok(LoadedManifest { manifest, root }) +} + +fn validate_manifest(manifest: &DatasetManifest) -> Result<(), Box> { + if manifest.images.is_empty() { + return Err("dataset manifest contains no images".into()); + } + + let mut group_splits: HashMap<(&str, &str), &str> = HashMap::new(); + let mut hashes: HashMap<&str, (&str, &Path)> = HashMap::new(); + let mut paths: HashMap<&Path, &str> = HashMap::new(); + for image in &manifest.images { + if image.split.is_empty() + || image.source.is_empty() + || image.group.is_empty() + || image.sha256.len() != 64 + { + return Err(format!("invalid manifest entry for {}", image.path.display()).into()); + } + let key = (image.source.as_str(), image.group.as_str()); + if let Some(old) = group_splits.insert(key, image.split.as_str()) + && old != image.split + { + return Err(format!( + "group {}/{} leaks across splits {old:?} and {:?}", + image.source, image.group, image.split + ) + .into()); + } + if let Some(old_split) = paths.insert(&image.path, image.split.as_str()) { + return Err(format!( + "path {} is listed more than once ({old_split} and {})", + image.path.display(), + image.split + ) + .into()); + } + if let Some((old_split, old_path)) = + hashes.insert(image.sha256.as_str(), (image.split.as_str(), &image.path)) + { + return Err(format!( + "identical files occur more than once: {} ({old_split}) and {} ({})", + old_path.display(), + image.path.display(), + image.split + ) + .into()); + } + } + Ok(()) +} + +pub fn images_for_split( + path: &Path, + split: &str, + limit: usize, +) -> Result, Box> { + let loaded = load_manifest(path)?; + let mut result = Vec::new(); + for image in loaded + .manifest + .images + .into_iter() + .filter(|image| image.split == split) + .take(limit) + { + result.push((loaded.root.join(&image.path), image)); + } + if result.is_empty() { + return Err(format!("manifest has no images in split {split:?}").into()); + } + Ok(result) +} + +/// Collect image paths, round-robin across subdirectories. +pub fn find_images(root: &Path, limit: usize) -> Vec { + let mut groups: Vec> = Vec::new(); + let mut stack = vec![root.to_path_buf()]; + while let Some(dir) = stack.pop() { + let Ok(entries) = std::fs::read_dir(&dir) else { + continue; + }; + let mut here = Vec::new(); + let mut items: Vec<_> = entries.filter_map(|e| e.ok()).map(|e| e.path()).collect(); + items.sort(); + for path in items { + if path.is_dir() { + stack.push(path); + } else if matches!( + path.extension().and_then(|e| e.to_str()), + Some("JPEG" | "jpeg" | "jpg" | "png" | "rgb") + ) { + here.push(path); + } + } + if !here.is_empty() { + groups.push(here); + } + } + groups.sort(); + + let mut out = Vec::new(); + let deepest = groups.iter().map(|g| g.len()).max().unwrap_or(0); + 'outer: for i in 0..deepest { + for group in &groups { + if let Some(path) = group.get(i) { + out.push(path.clone()); + if out.len() >= limit { + break 'outer; + } + } + } + } + out +} + +/// Load a photograph or a raw headset capture as interleaved RGB8. +pub fn load_frame(path: &Path, size: u32) -> Option> { + if path.extension().and_then(|e| e.to_str()) == Some("rgb") { + let bytes = std::fs::read(path).ok()?; + let expected = (size * size * 3) as usize; + if bytes.len() != expected { + log::warn!( + "{}: {} bytes, expected {expected} — captured at a different resolution?", + path.display(), + bytes.len() + ); + return None; + } + return Some(bytes); + } + load_rgb(path, size) +} + +fn load_rgb(path: &Path, size: u32) -> Option> { + let img = image::open(path).ok()?.to_rgb8(); + let (w, h) = (img.width(), img.height()); + let side = w.min(h); + let cropped = image::imageops::crop_imm(&img, (w - side) / 2, (h - side) / 2, side, side); + let resized = image::imageops::resize( + &cropped.to_image(), + size, + size, + image::imageops::FilterType::CatmullRom, + ); + Some(resized.into_raw()) +} + +pub fn sha256(path: &Path) -> Result { + let mut file = std::fs::File::open(path)?; + let mut hasher = Sha256::new(); + let mut buffer = vec![0u8; 1024 * 1024]; + loop { + let n = file.read(&mut buffer)?; + if n == 0 { + break; + } + hasher.update(&buffer[..n]); + } + Ok(format!("{:x}", hasher.finalize())) +} + +pub fn verify_image(path: &Path, image: &ManifestImage) -> Result<(), Box> { + let metadata = std::fs::metadata(path)?; + if metadata.len() != image.bytes { + return Err(format!( + "{} is {} bytes; manifest records {}", + path.display(), + metadata.len(), + image.bytes + ) + .into()); + } + let digest = sha256(path)?; + if digest != image.sha256 { + return Err(format!( + "{} has SHA-256 {digest}; manifest records {}", + path.display(), + image.sha256 + ) + .into()); + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn image(path: &str, split: &str, group: &str, hash: char) -> ManifestImage { + ManifestImage { + path: PathBuf::from(path), + split: split.to_string(), + source: "camera".to_string(), + group: group.to_string(), + sha256: std::iter::repeat_n(hash, 64).collect(), + bytes: 1, + } + } + + fn manifest(images: Vec) -> DatasetManifest { + DatasetManifest { + schema_version: 1, + name: "test".to_string(), + root: PathBuf::from("."), + images, + } + } + + #[test] + fn independent_groups_and_splits_are_valid() { + validate_manifest(&manifest(vec![ + image("a.rgb", "train", "session-a", 'a'), + image("b.rgb", "test", "session-b", 'b'), + ])) + .unwrap(); + } + + #[test] + fn group_cannot_cross_a_split() { + let error = validate_manifest(&manifest(vec![ + image("a.rgb", "train", "session-a", 'a'), + image("b.rgb", "test", "session-a", 'b'), + ])) + .unwrap_err() + .to_string(); + assert!(error.contains("leaks across splits"), "{error}"); + } + + #[test] + fn duplicate_content_is_rejected_even_within_one_split() { + let error = validate_manifest(&manifest(vec![ + image("a.rgb", "train", "session-a", 'a'), + image("b.rgb", "train", "session-a", 'a'), + ])) + .unwrap_err() + .to_string(); + assert!(error.contains("identical files"), "{error}"); + } + + #[test] + fn duplicate_path_is_rejected() { + let error = validate_manifest(&manifest(vec![ + image("a.rgb", "train", "session-a", 'a'), + image("a.rgb", "train", "session-a", 'b'), + ])) + .unwrap_err() + .to_string(); + assert!(error.contains("listed more than once"), "{error}"); + } +} diff --git a/environment/publication-source/source-snapshot/examples/evaluate_decoder.rs b/environment/publication-source/source-snapshot/examples/evaluate_decoder.rs new file mode 100644 index 0000000000000000000000000000000000000000..517dc09e6dee061568e4d2c81a8d2931681f5f2c --- /dev/null +++ b/environment/publication-source/source-snapshot/examples/evaluate_decoder.rs @@ -0,0 +1,559 @@ +//! Evaluate a trained decoder on an immutable held-out dataset manifest. +//! +//! Unlike `train_decoder`, this program never updates parameters and never +//! samples from the training cache. It verifies every input hash and writes +//! per-image metrics so aggregate claims can be regenerated from raw data. +//! +//! ```text +//! cargo run --release --example evaluate_decoder -- \ +//! --manifest experiments/dataset.json \ +//! --model model.safetensors --decoder decoder.bin \ +//! --split test --layers 3 --output artifacts/quality.json +//! ``` + +use std::path::{Path, PathBuf}; +use std::time::{Instant, SystemTime, UNIX_EPOCH}; + +use dinovision::decoder; +use dinovision::dinov3::Config; +use meganeura::train::{Mode, SessionConfig}; +use serde::Serialize; + +mod common; + +#[derive(Debug)] +struct Args { + manifest: PathBuf, + model: PathBuf, + decoder: PathBuf, + split: String, + layers: usize, + size: usize, + limit: usize, + output: PathBuf, + samples: usize, +} + +fn require_value(args: &mut impl Iterator, flag: &str) -> Result { + args.next() + .ok_or_else(|| format!("{flag} requires a value")) +} + +impl Args { + fn parse() -> Result { + let mut manifest = None; + let mut model = None; + let mut decoder = None; + let mut split = "test".to_string(); + let mut layers = 3usize; + let mut size = 224usize; + let mut limit = usize::MAX; + let mut output = PathBuf::from("artifacts/quality.json"); + let mut samples = 12usize; + + let mut args = std::env::args().skip(1); + while let Some(flag) = args.next() { + match flag.as_str() { + "--manifest" => manifest = Some(PathBuf::from(require_value(&mut args, &flag)?)), + "--model" => model = Some(PathBuf::from(require_value(&mut args, &flag)?)), + "--decoder" => decoder = Some(PathBuf::from(require_value(&mut args, &flag)?)), + "--split" => split = require_value(&mut args, &flag)?, + "--layers" => { + layers = require_value(&mut args, &flag)? + .parse() + .map_err(|_| "invalid --layers")? + } + "--size" => { + size = require_value(&mut args, &flag)? + .parse() + .map_err(|_| "invalid --size")? + } + "--limit" => { + limit = require_value(&mut args, &flag)? + .parse() + .map_err(|_| "invalid --limit")? + } + "--output" => output = PathBuf::from(require_value(&mut args, &flag)?), + "--samples" => { + samples = require_value(&mut args, &flag)? + .parse() + .map_err(|_| "invalid --samples")? + } + "-h" | "--help" => { + return Err( + "usage: evaluate_decoder --manifest FILE --model FILE --decoder FILE \ + [--split test] [--layers 3] [--size 224] [--limit N] \ + [--output FILE] [--samples N]" + .to_string(), + ); + } + _ => return Err(format!("unknown argument {flag:?}")), + } + } + + Ok(Self { + manifest: manifest.ok_or("--manifest is required")?, + model: model.ok_or("--model is required")?, + decoder: decoder.ok_or("--decoder is required")?, + split, + layers, + size, + limit, + output, + samples, + }) + } +} + +#[derive(Serialize)] +struct PerImage { + path: String, + source: String, + group: String, + sha256: String, + pixels: usize, + mse: f64, + mae: f64, + psnr_db: f64, + ssim: f64, +} + +#[derive(Serialize)] +struct Distribution { + mean: f64, + median: f64, + p25: f64, + p75: f64, + min: f64, + max: f64, +} + +#[derive(Serialize)] +struct Summary { + count: usize, + global_psnr_db: f64, + psnr_db: Distribution, + ssim: Distribution, + mae: Distribution, +} + +#[derive(Serialize)] +struct Evaluation { + schema_version: u32, + created_unix_seconds: u64, + dataset_name: String, + manifest: String, + manifest_sha256: String, + split: String, + image_size: usize, + encoder_layers: usize, + model: String, + model_sha256: String, + decoder: String, + decoder_sha256: String, + elapsed_seconds: f64, + summary: Summary, + images: Vec, +} + +fn distribution(values: impl IntoIterator) -> Distribution { + let mut values: Vec = values.into_iter().collect(); + values.sort_by(f64::total_cmp); + let n = values.len(); + assert!(n > 0); + let quantile = |q: f64| { + let at = q * (n - 1) as f64; + let lo = at.floor() as usize; + let hi = at.ceil() as usize; + values[lo] + (values[hi] - values[lo]) * (at - lo as f64) + }; + Distribution { + mean: values.iter().sum::() / n as f64, + median: quantile(0.5), + p25: quantile(0.25), + p75: quantile(0.75), + min: values[0], + max: values[n - 1], + } +} + +fn target_chw(rgb: &[u8], size: usize) -> Vec { + let pixels = size * size; + let mut target = vec![0.0f32; 3 * pixels]; + for c in 0..3 { + for p in 0..pixels { + target[c * pixels + p] = rgb[p * 3 + c] as f32 / 255.0; + } + } + target +} + +fn metrics(recon: &[f32], target: &[f32], size: usize) -> (f64, f64, f64, f64) { + let mut squared = 0.0f64; + let mut absolute = 0.0f64; + for (&a, &b) in recon.iter().zip(target) { + let d = (a - b) as f64; + squared += d * d; + absolute += d.abs(); + } + let mse = squared / recon.len() as f64; + let mae = absolute / recon.len() as f64; + let psnr = 10.0 * (1.0 / mse).log10(); + (mse, mae, psnr, ssim_rgb(recon, target, size)) +} + +/// RGB SSIM with the conventional 11x11 Gaussian window (sigma 1.5), +/// computed independently per channel over the valid image region. +fn ssim_rgb(a: &[f32], b: &[f32], size: usize) -> f64 { + const RADIUS: usize = 5; + const SIGMA: f64 = 1.5; + const C1: f64 = 0.01 * 0.01; + const C2: f64 = 0.03 * 0.03; + assert!(size > 2 * RADIUS); + let mut kernel = [0.0f64; 2 * RADIUS + 1]; + let mut kernel_sum = 0.0; + for (index, weight) in kernel.iter_mut().enumerate() { + let x = index as isize - RADIUS as isize; + *weight = (-(x * x) as f64 / (2.0 * SIGMA * SIGMA)).exp(); + kernel_sum += *weight; + } + for w in &mut kernel { + *w /= kernel_sum; + } + + let plane = size * size; + let valid = size - 2 * RADIUS; + let mut total = 0.0; + let mut count = 0usize; + for c in 0..3 { + // Five Gaussian-filtered moments, stored together to reuse both the + // input reads and kernel coefficients. The separable implementation + // is mathematically equivalent to the 11x11 2-D Gaussian window. + let mut horizontal = vec![[0.0f64; 5]; size * valid]; + for y in 0..size { + for x in 0..valid { + let mut moments = [0.0f64; 5]; + for (kx, &weight) in kernel.iter().enumerate() { + let index = c * plane + y * size + x + kx; + let va = a[index] as f64; + let vb = b[index] as f64; + moments[0] += weight * va; + moments[1] += weight * vb; + moments[2] += weight * va * va; + moments[3] += weight * vb * vb; + moments[4] += weight * va * vb; + } + horizontal[y * valid + x] = moments; + } + } + for y in 0..valid { + for x in 0..valid { + let mut moments = [0.0f64; 5]; + for (ky, &weight) in kernel.iter().enumerate() { + for i in 0..5 { + moments[i] += weight * horizontal[(y + ky) * valid + x][i]; + } + } + let [mean_a, mean_b, aa, bb, ab] = moments; + let var_a = (aa - mean_a * mean_a).max(0.0); + let var_b = (bb - mean_b * mean_b).max(0.0); + let covariance = ab - mean_a * mean_b; + total += ((2.0 * mean_a * mean_b + C1) * (2.0 * covariance + C2)) + / ((mean_a * mean_a + mean_b * mean_b + C1) * (var_a + var_b + C2)); + count += 1; + } + } + } + total / count as f64 +} + +fn save_sample( + path: &Path, + rgb: &[u8], + patches: &[f32], + encoder_output: &[f32], + features: &[f32], + recon: &[f32], + size: usize, +) { + let mut image = image::RgbImage::new((2 * size) as u32, size as u32); + let pixels = size * size; + for y in 0..size { + for x in 0..size { + let p = y * size + x; + image.put_pixel( + x as u32, + y as u32, + image::Rgb([rgb[p * 3], rgb[p * 3 + 1], rgb[p * 3 + 2]]), + ); + let value = |c: usize| (recon[c * pixels + p].clamp(0.0, 1.0) * 255.0) as u8; + image.put_pixel( + (size + x) as u32, + y as u32, + image::Rgb([value(0), value(1), value(2)]), + ); + } + } + image.save(path).expect("write reconstruction sample"); + let stem = path + .file_stem() + .expect("sample path has a stem") + .to_string_lossy(); + let parent = path.parent().unwrap_or_else(|| Path::new(".")); + std::fs::write( + parent.join(format!("{stem}-patches.f32")), + bytemuck::cast_slice(patches), + ) + .expect("write preprocessed patches"); + std::fs::write( + parent.join(format!("{stem}-encoder.f32")), + bytemuck::cast_slice(encoder_output), + ) + .expect("write raw encoder output"); + std::fs::write( + parent.join(format!("{stem}-features.f32")), + bytemuck::cast_slice(features), + ) + .expect("write raw encoder features"); + std::fs::write( + parent.join(format!("{stem}-reconstruction.f32")), + bytemuck::cast_slice(recon), + ) + .expect("write raw reconstruction sample"); +} + +fn main() -> Result<(), Box> { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + let args = Args::parse().map_err(|e| e.to_string())?; + let loaded = common::load_manifest(&args.manifest)?; + let dataset_name = loaded.manifest.name.clone(); + let entries = common::images_for_split(&args.manifest, &args.split, args.limit)?; + log::info!( + "evaluating {} images from split {:?}", + entries.len(), + args.split + ); + + let config = Config::vits16() + .at_resolution(args.size) + .with_layers(args.layers); + let gpu = dinovision::init_context(None).expect("GPU context"); + let (mut encoder, _) = dinovision::bench::build_encoder_session(gpu.clone(), &config, None); + let model = meganeura::data::safetensors::SafeTensorsModel::load(args.model.clone())?; + dinovision::weights::load_encoder(&mut encoder, &model, &config)?; + + let feat_len = config.hidden_size * config.num_patches(); + let img_len = 3 * config.image_size * config.image_size; + let mut graph = meganeura::Graph::new(); + let features = graph.input("feat", &[feat_len]); + let reconstruction = decoder::build_decoder(&mut graph, &config, features, 1); + graph.set_outputs(vec![reconstruction]); + let (mut decoder_session, _) = meganeura::train::build( + &graph, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + decoder::load_parameters(&mut decoder_session, &graph, &args.decoder)?; + + let sample_dir = args + .output + .parent() + .unwrap_or_else(|| Path::new(".")) + .join("quality_samples"); + if args.samples > 0 { + std::fs::create_dir_all(&sample_dir)?; + } + if let Some(parent) = args.output.parent() + && !parent.as_os_str().is_empty() + { + std::fs::create_dir_all(parent)?; + } + + let start = Instant::now(); + let total_entries = entries.len(); + let mut encoder_out = vec![0.0f32; config.num_tokens() * config.hidden_size]; + let mut recon = vec![0.0f32; img_len]; + let mut results = Vec::new(); + let mut total_squared_error = 0.0f64; + let mut total_values = 0usize; + + for (index, (path, entry)) in entries.into_iter().enumerate() { + common::verify_image(&path, &entry)?; + let rgb = common::load_frame(&path, config.image_size as u32) + .ok_or_else(|| format!("failed to load {}", path.display()))?; + let target = target_chw(&rgb, config.image_size); + let patches = dinovision::preprocess::patches_from_rgb8(&rgb, &config); + encoder.set_input("patches", &patches); + encoder.step(); + encoder.wait(); + encoder.read_output_by_index(0, &mut encoder_out); + let features = decoder::patch_features_to_nchw(&encoder_out, &config); + + decoder_session.set_input("feat", &features); + decoder_session.step(); + decoder_session.wait(); + decoder_session.read_output_by_index(0, &mut recon); + + let (mse, mae, psnr_db, ssim) = metrics(&recon, &target, config.image_size); + total_squared_error += mse * recon.len() as f64; + total_values += recon.len(); + results.push(PerImage { + path: entry.path.to_string_lossy().replace('\\', "/"), + source: entry.source, + group: entry.group, + sha256: entry.sha256, + pixels: config.image_size * config.image_size, + mse, + mae, + psnr_db, + ssim, + }); + + if index < args.samples { + save_sample( + &sample_dir.join(format!("{index:04}.png")), + &rgb, + &patches, + &encoder_out, + &features, + &recon, + config.image_size, + ); + } + log::info!( + "{}/{} PSNR {:.2} dB SSIM {:.4} {}", + index + 1, + total_entries, + psnr_db, + ssim, + path.display() + ); + } + + let global_mse = total_squared_error / total_values as f64; + let summary = Summary { + count: results.len(), + global_psnr_db: 10.0 * (1.0 / global_mse).log10(), + psnr_db: distribution(results.iter().map(|x| x.psnr_db)), + ssim: distribution(results.iter().map(|x| x.ssim)), + mae: distribution(results.iter().map(|x| x.mae)), + }; + let evaluation = Evaluation { + schema_version: 1, + created_unix_seconds: SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(), + dataset_name, + manifest: args.manifest.to_string_lossy().replace('\\', "/"), + manifest_sha256: common::sha256(&args.manifest)?, + split: args.split, + image_size: config.image_size, + encoder_layers: config.num_hidden_layers, + model: args.model.to_string_lossy().replace('\\', "/"), + model_sha256: common::sha256(&args.model)?, + decoder: args.decoder.to_string_lossy().replace('\\', "/"), + decoder_sha256: common::sha256(&args.decoder)?, + elapsed_seconds: start.elapsed().as_secs_f64(), + summary, + images: results, + }; + std::fs::write(&args.output, serde_json::to_vec_pretty(&evaluation)?)?; + println!( + "wrote {}: {} images, global PSNR {:.2} dB, median SSIM {:.4}", + args.output.display(), + evaluation.summary.count, + evaluation.summary.global_psnr_db, + evaluation.summary.ssim.median + ); + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn reference_ssim(a: &[f32], b: &[f32], size: usize) -> f64 { + const RADIUS: isize = 5; + const SIGMA: f64 = 1.5; + const C1: f64 = 0.01 * 0.01; + const C2: f64 = 0.03 * 0.03; + let mut kernel = Vec::new(); + let mut sum = 0.0; + for y in -RADIUS..=RADIUS { + for x in -RADIUS..=RADIUS { + let weight = (-((x * x + y * y) as f64) / (2.0 * SIGMA * SIGMA)).exp(); + kernel.push(weight); + sum += weight; + } + } + kernel.iter_mut().for_each(|weight| *weight /= sum); + + let plane = size * size; + let mut total = 0.0; + let mut count = 0; + for c in 0..3 { + for y in RADIUS as usize..size - RADIUS as usize { + for x in RADIUS as usize..size - RADIUS as usize { + let mut moments = [0.0f64; 5]; + let mut wi = 0; + for ky in -RADIUS..=RADIUS { + for kx in -RADIUS..=RADIUS { + let index = c * plane + + (y as isize + ky) as usize * size + + (x as isize + kx) as usize; + let va = a[index] as f64; + let vb = b[index] as f64; + let weight = kernel[wi]; + moments[0] += weight * va; + moments[1] += weight * vb; + moments[2] += weight * va * va; + moments[3] += weight * vb * vb; + moments[4] += weight * va * vb; + wi += 1; + } + } + let [mean_a, mean_b, aa, bb, ab] = moments; + let var_a = (aa - mean_a * mean_a).max(0.0); + let var_b = (bb - mean_b * mean_b).max(0.0); + let covariance = ab - mean_a * mean_b; + total += ((2.0 * mean_a * mean_b + C1) * (2.0 * covariance + C2)) + / ((mean_a * mean_a + mean_b * mean_b + C1) * (var_a + var_b + C2)); + count += 1; + } + } + } + total / count as f64 + } + + #[test] + fn identical_images_have_unit_ssim() { + let size = 16; + let image: Vec = (0..3 * size * size) + .map(|i| (i % 251) as f32 / 250.0) + .collect(); + assert!((ssim_rgb(&image, &image, size) - 1.0).abs() < 1e-10); + } + + #[test] + fn separable_ssim_matches_direct_window() { + let size = 16; + let a: Vec = (0..3 * size * size) + .map(|i| ((i * 37 + 11) % 251) as f32 / 250.0) + .collect(); + let b: Vec = (0..3 * size * size) + .map(|i| ((i * 19 + 7) % 241) as f32 / 240.0) + .collect(); + let expected = reference_ssim(&a, &b, size); + let actual = ssim_rgb(&a, &b, size); + assert!((actual - expected).abs() < 1e-12, "{actual} vs {expected}"); + } + + #[test] + fn distribution_interpolates_quartiles() { + let d = distribution([1.0, 2.0, 3.0, 4.0]); + assert_eq!(d.median, 2.5); + assert_eq!(d.p25, 1.75); + assert_eq!(d.p75, 3.25); + } +} diff --git a/environment/publication-source/source-snapshot/examples/preview.rs b/environment/publication-source/source-snapshot/examples/preview.rs new file mode 100644 index 0000000000000000000000000000000000000000..3f977940f6962fd08a088d81ca92268b465c7263 --- /dev/null +++ b/environment/publication-source/source-snapshot/examples/preview.rs @@ -0,0 +1,138 @@ +//! Run the full pipeline on desktop and write the result as an image. +//! +//! Exercises exactly what the headset does — inference worker, PCA fit, +//! colour projection — minus OpenXR, and writes a side-by-side PPM so the +//! output can actually be looked at. Rendering a feature view you cannot +//! see is a poor way to find out it is wrong. +//! +//! ```text +//! cargo run --release --example preview -- [out.ppm] [model.safetensors] +//! ``` +//! +//! Without a checkpoint it runs on synthetic weights: the pipeline is +//! exercised end to end, but the colours mean nothing. With real weights, +//! regions that belong to the same object should share a colour. + +use std::path::PathBuf; +use std::time::{Duration, Instant}; + +use dinovision::dinov3::Config; +use dinovision::inference::{self, Weights}; +use dinovision::pca::COMPONENTS; +use dinovision::source::{FrameSource, TestPattern}; + +/// Nearest-neighbour upscale of the feature grid, so each patch reads as a +/// solid block. Bilinear would look prettier and hide the true resolution. +fn upscale(grid_rgb: &[f32], grid: usize, out: usize) -> Vec { + let mut px = vec![0u8; out * out * 3]; + for y in 0..out { + let gy = (y * grid) / out; + for x in 0..out { + let gx = (x * grid) / out; + let src = (gy * grid + gx) * COMPONENTS; + let dst = (y * out + x) * 3; + for c in 0..3 { + px[dst + c] = (grid_rgb[src + c].clamp(0.0, 1.0) * 255.0) as u8; + } + } + } + px +} + +/// Source on the left, feature view on the right. +fn write_side_by_side(path: &PathBuf, left: &[u8], right: &[u8], size: usize) { + let mut joined = vec![0u8; size * size * 6]; + for y in 0..size { + let src = y * size * 3; + let dst = y * size * 6; + joined[dst..dst + size * 3].copy_from_slice(&left[src..src + size * 3]); + joined[dst + size * 3..dst + size * 6].copy_from_slice(&right[src..src + size * 3]); + } + image::RgbImage::from_raw(size as u32 * 2, size as u32, joined) + .expect("image dimensions do not match buffer") + .save(path) + .expect("failed to write image"); +} + +fn main() { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + let mut args = std::env::args().skip(1); + let out_path = PathBuf::from(args.next().unwrap_or_else(|| "preview.png".into())); + let weights = match args.next().map(PathBuf::from) { + Some(p) if p.exists() => { + log::info!("using weights from {}", p.display()); + Weights::SafeTensors(p) + } + Some(p) => panic!("{} does not exist", p.display()), + None => Weights::Synthetic, + }; + + let config = Config::vits16().at_resolution(256); + let gpu = dinovision::init_context(None).expect("failed to initialize GPU context"); + let worker = inference::spawn(gpu, config.clone(), weights, None, 1, dinovision::inference::Display::PcaColour); + + // `DINOVISION_SOURCE=screen` grabs the desktop instead of the synthetic + // scene, which is the quickest way to see the colouring against real + // imagery without opening a window. + let mut source: Box = match std::env::var("DINOVISION_SOURCE").as_deref() { + #[cfg(feature = "capture")] + Ok("screen") => match dinovision::source::ScreenCapture::new(config.image_size, 0) { + Ok(s) => Box::new(s), + Err(e) => panic!("screen capture unavailable: {e}"), + }, + #[cfg(not(feature = "capture"))] + Ok("screen") => panic!("rebuild with --features capture for screen capture"), + _ => Box::new(TestPattern::new(config.image_size)), + }; + let mut last_frame: Vec = Vec::new(); + + // Let the session build, then run a few frames so the PCA basis is + // refitted from real features rather than the placeholder. + let deadline = Instant::now() + Duration::from_secs(180); + let mut completed = 0; + while completed < 5 && Instant::now() < deadline { + if worker.is_ready() { + let rgb = source.next_frame().unwrap(); + last_frame = rgb.to_vec(); + let patches = dinovision::preprocess::patches_from_rgb8(rgb, &config); + worker.submit(patches); + } + std::thread::sleep(Duration::from_millis(20)); + completed = worker.generation(); + } + + let grid = worker + .latest() + .expect("inference produced no result before the deadline"); + log::info!( + "{} completed encodes, last took {:.1} ms ({}x{} grid)", + completed, + grid.latency_ms, + grid.grid, + grid.grid + ); + + let size = config.image_size; + let features = upscale(grid.patch_rgb(), grid.grid, size); + write_side_by_side(&out_path, &last_frame, &features, size); + + // A view that is one flat colour means the projection collapsed, which + // is easy to miss by eye in a small image. + let spread = { + let mut lo = [255u8; 3]; + let mut hi = [0u8; 3]; + for px in features.chunks_exact(3) { + for c in 0..3 { + lo[c] = lo[c].min(px[c]); + hi[c] = hi[c].max(px[c]); + } + } + (0..3).map(|c| hi[c] as i32 - lo[c] as i32).max().unwrap() + }; + println!("wrote {} (source | features)", out_path.display()); + println!("colour spread: {spread}/255"); + if spread < 16 { + println!("WARNING: the feature view is nearly flat — projection may have collapsed"); + } +} diff --git a/environment/publication-source/source-snapshot/examples/train_decoder.rs b/environment/publication-source/source-snapshot/examples/train_decoder.rs new file mode 100644 index 0000000000000000000000000000000000000000..cd903aa83c5ceeda2ef3112427c14073660c620b --- /dev/null +++ b/environment/publication-source/source-snapshot/examples/train_decoder.rs @@ -0,0 +1,436 @@ +//! Train the DINOv3 feature → RGB decoder, using meganeura for both halves. +//! +//! ```text +//! cargo run --release --example train_decoder -- \ +//! \ +//! [steps] [images] [layers] [size] [seed] [output-dir] +//! ``` +//! +//! Two phases. First every image is encoded once and its features cached in +//! memory, because the encoder is frozen and running it inside the training +//! loop would cost ~30× the decoder's own forward pass for no gradient. +//! Then the decoder trains on those pairs with Adam. +//! +//! Writes `decoder.bin` — raw f32, parameters in graph declaration order — +//! next to the working directory, plus a PNG strip of reconstructions so +//! the result can be judged by eye rather than by loss alone. + +use std::path::{Path, PathBuf}; +use std::time::{Instant, SystemTime, UNIX_EPOCH}; + +use dinovision::decoder; +use dinovision::dinov3::Config; +use meganeura::graph::Op; +use meganeura::train::{Mode, SessionConfig}; +use meganeura::{Graph, Session}; +use serde::Serialize; + +mod common; + +const BATCH: usize = 8; + +fn random_u64(state: &mut u64) -> u64 { + *state ^= *state >> 12; + *state ^= *state << 25; + *state ^= *state >> 27; + state.wrapping_mul(0x2545_F491_4F6C_DD1D) +} + +fn seeded_state(base: u64, seed: u64) -> u64 { + let state = base ^ seed; + if state == 0 { + 0xA076_1D64_78BD_642F + } else { + state + } +} + +fn shuffle(order: &mut [usize], state: &mut u64) { + for i in (1..order.len()).rev() { + order.swap(i, random_u64(state) as usize % (i + 1)); + } +} + +/// Deterministic small init. Kaiming-ish: scaled by fan-in so activations +/// neither vanish nor explode through four stages. +fn init_parameters(session: &mut Session, graph: &Graph, seed: u64) { + let mut state = seeded_state(0x9E37_79B9_7F4A_7C15, seed); + let mut next = move || ((random_u64(&mut state) >> 40) as f32 / (1u32 << 24) as f32) - 0.5; + for node in graph.nodes() { + let Op::Parameter { name } = &node.op else { + continue; + }; + let n = node.ty.num_elements(); + let shape = &node.ty.shape; + let data: Vec = if name.ends_with("norm.weight") { + vec![1.0; n] + } else if name.ends_with(".bias") { + vec![0.0; n] + } else { + // shape is [out, in, kh, kw]; fan_in = in * kh * kw. + let fan_in: usize = shape.iter().skip(1).product::().max(1); + let scale = (2.0 / fan_in as f32).sqrt() * 2.0; + (0..n).map(|_| next() * scale).collect() + }; + session.set_parameter(name, &data); + } +} + +#[derive(Serialize)] +struct TrainingRecord { + schema_version: u32, + completed_unix_seconds: u64, + dataset: String, + dataset_manifest_sha256: Option, + requested_images: usize, + training_images: usize, + model: String, + model_sha256: String, + initialization: String, + initialization_sha256: Option, + seed: u64, + image_size: usize, + encoder_layers: usize, + batch_size: usize, + steps: usize, + data_order: &'static str, + objective: &'static str, + optimizer: &'static str, + initial_learning_rate: f32, + final_learning_rate: f32, + decoder_parameters: usize, + encoding_seconds: f64, + training_seconds: f64, + final_l1: f32, + decoder: String, + decoder_sha256: String, + diagnostic_samples: String, +} + +fn portable_path(path: &Path) -> String { + path.to_string_lossy().replace('\\', "/") +} + +fn save_parameters(session: &Session, graph: &Graph, path: &Path) -> std::io::Result<()> { + let mut bytes = Vec::new(); + for node in graph.nodes() { + let Op::Parameter { name } = &node.op else { + continue; + }; + let mut buf = vec![0.0f32; node.ty.num_elements()]; + session.read_param(name, &mut buf); + bytes.extend_from_slice(bytemuck::cast_slice(&buf)); + } + std::fs::write(path, bytes) +} + +fn main() { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + let mut args = std::env::args().skip(1); + let image_dir = PathBuf::from(args.next().expect( + "usage: train_decoder \ + [steps] [images] [layers] [size] [seed] [output-dir]", + )); + let weights = PathBuf::from(args.next().expect("need the DINOv3 checkpoint")); + let steps: usize = args.next().and_then(|s| s.parse().ok()).unwrap_or(3000); + let max_images: usize = args.next().and_then(|s| s.parse().ok()).unwrap_or(2500); + // Truncating the encoder is the cheapest way to speed it up on a + // headset, and the later layers are where colour gets discarded, so a + // shallower encoder may reconstruct better as well as faster. + let layers: usize = args.next().and_then(|s| s.parse().ok()).unwrap_or(12); + let size: usize = args.next().and_then(|s| s.parse().ok()).unwrap_or(224); + let seed: u64 = args.next().and_then(|s| s.parse().ok()).unwrap_or(0); + let output_dir = args + .next() + .map(PathBuf::from) + .unwrap_or_else(|| PathBuf::from(".")); + assert!(steps > 0, "steps must be positive"); + std::fs::create_dir_all(&output_dir).expect("create output directory"); + + let config = Config::vits16().at_resolution(size).with_layers(layers); + let gpu = dinovision::init_context(None).expect("GPU context"); + + // ---- Phase 1: encode the dataset once ---- + let paths = if image_dir.extension().and_then(|e| e.to_str()) == Some("json") { + common::images_for_split(&image_dir, "train", max_images) + .unwrap_or_else(|e| panic!("{}: {e}", image_dir.display())) + .into_iter() + .map(|(path, image)| { + common::verify_image(&path, &image) + .unwrap_or_else(|e| panic!("dataset verification failed: {e}")); + path + }) + .collect() + } else { + common::find_images(&image_dir, max_images) + }; + assert!(!paths.is_empty(), "no images under {}", image_dir.display()); + log::info!("encoding {} images", paths.len()); + + let (mut encoder, _) = dinovision::bench::build_encoder_session(gpu.clone(), &config, None); + let model = meganeura::data::safetensors::SafeTensorsModel::load(weights.clone()) + .expect("read weights"); + dinovision::weights::load_encoder(&mut encoder, &model, &config).expect("bind weights"); + + let feat_len = config.hidden_size * config.num_patches(); + let img_len = 3 * config.image_size * config.image_size; + let mut features: Vec = Vec::with_capacity(paths.len() * feat_len); + // Targets stay u8 and are widened per batch. As f32 the cache would be + // 900 KB an image, and a few thousand images then no longer fit in RAM. + let mut targets: Vec = Vec::with_capacity(paths.len() * img_len); + + let start = Instant::now(); + let mut kept = 0usize; + let mut scratch = vec![0.0f32; config.num_tokens() * config.hidden_size]; + for (i, path) in paths.iter().enumerate() { + let Some(rgb) = common::load_frame(path, config.image_size as u32) else { + continue; + }; + let patches = dinovision::preprocess::patches_from_rgb8(&rgb, &config); + encoder.set_input("patches", &patches); + encoder.step(); + encoder.wait(); + encoder.read_output_by_index(0, &mut scratch); + + features.extend_from_slice(&decoder::patch_features_to_nchw(&scratch, &config)); + // Target is plain CHW in [0, 1] — the decoder predicts pixels, not + // ImageNet-normalized values. + let size = config.image_size; + for c in 0..3 { + for p in 0..size * size { + targets.push(rgb[p * 3 + c]); + } + } + kept += 1; + if i % 500 == 0 { + log::info!( + " {i}/{} ({:.0}s)", + paths.len(), + start.elapsed().as_secs_f64() + ); + } + } + drop(encoder); + assert!(kept > 0, "none of the selected images could be decoded"); + let encoding_seconds = start.elapsed().as_secs_f64(); + log::info!( + "encoded {kept} images in {:.0}s ({:.0} MB cached)", + encoding_seconds, + (features.len() * 4 + targets.len()) as f64 / 1e6 + ); + + // ---- Phase 2: train the decoder ---- + let mut g = Graph::new(); + let feat_in = g.input("feat", &[BATCH * feat_len]); + let recon = decoder::build_decoder(&mut g, &config, feat_in, BATCH); + let target_in = g.input("target", &[BATCH * img_len]); + // L1 rather than MSE. Squared error optimises the conditional mean, so + // wherever a feature is ambiguous the decoder hedges by averaging every + // possibility, which is blur by construction. L1 optimises the median + // and commits to one answer, usually looking markedly sharper at the + // same PSNR. + let loss = g.l1_loss(recon, target_in); + g.set_outputs(vec![loss, recon]); + + let (mut session, _) = meganeura::train::build( + &g, + SessionConfig { + mode: Mode::Training, + gpu: Some(gpu), + ..Default::default() + }, + ); + // `DINOVISION_INIT=decoder.bin` continues from existing weights instead + // of starting over. Necessary when adapting to a few hundred captured + // frames: 2M parameters trained from scratch on that much data would + // simply memorise it, where fine-tuning shifts an already-general + // decoder onto the new distribution. + let (initialization, initialization_sha256) = match std::env::var("DINOVISION_INIT") { + Ok(path) => { + let path = PathBuf::from(path); + decoder::load_parameters(&mut session, &g, &path) + .unwrap_or_else(|e| panic!("could not load {}: {e}", path.display())); + log::info!("fine-tuning from {}", path.display()); + let digest = common::sha256(&path).expect("hash initial decoder"); + (portable_path(&path), Some(digest)) + } + Err(_) => { + init_parameters(&mut session, &g, seed); + ("random".to_string(), None) + } + }; + session.set_adam(2e-3, 0.9, 0.999, 1e-8); + log::info!( + "training {} decoder parameters for {steps} steps, batch {BATCH}, encoder depth {layers}, \ + resolution {size}, seed {seed}", + decoder::parameter_count(&config) + ); + + let mut feat_batch = vec![0.0f32; BATCH * feat_len]; + let mut target_batch = vec![0.0f32; BATCH * img_len]; + let mut order: Vec = (0..kept).collect(); + let mut shuffle_state = seeded_state(0xD1B5_4A32_D192_ED03, seed); + shuffle(&mut order, &mut shuffle_state); + let mut cursor = 0usize; + let train_start = Instant::now(); + let mut final_l1 = f32::NAN; + let mut final_learning_rate = 2e-3; + + for step in 0..steps { + for b in 0..BATCH { + if cursor == kept { + shuffle(&mut order, &mut shuffle_state); + cursor = 0; + } + let idx = order[cursor]; + cursor += 1; + feat_batch[b * feat_len..(b + 1) * feat_len] + .copy_from_slice(&features[idx * feat_len..(idx + 1) * feat_len]); + for (dst, &src) in target_batch[b * img_len..(b + 1) * img_len] + .iter_mut() + .zip(&targets[idx * img_len..(idx + 1) * img_len]) + { + *dst = src as f32 / 255.0; + } + } + session.set_input("feat", &feat_batch); + session.set_input("target", &target_batch); + // Linear decay with a 5%-of-initial-rate floor. This is an + // implementation choice, not an admitted optimizer ablation. + let progress = step as f32 / steps as f32; + final_learning_rate = 2e-3 * (1.0 - progress).max(0.05); + session.set_adam(final_learning_rate, 0.9, 0.999, 1e-8); + session.step(); + session.wait(); + + if step % 100 == 0 || step == steps - 1 { + final_l1 = session.read_loss(); + log::info!( + "step {step:>5} L1 {final_l1:.5} ({:.0}s)", + train_start.elapsed().as_secs_f64() + ); + } + } + let training_seconds = train_start.elapsed().as_secs_f64(); + + let decoder_path = output_dir.join("decoder.bin"); + save_parameters(&session, &g, &decoder_path).expect("write decoder.bin"); + log::info!("wrote {}", decoder_path.display()); + + // ---- Sample strip: original above, reconstruction below ---- + let size = config.image_size; + for b in 0..BATCH { + let idx = b % kept; + feat_batch[b * feat_len..(b + 1) * feat_len] + .copy_from_slice(&features[idx * feat_len..(idx + 1) * feat_len]); + for (dst, &src) in target_batch[b * img_len..(b + 1) * img_len] + .iter_mut() + .zip(&targets[idx * img_len..(idx + 1) * img_len]) + { + *dst = src as f32 / 255.0; + } + } + session.set_input("feat", &feat_batch); + session.step(); + session.wait(); + let mut recon_out = vec![0.0f32; BATCH * img_len]; + session.read_output_by_index(1, &mut recon_out); + + let cols = 6.min(BATCH); + let mut strip = image::RgbImage::new((cols * size) as u32, (2 * size) as u32); + let mut total_psnr = 0.0; + for b in 0..cols { + let t = &target_batch[b * img_len..(b + 1) * img_len]; + let r = &recon_out[b * img_len..(b + 1) * img_len]; + total_psnr += decoder::psnr(r, t); + for y in 0..size { + for x in 0..size { + let at = |src: &[f32], c: usize| { + (src[c * size * size + y * size + x].clamp(0.0, 1.0) * 255.0) as u8 + }; + strip.put_pixel( + (b * size + x) as u32, + y as u32, + image::Rgb([at(t, 0), at(t, 1), at(t, 2)]), + ); + strip.put_pixel( + (b * size + x) as u32, + (size + y) as u32, + image::Rgb([at(r, 0), at(r, 1), at(r, 2)]), + ); + } + } + } + let samples_path = output_dir.join("decoder_samples.png"); + strip.save(&samples_path).expect("write samples"); + let manifest_sha256 = (image_dir.extension().and_then(|e| e.to_str()) == Some("json")) + .then(|| common::sha256(&image_dir).expect("hash dataset manifest")); + let record = TrainingRecord { + schema_version: 1, + completed_unix_seconds: SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("system time before Unix epoch") + .as_secs(), + dataset: portable_path(&image_dir), + dataset_manifest_sha256: manifest_sha256, + requested_images: max_images, + training_images: kept, + model: portable_path(&weights), + model_sha256: common::sha256(&weights).expect("hash encoder model"), + initialization, + initialization_sha256, + seed, + image_size: config.image_size, + encoder_layers: config.num_hidden_layers, + batch_size: BATCH, + steps, + data_order: "seeded Fisher-Yates; reshuffled after every complete pass", + objective: "mean absolute error (L1)", + optimizer: "Adam(beta1=0.9,beta2=0.999,epsilon=1e-8), linear decay to a 0.0001 floor at 95% of updates", + initial_learning_rate: 2e-3, + final_learning_rate, + decoder_parameters: decoder::parameter_count(&config), + encoding_seconds, + training_seconds, + final_l1, + decoder: portable_path(&decoder_path), + decoder_sha256: common::sha256(&decoder_path).expect("hash trained decoder"), + diagnostic_samples: portable_path(&samples_path), + }; + let record_path = output_dir.join("training.json"); + std::fs::write( + &record_path, + serde_json::to_vec_pretty(&record).expect("serialize training record"), + ) + .expect("write training record"); + println!( + "wrote {} and {}\nin-sample diagnostic mean PSNR {:.2} dB", + samples_path.display(), + record_path.display(), + total_psnr / cols as f32 + ); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn shuffle_is_seeded_and_preserves_every_index() { + let run = |seed| { + let mut order: Vec = (0..100).collect(); + let mut state = seeded_state(0xD1B5_4A32_D192_ED03, seed); + shuffle(&mut order, &mut state); + order + }; + let a = run(7); + let b = run(7); + let c = run(8); + assert_eq!(a, b); + assert_ne!(a, c); + let mut sorted = a; + sorted.sort_unstable(); + assert_eq!(sorted, (0..100).collect::>()); + } +} diff --git a/environment/publication-source/source-snapshot/examples/verify.rs b/environment/publication-source/source-snapshot/examples/verify.rs new file mode 100644 index 0000000000000000000000000000000000000000..49ad62242c4e569faedcfcf1f8fe8fb0dc4eca7e --- /dev/null +++ b/environment/publication-source/source-snapshot/examples/verify.rs @@ -0,0 +1,725 @@ +//! Compare our encoder against the HuggingFace reference, on desktop. +//! +//! ViT numerics are unforgiving: a transposed weight, a wrong RoPE pairing, +//! or a misordered patch flattening all produce output that looks +//! statistically reasonable and is completely wrong. This has to pass +//! before anything is deployed, because diagnosing it through logcat is +//! miserable. +//! +//! Inputs come from `tools/dump_reference.py`, which writes the *already +//! preprocessed* pixel tensor alongside the expected features. Taking the +//! pixel tensor verbatim keeps image resizing out of the comparison, so a +//! failure here is a failure in the graph. +//! +//! ```text +//! python tools/dump_reference.py --out ref/ +//! cargo run --release --bin verify -- ref/ [model.safetensors] +//! ``` + +use std::path::{Path, PathBuf}; + +use dinovision::dinov3::Config; +use meganeura::Graph; +use meganeura::train::{Mode, SessionConfig}; +use serde::{Deserialize, Serialize}; + +mod common; + +#[derive(Serialize)] +struct Verification { + schema_version: u32, + image_size: usize, + encoder_layers: usize, + model_sha256: String, + source_model_sha256: Option, + pixel_values_sha256: String, + reference_features_sha256: String, + meganeura_features_sha256: String, + elements: usize, + relative_l2: f64, + max_absolute_error: f32, + worst_absolute_token: usize, + cls_cosine: f32, + worst_patch_cosine: f32, + stages: Vec, + thresholds: Thresholds, + passed: bool, +} + +#[derive(Deserialize)] +struct ReferenceMetadata { + image_size: usize, + encoder_layers: usize, + pixel_values_sha256: String, + features_sha256: String, + exported_model_sha256: String, + source_model_sha256: Option, +} + +#[derive(Serialize)] +struct StageMetric { + name: String, + reference_file: String, + meganeura_file: String, + elements: usize, + reference_sha256: String, + meganeura_sha256: String, + relative_l2: f64, + max_absolute_error: f32, + cosine: f32, +} + +#[derive(Serialize)] +struct Thresholds { + max_relative_l2: f64, + min_cls_cosine: f32, + min_patch_cosine: f32, +} + +fn read_f32(path: &Path) -> Vec { + let bytes = std::fs::read(path).unwrap_or_else(|e| panic!("{}: {e}", path.display())); + assert_eq!( + bytes.len() % 4, + 0, + "{} is not a whole number of f32 values", + path.display() + ); + bytes + .chunks_exact(4) + .map(|c| f32::from_le_bytes([c[0], c[1], c[2], c[3]])) + .collect() +} + +fn embedding_forward( + gpu: std::sync::Arc, + config: &Config, + model: &meganeura::data::safetensors::SafeTensorsModel, + patches: &[f32], +) -> Vec { + let hidden = config.hidden_size; + let prefix = config.num_prefix_tokens(); + let mut graph = Graph::new(); + let input = graph.input("patches", &[config.num_patches(), config.patch_dim()]); + let weight = graph.parameter( + "embeddings.patch_embeddings.weight", + &[config.patch_dim(), hidden], + ); + let bias = graph.parameter("embeddings.patch_embeddings.bias", &[hidden]); + let patch_embeddings = graph.matmul(input, weight); + let patch_embeddings = graph.bias_add(patch_embeddings, bias); + let prefix_tokens = graph.parameter("prefix_tokens", &[prefix, hidden]); + let output = graph.concat( + prefix_tokens, + patch_embeddings, + 1, + (prefix * hidden) as u32, + (config.num_patches() * hidden) as u32, + 1, + ); + let output = graph.reshape(output, &[config.num_tokens(), hidden]); + graph.set_outputs(vec![output]); + + let (mut session, _) = meganeura::train::build( + &graph, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + let convolution = model + .tensor_f32_auto("embeddings.patch_embeddings.weight") + .expect("load patch embedding weight"); + session.set_parameter( + "embeddings.patch_embeddings.weight", + &dinovision::preprocess::conv_weight_to_matmul(&convolution, hidden, config.patch_dim()), + ); + session.set_parameter( + "embeddings.patch_embeddings.bias", + &model + .tensor_f32_auto("embeddings.patch_embeddings.bias") + .expect("load patch embedding bias"), + ); + let mut prefix_data = model + .tensor_f32_auto("embeddings.cls_token") + .expect("load CLS token"); + prefix_data.extend( + model + .tensor_f32_auto("embeddings.register_tokens") + .expect("load register tokens"), + ); + session.set_parameter("prefix_tokens", &prefix_data); + session.set_input("patches", patches); + session.step(); + session.wait(); + session.read_output(config.num_tokens() * hidden) +} + +fn first_projections( + gpu: std::sync::Arc, + config: &Config, + model: &meganeura::data::safetensors::SafeTensorsModel, + embeddings: &[f32], +) -> [Vec; 4] { + let hidden = config.hidden_size; + let mut graph = Graph::new(); + let input = graph.input("embeddings", &[config.num_tokens(), hidden]); + let norm_weight = graph.parameter("layer.0.norm1.weight", &[hidden]); + let norm_bias = graph.parameter("layer.0.norm1.bias", &[hidden]); + let normalized = graph.layer_norm(input, norm_weight, norm_bias, config.layer_norm_eps); + let mut projections = Vec::new(); + for (name, has_bias) in [("q_proj", true), ("k_proj", false), ("v_proj", true)] { + let weight = graph.parameter( + &format!("layer.0.attention.{name}.weight"), + &[hidden, hidden], + ); + let projected = graph.matmul(normalized, weight); + let projected = if has_bias { + let bias = graph.parameter(&format!("layer.0.attention.{name}.bias"), &[hidden]); + graph.bias_add(projected, bias) + } else { + projected + }; + projections.push(projected); + } + graph.set_outputs(vec![ + normalized, + projections[0], + projections[1], + projections[2], + ]); + let (mut session, _) = meganeura::train::build( + &graph, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + let prefix = if model + .tensor_info() + .contains_key("model.layer.0.norm1.weight") + { + "model." + } else { + "" + }; + for part in ["weight", "bias"] { + session.set_parameter( + &format!("layer.0.norm1.{part}"), + &model + .tensor_f32_auto(&format!("{prefix}layer.0.norm1.{part}")) + .expect("load first norm"), + ); + } + for (name, has_bias) in [("q_proj", true), ("k_proj", false), ("v_proj", true)] { + session.set_parameter( + &format!("layer.0.attention.{name}.weight"), + &model + .tensor_f32_auto_transposed(&format!("{prefix}layer.0.attention.{name}.weight")) + .expect("load first projection"), + ); + if has_bias { + session.set_parameter( + &format!("layer.0.attention.{name}.bias"), + &model + .tensor_f32_auto(&format!("{prefix}layer.0.attention.{name}.bias")) + .expect("load first projection bias"), + ); + } + } + session.set_input("embeddings", embeddings); + session.step(); + session.wait(); + std::array::from_fn(|index| { + let mut output = vec![0.0; config.num_tokens() * hidden]; + session.read_output_by_index(index, &mut output); + output + }) +} + +fn first_attention( + gpu: std::sync::Arc, + config: &Config, + q: &[f32], + k: &[f32], + v: &[f32], +) -> [Vec; 3] { + let tokens = config.num_tokens(); + let heads = config.num_attention_heads; + let head_dim = config.head_dim(); + let hidden = config.hidden_size; + let mut graph = Graph::new(); + let q_node = graph.input("q", &[tokens, hidden]); + let k_node = graph.input("k", &[tokens, hidden]); + let v_node = graph.input("v", &[tokens, hidden]); + let (cos_data, sin_data) = dinovision::dinov3::rope_tables(config); + let cos = graph.constant(cos_data, &[tokens, hidden]); + let sin = graph.constant(sin_data, &[tokens, hidden]); + let apply_rope = |graph: &mut Graph, input| { + let blocks = tokens as u32 * heads; + let half = head_dim / 2; + let first = graph.split_a(input, blocks, half, half, 1); + let second = graph.split_b(input, blocks, half, half, 1); + let negative_second = graph.neg(second); + let rotated = graph.concat(negative_second, first, blocks, half, half, 1); + let rotated = graph.reshape(rotated, &[tokens, hidden]); + let straight = graph.mul(input, cos); + let crossed = graph.mul(rotated, sin); + graph.add(straight, crossed) + }; + let q_rope = apply_rope(&mut graph, q_node); + let k_rope = apply_rope(&mut graph, k_node); + let attention = graph.full_attention(q_rope, k_rope, v_node, heads, heads, head_dim); + graph.set_outputs(vec![q_rope, k_rope, attention]); + let (mut session, _) = meganeura::train::build( + &graph, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + session.set_input("q", q); + session.set_input("k", k); + session.set_input("v", v); + session.step(); + session.wait(); + std::array::from_fn(|index| { + let mut output = vec![0.0; tokens * hidden]; + session.read_output_by_index(index, &mut output); + output + }) +} + +fn first_remainder( + gpu: std::sync::Arc, + config: &Config, + model: &meganeura::data::safetensors::SafeTensorsModel, + embeddings: &[f32], + attention: &[f32], +) -> Vec> { + let tokens = config.num_tokens(); + let hidden = config.hidden_size; + let intermediate = config.intermediate_size; + let mut graph = Graph::new(); + let embeddings_node = graph.input("embeddings", &[tokens, hidden]); + let attention_node = graph.input("attention", &[tokens, hidden]); + let output_weight = graph.parameter("layer.0.attention.o_proj.weight", &[hidden, hidden]); + let output_bias = graph.parameter("layer.0.attention.o_proj.bias", &[hidden]); + let attention_projected = graph.matmul(attention_node, output_weight); + let attention_projected = graph.bias_add(attention_projected, output_bias); + let scale1 = graph.parameter("layer.0.layer_scale1.lambda1", &[hidden]); + let transposed = graph.transpose(attention_projected); + let flat = graph.reshape(transposed, &[hidden * tokens]); + let scaled = graph.mul_per_channel(flat, scale1, hidden as u32, tokens as u32); + let scaled = graph.reshape(scaled, &[hidden, tokens]); + let attention_scaled = graph.transpose(scaled); + let residual = graph.add(embeddings_node, attention_scaled); + + let norm2_weight = graph.parameter("layer.0.norm2.weight", &[hidden]); + let norm2_bias = graph.parameter("layer.0.norm2.bias", &[hidden]); + let norm2 = graph.layer_norm(residual, norm2_weight, norm2_bias, config.layer_norm_eps); + let up_weight = graph.parameter("layer.0.mlp.up_proj.weight", &[hidden, intermediate]); + let up_bias = graph.parameter("layer.0.mlp.up_proj.bias", &[intermediate]); + let mlp_up = graph.matmul(norm2, up_weight); + let mlp_up = graph.bias_add(mlp_up, up_bias); + let mlp_activated = graph.gelu(mlp_up); + let down_weight = graph.parameter("layer.0.mlp.down_proj.weight", &[intermediate, hidden]); + let down_bias = graph.parameter("layer.0.mlp.down_proj.bias", &[hidden]); + let mlp_down = graph.matmul(mlp_activated, down_weight); + let mlp_down = graph.bias_add(mlp_down, down_bias); + let scale2 = graph.parameter("layer.0.layer_scale2.lambda1", &[hidden]); + let transposed = graph.transpose(mlp_down); + let flat = graph.reshape(transposed, &[hidden * tokens]); + let scaled = graph.mul_per_channel(flat, scale2, hidden as u32, tokens as u32); + let scaled = graph.reshape(scaled, &[hidden, tokens]); + let mlp_scaled = graph.transpose(scaled); + let layer_output = graph.add(residual, mlp_scaled); + let final_weight = graph.parameter("norm.weight", &[hidden]); + let final_bias = graph.parameter("norm.bias", &[hidden]); + let final_norm = graph.layer_norm( + layer_output, + final_weight, + final_bias, + config.layer_norm_eps, + ); + graph.set_outputs(vec![ + attention_projected, + attention_scaled, + residual, + norm2, + mlp_up, + mlp_activated, + mlp_down, + mlp_scaled, + layer_output, + final_norm, + ]); + + let (mut session, _) = meganeura::train::build( + &graph, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + let prefix = if model + .tensor_info() + .contains_key("model.layer.0.norm1.weight") + { + "model." + } else { + "" + }; + for name in [ + "attention.o_proj.weight", + "mlp.up_proj.weight", + "mlp.down_proj.weight", + ] { + session.set_parameter( + &format!("layer.0.{name}"), + &model + .tensor_f32_auto_transposed(&format!("{prefix}layer.0.{name}")) + .expect("load first-layer matrix"), + ); + } + for name in [ + "attention.o_proj.bias", + "layer_scale1.lambda1", + "norm2.weight", + "norm2.bias", + "mlp.up_proj.bias", + "mlp.down_proj.bias", + "layer_scale2.lambda1", + ] { + session.set_parameter( + &format!("layer.0.{name}"), + &model + .tensor_f32_auto(&format!("{prefix}layer.0.{name}")) + .expect("load first-layer vector"), + ); + } + for part in ["weight", "bias"] { + session.set_parameter( + &format!("norm.{part}"), + &model + .tensor_f32_auto(&format!("norm.{part}")) + .expect("load final norm"), + ); + } + session.set_input("embeddings", embeddings); + session.set_input("attention", attention); + session.step(); + session.wait(); + [ + hidden, + hidden, + hidden, + hidden, + intermediate, + intermediate, + hidden, + hidden, + hidden, + hidden, + ] + .into_iter() + .enumerate() + .map(|(index, width)| { + let mut output = vec![0.0; tokens * width]; + session.read_output_by_index(index, &mut output); + output + }) + .collect() +} + +fn relative_l2(actual: &[f32], expected: &[f32]) -> f64 { + assert_eq!(actual.len(), expected.len()); + let squared_error: f64 = actual + .iter() + .zip(expected) + .map(|(a, b)| (*a as f64 - *b as f64).powi(2)) + .sum(); + let squared_reference: f64 = expected.iter().map(|x| (*x as f64).powi(2)).sum(); + squared_error.sqrt() / squared_reference.sqrt().max(f64::MIN_POSITIVE) +} + +fn cosine(actual: &[f32], expected: &[f32]) -> f32 { + assert_eq!(actual.len(), expected.len()); + let dot: f64 = actual + .iter() + .zip(expected) + .map(|(a, b)| *a as f64 * *b as f64) + .sum(); + let actual_norm = actual + .iter() + .map(|value| (*value as f64).powi(2)) + .sum::() + .sqrt(); + let expected_norm = expected + .iter() + .map(|value| (*value as f64).powi(2)) + .sum::() + .sqrt(); + (dot / (actual_norm * expected_norm).max(f64::MIN_POSITIVE)) as f32 +} + +fn compare_stage(ref_dir: &Path, name: &str, reference_file: &str, actual: &[f32]) -> StageMetric { + let reference_path = ref_dir.join(reference_file); + let expected = read_f32(&reference_path); + assert_eq!( + actual.len(), + expected.len(), + "stage {name:?} has {} Meganeura values and {} reference values", + actual.len(), + expected.len() + ); + let meganeura_file = format!("meganeura-{reference_file}"); + let meganeura_path = ref_dir.join(&meganeura_file); + std::fs::write(&meganeura_path, bytemuck::cast_slice(actual)) + .unwrap_or_else(|error| panic!("{}: {error}", meganeura_path.display())); + StageMetric { + name: name.to_string(), + reference_file: reference_file.to_string(), + meganeura_file, + elements: actual.len(), + reference_sha256: common::sha256(&reference_path).expect("hash reference stage"), + meganeura_sha256: common::sha256(&meganeura_path).expect("hash Meganeura stage"), + relative_l2: relative_l2(actual, &expected), + max_absolute_error: actual + .iter() + .zip(&expected) + .map(|(a, b)| (*a - *b).abs()) + .fold(0.0, f32::max), + cosine: cosine(actual, &expected), + } +} + +fn main() { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + let mut args = std::env::args().skip(1); + let ref_dir = PathBuf::from( + args.next() + .expect("usage: verify [model.safetensors]"), + ); + let weights_path = args + .next() + .map(PathBuf::from) + .unwrap_or_else(|| ref_dir.join("model.safetensors")); + + let pixels = read_f32(&ref_dir.join("pixel_values.bin")); + let expected = read_f32(&ref_dir.join("features.bin")); + let reference: ReferenceMetadata = serde_json::from_slice( + &std::fs::read(ref_dir.join("reference.json")).expect("read reference.json"), + ) + .expect("parse reference.json"); + let pixel_values_sha256 = + common::sha256(&ref_dir.join("pixel_values.bin")).expect("hash input"); + let reference_features_sha256 = + common::sha256(&ref_dir.join("features.bin")).expect("hash reference output"); + let model_sha256 = common::sha256(&weights_path).expect("hash loaded model"); + assert_eq!( + pixel_values_sha256, reference.pixel_values_sha256, + "pixel_values.bin hash disagrees with reference.json" + ); + assert_eq!( + reference_features_sha256, reference.features_sha256, + "features.bin hash disagrees with reference.json" + ); + assert_eq!( + model_sha256, reference.exported_model_sha256, + "loaded model hash disagrees with reference.json" + ); + + // Infer the resolution from the pixel tensor rather than assuming it, + // so the reference script can dump any supported size. + let side = ((pixels.len() / 3) as f64).sqrt() as usize; + assert_eq!( + 3 * side * side, + pixels.len(), + "pixel tensor is not 3 x N x N" + ); + assert_eq!( + side, reference.image_size, + "pixel tensor resolution disagrees with reference.json" + ); + let config = Config::vits16() + .at_resolution(side) + .with_layers(reference.encoder_layers); + log::info!( + "reference: {side}x{side} -> {}x{} grid, {} tokens", + config.grid(), + config.grid(), + config.num_tokens() + ); + assert_eq!( + expected.len(), + config.num_tokens() * config.hidden_size, + "expected features should be [{}, {}]", + config.num_tokens(), + config.hidden_size + ); + + let gpu = dinovision::init_context(None).expect("failed to initialize GPU context"); + + let model = meganeura::data::safetensors::SafeTensorsModel::load(weights_path.clone()) + .unwrap_or_else(|e| panic!("{}: {e}", weights_path.display())); + let patches = dinovision::preprocess::patches_from_pixels_chw(&pixels, &config); + let mut stages = Vec::new(); + let actual_embeddings = embedding_forward(gpu.clone(), &config, &model, &patches); + let embedding_metric = + compare_stage(&ref_dir, "embeddings", "embeddings.bin", &actual_embeddings); + println!( + "embedding relative L2 : {:.6}", + embedding_metric.relative_l2 + ); + stages.push(embedding_metric); + let actual_first = first_projections(gpu.clone(), &config, &model, &actual_embeddings); + for (label, actual, file) in [ + ("first norm1", &actual_first[0], "first-norm1.bin"), + ("first Q", &actual_first[1], "first-q.bin"), + ("first K", &actual_first[2], "first-k.bin"), + ("first V", &actual_first[3], "first-v.bin"), + ] { + let metric = compare_stage(&ref_dir, label, file, actual); + println!("{label:<18}: {:.6}", metric.relative_l2); + stages.push(metric); + } + let actual_attention = first_attention( + gpu.clone(), + &config, + &actual_first[1], + &actual_first[2], + &actual_first[3], + ); + for (label, actual, file) in [ + ("first Q RoPE", &actual_attention[0], "first-q-rope.bin"), + ("first K RoPE", &actual_attention[1], "first-k-rope.bin"), + ( + "first attention", + &actual_attention[2], + "first-attention.bin", + ), + ] { + let metric = compare_stage(&ref_dir, label, file, actual); + println!("{label:<18}: {:.6}", metric.relative_l2); + stages.push(metric); + } + let actual_remainder = first_remainder( + gpu.clone(), + &config, + &model, + &actual_embeddings, + &actual_attention[2], + ); + for (index, (label, file)) in [ + ("attention projected", "first-attention-projected.bin"), + ("attention scaled", "first-attention-scaled.bin"), + ("attention residual", "first-residual.bin"), + ("first norm2", "first-norm2.bin"), + ("first MLP up", "first-mlp-up.bin"), + ("first MLP GELU", "first-mlp-activated.bin"), + ("first MLP down", "first-mlp-down.bin"), + ("first MLP scaled", "first-mlp-scaled.bin"), + ("first output", "first-output.bin"), + ("first final norm", "first-final-norm.bin"), + ] + .into_iter() + .enumerate() + { + let metric = compare_stage(&ref_dir, label, file, &actual_remainder[index]); + println!("{label:<20}: {:.6}", metric.relative_l2); + stages.push(metric); + } + + let (mut session, _) = dinovision::bench::build_encoder_session(gpu, &config, None); + dinovision::weights::load_encoder(&mut session, &model, &config).expect("load weights"); + + session.set_input("patches", &patches); + session.step(); + session.wait(); + + let got = session.read_output(config.num_tokens() * config.hidden_size); + + // Report both absolute error and cosine similarity per token group. + // Cosine matters more for what we do downstream: PCA colouring and a + // decoder both care about feature *direction*, and a uniform scale + // error would still look right while indicating a real bug. + let mut worst_abs = 0.0f32; + let mut worst_token = 0usize; + let mut squared_error = 0.0f64; + let mut squared_reference = 0.0f64; + for t in 0..config.num_tokens() { + for d in 0..config.hidden_size { + let i = t * config.hidden_size + d; + let difference = got[i] - expected[i]; + let e = difference.abs(); + squared_error += (difference as f64).powi(2); + squared_reference += (expected[i] as f64).powi(2); + if e > worst_abs { + worst_abs = e; + worst_token = t; + } + } + } + let relative_l2 = squared_error.sqrt() / squared_reference.sqrt().max(f64::MIN_POSITIVE); + + let h = config.hidden_size; + let cls_cos = cosine(&got[0..h], &expected[0..h]); + let mut worst_patch_cos = 1.0f32; + for t in config.num_prefix_tokens()..config.num_tokens() { + let c = cosine(&got[t * h..(t + 1) * h], &expected[t * h..(t + 1) * h]); + worst_patch_cos = worst_patch_cos.min(c); + } + + println!("relative L2 : {relative_l2:.6}"); + println!("max |ours - reference| : {worst_abs:.5} (worst at token {worst_token})"); + println!("CLS cosine : {cls_cos:.6}"); + println!("worst patch cosine : {worst_patch_cos:.6}"); + + // f32 GPU accumulation in a different order than PyTorch's will not + // reproduce bit-for-bit; 0.999 cosine across every patch is the real + // signal that the architecture is right. + let thresholds = Thresholds { + max_relative_l2: 0.01, + min_cls_cosine: 0.999, + min_patch_cosine: 0.999, + }; + let ok = relative_l2 <= thresholds.max_relative_l2 + && worst_patch_cos > thresholds.min_patch_cosine + && cls_cos > thresholds.min_cls_cosine; + let final_metric = compare_stage(&ref_dir, "full encoder output", "features.bin", &got); + let meganeura_features_sha256 = final_metric.meganeura_sha256.clone(); + stages.push(final_metric); + let verification = Verification { + schema_version: 1, + image_size: config.image_size, + encoder_layers: config.num_hidden_layers, + model_sha256, + source_model_sha256: reference.source_model_sha256, + pixel_values_sha256, + reference_features_sha256, + meganeura_features_sha256, + elements: got.len(), + relative_l2, + max_absolute_error: worst_abs, + worst_absolute_token: worst_token, + cls_cosine: cls_cos, + worst_patch_cosine: worst_patch_cos, + stages, + thresholds, + passed: ok, + }; + std::fs::write( + ref_dir.join("verification.json"), + serde_json::to_vec_pretty(&verification).expect("serialize verification"), + ) + .expect("write verification record"); + println!("\n{}", if ok { "PASS" } else { "FAIL" }); + if !ok { + std::process::exit(1); + } +} diff --git a/environment/publication-source/source-snapshot/examples/viewer.rs b/environment/publication-source/source-snapshot/examples/viewer.rs new file mode 100644 index 0000000000000000000000000000000000000000..f69325291d2ccf2e28827391736c433f724a2b53 --- /dev/null +++ b/environment/publication-source/source-snapshot/examples/viewer.rs @@ -0,0 +1,288 @@ +//! Live DINO feature view in a desktop window. +//! +//! The same pipeline the headset runs — capture, encode, PCA colour, +//! display — pointed at a monitor instead of a passthrough camera. Two +//! reasons it exists: +//! +//! * It is the demo you can actually show someone. Point it at a video, a +//! photo, a game, and watch objects resolve into stable colour regions. +//! * It de-risks the Quest camera. The capture loop, the downscale, and the +//! "new frame arrives asynchronously while the window redraws" structure +//! are all the same; the passthrough camera becomes another +//! `FrameSource` and nothing around it changes. +//! +//! ```text +//! cargo run --release --features capture --example viewer -- [model.safetensors] [monitor] +//! ``` +//! +//! Without a checkpoint it runs on synthetic weights, which still shows the +//! scene's structure but colours it arbitrarily. + +use std::sync::Arc; +use std::time::{Duration, Instant}; + +use blade_graphics as gpu; +use dinovision::dinov3::Config; +use dinovision::inference::{self, Weights, Worker}; +use dinovision::render::GridView; +use dinovision::source::FrameSource; + +fn surface_config(size: winit::dpi::PhysicalSize) -> gpu::SurfaceConfig { + gpu::SurfaceConfig { + size: gpu::Extent { + width: size.width.max(1), + height: size.height.max(1), + depth: 1, + }, + usage: gpu::TextureUsage::TARGET, + display_sync: gpu::DisplaySync::Recent, + ..Default::default() + } +} + +struct Viewer { + context: Arc, + surface: gpu::Surface, + encoder: gpu::CommandEncoder, + view: GridView, + worker: Worker, + source: Box, + config: Config, + last_shown: u64, + frames: u64, + encodes: u64, + last_report: Instant, + window: winit::window::Window, +} + +impl Viewer { + fn redraw(&mut self) { + // Feed the encoder whenever it is free. Unlike the headset there is + // no compositor to starve here, so it runs flat out. + if self.worker.is_ready() + && let Some(rgb) = self.source.next_frame() + { + let patches = dinovision::preprocess::patches_from_rgb8(rgb, &self.config); + self.worker.submit(patches); + } + + let generation = self.worker.generation(); + if generation != self.last_shown + && let Some(grid) = self.worker.latest() + { + self.view.upload(&self.context, grid.patch_rgb()); + self.last_shown = generation; + self.encodes += 1; + } + + let frame = self.surface.acquire_frame(); + self.encoder.start(); + self.encoder.init_texture(frame.texture()); + { + let mut pass = self.encoder.render("view", gpu::RenderTargetSet { + colors: &[gpu::RenderTarget { + view: frame.texture_view(), + init_op: gpu::InitOp::DontCare, + finish_op: gpu::FinishOp::Store, + }], + depth_stencil: None, + }); + self.view.draw(&mut pass, 0); + } + self.encoder.present(frame); + let _sp = self.context.submit(&mut self.encoder); + + self.frames += 1; + if self.last_report.elapsed() >= Duration::from_secs(3) { + let secs = self.last_report.elapsed().as_secs_f64(); + let latency = self + .worker + .latest() + .map(|g| g.latency_ms) + .unwrap_or(f64::NAN); + self.window.set_title(&format!( + "dinovision — {:.0} fps display, {:.1} Hz inference ({:.0} ms)", + self.frames as f64 / secs, + self.encodes as f64 / secs, + latency + )); + self.frames = 0; + self.encodes = 0; + self.last_report = Instant::now(); + } + } +} + +#[derive(Default)] +struct App { + viewer: Option, + weights: Option, + decoder: Option, + monitor: usize, +} + +impl winit::application::ApplicationHandler for App { + fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + if self.viewer.is_some() { + return; + } + let window = event_loop + .create_window( + winit::window::Window::default_attributes() + .with_title("dinovision — starting…") + .with_inner_size(winit::dpi::LogicalSize::new(720, 720)), + ) + .expect("failed to create window"); + + let context = Arc::new(unsafe { + gpu::Context::init(gpu::ContextDesc { + presentation: true, + validation: false, + ..Default::default() + }) + .expect("failed to initialize GPU context") + }); + + let surface = context + .create_surface_configured(&window, surface_config(window.inner_size())) + .expect("failed to create surface"); + + let config = Config::vits16().at_resolution(224); + // A reconstruction fills the whole image, so the display grid is the + // image size; PCA colouring only has one value per patch. + let display = match self.decoder.clone() { + Some(path) => { + log::info!("decoder: {}", path.display()); + inference::Display::Reconstruction(path) + } + None => inference::Display::PcaColour, + }; + let view_grid = match &display { + inference::Display::Reconstruction(_) => config.image_size, + inference::Display::PcaColour => config.grid(), + }; + let view = GridView::new(&context, surface.info().format, view_grid); + + let weights = match self.weights.clone() { + Some(p) => { + log::info!("weights: {}", p.display()); + Weights::SafeTensors(p) + } + None => { + log::warn!("no checkpoint given — synthetic weights, colours are arbitrary"); + Weights::Synthetic + } + }; + // One submission: nothing else is competing for this GPU, so the + // chunking that matters on a headset would only cost overhead. + let worker = inference::spawn(Arc::clone(&context), config.clone(), weights, None, 1, display); + + let source: Box = match dinovision::source::ScreenCapture::new( + config.image_size, + self.monitor, + ) { + Ok(s) => Box::new(s), + Err(e) => { + log::warn!("screen capture unavailable ({e}); falling back to the test pattern"); + Box::new(dinovision::source::TestPattern::new(config.image_size)) + } + }; + + let encoder = context.create_command_encoder(gpu::CommandEncoderDesc { + name: "viewer", + buffer_count: 2, + manual_barriers: false, + }); + + self.viewer = Some(Viewer { + context, + surface, + encoder, + view, + worker, + source, + config, + last_shown: 0, + frames: 0, + encodes: 0, + last_report: Instant::now(), + window, + }); + } + + fn about_to_wait(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) { + if let Some(v) = &self.viewer { + v.window.request_redraw(); + } + } + + fn window_event( + &mut self, + event_loop: &winit::event_loop::ActiveEventLoop, + _id: winit::window::WindowId, + event: winit::event::WindowEvent, + ) { + let Some(viewer) = self.viewer.as_mut() else { + return; + }; + match event { + winit::event::WindowEvent::CloseRequested => event_loop.exit(), + winit::event::WindowEvent::KeyboardInput { + event: + winit::event::KeyEvent { + physical_key: winit::keyboard::PhysicalKey::Code(code), + state: winit::event::ElementState::Pressed, + .. + }, + .. + } => match code { + winit::keyboard::KeyCode::Escape => event_loop.exit(), + // Refit the colour basis on demand: point the capture at + // something new and the old principal components will be a + // poor fit for it. + winit::keyboard::KeyCode::KeyR => { + log::info!("refitting colour basis"); + viewer.worker.request_refit(); + } + _ => {} + }, + winit::event::WindowEvent::Resized(size) => { + viewer + .context + .reconfigure_surface(&mut viewer.surface, surface_config(size)); + } + winit::event::WindowEvent::RedrawRequested => viewer.redraw(), + _ => {} + } + } +} + +fn main() { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + let mut args = std::env::args().skip(1); + let weights = args.next().map(std::path::PathBuf::from).filter(|p| { + let ok = p.exists(); + if !ok { + log::warn!("{} does not exist; using synthetic weights", p.display()); + } + ok + }); + // A decoder file switches the view from PCA colour to a real RGB + // reconstruction. + let decoder = args.next().map(std::path::PathBuf::from).filter(|p| p.exists()); + let monitor = args.next().and_then(|s| s.parse().ok()).unwrap_or(0); + + println!("R refits the colour basis · Esc quits"); + + let event_loop = winit::event_loop::EventLoop::new().expect("failed to create event loop"); + event_loop.set_control_flow(winit::event_loop::ControlFlow::Poll); + event_loop + .run_app(&mut App { + viewer: None, + weights, + decoder, + monitor, + }) + .expect("event loop failed"); +} diff --git a/environment/publication-source/source-snapshot/experiments/AUDIT.md b/environment/publication-source/source-snapshot/experiments/AUDIT.md new file mode 100644 index 0000000000000000000000000000000000000000..953d5cc00d7ad0a130128911c67d59be28b36e90 --- /dev/null +++ b/environment/publication-source/source-snapshot/experiments/AUDIT.md @@ -0,0 +1,92 @@ +# Audit record for the Meganeura case study + +Date: 2026-08-01 (America/Los_Angeles) + +## Decision + +The original `REPORT.md` is not admissible as paper evidence. It is a useful +engineering narrative, but several headline results were either evaluated on +training examples, measured with a biased timing protocol, or produced by an +incorrect DINOv3 graph. The case study can become paper material after the +fresh Quest correctness and measurement gates in `experiments/README.md` are +complete. Corrected three-seed held-out decoder evaluation is now complete. + +The defensible case-study claim is deliberately narrow: + +> A decoder graph is trained through Meganeura autodiff and Adam on the host, +> then its forward path is joined to a frozen DINOv3 encoder and compiled by +> the same Meganeura graph compiler/runtime for Vulkan inference in an Android +> XR application sharing Blade's graphics context and queue. + +Training caches frozen encoder features and executes a batched decoder-only +graph. Deployment executes a batch-one joined encoder/decoder graph. They +share decoder construction, parameters, IR operations, compiler, and runtime; +they are not literally the same complete graph. + +## Findings that invalidate historical numbers + +| Historical evidence | Audit finding | Disposition | +|---|---|---| +| Decoder PSNR in `REPORT.md` | The trainer reconstructed the first six cached training images and averaged their PSNR. There was no held-out split, per-image record, or seed replication. | Replaced by an upstream-defined Imagenette validation split, all 3,925 images, per-image PSNR/SSIM/MAE, exact hashes, and three initializations. | +| Isolated device timings | The benchmark used one untimed warmup and reported the minimum retained sample as throughput. Clock ramp and process-to-process state were not controlled. | Rerun with at least five warmups, 20 retained samples, median/IQR/raw samples, and three fresh processes in a declared headset state. | +| DINOv3 encoder correctness | The app passed `[tokens, hidden]` data to Meganeura's NCHW-flat `mul_per_channel` as if it broadcast over the trailing dimension. Only the first token received the intended LayerScale update; later token residual branches were effectively suppressed. | Fixed by transposing to `[hidden, tokens]`, flattening for the NCHW operator, applying the hidden gain with `spatial=tokens`, reshaping, and transposing back. All old decoders and device timings are invalid. | +| Live XR “inference Hz” | Two asynchronous eye completions were combined into one count, and the raw-camera toggle still submitted hidden inference. | App records each eye independently and true raw-camera mode bypasses the model. | +| 240-pixel, f16, and operation-share conclusions | These were microbenchmark observations or extrapolations, not matched end-to-end experiments or a deployed-graph profile. | Exclude causal or “closed” claims unless the matched experiments are run. | + +The invalid pre-fix decoder runs are preserved locally under +`C:\tmp\dinovision-runs`; they must not be uploaded or cited. The corrected +matrix uses a separate root so no artifact can be mistaken for a valid run. + +## Independent encoder validation after the fix + +The reference is `facebook/dinov3-vits16-pretrain-lvd1689m`, executed in +Torch 2.13.0+cpu and Transformers 5.14.1 from the same deterministic normalized +pixel tensor and exact checkpoint. Meganeura uses f32 scalar matmul on the RTX +3050 for this comparison. Thresholds were declared before the corrected run: +relative L2 at most 0.01, CLS cosine above 0.999, and every patch-token cosine +above 0.999. + +| Depth | Relative L2 | CLS cosine | Worst patch cosine | Result | +|---:|---:|---:|---:|---| +| 1 layer | 0.000781 | 1.000000 | 0.999990 | pass | +| 3 layers (deployed) | 0.001403 | 1.000000 | 0.999995 | pass | +| 12 layers (upstream depth) | 0.002253 | 0.999997 | 0.999996 | pass | + +At the first layer, embeddings, LayerNorm, Q/K/V projections, and RoPE agree +to the displayed six decimal places. Attention differs by 0.005852 relative +L2; after learned LayerScale the residual differs by 0.000566. Exact-shape +tests independently compare Meganeura attention and the corrected trailing +LayerScale broadcast against CPU implementations. + +A deliberately small deterministic replay also ran the same 20-update, +16-image, seed-20260801 cell twice. The two serialized decoders are +byte-identical (SHA-256 +`2959b06784576bb1bc495b4e0a0d2f4aeebb216d56f7fc078843df4b7ec12686`). +This validates the seeded code path and serialization, not full-run +repeatability across machines or drivers. + +The audit also recommends hardening Meganeura's `mul_per_channel` builder. +Its documented flat NCHW input/gate contract is not currently asserted, and +the compiler derives the dispatch length from `shape[0]`. Validating rank, +element count, channel/spatial divisibility, and gate length at graph +construction would have rejected the original misuse before execution. This +is not needed to reinterpret the corrected results, but it is a worthwhile +paper-artifact change in Meganeura itself. + +## Evidence still required + +- A public decoder artifact whose metadata binds it to the corrected source, + DINO checkpoint hash, dataset-manifest hash, depth, resolution, and seed. +- Host/Quest equality on preprocessed patches, encoder features, spatial + decoder input, and reconstruction for one fixed public frame. +- Fresh isolated Quest timings and live-worn XR chunk sweep from the corrected + graph, with raw samples and state snapshots. +- Clean, immutable DinoVision and Meganeura revisions. The current worktree is + a development freeze candidate, not yet a citable revision. +- A validation-clean debug host context. Numerical tests pass, but the + resolved Blade Vulkan setup currently emits two device-creation VUIDs; this + is distinct from the corrected Meganeura tensor results and should be + tracked rather than hidden. + +Until those items are complete, the correct paper status is **promising but +not merge-ready**. diff --git a/environment/publication-source/source-snapshot/experiments/README.md b/environment/publication-source/source-snapshot/experiments/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ce817cb48a1c049cdf1e39402c739093b8087ee7 --- /dev/null +++ b/environment/publication-source/source-snapshot/experiments/README.md @@ -0,0 +1,234 @@ +# DinoVision paper artifact protocol + +This experiment is a deployment case study for Meganeura, not an additional +cell in the paper's matched Meganeura/PyTorch performance-portability matrix. +Its target claim is narrower and complementary; it is admitted only after the +correctness and device gates below pass: + +> One decoder definition is trained through Meganeura autodiff on an RTX GPU +> and instantiated for inference, joined to a DINOv3 encoder, through the same +> compiler and Vulkan runtime on an Adreno-based Android XR device. The +> application shares Blade's graphics context and queue with inference. + +The artifact must distinguish that demonstrated claim from hypotheses about +decoder quality, f16 arithmetic, zero-copy integration, or camera perception. + +## Frozen revisions and assets + +A paper freeze should use clean revisions. During development, every run must +instead retain an exact source snapshot in addition to its base revisions. +The evidence bundle records: + +- full Git revisions for DinoVision and Meganeura, the Blade revision selected + by Cargo, cleanliness state, and any exact source snapshot needed to + reproduce a dirty development run; +- `Cargo.lock`, `cargo tree`, Rust/NDK/ADB versions, GPU/driver, Horizon build, + refresh configuration, thermal state, and all runtime toggle values; +- SHA-256 hashes for the upstream DINO checkpoint and each decoder; +- the immutable dataset manifest and the exact command line; +- raw timing or per-image records, followed by separately generated summary + tables and figures. + +The canonical DINO checkpoint remains an upstream dependency rather than being +duplicated. Meta's DINOv3 License permits redistribution only under that +agreement and requires a copy of it, a prominent “Built with DINOv3” notice, +and acknowledgment in resulting research. The artifact links to the gated +canonical model and preserves its hash. Decoder weights are treated +conservatively as DINOv3-derived: their model repository carries the DINOv3 +agreement and notice rather than presenting the weights as unconditionally +MIT-licensed. The DinoVision source remains MIT. Generated decoder weights are +published with their architecture, depth, resolution, dataset-manifest hash, +and training metadata. + +## Dataset validity + +Generate `dataset.json` with `tools/make_dataset_manifest.py`. A `group` is a +leakage boundary: one headset capture session, room/lighting traversal, or +photo collection. A group may occur in exactly one of `train`, `validation`, +and `test`. Identical file hashes may not cross splits. + +The paper-quality dataset should contain at least: + +- an Imagenette/photo training source; +- multiple independent headset capture sessions for training; +- held-out capture sessions from different trajectories and lighting for + validation and test; +- a separately reported held-out photo split, so domain adaptation is not + hidden inside one aggregate. + +Sequential camera frames must never be randomly divided across splits. +Create each capture group under its own immutable session name by writing that +name into the device's `capture` flag before launching the app, for example +`echo room-a-01 > /data/local/tmp/dinovision/capture`. The app refuses to +overwrite a non-empty session directory. + +## Reconstruction evaluation + +Use `examples/evaluate_decoder.rs`. It verifies all input hashes and emits +per-image MSE, MAE, PSNR, and RGB SSIM, plus global PSNR and distributions. +The sample PNGs place the target on the left and reconstruction on the right; +the same directory retains raw preprocessed patches, the full encoder output, +the spatial decoder input, and decoder output for numerical cross-device +comparison. + +The deployment artifact repeats its selected `3 layers @ 224` cell with three +decoder initializations. If the report retains comparative depth or resolution +claims, extend that into this matched matrix, again with three seeds per cell: + +| Encoder | Resolution | Decoder | Purpose | +|---|---:|---|---| +| 12 layers | 224 | early two-stage blend | official final representation | +| 3 layers | 224 | early two-stage blend | deployed latency choice | +| 3 layers | 240 | retargeted and retrained | test the tail-waste hypothesis end to end | + +If the report retains claims about L1, constant learning rate, or the number of +blend stages, those become matched ablations under the same manifests and +seeds. Otherwise they are described as implementation choices, not findings. + +Example: + +```powershell +python tools/make_dataset_manifest.py ` + --root C:\Data\dinovision ` + --output experiments\dataset.json ` + --entry train photo imagenette-train imagenette\train ` + --entry train capture room-a captures\room-a ` + --entry test capture room-b captures\room-b + +cargo run --release --example evaluate_decoder -- ` + --manifest experiments\dataset.json ` + --model model.safetensors --decoder decoder.bin ` + --split test --layers 3 --output artifacts\quality-3l-224.json +``` + +Training uses a deterministic, seed-controlled shuffle and writes its decoder, +diagnostic strip, and `training.json` into the requested output directory: + +```powershell +cargo run --release --example train_decoder -- ` + experiments\dataset.json model.safetensors ` + 12000 2500 3 224 0 artifacts\train-3l-224-seed0 +``` + +## Timing validity + +Isolated native benchmarks and live-XR co-tenancy are separate experiments. + +For isolated kernel/encoder timings: + +- use five or more untimed warmups and at least 20 retained synchronized + samples; +- report median, IQR, minimum, maximum, and every raw sample; +- stabilize the headset in one power/display state before the matrix; +- randomize or bracket variants rather than relying on monotonic clock ramp; +- repeat the matrix in at least three fresh processes. + +For the XR application, retain every `DINOVISION_APP_JSON` record and report: + +- application render-submission rate; +- each eye's independent update rate and the lower of the two rates; +- per-worker wall latency, explicitly not capture-to-photon latency; +- mono/stereo, chunk count, inference interval, display refresh, and duration. + +Sweep `submission_chunks = 1, 2, 4, 8, 12, 16` at a fixed interval in the +predeclared order `4, 16, 1, 12, 2, 8`, rather than coupling chunk count to +startup or thermal drift. Report both isolated throughput cost and live +render/update tradeoff. Run long enough to expose sustained thermal behavior. +App submission rate must not be called compositor or display rate. + +## Correctness + +Before performance or quality results are admitted: + +1. run the Hugging Face reference comparison and retain its tensors/output; +2. run the same fixed raw image and weights through `evaluate_decoder` on RTX + and Adreno, retaining `*-patches.f32`, `*-encoder.f32`, `*-features.f32`, + and `*-reconstruction.f32`; +3. report relative output L2, maximum absolute error, and per-token cosine; +4. confirm decoder output agreement across the two devices; +5. run `cargo test --workspace --all-targets`, with the real-weight semantic + test enabled rather than silently skipped. + +Use `tools/compare_f32.py` for each host/device tensor pair. It records both +input hashes, relative L2, cosine similarity, mean/max absolute error, and the +explicit pass thresholds rather than relying on a console-only comparison. + +## Audited command sequence + +The wrappers refuse to merge results into non-empty directories. On a device +with historical DinoVision data, the recovery pull is deliberately the first +device operation: + +```powershell +.\tools\run_decoder_matrix.ps1 ` + -Manifest C:\Data\manifests\imagenette2-320.json ` + -Model C:\Models\dinov3-vits16\model.safetensors ` + -OutputRoot C:\Runs\dinovision-quality + +.\tools\build_android_artifacts.ps1 ` + -OutputDir C:\Runs\dinovision-android-build + +.\tools\pull_quest_artifacts.ps1 ` + -OutputDir C:\Runs\quest-recovery-before-corrected-run +``` + +Generate the host half of the fixed-frame comparison with the preselected +seed-0 decoder, then run the checked device half: + +```powershell +cargo run --release --example evaluate_decoder -- ` + --manifest C:\Data\correctness\manifests\correctness-224.json ` + --model C:\Models\dinov3-vits16\model.safetensors ` + --decoder C:\Runs\dinovision-quality\3l224-seed0\decoder.bin ` + --split test --layers 3 --size 224 ` + --output C:\Data\correctness\host-seed0\quality.json --samples 1 + +.\tools\run_cross_device_correctness.ps1 ` + -OutputDir C:\Runs\quest-correctness ` + -RecoveryManifest C:\Runs\quest-recovery-before-corrected-run\recovery_manifest.json ` + -Binary C:\Runs\dinovision-android-build\evaluate_decoder ` + -CorrectnessRoot C:\Data\correctness ` + -HostSampleDir C:\Data\correctness\host-seed0\quality_samples ` + -Model C:\Models\dinov3-vits16\model.safetensors ` + -Decoder C:\Runs\dinovision-quality\3l224-seed0\decoder.bin +``` + +Only after that comparison passes are timing runs admissible: + +```powershell +.\tools\run_quest_bench.ps1 ` + -OutputDir C:\Runs\quest-isolated ` + -RecoveryManifest C:\Runs\quest-recovery-before-corrected-run\recovery_manifest.json ` + -Binary C:\Runs\dinovision-android-build\bench ` + -Condition live-worn -Processes 3 -Iterations 20 + +python .\tools\summarize_bench.py ` + --records C:\Runs\quest-isolated\benchmark-records.json ` + --metadata C:\Runs\quest-isolated\benchmark-metadata.json ` + --output-json C:\Runs\quest-isolated\benchmark-summary.json ` + --output-markdown C:\Runs\quest-isolated\benchmark-summary.md + +.\tools\run_xr_sweep.ps1 ` + -OutputDir C:\Runs\quest-live-xr ` + -RecoveryManifest C:\Runs\quest-recovery-before-corrected-run\recovery_manifest.json ` + -Apk C:\Runs\dinovision-android-build\dinovision_xr.apk ` + -Model C:\Models\dinov3-vits16\model.safetensors ` + -Decoder C:\Runs\dinovision-quality\3l224-seed0\decoder.bin +``` + +The XR summary consumes the six `chunks-*-records.json` files as repeated +`--records` arguments. The sweep backs up and restores every runtime toggle +and both preexisting weight files; it never enables camera capture. + +## Interpretation rules + +- A microbenchmark may explain a hypothesis, but only a profile of the + deployed graph may assign wall time to an operation class. +- f16 weight storage says nothing conclusive about unimplemented f16 + arithmetic. +- The 240-pixel encoder result is not an end-to-end result until its decoder, + preprocessing, readback, and rendering path are included. +- Direct GPU output is future work until output lifetime, EMA, layout, and + synchronization are implemented and measured. +- Stereo fusion, comfort, camera rate, and capture-to-photon claims require + timestamps/calibration or are labeled single-user observations. diff --git a/environment/publication-source/source-snapshot/experiments/paper-section.tex b/environment/publication-source/source-snapshot/experiments/paper-section.tex new file mode 100644 index 0000000000000000000000000000000000000000..99e4eef1ab0d38d381bcca6630f027b8c9b7c4dc --- /dev/null +++ b/environment/publication-source/source-snapshot/experiments/paper-section.tex @@ -0,0 +1,117 @@ +% DinoVision paper-section freeze candidate, 2026-08-01 America/Los_Angeles. +% Host evidence is complete. Keep the deployment-gate paragraph until the +% corrected Quest numerical comparison and timing protocols have passed. + +\subsection{End-to-end case study: DinoVision} +\label{sec:dinovision} + +We evaluate Meganeura beyond isolated operators with DinoVision, an Android XR +application that reconstructs passthrough imagery from intermediate +DINOv3~\cite{simeoni2025dinov3} +features. The application center-crops and resizes an RGB frame to +$224\times224$, executes the first three layers of a frozen DINOv3 ViT-S/16 +encoder, rearranges its $14\times14\times384$ patch features, and decodes them +to RGB. The encoder and decoder form one batch-one inference graph on the +device. In the live application, Meganeura sessions share Blade's Vulkan +context and queue with OpenXR rendering. + +This case study exercises patch projection, learned prefix tokens, axial RoPE, +multi-head attention, LayerNorm, GELU MLPs, LayerScale, residual connections, +convolution, group normalization, SiLU, upsampling, autodiff, Adam, parameter +serialization, and Android cross-compilation. It is evidence about the +breadth and integration of the Meganeura stack, rather than a comparison with +PyTorch or a claim of capture-to-photon latency. + +\paragraph{Training and evaluation.} +The frozen encoder is used to cache features on an NVIDIA host, after which +Meganeura trains a 2,012,547-parameter decoder-only batch graph. Deployment +uses the same decoder construction and learned parameters in a batch-one +joined graph. Thus the two paths share IR operations, compiler, and runtime, +but are not literally the same complete graph. + +We preserve Imagenette's upstream train/validation split. Each of three runs +uses the same class-interleaved 2,500-image training subset (250 images per +class), 12,000 batch-eight Adam updates, and a distinct seed controlling both +initialization and data order. We evaluate every run on all 3,925 validation +images. Seed zero was selected for deployment before validation; seed one is +the strongest replicate, ruling out best-seed selection of the deployed +artifact. Table~\ref{tab:dinovision-quality} reports held-out quality. The +aggregate covers 11,775 reconstruction executions, with the same validation +set reused across seeds. + +\begin{table}[t] + \centering + \caption{Held-out DinoVision reconstruction quality. The last row is the + mean $\pm$ sample standard deviation across independently initialized + decoders.} + \label{tab:dinovision-quality} + \begin{tabular}{rcccc} + \hline + Seed & Global PSNR & Median PSNR & Median SSIM & Median MAE \\ + & (dB) & (dB) & & \\ + \hline + 0 (deployed) & 21.7688 & 22.3603 & 0.6338 & 0.04729 \\ + 1 & 21.9830 & 22.5714 & 0.6491 & 0.04598 \\ + 2 & 21.8170 & 22.3911 & 0.6388 & 0.04700 \\ + mean $\pm$ SD & $21.86\pm0.11$ & $22.44\pm0.11$ & + $0.6406\pm0.0078$ & $0.0468\pm0.0007$ \\ + \hline + \end{tabular} +\end{table} + +\paragraph{Independent correctness gate.} +The audit found a silent layout error in the initial implementation: +Meganeura's NCHW-flat per-channel multiplication was applied directly to a +$[\mathrm{tokens},\mathrm{hidden}]$ LayerScale branch. Only the first token +received the intended residual update, yet downstream images remained +plausible. We invalidated all weights and measurements produced by that +graph, corrected the layout, and retrained all three replicates. + +For the corrected implementation, an independent Torch/Transformers reference +and Meganeura consume the same normalized floating-point tensor and checkpoint +parameters. The predeclared acceptance thresholds are relative $L_2\leq +0.01$, CLS cosine $>0.999$, and every patch-token cosine $>0.999$. +Table~\ref{tab:dinovision-correctness} shows that the deployed three-layer +graph and the complete twelve-layer control pass. Exact-shape CPU tests also +cover the attention and LayerScale operators. + +\begin{table}[t] + \centering + \caption{Meganeura encoder agreement with the independent reference.} + \label{tab:dinovision-correctness} + \begin{tabular}{rccc} + \hline + Encoder depth & Relative $L_2$ & CLS cosine & Worst patch cosine \\ + \hline + 1 & 0.000781 & 1.000000 & 0.999990 \\ + 3 & 0.001403 & 1.000000 & 0.999995 \\ + 12 & 0.002253 & 0.999997 & 0.999996 \\ + \hline + \end{tabular} +\end{table} + +The failure suggests a reusable Meganeura hardening change: graph construction +should validate the rank, flattened element count, channel/spatial product, +and gate length of per-channel multiplication. The compiler revision used +here derives dispatch length from the first shape coordinate, so the invalid +layout otherwise fails silently. + +\paragraph{Deployment gate.} +The corrected graph cross-compiles for Android API 34/aarch64, including the +native evaluator, benchmark, and XR APK. We do not report historical headset +numbers: they were generated by the invalid graph and a minimum-of-samples +timing protocol. Device performance is admissible only after (1) a fixed-frame +host/Quest comparison passes for patches, encoder output, spatial decoder +input, and reconstruction; (2) three fresh native processes each retain at +least 20 synchronized samples after warmup; and (3) a live-worn XR sweep +records all predeclared submission-chunk settings with power, thermal, display, +and runtime state. Until those gates pass, DinoVision supports host training, +independent encoder correctness, and cross-compilation claims, but not Android +correctness or performance claims. + +The public artifact at +\texttt{https://huggingface.co/mad-bot/dinovision} contains the selected and +replicate decoder weights, per-image held-out records, immutable manifests, +independent-reference tensors, and exact source snapshots. It deliberately +excludes the gated DINOv3 checkpoint, dataset photographs, and private headset +captures. diff --git a/environment/publication-source/source-snapshot/huggingface/DINOv3-LICENSE.md b/environment/publication-source/source-snapshot/huggingface/DINOv3-LICENSE.md new file mode 100644 index 0000000000000000000000000000000000000000..f531b1e6b5ab2318957bbf8ad1bda9f800a23e17 --- /dev/null +++ b/environment/publication-source/source-snapshot/huggingface/DINOv3-LICENSE.md @@ -0,0 +1,66 @@ +# DINOv3 License + +*Last Updated: August 19, 2025* + +**“Agreement”** means the terms and conditions for use, reproduction, distribution and modification of the DINO Materials set forth herein. + +**“DINO Materials”** means, collectively, Documentation and the models, software and algorithms, including machine-learning model code, trained model weights, inference-enabling code, training-enabling code, fine-tuning enabling code, and other elements of the foregoing distributed by Meta and made available under this Agreement. + +**“Documentation”** means the specifications, manuals and documentation accompanying +DINO Materials distributed by Meta. + +**“Licensee”** or **“you”** means you, or your employer or any other person or entity (if you are entering into this Agreement on such person or entity’s behalf), of the age required under applicable laws, rules or regulations to provide legal consent and that has legal authority to bind your employer or such other person or entity if you are entering in this Agreement on their behalf. + +**“Meta”** or **“we”** means Meta Platforms Ireland Limited (if you are located in or, if you are an entity, your principal place of business is in the EEA or Switzerland) or Meta Platforms, Inc. (if you are located outside of the EEA or Switzerland). + +**“Sanctions”** means any economic or trade sanctions or restrictions administered or enforced by the United States (including the Office of Foreign Assets Control of the U.S. Department of the Treasury (“OFAC”), the U.S. Department of State and the U.S. Department of Commerce), the United Nations, the European Union, or the United Kingdom. + +**“Trade Controls”** means any of the following: Sanctions and applicable export and import controls. + +By clicking “I Accept” below or by using or distributing any portion or element of the DINO Materials, you agree to be bound by this Agreement. + +## 1. License Rights and Redistribution. + +a. Grant of Rights. You are granted a non-exclusive, worldwide, non-transferable and royalty-free limited license under Meta’s intellectual property or other rights owned by Meta embodied in the DINO Materials to use, reproduce, distribute, copy, create derivative works of, and make modifications to the DINO Materials. + +b. Redistribution and Use. + +i. Distribution of DINO Materials, and any derivative works thereof, are subject to the terms of this Agreement. If you distribute or make the DINO Materials, or any derivative works thereof, available to a third party, you may only do so under the terms of this Agreement and you shall provide a copy of this Agreement with any such DINO Materials. + +ii. If you submit for publication the results of research you perform on, using, or otherwise in connection with DINO Materials, you must acknowledge the use of DINO Materials in your publication. + +iii. Your use of the DINO Materials must comply with applicable laws and regulations, including Trade Control Laws and applicable privacy and data protection laws. + +iv. Your use of the DINO Materials will not involve or encourage others to reverse engineer, decompile or discover the underlying components of the DINO Materials. + +v. You are not the target of Trade Controls and your use of DINO Materials must comply with Trade Controls. You agree not to use, or permit others to use, DINO Materials for any activities subject to the International Traffic in Arms Regulations (ITAR) or end uses prohibited by Trade Controls, including those related to military or warfare purposes, nuclear industries or applications, espionage, or the development or use of guns or illegal weapons. + +## 2. User Support. + +Your use of the DINO Materials is done at your own discretion; Meta does not process any information nor provide any service in relation to such use. Meta is under no obligation to provide any support services for the DINO Materials. Any support provided is “as is”, “with all faults”, and without warranty of any kind. + +## 3. Disclaimer of Warranty. + +UNLESS REQUIRED BY APPLICABLE LAW, THE DINO MATERIALS AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED ON AN “AS IS” BASIS, WITHOUT WARRANTIES OF ANY KIND, AND META DISCLAIMS ALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE DINO MATERIALS AND ASSUME ANY RISKS ASSOCIATED WITH YOUR USE OF THE DINO MATERIALS AND ANY OUTPUT AND RESULTS. + +## 4. Limitation of Liability. + +IN NO EVENT WILL META OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, FOR ANY LOST PROFITS OR ANY DIRECT OR INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF META OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING. + +## 5. Intellectual Property. + +a. Subject to Meta’s ownership of DINO Materials and derivatives made by or for Meta, with respect to any derivative works and modifications of the DINO Materials that are made by you, as between you and Meta, you are and will be the owner of such derivative works and modifications. + +b. If you institute litigation or other proceedings against Meta or any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the DINO Materials, outputs or results, or any portion of any of the foregoing, constitutes infringement of intellectual property or other rights owned or licensable by you, then any licenses granted to you under this Agreement shall terminate as of the date such litigation or claim is filed or instituted. You will indemnify and hold harmless Meta from and against any claim by any third party arising out of or related to your use or distribution of the DINO Materials. + +## 6. Term and Termination. + +The term of this Agreement will commence upon your acceptance of this Agreement or access to the DINO Materials and will continue in full force and effect until terminated in accordance with the terms and conditions herein. Meta may terminate this Agreement if you are in breach of any term or condition of this Agreement. Upon termination of this Agreement, you shall delete and cease use of the DINO Materials. Sections 3, 4 and 7 shall survive the termination of this Agreement. + +## 7. Governing Law and Jurisdiction. + +This Agreement will be governed and construed under the laws of the State of California without regard to choice of law principles, and the UN Convention on Contracts for the International Sale of Goods does not apply to this Agreement. The courts of California shall have exclusive jurisdiction of any dispute arising out of this Agreement. + +## 8. Modifications and Amendments. + +Meta may modify this Agreement from time to time; provided that they are similar in spirit to the current version of the Agreement, but may differ in detail to address new problems or concerns. All such changes will be effective immediately. Your continued use of the DINO Materials after any modification to this Agreement constitutes your agreement to such modification. Except as provided in this Agreement, no modification or addition to any provision of this Agreement will be binding unless it is in writing and signed by an authorized representative of both you and Meta. diff --git a/environment/publication-source/source-snapshot/huggingface/NOTICE.md b/environment/publication-source/source-snapshot/huggingface/NOTICE.md new file mode 100644 index 0000000000000000000000000000000000000000..7ba64354bdf098624ba0c1597b0fcde6bb96bcc4 --- /dev/null +++ b/environment/publication-source/source-snapshot/huggingface/NOTICE.md @@ -0,0 +1,17 @@ +# Built with DINOv3 + +The DinoVision decoder weights were trained from features produced by Meta's +DINOv3 ViT-S/16 checkpoint. The encoder checkpoint is not redistributed in +this artifact. Obtain it from the canonical gated repository and comply with +the DINOv3 License included as `DINOv3-LICENSE.md`. + +DinoVision source code is MIT-licensed. The learned decoder weights are +treated conservatively as DINOv3-derived and distributed under the DINOv3 +agreement. + +`DINOv3-LICENSE.md` is the upstream DINOv3 repository's agreement (SHA-256 +`25d122eb8f5b880fd23c736fb6ea8018ee45c12237e00b8a86d14c653904999e`). +Meta may amend the agreement; consult the +[current official terms](https://ai.meta.com/resources/models-and-libraries/dinov3-license/) +as well. The live terms require the prominent notice above in addition to a +copy of the agreement and acknowledgment in research publications. diff --git a/environment/publication-source/source-snapshot/huggingface/README.md b/environment/publication-source/source-snapshot/huggingface/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0417acb48a180650be2a80a9253bc0d84d16b9ff --- /dev/null +++ b/environment/publication-source/source-snapshot/huggingface/README.md @@ -0,0 +1,156 @@ +--- +license: other +license_name: dinov3-license +license_link: https://ai.meta.com/resources/models-and-libraries/dinov3-license/ +library_name: meganeura +pipeline_tag: image-to-image +base_model: facebook/dinov3-vits16-pretrain-lvd1689m +tags: +- dinov3 +- meganeura +- vulkan +- android +- image-reconstruction +--- + +# DinoVision decoder + +> **Built with DINOv3** + +This repository contains the RGB decoder weights and audited records for the +DinoVision Meganeura case study. The decoder is trained on the host with +Meganeura autodiff and Adam, then joined to a frozen three-layer DINOv3 +ViT-S/16 encoder for Vulkan inference on Android XR. + +The artifact is not a standalone Hugging Face image-to-image pipeline. Use it +with [DinoVision](https://github.com/kvark/dinovision) and +[Meganeura](https://github.com/kvark/meganeura). + +## Required base model + +The Meta encoder checkpoint is deliberately not duplicated here. Obtain the +gated +[`facebook/dinov3-vits16-pretrain-lvd1689m`](https://huggingface.co/facebook/dinov3-vits16-pretrain-lvd1689m) +checkpoint after accepting its terms. + +| Item | Value | +|---|---| +| Encoder checkpoint SHA-256 | `4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d` | +| Encoder depth | first 3 of 12 layers | +| Input | normalized RGB, 224 by 224 | +| Encoder patch grid | 14 by 14, 384 channels | +| Decoder parameters | 2,012,547 | +| Decoder output | RGB, 224 by 224, sigmoid range | + +## Selected artifact + +Seed 0 is selected by a rule fixed before validation; it is not selected as +the best of the three runs. + + + +On the complete 3,925-image Imagenette validation split, three independently +initialized decoders obtain: + +| Seeds | Global PSNR (dB) | Median-image PSNR (dB) | Median RGB SSIM | Median MAE | +|---:|---:|---:|---:|---:| +| 3 | 21.86 +/- 0.11 | 22.44 +/- 0.11 | 0.6406 +/- 0.0078 | 0.0468 +/- 0.0007 | + +Values are the mean +/- sample standard deviation across seeds. Per-image +medians are computed within each seed before aggregation. Seed-level results: + +| Seed | Raw decoder SHA-256 | SafeTensors SHA-256 | Global PSNR (dB) | Median RGB SSIM | +|---:|---|---|---:|---:| +| 0 (selected) | `d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c` | `f287b5d1e4e14bed15e4883c3ea5b9f01d28e3123f3fb3308ace714e4b292123` | 21.7688 | 0.6338 | +| 1 | `1dbc2b99603604814e5d6f99f3a5ed765863c3e2db5012fd95d8bc87954879a6` | `1dcffb47b5c5ce5496286558600223f64a55512057e098c2bf0b3b9566c20700` | 21.9830 | 0.6491 | +| 2 | `2085a6923760c0266c4f965db2014afd7cf4b7fcbde2c203d9e399c37fe2af67` | `82d5178115a6251e69f72061d0ec5907c4968e89ee9f8d3fe53b32a26e9f7bfc` | 21.8170 | 0.6388 | + +Seed 1 is the strongest validation replicate, so the preselected seed 0 was +not chosen post hoc. The aggregate record is `quality/summary.json` (SHA-256 +`06d34ea8eff9d0bf50dbae467891347d7032bcd85b5080b45d381bca02ba4350`). +No pre-audit decoder is published. + + + +`decoder.bin` is the runtime format: little-endian f32 parameters in +Meganeura graph-declaration order. `decoder.safetensors` contains the same +values as 26 named tensors and records the encoder depth, resolution, seed, +base-model hash, and dataset-manifest hash. The SafeTensors conversion checks +every tensor for exact round-trip equality. + +## Training and evaluation + +Each replicate uses 2,500 class-interleaved Imagenette training images (250 +from each of ten classes), +12,000 batch-8 updates, mean absolute error, and Adam with a linearly decayed +learning rate from 0.002 to 0.0001 over the first 95% of updates and a 0.0001 +floor thereafter. Seeds independently control parameter initialization and +data order. + +Evaluation processes all 3,925 images in the upstream Imagenette validation +split. Every file is verified against an immutable manifest. The artifact +retains per-image MSE, MAE, PSNR, and RGB SSIM (11 by 11 Gaussian window, +sigma 1.5), plus aggregate distributions. Training wall time is excluded as a +performance result because the interactive host was not controlled. + +The previous DinoVision graph misapplied DINOv3 LayerScale and is invalid. +The corrected three-layer Meganeura encoder was compared with an independent +Torch 2.13.0+cpu / Transformers 5.14.1 execution of the canonical checkpoint: + +| Depth | Relative L2 | CLS cosine | Worst patch cosine | +|---:|---:|---:|---:| +| 3 layers | 0.001403 | 1.000000 | 0.999995 | +| 12 layers | 0.002253 | 0.999997 | 0.999996 | + +A short reproducibility cell (20 updates over 16 images, seed 20260801) was +executed twice from fresh output directories. Both runs produced the same raw +decoder SHA-256, +`2959b06784576bb1bc495b4e0a0d2f4aeebb216d56f7fc078843df4b7ec12686`. +This is a deterministic-path smoke test, not an additional quality result. + +## File layout + +- `decoder.bin`, `decoder.safetensors`, `training.json`: selected seed 0. +- `replicates/`: all seeded decoder weights and immutable training records. +- `quality/`: per-image held-out records and generated aggregate summaries. +- `manifests/`: public dataset and correctness manifests. +- `correctness/`: independent-implementation and host/device numerical checks. +- `benchmarks/`: raw and summarized corrected Quest measurements, when present. +- `environment/`: source/revision, dependency, toolchain, and device metadata. +- `reproducibility/`: the checked short deterministic replay records. + +Target/reconstruction PNGs from Imagenette are not redistributed. Private +headset captures are also excluded. The fixed synthetic correctness frame is +public and is included with its hash. + +## Intended use and limitations + +These weights support research reproduction of a systems case study. They are +not intended for photographic restoration, surveillance, identity inference, +medical use, or safety-critical perception. Reconstruction quality is +evaluated on held-out photographs, not independent headset capture sessions. +Worker latency is not capture-to-photon latency, and the artifact does not +claim a PyTorch-on-Android speedup. + +## License and acknowledgment + +The DinoVision source code is MIT-licensed. These learned weights are treated +conservatively as DINOv3-derived and distributed under the included +`DINOv3-LICENSE.md`. Use of the required base model and these artifacts is +subject to that agreement. Research using this artifact must acknowledge +DINOv3; see the canonical model card for the official citation. The included +agreement is preserved byte-for-byte from the upstream DINOv3 repository; the +[live Meta terms](https://ai.meta.com/resources/models-and-libraries/dinov3-license/) +should also be consulted because they may be amended. + +```bibtex +@misc{simeoni2025dinov3, + title = {{DINOv3}}, + author = {Sim{\'e}oni, Oriane and Vo, Huy V. and Seitzer, Maximilian and others}, + year = {2025}, + eprint = {2508.10104}, + archivePrefix = {arXiv}, + primaryClass = {cs.CV}, + url = {https://arxiv.org/abs/2508.10104} +} +``` diff --git a/environment/publication-source/source-snapshot/src/bench.rs b/environment/publication-source/source-snapshot/src/bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..2b0c760ae60f9ecd52ea94c60673fcd40d71346e --- /dev/null +++ b/environment/publication-source/source-snapshot/src/bench.rs @@ -0,0 +1,469 @@ +//! Throughput measurement, shared by the desktop and on-device entry +//! points. +//! +//! The question this exists to answer: the Adreno in a Quest 3 is not +//! expected to expose `VK_KHR_cooperative_matrix`, so meganeura will fall +//! back to its register-tiled scalar matmul. Whether the encoder then +//! lands at 20 ms or 200 ms per frame decides the input resolution, the +//! inference rate, and whether the render loop has to be decoupled from +//! inference (it almost certainly does). +//! +//! Everything here reports achieved GFLOP/s next to the theoretical MAC +//! count, so a number that looks fast can be checked against what the +//! device could possibly do. + +use std::sync::Arc; +use std::time::Instant; + +use meganeura::graph::Op; +use meganeura::train::{Mode, SessionConfig}; +use meganeura::{Graph, Session}; + +use crate::dinov3::Config; + +/// One timing result. +#[derive(Debug, Clone)] +pub struct Timing { + pub label: String, + /// Minimum retained sample. Useful diagnostically, but not the primary + /// result: selecting the minimum biases comparisons on a noisy device. + pub best_ms: f64, + pub mean_ms: f64, + pub median_ms: f64, + pub p25_ms: f64, + pub p75_ms: f64, + pub max_ms: f64, + /// Every retained synchronized wall-time observation. + pub samples_ms: Vec, + /// Multiply-accumulates per iteration, for the GFLOP/s figure. + pub macs: u64, +} + +impl Timing { + /// Median achieved GFLOP/s, counting a multiply-accumulate as two + /// operations. + pub fn gflops(&self) -> f64 { + (self.macs as f64 * 2.0) / (self.median_ms / 1000.0) / 1e9 + } + + /// One self-contained JSON record suitable for retaining from logcat. + pub fn json_line(&self) -> String { + let label = self.label.replace('\\', "\\\\").replace('"', "\\\""); + let samples = self + .samples_ms + .iter() + .map(|v| format!("{v:.6}")) + .collect::>() + .join(","); + format!( + "{{\"schema_version\":1,\"kind\":\"dinovision_benchmark\",\ + \"label\":\"{label}\",\"macs\":{},\"median_ms\":{:.6},\ + \"p25_ms\":{:.6},\"p75_ms\":{:.6},\"min_ms\":{:.6},\ + \"max_ms\":{:.6},\"mean_ms\":{:.6},\"samples_ms\":[{samples}]}}", + self.macs, + self.median_ms, + self.p25_ms, + self.p75_ms, + self.best_ms, + self.max_ms, + self.mean_ms, + ) + } +} + +impl std::fmt::Display for Timing { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{:<28} median {:>8.2} ms IQR [{:>7.2}, {:>7.2}] min/max [{:>7.2}, {:>7.2}] {:>7.1} GFLOP/s", + self.label, + self.median_ms, + self.p25_ms, + self.p75_ms, + self.best_ms, + self.max_ms, + self.gflops() + ) + } +} + +/// Log the device identity and whether cooperative matrix is usable. +/// +/// This is the single most important line of the whole benchmark: it +/// determines which matmul kernel every subsequent number came from. +pub fn describe_device(gpu: &blade_graphics::Context) { + let info = gpu.device_information(); + log::info!("device : {}", info.device_name); + log::info!("driver : {} {}", info.driver_name, info.driver_info); + + let caps = meganeura::runtime::auto_tune(gpu, 0).coop_caps; + if caps.f16_tile == 0 && caps.f32_tile == 0 { + log::warn!("coop matrix : NOT AVAILABLE — expect the register-tiled scalar matmul"); + } else { + log::info!( + "coop matrix : available (f32 tile {}, f16 tile {})", + caps.f32_tile, + caps.f16_tile + ); + } +} + +/// Fill every parameter with small deterministic pseudo-random values. +/// +/// Timing is not sensitive to weight *values*, but leaving parameters at +/// zero would make every activation zero, and a benchmark whose data is +/// entirely one value invites doubt about data-dependent fast paths. +/// Cheap insurance. +pub fn fill_parameters(session: &mut Session, graph: &Graph) { + let mut state = 0x2545_F491_4F6C_DD1Du64; + let mut scratch = Vec::new(); + for node in graph.nodes() { + let Op::Parameter { name } = &node.op else { + continue; + }; + scratch.clear(); + scratch.reserve(node.ty.num_elements()); + for _ in 0..node.ty.num_elements() { + // xorshift64*, inlined to avoid a dependency. + state ^= state >> 12; + state ^= state << 25; + state ^= state >> 27; + let bits = state.wrapping_mul(0x2545_F491_4F6C_DD1D) >> 40; + scratch.push((bits as f32 / (1u32 << 24) as f32 - 0.5) * 0.05); + } + session.set_parameter(name, &scratch); + } +} + +pub(crate) fn time_session(session: &mut Session, label: &str, macs: u64, iters: usize) -> Timing { + // Five is the paper protocol's minimum. The environment override exists + // for diagnostic sweeps, and is recorded alongside the raw samples by + // the calling artifact script. + let warmups = std::env::var("DINOVISION_WARMUPS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(5); + for _ in 0..warmups { + session.step(); + session.wait(); + } + + let mut samples_ms = Vec::with_capacity(iters.max(1)); + for _ in 0..iters.max(1) { + let start = Instant::now(); + session.step(); + session.wait(); + samples_ms.push(start.elapsed().as_secs_f64() * 1000.0); + } + + let mut sorted = samples_ms.clone(); + sorted.sort_by(f64::total_cmp); + let quantile = |q: f64| { + let at = q * (sorted.len() - 1) as f64; + let lo = at.floor() as usize; + let hi = at.ceil() as usize; + sorted[lo] + (sorted[hi] - sorted[lo]) * (at - lo as f64) + }; + Timing { + label: label.to_string(), + best_ms: sorted[0], + mean_ms: samples_ms.iter().sum::() / samples_ms.len() as f64, + median_ms: quantile(0.5), + p25_ms: quantile(0.25), + p75_ms: quantile(0.75), + max_ms: sorted[sorted.len() - 1], + samples_ms, + macs, + } +} + +/// Time a bare `[m, k] @ [k, n]` matmul. +/// +/// Run at the shapes the encoder actually uses, so the result is an upper +/// bound on what the encoder could reach rather than a peak-throughput +/// number from an unrepresentatively large matrix. +pub fn matmul_throughput( + gpu: Arc, + m: usize, + k: usize, + n: usize, + iters: usize, +) -> Timing { + let mut g = Graph::new(); + let a = g.input("a", &[m, k]); + let b = g.parameter("b", &[k, n]); + let y = g.matmul(a, b); + g.set_outputs(vec![y]); + + let (mut session, _) = meganeura::train::build( + &g, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + fill_parameters(&mut session, &g); + session.set_input("a", &vec![0.01f32; m * k]); + + time_session( + &mut session, + &format!("matmul {m}x{k}x{n}"), + (m * k * n) as u64, + iters, + ) +} + +/// Sweep matmul shapes to find what the kernel is actually short of. +/// +/// This diagnostic separates three plausible sources of lost utilization; +/// no operation-share or f16 conclusion is inferred from it without a +/// matched end-to-end run: +/// +/// * **Tail waste.** `m` is 201 — 196 patches, CLS, 4 registers — against +/// `BM = 64`, so the last tile row is 9/64 useful and 21% of every +/// dispatch is padding. Padding `m` to 256 does 27% more arithmetic; if +/// the wall time does not move, we were paying for it already. +/// * **Occupancy.** Tiles are 64×64 with `KTILE = 32`, so a workgroup holds +/// 16.4 KB of shared memory and few stay resident. Widening `n` at fixed +/// cost per workgroup raises the workgroup count; if throughput climbs +/// with it, the device is starved rather than saturated. This is also the +/// one thing f16 would genuinely fix, by halving the LDS footprint. +/// * **Prologue cost.** `k = 384` is 12 k-tiles, so the per-tile load and +/// double barrier amortize over very few iterations. Deepening `k` at the +/// same output size isolates that. +/// +/// The large square shapes at the end give the kernel's ceiling with every +/// one of those effects removed, which is the number f16 arithmetic would +/// have to improve on to be worth the work. +pub fn matmul_shapes(gpu: Arc, iters: usize) -> Vec { + let mut results = Vec::new(); + for (m, k, n, note) in [ + (201, 384, 1536, "encoder MLP up, as it runs"), + (256, 384, 1536, "m padded to a whole tile: +27% MACs"), + (201, 384, 384, "24 workgroups"), + (201, 384, 1536, "96 workgroups"), + (201, 384, 6144, "384 workgroups"), + (201, 1536, 1536, "4x the k-tiles per workgroup"), + (512, 512, 512, "square, no tail"), + (1024, 1024, 1024, "square, no tail"), + (2048, 2048, 2048, "square, kernel ceiling"), + ] { + let t = matmul_throughput(gpu.clone(), m, k, n, iters); + log::info!("{t} ({note})"); + results.push(t); + } + + // Probe the tail-waste hypothesis. Every token-major matmul has `m = tokens`, and + // 201 tokens occupy four 64-row tiles — 256 rows, of which 55 are + // padding we already pay for. A 240² input gives a 15×15 grid, so 225 + // patches plus 5 prefix tokens is 230 rows: still four tiles, still the + // same dispatch, but 15% more spatial resolution reaching the decoder. + // + // Not entirely free — attention scores are O(tokens²) and they are ~8% + // of the layer — so measure it rather than assert it. + // Bracket 240 with repeated 224 cells so time drift is visible rather than + // silently attributed to the middle shape. + for size in [224, 240, 224] { + let c = Config::vits16().at_resolution(size).with_layers(3); + let mut t = encoder_forward(gpu.clone(), &c, iters); + t.label = format!("dinov3 @{size} 3L"); + log::info!( + "{t} (grid {}x{}, {} tokens)", + c.grid(), + c.grid(), + c.num_tokens() + ); + results.push(t); + } + results +} + +/// Build an encoder session on the shared context. +/// +/// Weights are left to the caller: [`crate::weights::load_encoder`] for +/// real features, [`fill_parameters`] for pure timing. +pub fn build_encoder_session( + gpu: Arc, + config: &Config, + cache: Option<&std::path::Path>, +) -> (Session, Graph) { + let mut g = Graph::new(); + let out = crate::dinov3::build_encoder(&mut g, config); + g.set_outputs(vec![out]); + + let build_start = Instant::now(); + let (session, _) = meganeura::train::build( + &g, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + cache, + ..Default::default() + }, + ); + // Worth reporting separately: on a mobile CPU, graph optimization plus + // WGSL-to-SPIR-V for every kernel is slow enough to matter at startup, + // and it is exactly what the plan cache is meant to remove. + log::info!( + "session build: {:.1} s (cache {})", + build_start.elapsed().as_secs_f64(), + if cache.is_some() { "on" } else { "off" } + ); + (session, g) +} + +/// Time a full DINOv3 forward pass with synthetic weights. +pub fn encoder_forward(gpu: Arc, config: &Config, iters: usize) -> Timing { + let (mut session, g) = build_encoder_session(gpu, config, None); + fill_parameters(&mut session, &g); + session.set_input( + "patches", + &vec![0.1f32; config.num_patches() * config.patch_dim()], + ); + + time_session( + &mut session, + &format!("dinov3 vits16 @{}", config.image_size), + config.forward_macs(), + iters, + ) +} + +/// Time the deployed joined encoder-to-RGB graph, including decoder and all +/// graph-internal layout transformations. Camera conversion, CPU patchifying, +/// output readback, and rendering are outside this isolated measurement. +pub fn roundtrip_forward( + gpu: Arc, + config: &Config, + submission_chunks: usize, + iters: usize, +) -> Timing { + let mut graph = Graph::new(); + let encoder_output = crate::dinov3::build_encoder(&mut graph, config); + let reconstruction = crate::decoder::attach_to_encoder(&mut graph, config, encoder_output); + graph.set_outputs(vec![reconstruction]); + let (mut session, _) = meganeura::train::build( + &graph, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + session.set_submission_chunks(submission_chunks); + fill_parameters(&mut session, &graph); + session.set_input( + "patches", + &vec![0.1f32; config.num_patches() * config.patch_dim()], + ); + time_session( + &mut session, + &format!( + "roundtrip @{} {}L x{}", + config.image_size, config.num_hidden_layers, submission_chunks + ), + config.forward_macs() + crate::decoder::forward_macs(config), + iters, + ) +} + +/// The full benchmark: device identity, matmul throughput at the shapes +/// the encoder uses, then the encoder itself across candidate input +/// resolutions. +pub fn run_all(gpu: Arc, iters: usize) -> Vec { + describe_device(&gpu); + + let base = Config::vits16(); + let tokens = base.num_tokens(); + let hidden = base.hidden_size; + let mut results = Vec::new(); + + // The three matmul shapes that dominate a ViT-S forward pass. + for (m, k, n) in [ + (tokens, hidden, hidden), // Q/K/V/output projection + (tokens, hidden, base.intermediate_size), // MLP up + (tokens, base.intermediate_size, hidden), // MLP down + ] { + let t = matmul_throughput(gpu.clone(), m, k, n, iters); + log::info!("{t}"); + results.push(t); + } + + // 224 is the reference resolution (14×14 features); 256 buys a 16×16 + // grid for ~30% more work. Anything larger is unlikely to fit a + // real-time budget, which is what these numbers will confirm or deny. + for size in [224, 256] { + let config = base.clone().at_resolution(size); + let t = encoder_forward(gpu.clone(), &config, iters); + log::info!( + "{t} (grid {}x{}, {} tokens)", + config.grid(), + config.grid(), + config.num_tokens() + ); + results.push(t); + } + + // ViT-S/16 is the smallest DINOv3 there is, so cheaper means fewer + // layers or fewer tokens rather than a smaller model. Measure both + // knobs, since which one to spend is a quality judgement that wants + // real numbers under it. + for layers in [6, 3] { + let c = base.clone().at_resolution(224).with_layers(layers); + let mut t = encoder_forward(gpu.clone(), &c, iters); + t.label = format!("dinov3 @224 {layers}L"); + log::info!("{t} ({layers} of 12 layers)"); + results.push(t); + } + for size in [160, 128] { + let c = base.clone().at_resolution(size); + let mut t = encoder_forward(gpu.clone(), &c, iters); + t.label = format!("dinov3 vits16 @{size}"); + log::info!("{t} (grid {}x{})", c.grid(), c.grid()); + results.push(t); + } + + // The actual reconstruction workload is a joined three-layer encoder and + // decoder. Keep isolated chunk costs beside the live-XR sweep so queue + // fairness is not presented without its throughput price. + let reconstruction = base.clone().at_resolution(224).with_layers(3); + // The order is fixed before corrected device data and deliberately not + // monotonic, matching the live sweep's protection against time drift. + for chunks in [4, 16, 1, 12, 2, 8] { + let t = roundtrip_forward(gpu.clone(), &reconstruction, chunks, iters); + log::info!("{t} (joined encoder + decoder, {chunks} submission chunks)"); + results.push(t); + } + + // f16 weight storage halves weight traffic. Whether that shows up + // depends on whether the device is short of bandwidth or of ALU, which + // is exactly the thing worth measuring rather than reasoning about. + let f16 = base.clone().at_resolution(224).with_f16_weights(true); + let mut t = encoder_forward(gpu.clone(), &f16, iters); + t.label = "dinov3 vits16 @224 f16w".to_string(); + log::info!("{t} (f16 weight storage, f32 arithmetic)"); + results.push(t); + + // Chunked submission should cost a little throughput — several submits + // instead of one — in exchange for letting a co-tenant interleave. This + // measures the price when nothing else is on the queue. + let chunked = base.clone().at_resolution(224); + let (mut session, g) = build_encoder_session(gpu, &chunked, None); + session.set_submission_chunks(12); + fill_parameters(&mut session, &g); + session.set_input( + "patches", + &vec![0.1f32; chunked.num_patches() * chunked.patch_dim()], + ); + let t = time_session( + &mut session, + "dinov3 vits16 @224 x12", + chunked.forward_macs(), + iters, + ); + log::info!("{t} (12 submissions instead of 1)"); + results.push(t); + + results +} diff --git a/environment/publication-source/source-snapshot/src/camera.rs b/environment/publication-source/source-snapshot/src/camera.rs new file mode 100644 index 0000000000000000000000000000000000000000..ac6689ba1500b8b614054d4df60d6fdc8ed717a9 --- /dev/null +++ b/environment/publication-source/source-snapshot/src/camera.rs @@ -0,0 +1,731 @@ +//! Quest passthrough camera, through the Camera2 NDK. +//! +//! Meta exposes the forward-facing cameras on Quest 3 and 3S as ordinary +//! Camera2 devices, distinguished from the avatar cameras by vendor tags. +//! Their own documentation covers the Kotlin path; this is the native one, +//! because everything else here is Rust and bouncing frames through JNI to +//! get them back into a Vulkan pipeline would be absurd. +//! +//! Requirements, all of which fail silently if missed: +//! +//! * `horizonos.permission.HEADSET_CAMERA` **granted at runtime**. Declaring +//! it is not enough. For a POC: +//! `adb shell pm grant rust.dinovision_xr horizonos.permission.HEADSET_CAMERA` +//! * minSdk 34 and NDK r27 for the API-34 sysroot. Note that Horizon OS +//! v205 does *not* export `ACameraManager_getTagFromName`, so Meta's +//! vendor tags cannot be resolved by name; cameras are identified by +//! lens facing and supported formats instead. +//! * Passthrough enabled on the device. +//! +//! The camera delivers 1280×960 YUV420 at 60 Hz. The encoder wants a +//! 224×224 RGB square, so [`FrameSource::next_frame`] centre-crops, +//! box-downscales, and converts in one pass over the destination. + +#![cfg(target_os = "android")] + +use std::ffi::{c_char, c_int, c_void}; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::time::{Duration, Instant}; + +use crate::source::FrameSource; + +/// How long to wait between reopen attempts. The camera stays disabled for +/// as long as the headset is off, so retrying hard would just spin. +const REOPEN_INTERVAL: Duration = Duration::from_secs(1); + +// --- Opaque handles ------------------------------------------------------- + +#[repr(C)] +struct ACameraManager(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct ACameraDevice(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct ACameraMetadata(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct ACameraCaptureSession(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct ACaptureRequest(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct ACameraOutputTarget(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct ACaptureSessionOutput(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct ACaptureSessionOutputContainer(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct AImageReader(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct AImage(#[allow(dead_code)] [u8; 0]); +#[repr(C)] +struct ANativeWindow(#[allow(dead_code)] [u8; 0]); + +#[repr(C)] +struct ACameraIdList { + num_cameras: c_int, + camera_ids: *mut *const c_char, +} + +#[repr(C)] +struct ACameraMetadataConstEntry { + tag: u32, + kind: u8, + count: u32, + data: *const u8, +} + +#[repr(C)] +struct ACameraDeviceStateCallbacks { + context: *mut c_void, + on_disconnected: extern "C" fn(*mut c_void, *mut ACameraDevice), + on_error: extern "C" fn(*mut c_void, *mut ACameraDevice, c_int), +} + +#[repr(C)] +struct ACameraCaptureSessionStateCallbacks { + context: *mut c_void, + on_closed: extern "C" fn(*mut c_void, *mut ACameraCaptureSession), + on_ready: extern "C" fn(*mut c_void, *mut ACameraCaptureSession), + on_active: extern "C" fn(*mut c_void, *mut ACameraCaptureSession), +} + +const AIMAGE_FORMAT_YUV_420_888: c_int = 0x23; +const TEMPLATE_PREVIEW: c_int = 1; +const ACAMERA_OK: c_int = 0; +const AMEDIA_OK: c_int = 0; + +/// Standard metadata tags, section ordinal `<< 16` plus index. +/// +/// Meta's vendor tags would be nicer, but resolving a vendor tag by name +/// needs `ACameraManager_getTagFromName`, and Horizon OS v205 does not +/// export it — linking against it stops the whole library from loading +/// with `UnsatisfiedLinkError`. Standard tags are all that is portable +/// here, so the passthrough cameras get identified by what they can do +/// rather than by what they are called. +const ACAMERA_LENS_FACING: u32 = (8 << 16) + 5; +const ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS: u32 = (13 << 16) + 10; + +/// The passthrough cameras look outward at the world, so they report +/// `LENS_FACING_BACK`. The Quest also exposes a front-facing camera — +/// the avatar one — which advertises the same resolutions but is +/// separately restricted and denies `openCamera` outright. +const LENS_FACING_BACK: u8 = 1; + +/// Camera2 error codes, so a failure says something rather than showing a +/// bare negative number. +fn camera_error(code: c_int) -> &'static str { + match code { + -10001 => "invalid parameter", + -10002 => "camera disconnected", + -10003 => "not enough memory", + -10004 => "metadata not found", + -10005 => "camera device error", + -10006 => "camera service error", + -10007 => "session closed", + -10008 => "invalid operation", + -10009 => "stream configure failed", + -10010 => "camera in use", + -10011 => "max cameras in use", + -10012 => "camera disabled", + -10013 => "permission denied", + -10014 => "unsupported operation", + _ => "unknown", + } +} + +#[link(name = "camera2ndk")] +unsafe extern "C" { + fn ACameraManager_create() -> *mut ACameraManager; + fn ACameraManager_delete(m: *mut ACameraManager); + fn ACameraManager_getCameraIdList(m: *mut ACameraManager, out: *mut *mut ACameraIdList) -> c_int; + fn ACameraManager_deleteCameraIdList(l: *mut ACameraIdList); + fn ACameraManager_getCameraCharacteristics( + m: *mut ACameraManager, + id: *const c_char, + out: *mut *mut ACameraMetadata, + ) -> c_int; + fn ACameraManager_openCamera( + m: *mut ACameraManager, + id: *const c_char, + cb: *mut ACameraDeviceStateCallbacks, + out: *mut *mut ACameraDevice, + ) -> c_int; + fn ACameraMetadata_getConstEntry( + md: *const ACameraMetadata, + tag: u32, + entry: *mut ACameraMetadataConstEntry, + ) -> c_int; + fn ACameraMetadata_free(md: *mut ACameraMetadata); + fn ACameraDevice_close(d: *mut ACameraDevice) -> c_int; + fn ACameraDevice_createCaptureRequest( + d: *mut ACameraDevice, + template: c_int, + out: *mut *mut ACaptureRequest, + ) -> c_int; + fn ACameraDevice_createCaptureSession( + d: *mut ACameraDevice, + outputs: *const ACaptureSessionOutputContainer, + cb: *const ACameraCaptureSessionStateCallbacks, + session: *mut *mut ACameraCaptureSession, + ) -> c_int; + fn ACaptureSessionOutputContainer_create( + out: *mut *mut ACaptureSessionOutputContainer, + ) -> c_int; + fn ACaptureSessionOutputContainer_add( + c: *mut ACaptureSessionOutputContainer, + o: *const ACaptureSessionOutput, + ) -> c_int; + fn ACaptureSessionOutputContainer_free(c: *mut ACaptureSessionOutputContainer); + fn ACaptureSessionOutput_create( + w: *mut ANativeWindow, + out: *mut *mut ACaptureSessionOutput, + ) -> c_int; + fn ACaptureSessionOutput_free(o: *mut ACaptureSessionOutput); + fn ACameraOutputTarget_create(w: *mut ANativeWindow, out: *mut *mut ACameraOutputTarget) + -> c_int; + fn ACameraOutputTarget_free(t: *mut ACameraOutputTarget); + fn ACaptureRequest_addTarget(r: *mut ACaptureRequest, t: *const ACameraOutputTarget) -> c_int; + fn ACaptureRequest_free(r: *mut ACaptureRequest); + fn ACameraCaptureSession_setRepeatingRequest( + s: *mut ACameraCaptureSession, + cb: *mut c_void, + num: c_int, + requests: *mut *mut ACaptureRequest, + seq: *mut c_int, + ) -> c_int; + fn ACameraCaptureSession_close(s: *mut ACameraCaptureSession); +} + +#[link(name = "mediandk")] +unsafe extern "C" { + fn AImageReader_new( + width: c_int, + height: c_int, + format: c_int, + max_images: c_int, + out: *mut *mut AImageReader, + ) -> c_int; + fn AImageReader_delete(r: *mut AImageReader); + fn AImageReader_getWindow(r: *mut AImageReader, out: *mut *mut ANativeWindow) -> c_int; + fn AImageReader_acquireLatestImage(r: *mut AImageReader, out: *mut *mut AImage) -> c_int; + fn AImage_delete(i: *mut AImage); + fn AImage_getWidth(i: *const AImage, out: *mut i32) -> c_int; + fn AImage_getHeight(i: *const AImage, out: *mut i32) -> c_int; + fn AImage_getPlaneRowStride(i: *const AImage, plane: c_int, out: *mut i32) -> c_int; + fn AImage_getPlanePixelStride(i: *const AImage, plane: c_int, out: *mut i32) -> c_int; + fn AImage_getPlaneData( + i: *const AImage, + plane: c_int, + data: *mut *mut u8, + len: *mut c_int, + ) -> c_int; +} + +/// Set from the device callbacks, cleared when the camera is reopened. +/// +/// A process-global rather than a per-camera flag because the callbacks +/// take a raw context pointer and this app only ever opens one camera; +/// threading an `Arc` through the FFI to support a second would be +/// ceremony for a case that does not exist. +static DEVICE_ERROR: AtomicBool = AtomicBool::new(false); + +extern "C" fn on_disconnected(_ctx: *mut c_void, _d: *mut ACameraDevice) { + log::warn!("camera disconnected"); + DEVICE_ERROR.store(true, Ordering::Release); +} + +extern "C" fn on_error(_ctx: *mut c_void, _d: *mut ACameraDevice, err: c_int) { + // Code 3 is ERROR_CAMERA_DISABLED, which Horizon OS raises whenever the + // headset comes off. It is routine rather than exceptional here, so the + // camera reopens instead of the view freezing on its last frame. + log::warn!( + "camera device error {err}{}", + if err == 3 { " (disabled — headset removed?)" } else { "" } + ); + DEVICE_ERROR.store(true, Ordering::Release); +} +extern "C" fn on_session(_ctx: *mut c_void, _s: *mut ACameraCaptureSession) {} + +/// Which of the two forward-facing cameras to read. +#[derive(Clone, Copy, Debug)] +pub enum Eye { + Left, + Right, +} + +impl Eye { + fn position(self) -> u8 { + match self { + Eye::Left => 0, + Eye::Right => 1, + } + } +} + +/// A live passthrough camera delivering square RGB frames. +pub struct PassthroughCamera { + manager: *mut ACameraManager, + device: *mut ACameraDevice, + session: *mut ACameraCaptureSession, + request: *mut ACaptureRequest, + target: *mut ACameraOutputTarget, + output: *mut ACaptureSessionOutput, + container: *mut ACaptureSessionOutputContainer, + reader: *mut AImageReader, + size: usize, + buf: Vec, + have_frame: bool, + /// Kept so the camera can be reopened after the device errors. + eye: Eye, + capture: (i32, i32), + last_reopen: Instant, +} + +// The handles are only touched from the thread that owns the struct; the +// NDK does not pin them to a thread. +unsafe impl Send for PassthroughCamera {} + +impl PassthroughCamera { + /// Open the passthrough camera for one eye at `size × size` output. + /// + /// `capture` is the sensor resolution to request — 1280×960 is what the + /// Quest 3/3S offer. + pub fn new(size: usize, eye: Eye, capture: (i32, i32)) -> Result { + unsafe { + let manager = ACameraManager_create(); + if manager.is_null() { + return Err("ACameraManager_create returned null".into()); + } + + let mut list: *mut ACameraIdList = std::ptr::null_mut(); + if ACameraManager_getCameraIdList(manager, &mut list) != ACAMERA_OK || list.is_null() { + ACameraManager_delete(manager); + return Err("could not enumerate cameras — is HEADSET_CAMERA granted?".into()); + } + let ids = std::slice::from_raw_parts((*list).camera_ids, (*list).num_cameras as usize); + log::info!("{} cameras visible", ids.len()); + + let candidates = Self::candidates(manager, ids, eye, capture); + if candidates.is_empty() { + ACameraManager_deleteCameraIdList(list); + ACameraManager_delete(manager); + return Err("no outward-facing camera offers the requested format".into()); + } + + // --- Reader and its surface --- + let mut reader: *mut AImageReader = std::ptr::null_mut(); + if AImageReader_new( + capture.0, + capture.1, + AIMAGE_FORMAT_YUV_420_888, + // A small queue: we always take the newest frame and drop + // the rest, so depth only adds latency. + 4, + &mut reader, + ) != AMEDIA_OK + { + ACameraManager_deleteCameraIdList(list); + ACameraManager_delete(manager); + return Err("AImageReader_new failed".into()); + } + let mut window: *mut ANativeWindow = std::ptr::null_mut(); + AImageReader_getWindow(reader, &mut window); + + // --- Open the device --- + let mut callbacks = ACameraDeviceStateCallbacks { + context: std::ptr::null_mut(), + on_disconnected, + on_error, + }; + // Try each candidate in preference order. Which camera id maps + // to which physical sensor is not documented, and some are + // restricted in ways that only surface at open time, so trying + // beats predicting. + let mut device: *mut ACameraDevice = std::ptr::null_mut(); + let mut last = ACAMERA_OK; + for &id in &candidates { + let status = ACameraManager_openCamera(manager, id, &mut callbacks, &mut device); + if status == ACAMERA_OK && !device.is_null() { + log::info!("opened camera {:?}", std::ffi::CStr::from_ptr(id)); + break; + } + log::warn!( + "camera {:?} would not open: {} ({status})", + std::ffi::CStr::from_ptr(id), + camera_error(status) + ); + last = status; + device = std::ptr::null_mut(); + } + ACameraManager_deleteCameraIdList(list); + if device.is_null() { + AImageReader_delete(reader); + ACameraManager_delete(manager); + return Err(format!( + "no camera would open; last error {} ({last}){}", + camera_error(last), + if last == -10013 { + " — HEADSET_CAMERA is a runtime permission and must be \ + granted, and passthrough must be enabled" + } else { + "" + } + )); + } + + // --- Session and repeating request --- + let mut container: *mut ACaptureSessionOutputContainer = std::ptr::null_mut(); + ACaptureSessionOutputContainer_create(&mut container); + let mut output: *mut ACaptureSessionOutput = std::ptr::null_mut(); + ACaptureSessionOutput_create(window, &mut output); + ACaptureSessionOutputContainer_add(container, output); + + let session_cb = ACameraCaptureSessionStateCallbacks { + context: std::ptr::null_mut(), + on_closed: on_session, + on_ready: on_session, + on_active: on_session, + }; + let mut session: *mut ACameraCaptureSession = std::ptr::null_mut(); + if ACameraDevice_createCaptureSession(device, container, &session_cb, &mut session) + != ACAMERA_OK + { + return Err("createCaptureSession failed".into()); + } + + let mut request: *mut ACaptureRequest = std::ptr::null_mut(); + ACameraDevice_createCaptureRequest(device, TEMPLATE_PREVIEW, &mut request); + let mut target: *mut ACameraOutputTarget = std::ptr::null_mut(); + ACameraOutputTarget_create(window, &mut target); + ACaptureRequest_addTarget(request, target); + + let mut requests = [request]; + if ACameraCaptureSession_setRepeatingRequest( + session, + std::ptr::null_mut(), + 1, + requests.as_mut_ptr(), + std::ptr::null_mut(), + ) != ACAMERA_OK + { + return Err("setRepeatingRequest failed".into()); + } + + log::info!( + "passthrough camera streaming {}x{} -> {size}x{size}", + capture.0, + capture.1 + ); + Ok(Self { + manager, + device, + session, + request, + target, + output, + container, + reader, + size, + // Mid-grey until the first frame lands, so a stalled camera + // is visibly "no data" rather than black. + buf: vec![128; size * size * 3], + have_frame: false, + eye, + capture, + last_reopen: Instant::now(), + }) + } + } + + /// Find the passthrough camera for the requested eye. + /// + /// Meta identifies these with vendor tags, but resolving a vendor tag + /// needs `ACameraManager_getTagFromName`, which Horizon OS v205 does not + /// export — and merely *linking* it prevents the library from loading at + /// all. So the cameras are identified by capability instead: the + /// passthrough pair are the ones offering the requested YUV420 size. + /// Among those, the list order is left then right, matching how Meta + /// numbers them. + unsafe fn candidates( + manager: *mut ACameraManager, + ids: &[*const c_char], + eye: Eye, + capture: (i32, i32), + ) -> Vec<*const c_char> { + unsafe { + let mut matching = Vec::new(); + for &id in ids { + let mut md: *mut ACameraMetadata = std::ptr::null_mut(); + if ACameraManager_getCameraCharacteristics(manager, id, &mut md) != ACAMERA_OK { + continue; + } + + let mut entry = ACameraMetadataConstEntry { + tag: 0, + kind: 0, + count: 0, + data: std::ptr::null(), + }; + let facing = (ACameraMetadata_getConstEntry(md, ACAMERA_LENS_FACING, &mut entry) + == ACAMERA_OK + && entry.count > 0) + .then(|| *entry.data); + + let mut supported = false; + let mut entry = ACameraMetadataConstEntry { + tag: 0, + kind: 0, + count: 0, + data: std::ptr::null(), + }; + if ACameraMetadata_getConstEntry( + md, + ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, + &mut entry, + ) == ACAMERA_OK + && !entry.data.is_null() + { + // int32[n * 4]: format, width, height, is-input. + let values = + std::slice::from_raw_parts(entry.data as *const i32, entry.count as usize); + supported = values.chunks_exact(4).any(|c| { + c[0] == AIMAGE_FORMAT_YUV_420_888 + && c[1] == capture.0 + && c[2] == capture.1 + && c[3] == 0 + }); + } + ACameraMetadata_free(md); + + log::info!( + "camera {:?}: facing={facing:?} offers {}x{} YUV420: {supported}", + std::ffi::CStr::from_ptr(id), + capture.0, + capture.1 + ); + if supported { + matching.push((id, facing)); + } + } + + // Outward-facing first, and within that the requested eye + // first — but keep the rest as fallbacks, since the mapping + // from camera id to physical sensor is undocumented. + let (mut outward, inward): (Vec<_>, Vec<_>) = matching + .into_iter() + .partition(|&(_, facing)| facing == Some(LENS_FACING_BACK)); + + let wanted = eye.position() as usize; + if wanted < outward.len() { + outward.swap(0, wanted); + } + let ordered: Vec<*const c_char> = outward + .into_iter() + .chain(inward) + .map(|(id, _)| id) + .collect(); + + if ordered.is_empty() { + log::warn!( + "no camera advertises {}x{} YUV420; trying all of them", + capture.0, + capture.1 + ); + return ids.to_vec(); + } + ordered + } + } + + /// Pull the newest frame, converting YUV420 to a square RGB crop. + fn pump(&mut self) -> bool { + unsafe { + let mut image: *mut AImage = std::ptr::null_mut(); + if AImageReader_acquireLatestImage(self.reader, &mut image) != AMEDIA_OK + || image.is_null() + { + return false; + } + + let (mut w, mut h) = (0i32, 0i32); + AImage_getWidth(image, &mut w); + AImage_getHeight(image, &mut h); + + let plane = |index: c_int| -> Option<(*mut u8, usize, usize)> { + let (mut data, mut len) = (std::ptr::null_mut(), 0); + if AImage_getPlaneData(image, index, &mut data, &mut len) != AMEDIA_OK { + return None; + } + let (mut row, mut pixel) = (0i32, 0i32); + AImage_getPlaneRowStride(image, index, &mut row); + AImage_getPlanePixelStride(image, index, &mut pixel); + Some((data, row as usize, pixel.max(1) as usize)) + }; + + let (Some((y_data, y_row, _)), Some((u_data, u_row, u_pix)), Some((v_data, v_row, v_pix))) = + (plane(0), plane(1), plane(2)) + else { + AImage_delete(image); + return false; + }; + + yuv420_to_square_rgb( + YuvPlanes { + y: y_data, + y_row, + u: u_data, + u_row, + u_pix, + v: v_data, + v_row, + v_pix, + }, + w as usize, + h as usize, + self.size, + &mut self.buf, + ); + AImage_delete(image); + self.have_frame = true; + true + } + } +} + +impl Drop for PassthroughCamera { + fn drop(&mut self) { + unsafe { + if !self.session.is_null() { + ACameraCaptureSession_close(self.session); + } + if !self.request.is_null() { + ACaptureRequest_free(self.request); + } + if !self.target.is_null() { + ACameraOutputTarget_free(self.target); + } + if !self.container.is_null() { + ACaptureSessionOutputContainer_free(self.container); + } + if !self.output.is_null() { + ACaptureSessionOutput_free(self.output); + } + if !self.device.is_null() { + ACameraDevice_close(self.device); + } + if !self.reader.is_null() { + AImageReader_delete(self.reader); + } + if !self.manager.is_null() { + ACameraManager_delete(self.manager); + } + } + } +} + +impl FrameSource for PassthroughCamera { + fn size(&self) -> usize { + self.size + } + + fn next_frame(&mut self) -> Option<&[u8]> { + // Taking the headset off disables the camera, which is a normal + // thing to do rather than a fatal one. Reopen instead of freezing + // on the last frame forever. + if DEVICE_ERROR.load(Ordering::Acquire) + && self.last_reopen.elapsed() >= REOPEN_INTERVAL + { + self.last_reopen = Instant::now(); + match Self::new(self.size, self.eye, self.capture) { + Ok(mut fresh) => { + // Carry the last good frame across so the view does not + // flash grey on every reopen. + std::mem::swap(&mut fresh.buf, &mut self.buf); + fresh.have_frame = self.have_frame; + DEVICE_ERROR.store(false, Ordering::Release); + // Dropping the old value closes the previous handles. + *self = fresh; + log::info!("camera reopened"); + } + Err(e) => log::warn!("camera reopen failed: {e}"), + } + } + + // A frame may not have arrived since the last call; showing the + // previous one beats stalling the pipeline. + self.pump(); + self.have_frame.then_some(&self.buf[..]) + } +} + +struct YuvPlanes { + y: *mut u8, + y_row: usize, + u: *mut u8, + u_row: usize, + u_pix: usize, + v: *mut u8, + v_row: usize, + v_pix: usize, +} + +/// Resample the *whole* YUV420 frame into a square RGB buffer. +/// +/// Deliberately not a centre crop. The encoder needs a square, but cropping +/// 1280×960 to 960×960 throws away a quarter of the horizontal field of +/// view, and the point of this app is to show what the camera saw. Squashing +/// the full frame instead keeps all of it; the aspect is restored at display +/// time by drawing the quad at the camera's real 4:3 shape, so nothing ends +/// up stretched on screen. DINO sees a horizontally compressed image, which +/// costs a little feature quality and is a far better trade than losing the +/// periphery. +/// +/// Box-averages luma over each destination pixel's source footprint — +/// point-sampling 960 down to 224 aliases badly enough to change what the +/// patch embedding sees. Chroma is sampled at the centre, which is +/// imperceptible after a 4× reduction and halves the work. +/// +/// # Safety +/// +/// The plane pointers must be valid for the given strides and dimensions. +unsafe fn yuv420_to_square_rgb( + p: YuvPlanes, + width: usize, + height: usize, + size: usize, + out: &mut [u8], +) { + for oy in 0..size { + let sy0 = oy * height / size; + let sy1 = ((oy + 1) * height / size).max(sy0 + 1).min(height); + for ox in 0..size { + let sx0 = ox * width / size; + let sx1 = ((ox + 1) * width / size).max(sx0 + 1).min(width); + + let mut acc = 0u32; + let mut n = 0u32; + for sy in sy0..sy1 { + let row = unsafe { p.y.add(sy * p.y_row) }; + for sx in sx0..sx1 { + acc += unsafe { *row.add(sx) } as u32; + n += 1; + } + } + let luma = (acc / n.max(1)) as f32; + + // Chroma planes are half resolution in both axes. + let cx = ((sx0 + sx1) / 2) / 2; + let cy = ((sy0 + sy1) / 2) / 2; + let u = unsafe { *p.u.add(cy * p.u_row + cx * p.u_pix) } as f32 - 128.0; + let v = unsafe { *p.v.add(cy * p.v_row + cx * p.v_pix) } as f32 - 128.0; + + // BT.601, which is what Camera2 delivers. + let r = luma + 1.402 * v; + let g = luma - 0.344_136 * u - 0.714_136 * v; + let b = luma + 1.772 * u; + + let o = (oy * size + ox) * 3; + out[o] = r.clamp(0.0, 255.0) as u8; + out[o + 1] = g.clamp(0.0, 255.0) as u8; + out[o + 2] = b.clamp(0.0, 255.0) as u8; + } + } +} diff --git a/environment/publication-source/source-snapshot/src/decoder.rs b/environment/publication-source/source-snapshot/src/decoder.rs new file mode 100644 index 0000000000000000000000000000000000000000..fd7c413f8558cca42db2d9640d8c164fcda16d24 --- /dev/null +++ b/environment/publication-source/source-snapshot/src/decoder.rs @@ -0,0 +1,385 @@ +//! Reconstructing RGB from DINOv3 patch features. +//! +//! This is the roundtrip the project is named for: encode an image to +//! features, decode those features back to pixels, and look at what +//! survived. +//! +//! # What to expect +//! +//! At 224² the encoder produces a 14×14 grid of 384-dimensional features — +//! about 75k numbers standing in for a 150k-value image. That alone would +//! permit a decent reconstruction, but DINOv3 features are trained for +//! *semantic invariance*: two views of the same object should land in the +//! same place regardless of colour, lighting, or fine texture, which means +//! precisely that information is discarded on purpose. So the reconstruction +//! recovers layout and dominant colour well and fine detail poorly. That is +//! the interesting result, not a defect in the decoder. +//! +//! # Shape +//! +//! A plain convolutional upsampler, four stages of ×2 from 14 to 224: +//! +//! ```text +//! [384, 14, 14] → 256@28 → 128@56 → 64@112 → 32@224 → 3@224 +//! ``` +//! +//! 2.01M parameters and about 1.14 GMAC per image. The early two stages use +//! a second convolution to blend patch seams; the later stages do not. +//! +//! No skip connections and nothing fancy: the point is to measure what the +//! features carry, and a decoder with its own access to the input would +//! confuse that question entirely. + +use meganeura::{Graph, NodeId}; + +use crate::dinov3::Config; + +/// Channel widths after each upsampling stage, from the feature grid up. +pub const STAGES: [usize; 4] = [256, 128, 64, 32]; +/// How many of the early stages get a second convolution. Seams originate +/// at the patch grid, so blending earns its cost at low resolution and +/// mostly smooths detail away at high resolution. +pub const BLEND_STAGES: usize = 2; +/// Channels per group in the group norms. +const GROUP_SIZE: usize = 16; +const EPS: f32 = 1e-5; + +/// Total parameter count, for reporting and for sizing a weights file. +pub fn parameter_count(config: &Config) -> usize { + let mut total = 0; + let mut in_c = config.hidden_size; + for (i, &out_c) in STAGES.iter().enumerate() { + total += out_c * in_c * 9 + out_c + out_c * 2; + if i < BLEND_STAGES { + total += out_c * out_c * 9 + out_c + out_c * 2; + } + in_c = out_c; + } + total += 3 * in_c * 9 + 3; // final projection to RGB + total +} + +/// Multiply-accumulates in the decoder's convolution kernels at batch one. +/// Bias, normalization, activations, and upsampling are intentionally not +/// folded into this number; timing still includes every operation. +pub fn forward_macs(config: &Config) -> u64 { + let mut total = 0u64; + let mut in_c = config.hidden_size; + let mut hw = config.grid(); + for (i, &out_c) in STAGES.iter().enumerate() { + total += (out_c * in_c * 9 * hw * hw) as u64; + if i < BLEND_STAGES { + total += (out_c * out_c * 9 * hw * hw) as u64; + } + hw *= 2; + in_c = out_c; + } + total + (3 * in_c * 9 * hw * hw) as u64 +} + +/// One `conv3x3 → bias → group-norm → SiLU` block at a fixed resolution. +fn block( + g: &mut Graph, + x: NodeId, + name: &str, + batch: usize, + in_c: usize, + out_c: usize, + hw: usize, +) -> NodeId { + let kernel = g.parameter(&format!("{name}.weight"), &[out_c, in_c, 3, 3]); + let x = g.conv2d( + x, + kernel, + batch as u32, + in_c as u32, + hw as u32, + hw as u32, + out_c as u32, + 3, + 3, + 1, + 1, + ); + let bias = g.parameter(&format!("{name}.bias"), &[out_c]); + let x = g.add_per_channel(x, bias, out_c as u32, (hw * hw) as u32); + + let gn_w = g.parameter(&format!("{name}.norm.weight"), &[out_c]); + let gn_b = g.parameter(&format!("{name}.norm.bias"), &[out_c]); + let x = g.group_norm( + x, + gn_w, + gn_b, + batch as u32, + out_c as u32, + (hw * hw) as u32, + (out_c / GROUP_SIZE) as u32, + EPS, + ); + g.silu(x) +} + +/// Build the decoder over an existing feature node. +/// +/// `features` must be `[batch, hidden, grid, grid]` flattened NCHW — patch +/// tokens only, transposed out of the encoder's token-major layout. See +/// [`patch_features_to_nchw`]. +/// +/// Returns `[batch, 3, image_size, image_size]` in `[0, 1]`. +pub fn build_decoder(g: &mut Graph, config: &Config, features: NodeId, batch: usize) -> NodeId { + let mut x = features; + let mut in_c = config.hidden_size; + let mut hw = config.grid(); + + for (i, &out_c) in STAGES.iter().enumerate() { + x = block(g, x, &format!("dec.{i}"), batch, in_c, out_c, hw); + // A second convolution, but only where it pays for itself. + // + // The seams come from the input being piecewise constant — one + // feature vector per 16×16 patch — so hiding them needs a receptive + // field wide enough to mix across cells, and one 3×3 per scale + // reaches only a single neighbour. Doing that at *every* scale + // removed the tiling but doubled the decoder, and the decoder is + // ~40% of the frame on device. + // + // Each stage halves the channels and doubles the resolution, so all + // four second convolutions cost the same. The early ones are where + // patch boundaries actually live; by 56² and beyond the grid has + // already been blended and the extra pass mostly smooths detail + // away. Keeping the first two buys the seam repair for half the + // price. + if i < BLEND_STAGES { + x = block(g, x, &format!("dec.{i}b"), batch, out_c, out_c, hw); + } + x = g.upsample_2x(x, batch as u32, out_c as u32, hw as u32, hw as u32); + hw *= 2; + in_c = out_c; + } + assert_eq!( + hw, config.image_size, + "stage count does not reach the image resolution" + ); + + let kernel = g.parameter("dec.out.weight", &[3, in_c, 3, 3]); + let x = g.conv2d( + x, + kernel, + batch as u32, + in_c as u32, + hw as u32, + hw as u32, + 3, + 3, + 3, + 1, + 1, + ); + let bias = g.parameter("dec.out.bias", &[3]); + let x = g.add_per_channel(x, bias, 3, (hw * hw) as u32); + // Sigmoid rather than a clamp: pixels live in [0, 1] and a hard clamp + // has zero gradient outside the range, which strands any channel that + // starts saturated. + g.sigmoid(x) +} + +/// Attach the decoder directly to a live encoder output. +/// +/// Does in the graph what [`patch_features_to_nchw`] does on the CPU: drop +/// the prefix tokens and transpose from the encoder's token-major layout to +/// the channel-major one convolution needs. Batch 1 only — that is what +/// inference runs. +pub fn attach_to_encoder(g: &mut Graph, config: &Config, encoder_out: NodeId) -> NodeId { + let hidden = config.hidden_size; + let patches = config.num_patches(); + let prefix = config.num_prefix_tokens(); + + // Slice off CLS and the register tokens. They carry global rather than + // spatial information and have no place on a feature map. + let patch_tokens = g.split_b( + encoder_out, + 1, + (prefix * hidden) as u32, + (patches * hidden) as u32, + 1, + ); + let patch_tokens = g.reshape(patch_tokens, &[patches, hidden]); + let planes = g.transpose(patch_tokens); + let planes = g.reshape(planes, &[hidden * patches]); + build_decoder(g, config, planes, 1) +} + +/// Load parameters written by `examples/train_decoder.rs`. +/// +/// The file is raw f32 in graph declaration order, so it is only valid for +/// the graph shape that produced it; a length mismatch means the decoder +/// architecture changed and the weights are stale. +pub fn load_parameters( + session: &mut meganeura::Session, + graph: &Graph, + path: &std::path::Path, +) -> Result<(), Box> { + let bytes = std::fs::read(path)?; + let values: Vec = bytes + .chunks_exact(4) + .map(|c| f32::from_le_bytes([c[0], c[1], c[2], c[3]])) + .collect(); + + let mut offset = 0; + let mut loaded = 0; + for node in graph.nodes() { + let meganeura::graph::Op::Parameter { name } = &node.op else { + continue; + }; + // Only decoder parameters live in this file; the encoder's come + // from the checkpoint. + if !name.starts_with("dec.") { + continue; + } + let n = node.ty.num_elements(); + if offset + n > values.len() { + return Err(format!( + "{} is too short: needed {} values by parameter '{name}', have {}", + path.display(), + offset + n, + values.len() + ) + .into()); + } + session.set_parameter(name, &values[offset..offset + n]); + offset += n; + loaded += 1; + } + if offset != values.len() { + return Err(format!( + "{} has {} values but the graph consumed {offset}; the decoder \ + architecture and the weights disagree", + path.display(), + values.len() + ) + .into()); + } + log::info!("loaded {loaded} decoder parameters from {}", path.display()); + Ok(()) +} + +/// Rearrange the encoder's `[tokens, hidden]` output into the `[hidden, +/// grid, grid]` NCHW block the decoder consumes, dropping the CLS and +/// register tokens. +/// +/// The encoder is token-major (each row one token); convolution wants +/// channel-major. Done on the CPU here because it happens once per image +/// during dataset preparation; the live path folds it into the graph. +pub fn patch_features_to_nchw(features: &[f32], config: &Config) -> Vec { + let hidden = config.hidden_size; + let patches = config.num_patches(); + let skip = config.num_prefix_tokens(); + assert_eq!(features.len(), config.num_tokens() * hidden); + + let mut out = vec![0.0f32; hidden * patches]; + for p in 0..patches { + let src = (skip + p) * hidden; + for c in 0..hidden { + out[c * patches + p] = features[src + c]; + } + } + out +} + +/// Peak signal-to-noise ratio in dB between two `[0, 1]` images. +/// +/// The number to quote for reconstruction quality. Roughly: below 15 dB is +/// unrecognizable, 20 dB is a recognizable blur, 30 dB is visually close. +pub fn psnr(a: &[f32], b: &[f32]) -> f32 { + assert_eq!(a.len(), b.len()); + let mse: f64 = a + .iter() + .zip(b) + .map(|(x, y)| { + let d = (x - y) as f64; + d * d + }) + .sum::() + / a.len() as f64; + if mse <= f64::EPSILON { + return f32::INFINITY; + } + (10.0 * (1.0 / mse).log10()) as f32 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn stages_reach_the_image_resolution() { + let c = Config::vits16(); + assert_eq!(c.grid() * 2usize.pow(STAGES.len() as u32), c.image_size); + } + + #[test] + fn every_stage_divides_into_groups() { + for &c in &STAGES { + assert_eq!(c % GROUP_SIZE, 0, "{c} channels do not group evenly"); + } + } + + #[test] + fn parameter_count_is_modest() { + let n = parameter_count(&Config::vits16()); + assert!( + (1_000_000..4_000_000).contains(&n), + "unexpected decoder size: {n}" + ); + } + + #[test] + fn forward_macs_match_the_deployed_decoder() { + let c = Config::vits16().at_resolution(224).with_layers(3); + assert_eq!(forward_macs(&c), 1_141_604_352); + } + + #[test] + fn graph_builds_with_the_right_output_shape() { + let c = Config::vits16(); + let mut g = Graph::new(); + let feat = g.input("feat", &[c.hidden_size * c.num_patches()]); + let out = build_decoder(&mut g, &c, feat, 1); + assert_eq!( + g.node(out).ty.num_elements(), + 3 * c.image_size * c.image_size + ); + } + + /// The NCHW rearrangement must move each token's channel `c` to plane + /// `c` at the token's grid position, and must skip the prefix tokens. + #[test] + fn nchw_rearrangement_is_a_transpose_past_the_prefix() { + let c = Config::vits16(); + let h = c.hidden_size; + // Encode each value as token*1000 + channel so the mapping is + // checkable by arithmetic. + let features: Vec = (0..c.num_tokens() * h) + .map(|i| ((i / h) * 1000 + (i % h)) as f32) + .collect(); + let nchw = patch_features_to_nchw(&features, &c); + assert_eq!(nchw.len(), h * c.num_patches()); + + for &(p, ch) in &[(0usize, 0usize), (37, 5), (195, 383)] { + let token = c.num_prefix_tokens() + p; + assert_eq!( + nchw[ch * c.num_patches() + p], + (token * 1000 + ch) as f32, + "patch {p} channel {ch} came from the wrong token" + ); + } + } + + #[test] + fn psnr_behaves() { + let a = vec![0.5f32; 100]; + assert!(psnr(&a, &a).is_infinite(), "identical images are lossless"); + // A uniform 0.1 error is MSE 0.01, i.e. 20 dB. + let b: Vec = a.iter().map(|v| v + 0.1).collect(); + assert!((psnr(&a, &b) - 20.0).abs() < 0.1); + } +} diff --git a/environment/publication-source/source-snapshot/src/dinov3.rs b/environment/publication-source/source-snapshot/src/dinov3.rs new file mode 100644 index 0000000000000000000000000000000000000000..93ed9c3e012603ae083746ccb27ee41241c7cad5 --- /dev/null +++ b/environment/publication-source/source-snapshot/src/dinov3.rs @@ -0,0 +1,519 @@ +//! DINOv3 ViT encoder, expressed directly in meganeura's graph IR. +//! +//! Built by hand rather than imported: `meganeura::load_onnx` currently +//! recognizes only `Add`, `Gemm`, `MatMul`, and `Relu`, which is nowhere +//! near enough for a ViT. Every op this needs already exists in the IR, +//! so the graph is a faithful transcription of +//! `transformers/models/dinov3_vit/modeling_dinov3_vit.py`. +//! +//! Three things distinguish DINOv3 from a garden-variety ViT, and each is +//! handled below: +//! +//! 1. **No learned position embedding.** Position enters only as 2D axial +//! RoPE applied to Q and K inside every layer. +//! 2. **Prefix tokens.** A CLS token and `num_register_tokens` register +//! tokens are prepended to the patch tokens, and RoPE deliberately +//! skips them. +//! 3. **LayerScale.** Each residual branch is scaled by a learned +//! per-channel vector before being added back. + +use meganeura::{Graph, NodeId}; + +/// Architecture hyperparameters, mirroring HuggingFace's `DINOv3ViTConfig`. +#[derive(Debug, Clone)] +pub struct Config { + pub hidden_size: usize, + pub num_hidden_layers: usize, + pub num_attention_heads: u32, + pub intermediate_size: usize, + pub num_register_tokens: usize, + pub patch_size: usize, + /// Side length in pixels of the (square) input the graph is compiled + /// for. RoPE lets the real model take any size, but a meganeura graph + /// has static shapes, so one session serves one resolution. + pub image_size: usize, + pub layer_norm_eps: f32, + pub rope_theta: f32, + /// `false` selects the plain GELU MLP; DINOv3 only gates on ViT-L and + /// larger. Gated MLPs are not implemented here yet. + pub use_gated_mlp: bool, + /// Store the projection weights as f16, halving weight traffic from + /// 86 MB to 43 MB per forward pass. + /// + /// Storage only — meganeura's generated matmul reads `array` and + /// converts to f32 for the arithmetic, so this buys bandwidth, not ALU + /// rate. Whether that helps depends on which of the two the device is + /// short of; measure with `examples/bench` rather than assuming. + /// + /// Norms, biases, and LayerScale stay f32: they are a rounding error in + /// size and the most precision-sensitive parts of the network. + pub f16_weights: bool, +} + +impl Config { + /// `facebook/dinov3-vits16-pretrain-lvd1689m` — 21M parameters. + pub fn vits16() -> Self { + Self { + hidden_size: 384, + num_hidden_layers: 12, + num_attention_heads: 6, + intermediate_size: 1536, + num_register_tokens: 4, + patch_size: 16, + image_size: 224, + layer_norm_eps: 1e-5, + rope_theta: 100.0, + use_gated_mlp: false, + f16_weights: false, + } + } + + /// Enable f16 weight storage. See [`Config::f16_weights`]. + pub fn with_f16_weights(mut self, enabled: bool) -> Self { + self.f16_weights = enabled; + self + } + + /// Keep only the first `n` transformer layers. + /// + /// The deployment case study uses three layers to bound mobile work. Its + /// decoder is trained specifically against that representation; decoder + /// weights are not interchangeable across depths. `n = 0` is retained as + /// an embedding-plus-final-norm diagnostic for reference validation. + pub fn with_layers(mut self, n: usize) -> Self { + assert!(n <= 12, "DINOv3 ViT-S/16 has 12 layers, not {n}"); + self.num_hidden_layers = n; + self + } + + /// Same weights, different input resolution. The patch grid scales + /// with it, so cost grows quadratically — 224 gives a 14×14 grid at + /// ~4.6 GMAC, 448 gives 28×28 at ~4× that. + pub fn at_resolution(mut self, image_size: usize) -> Self { + assert_eq!( + image_size % self.patch_size, + 0, + "image_size {image_size} is not a multiple of patch_size {}", + self.patch_size + ); + self.image_size = image_size; + self + } + + pub fn head_dim(&self) -> u32 { + self.hidden_size as u32 / self.num_attention_heads + } + + /// Patches along one side of the image — the feature grid resolution. + pub fn grid(&self) -> usize { + self.image_size / self.patch_size + } + + pub fn num_patches(&self) -> usize { + self.grid() * self.grid() + } + + /// CLS + register tokens, which sit ahead of the patch tokens. + pub fn num_prefix_tokens(&self) -> usize { + 1 + self.num_register_tokens + } + + pub fn num_tokens(&self) -> usize { + self.num_prefix_tokens() + self.num_patches() + } + + /// Length of one flattened patch: `3 * patch_size²`. + pub fn patch_dim(&self) -> usize { + 3 * self.patch_size * self.patch_size + } + + /// Multiply-accumulate count for one forward pass, for sanity-checking + /// measured throughput against achievable device throughput. + pub fn forward_macs(&self) -> u64 { + let t = self.num_tokens() as u64; + let d = self.hidden_size as u64; + let ff = self.intermediate_size as u64; + let per_layer = + // Q, K, V, and output projections + 4 * t * d * d + // scores and the value-weighted sum + + 2 * t * t * d + // MLP up and down + + 2 * t * d * ff; + let patch_projection = self.num_patches() as u64 * self.patch_dim() as u64 * d; + self.num_hidden_layers as u64 * per_layer + patch_projection + } +} + +/// Precomputed 2D axial RoPE tables, each `[num_tokens, hidden_size]`. +/// +/// Two deviations from a literal transcription, both deliberate: +/// +/// * Prefix rows are `(cos, sin) = (1, 0)`, making the rotation an +/// identity there. DINOv3 skips RoPE on CLS and register tokens by +/// slicing the token dimension; encoding it as data instead keeps the +/// graph free of token-dimension splits. +/// * The per-head table is replicated across all heads, so the tables +/// multiply Q and K elementwise with no per-head indexing. +/// +/// The coordinate jitter/shift/rescale in the reference is training-only +/// (`if self.training`), so `pos_embed_rescale` is correctly ignored here. +pub fn rope_tables(config: &Config) -> (Vec, Vec) { + let head_dim = config.head_dim() as usize; + // inv_freq has head_dim/4 entries: half the rotated pairs go to the + // y axis and half to x. + let quarter = head_dim / 4; + let half = head_dim / 2; + let heads = config.num_attention_heads as usize; + let hidden = config.hidden_size; + let grid = config.grid(); + + // inv_freq = 1 / theta^linspace(0, 1, head_dim/4) + let inv_freq: Vec = (0..quarter) + .map(|i| 1.0 / config.rope_theta.powf(i as f32 * 4.0 / head_dim as f32)) + .collect(); + + let mut cos = vec![0.0f32; config.num_tokens() * hidden]; + let mut sin = vec![0.0f32; config.num_tokens() * hidden]; + + // Identity rotation over the prefix tokens. + for t in 0..config.num_prefix_tokens() { + for c in 0..hidden { + cos[t * hidden + c] = 1.0; + sin[t * hidden + c] = 0.0; + } + } + + let mut angles = vec![0.0f32; half]; + for py in 0..grid { + for px in 0..grid { + // Patch-center coordinates normalized to [-1, +1]. The + // reference stacks them (y, x), and that order decides which + // half of the rotated pairs encodes which axis. + let y = 2.0 * ((py as f32 + 0.5) / grid as f32) - 1.0; + let x = 2.0 * ((px as f32 + 0.5) / grid as f32) - 1.0; + for i in 0..quarter { + angles[i] = std::f32::consts::TAU * y * inv_freq[i]; + angles[quarter + i] = std::f32::consts::TAU * x * inv_freq[i]; + } + + let t = config.num_prefix_tokens() + py * grid + px; + let row = t * hidden; + for h in 0..heads { + for d in 0..head_dim { + // `angles.tile(2)`: the upper half repeats the lower, + // which is what pairs dimension d with d + head_dim/2 + // under `rotate_half`. + let a = angles[d % half]; + cos[row + h * head_dim + d] = a.cos(); + sin[row + h * head_dim + d] = a.sin(); + } + } + } + } + + (cos, sin) +} + +/// `x * cos + rotate_half(x) * sin`, where +/// `rotate_half([x1, x2]) = [-x2, x1]` splits each head's `head_dim` in +/// two. +/// +/// Q and K arrive from `matmul` as `[tokens, heads * head_dim]`, and +/// meganeura's attention reads head `h` of token `t` at +/// `t * heads * head_dim + h * head_dim` — head-major, so each head's +/// slice is contiguous. That lets the split treat the tensor as +/// `tokens * heads` independent blocks of `head_dim`, with no transpose. +fn apply_rope( + g: &mut Graph, + x: NodeId, + cos: NodeId, + sin: NodeId, + tokens: usize, + heads: u32, + head_dim: u32, +) -> NodeId { + let hidden = (heads * head_dim) as usize; + let blocks = tokens as u32 * heads; + let half = head_dim / 2; + + let x1 = g.split_a(x, blocks, half, half, 1); + let x2 = g.split_b(x, blocks, half, half, 1); + let neg_x2 = g.neg(x2); + let rotated = g.concat(neg_x2, x1, blocks, half, half, 1); + let rotated = g.reshape(rotated, &[tokens, hidden]); + + let straight = g.mul(x, cos); + let crossed = g.mul(rotated, sin); + g.add(straight, crossed) +} + +/// Apply a learned gain to the trailing hidden dimension of a +/// `[tokens, hidden]` matrix. +/// +/// Meganeura's `mul_per_channel` follows NCHW layout and indexes its gate as +/// `linear_index / spatial`; using it directly with `spatial = 1` would read +/// beyond the hidden-sized gate after the first token. Transposing to +/// `[hidden, tokens]` makes each hidden coordinate an NCHW channel, with all +/// tokens as its spatial extent, and therefore gives the LayerScale broadcast +/// used by the reference implementation. +fn layer_scale(g: &mut Graph, x: NodeId, gain: NodeId, tokens: usize, hidden: usize) -> NodeId { + let hidden_by_tokens = g.transpose(x); + // `mul_per_channel` is an NCHW-flat operator. Keeping the two-dimensional + // transpose shape would make its compiler interpret only the first axis + // as the element count. + let flat = g.reshape(hidden_by_tokens, &[hidden * tokens]); + let scaled = g.mul_per_channel(flat, gain, hidden as u32, tokens as u32); + let scaled = g.reshape(scaled, &[hidden, tokens]); + g.transpose(scaled) +} + +/// Build the encoder and return the final `[num_tokens, hidden_size]` +/// feature node. +/// +/// Declares one input, `"patches"`, of shape `[num_patches, patch_dim]` — +/// see [`crate::preprocess`] for the layout it expects. Parameter names +/// match the HuggingFace checkpoint so [`crate::weights`] can bind them +/// directly. +/// +/// Row 0 of the output is the CLS token, rows `1..=num_register_tokens` +/// are the registers, and the patch features follow in row-major grid +/// order. +pub fn build_encoder(g: &mut Graph, config: &Config) -> NodeId { + assert!( + !config.use_gated_mlp, + "gated MLP (ViT-L and larger) is not implemented" + ); + + let hidden = config.hidden_size; + let eps = config.layer_norm_eps; + let heads = config.num_attention_heads; + let head_dim = config.head_dim(); + let tokens = config.num_tokens(); + let prefix = config.num_prefix_tokens(); + + // Projection weights, in whichever storage the config asks for. Only + // the large 2D matrices participate; everything else stays f32. + let weight = |g: &mut Graph, name: &str, shape: &[usize]| { + if config.f16_weights { + g.parameter_f16(name, shape) + } else { + g.parameter(name, shape) + } + }; + + // --- Patch embedding --- + // + // The reference applies a Conv2d with kernel == stride == patch_size, + // which is exactly a per-patch linear map. Feeding pre-flattened + // patches turns it into a single matmul and keeps the (cheap, + // memory-bound) patch extraction outside the graph, where a render + // pass can do it straight from the camera texture later. + let patches = g.input("patches", &[config.num_patches(), config.patch_dim()]); + let patch_w = g.parameter( + "embeddings.patch_embeddings.weight", + &[config.patch_dim(), hidden], + ); + let patch_b = g.parameter("embeddings.patch_embeddings.bias", &[hidden]); + let patch_embeds = g.matmul(patches, patch_w); + let patch_embeds = g.bias_add(patch_embeds, patch_b); + + // --- Prepend CLS + register tokens --- + // + // One `[prefix, hidden]` parameter rather than separate cls_token and + // register_tokens nodes: the loader concatenates them, which costs one + // memcpy offline and saves a concat per forward pass. + let prefix_tokens = g.parameter("prefix_tokens", &[prefix, hidden]); + let mut x = g.concat( + prefix_tokens, + patch_embeds, + 1, + (prefix * hidden) as u32, + (config.num_patches() * hidden) as u32, + 1, + ); + x = g.reshape(x, &[tokens, hidden]); + + // RoPE tables are the same for every layer and for both Q and K, so + // they become two constant buffers shared by all 24 uses. + let (cos_data, sin_data) = rope_tables(config); + let cos = g.constant(cos_data, &[tokens, hidden]); + let sin = g.constant(sin_data, &[tokens, hidden]); + + for i in 0..config.num_hidden_layers { + let p = format!("layer.{i}"); + + // --- Attention block --- + let n1_w = g.parameter(&format!("{p}.norm1.weight"), &[hidden]); + let n1_b = g.parameter(&format!("{p}.norm1.bias"), &[hidden]); + let h = g.layer_norm(x, n1_w, n1_b, eps); + + let wq = weight( + g, + &format!("{p}.attention.q_proj.weight"), + &[hidden, hidden], + ); + let bq = g.parameter(&format!("{p}.attention.q_proj.bias"), &[hidden]); + let wk = weight( + g, + &format!("{p}.attention.k_proj.weight"), + &[hidden, hidden], + ); + let wv = weight( + g, + &format!("{p}.attention.v_proj.weight"), + &[hidden, hidden], + ); + let bv = g.parameter(&format!("{p}.attention.v_proj.bias"), &[hidden]); + + let q = g.matmul(h, wq); + let q = g.bias_add(q, bq); + // `key_bias: false` in the config — K genuinely has no bias. + let k = g.matmul(h, wk); + let v = g.matmul(h, wv); + let v = g.bias_add(v, bv); + + let q = apply_rope(g, q, cos, sin, tokens, heads, head_dim); + let k = apply_rope(g, k, cos, sin, tokens, heads, head_dim); + + // Non-causal: every token attends to every other. meganeura + // scales by head_dim^-0.5 internally, matching the reference. + let attn = g.full_attention(q, k, v, heads, heads, head_dim); + + let wo = weight( + g, + &format!("{p}.attention.o_proj.weight"), + &[hidden, hidden], + ); + let bo = g.parameter(&format!("{p}.attention.o_proj.bias"), &[hidden]); + let attn = g.matmul(attn, wo); + let attn = g.bias_add(attn, bo); + + // LayerScale: learned gain over the trailing hidden dimension. + let ls1 = g.parameter(&format!("{p}.layer_scale1.lambda1"), &[hidden]); + let attn = layer_scale(g, attn, ls1, tokens, hidden); + x = g.add(x, attn); + + // --- MLP block --- + let n2_w = g.parameter(&format!("{p}.norm2.weight"), &[hidden]); + let n2_b = g.parameter(&format!("{p}.norm2.bias"), &[hidden]); + let h = g.layer_norm(x, n2_w, n2_b, eps); + + let up_w = weight( + g, + &format!("{p}.mlp.up_proj.weight"), + &[hidden, config.intermediate_size], + ); + let up_b = g.parameter( + &format!("{p}.mlp.up_proj.bias"), + &[config.intermediate_size], + ); + let down_w = weight( + g, + &format!("{p}.mlp.down_proj.weight"), + &[config.intermediate_size, hidden], + ); + let down_b = g.parameter(&format!("{p}.mlp.down_proj.bias"), &[hidden]); + + let m = g.matmul(h, up_w); + let m = g.bias_add(m, up_b); + let m = g.gelu(m); + let m = g.matmul(m, down_w); + let m = g.bias_add(m, down_b); + + let ls2 = g.parameter(&format!("{p}.layer_scale2.lambda1"), &[hidden]); + let m = layer_scale(g, m, ls2, tokens, hidden); + x = g.add(x, m); + } + + let n_w = g.parameter("norm.weight", &[hidden]); + let n_b = g.parameter("norm.bias", &[hidden]); + g.layer_norm(x, n_w, n_b, eps) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn vits16_shapes() { + let c = Config::vits16(); + assert_eq!(c.grid(), 14); + assert_eq!(c.num_patches(), 196); + assert_eq!(c.num_prefix_tokens(), 5); + assert_eq!(c.num_tokens(), 201); + assert_eq!(c.head_dim(), 64); + assert_eq!(c.patch_dim(), 768); + } + + #[test] + fn forward_macs_match_the_declared_matmuls() { + assert_eq!( + Config::vits16().with_layers(3).forward_macs(), + 1_217_878_272 + ); + assert_eq!(Config::vits16().forward_macs(), 4_698_104_832); + } + + #[test] + fn rope_prefix_rows_are_identity() { + let c = Config::vits16(); + let (cos, sin) = rope_tables(&c); + assert_eq!(cos.len(), c.num_tokens() * c.hidden_size); + for t in 0..c.num_prefix_tokens() { + for d in 0..c.hidden_size { + assert_eq!(cos[t * c.hidden_size + d], 1.0); + assert_eq!(sin[t * c.hidden_size + d], 0.0); + } + } + } + + #[test] + fn rope_replicates_across_heads_and_tiles_halves() { + let c = Config::vits16(); + let (cos, sin) = rope_tables(&c); + let hd = c.head_dim() as usize; + let half = hd / 2; + // Pick a patch token well away from the grid origin. + let row = (c.num_prefix_tokens() + 100) * c.hidden_size; + for d in 0..hd { + // Every head sees the same angle... + for h in 1..c.num_attention_heads as usize { + assert_eq!(cos[row + d], cos[row + h * hd + d]); + assert_eq!(sin[row + d], sin[row + h * hd + d]); + } + // ...and the upper half of each head repeats the lower half, + // which is what makes rotate_half pair d with d + half. + if d < half { + assert_eq!(cos[row + d], cos[row + d + half]); + assert_eq!(sin[row + d], sin[row + d + half]); + } + } + } + + #[test] + fn rope_center_of_grid_is_near_zero_angle() { + // A 14×14 grid has no patch exactly at the center, but the two + // straddling it must have opposite-signed angles. + let c = Config::vits16(); + let (_, sin) = rope_tables(&c); + let grid = c.grid(); + let hidden = c.hidden_size; + let lo = (c.num_prefix_tokens() + (grid / 2 - 1) * grid + grid / 2 - 1) * hidden; + let hi = (c.num_prefix_tokens() + (grid / 2) * grid + grid / 2) * hidden; + assert!( + sin[lo] < 0.0 && sin[hi] > 0.0, + "expected opposite signs straddling the grid center, got {} and {}", + sin[lo], + sin[hi] + ); + } + + #[test] + fn graph_builds_and_declares_expected_slots() { + let c = Config::vits16(); + let mut g = Graph::new(); + let out = build_encoder(&mut g, &c); + assert_eq!(g.node(out).ty.shape, vec![c.num_tokens(), c.hidden_size]); + } +} diff --git a/environment/publication-source/source-snapshot/src/inference.rs b/environment/publication-source/source-snapshot/src/inference.rs new file mode 100644 index 0000000000000000000000000000000000000000..8ce3644624e198a7b3608e27a31057de34273fa2 --- /dev/null +++ b/environment/publication-source/source-snapshot/src/inference.rs @@ -0,0 +1,370 @@ +//! The inference worker: a thread that owns the meganeura session and +//! publishes coloured feature grids for the renderer to display. +//! +//! # Why a thread at all +//! +//! The encoder is expected to take 40–60 ms on a Quest 3 while the +//! compositor wants a frame every 13.9 ms. Running inference inline would +//! put the render loop on the encoder's cadence, which is uncomfortable at +//! best. Instead the renderer runs free, always drawing the most recent +//! completed result, and inference lands whenever it lands. +//! +//! # Why the worker builds its own session +//! +//! `meganeura::Session` is not `Send` — it owns a `CommandEncoder` holding +//! raw Vulkan handles. It cannot be constructed here and moved. What *is* +//! shareable is `Arc`, so the worker receives the +//! context and builds the session in place. See `tests/threading.rs`. +//! +//! # The caveat this design cannot fix +//! +//! Both threads submit to the same Vulkan queue, which blade guards with a +//! mutex. A long compute submission can still delay the render submission +//! queued behind it — threading decouples *CPU* orchestration, not GPU +//! occupancy. Whether that shows up as dropped frames is exactly what the +//! on-device numbers will reveal; if it does, the fix is splitting the plan +//! across frames, which needs meganeura to grow partial execution +//! (`step()` currently submits every dispatch in one go). + +use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use std::sync::{Arc, Mutex, mpsc}; +use std::time::Instant; + +use crate::dinov3::Config; +use crate::pca::{self, Basis}; + +/// A completed inference result: a square RGB image, either the coarse +/// feature colouring or a full reconstruction. +#[derive(Debug, Clone)] +pub struct FeatureGrid { + /// Row-major RGB. For [`Display::PcaColour`] this is `[tokens, 3]` + /// including the prefix tokens; for [`Display::Reconstruction`] it is + /// already `[grid * grid, 3]` with no prefix. + pub colors: Vec, + /// Side length of the displayable square: the patch grid for PCA + /// colouring, the image size for a reconstruction. + pub grid: usize, + pub prefix_tokens: usize, + /// Encoder wall time, for the on-screen/logged rate readout. + pub latency_ms: f64, +} + +impl FeatureGrid { + /// The displayable `grid × grid × 3` image, with any prefix tokens + /// dropped. + pub fn patch_rgb(&self) -> &[f32] { + &self.colors[self.prefix_tokens * pca::COMPONENTS..] + } +} + +/// What the encoder's output is turned into for display. +#[derive(Clone, Debug)] +pub enum Display { + /// Project patch features onto their top three principal components and + /// read those off as RGB. No training, one `[hidden, 3]` matmul, and a + /// `grid × grid` result. Shows what the features *distinguish*. + PcaColour, + /// Reconstruct RGB through the trained decoder — the actual roundtrip. + /// Produces a full `image_size × image_size` picture, so the readback + /// per frame is ~600 KB rather than ~3 KB. Shows what the features + /// *retain*. + Reconstruction(std::path::PathBuf), +} + +/// What the worker is told to do next. +enum Command { + /// Encode this image. `[num_patches, patch_dim]`, from + /// [`crate::preprocess`]. + Submit(Vec), + /// Refit the PCA basis from the next frame's features. + Refit, + Stop, +} + +/// Handle to a running worker. +pub struct Worker { + tx: mpsc::Sender, + latest: Arc>>, + generation: Arc, + ready: Arc, + handle: Option>, +} + +impl Worker { + /// Queue a frame for encoding. + /// + /// Returns `false` if the worker is busy or gone. Dropping frames is + /// the correct behaviour: the camera produces 60 Hz and the encoder + /// cannot keep up, so anything queued would be stale by the time it ran. + pub fn submit(&self, patches: Vec) -> bool { + if !self.ready.load(Ordering::Acquire) { + return false; + } + self.ready.store(false, Ordering::Release); + self.tx.send(Command::Submit(patches)).is_ok() + } + + /// Ask for the colour basis to be refitted from the next frame. + pub fn request_refit(&self) { + let _ = self.tx.send(Command::Refit); + } + + /// The most recent completed result, if any. + pub fn latest(&self) -> Option { + self.latest.lock().ok().and_then(|g| g.clone()) + } + + /// Monotonic count of completed encodes, so the renderer can tell a + /// fresh result from a repeat without comparing pixel data. + pub fn generation(&self) -> u64 { + self.generation.load(Ordering::Acquire) + } + + /// True when the worker is idle and would accept a frame. + pub fn is_ready(&self) -> bool { + self.ready.load(Ordering::Acquire) + } +} + +impl Drop for Worker { + fn drop(&mut self) { + let _ = self.tx.send(Command::Stop); + if let Some(handle) = self.handle.take() { + let _ = handle.join(); + } + } +} + +/// How the worker should obtain its weights. +pub enum Weights { + /// Load a checkpoint from disk. On device this is a path the app has + /// pushed or unpacked from its assets. + SafeTensors(std::path::PathBuf), + /// Deterministic synthetic weights. Produces meaningless features, but + /// exercises the entire pipeline end to end — useful for bringing the + /// render path up before the real checkpoint is on the device. + Synthetic, +} + +/// Start the worker. +/// +/// Returns immediately; the session is built on the worker thread, which +/// takes a few seconds on a mobile CPU. [`Worker::is_ready`] reports false +/// until it is done, and [`Worker::latest`] yields `None`. +pub fn spawn( + gpu: Arc, + config: Config, + weights: Weights, + plan_cache: Option, + submission_chunks: usize, + display: Display, +) -> Worker { + let (tx, rx) = mpsc::channel(); + let latest = Arc::new(Mutex::new(None)); + let generation = Arc::new(AtomicU64::new(0)); + let ready = Arc::new(AtomicBool::new(false)); + + let handle = { + let latest = Arc::clone(&latest); + let generation = Arc::clone(&generation); + let ready = Arc::clone(&ready); + std::thread::Builder::new() + .name("dinovision-inference".into()) + .spawn(move || { + worker_main( + gpu, + config, + weights, + plan_cache, + submission_chunks, + display, + rx, + latest, + generation, + ready, + ); + }) + .expect("failed to spawn inference thread") + }; + + Worker { + tx, + latest, + generation, + ready, + handle: Some(handle), + } +} + +#[allow(clippy::too_many_arguments)] +fn worker_main( + gpu: Arc, + config: Config, + weights: Weights, + plan_cache: Option, + submission_chunks: usize, + display: Display, + rx: mpsc::Receiver, + latest: Arc>>, + generation: Arc, + ready: Arc, +) { + // For PCA colouring both the colours and the features are outputs: + // colours every frame (3 KB), features only when refitting the basis + // (300 KB), which is why they are separate. A reconstruction needs + // neither — the decoder consumes the features inside the graph. + let reconstructing = matches!(display, Display::Reconstruction(_)); + let mut g = meganeura::Graph::new(); + let features = crate::dinov3::build_encoder(&mut g, &config); + if reconstructing { + let rgb = crate::decoder::attach_to_encoder(&mut g, &config, features); + g.set_outputs(vec![rgb]); + } else { + let colors = pca::add_projection(&mut g, features, config.hidden_size); + g.set_outputs(vec![colors, features]); + } + + let build_start = Instant::now(); + let (mut session, _) = meganeura::train::build(&g, meganeura::train::SessionConfig { + mode: meganeura::train::Mode::Inference, + gpu: Some(gpu), + cache: plan_cache.as_deref(), + ..Default::default() + }); + log::info!( + "inference session ready in {:.1} s", + build_start.elapsed().as_secs_f64() + ); + + // Hand the queue back periodically so the renderer can get a frame in. + // One long submission is faster in isolation but starves everything + // else sharing the device. + session.set_submission_chunks(submission_chunks); + + match weights { + Weights::SafeTensors(path) => { + match meganeura::data::safetensors::SafeTensorsModel::load(path.clone()) { + Ok(model) => { + if let Err(e) = crate::weights::load_encoder(&mut session, &model, &config) { + log::error!("failed to bind weights from {}: {e}", path.display()); + return; + } + } + Err(e) => { + log::error!("failed to read {}: {e}", path.display()); + return; + } + } + } + Weights::Synthetic => { + log::warn!("running with synthetic weights — features are meaningless"); + crate::bench::fill_parameters(&mut session, &g); + } + } + + let tokens = config.num_tokens(); + let mut basis = Basis::placeholder(config.hidden_size); + let mut refit_pending = false; + let mut colors_out; + let mut features_out = vec![0.0f32; tokens * config.hidden_size]; + // Reconstruction reads a planar [3, H, W] image; the renderer wants it + // interleaved, so keep a staging buffer for the transpose. + let mut planar = Vec::new(); + + match &display { + Display::PcaColour => { + // Start with a placeholder basis so the first frame displays + // something, then refit from real features as soon as one lands. + refit_pending = true; + apply_basis(&mut session, &basis); + colors_out = vec![0.0f32; tokens * pca::COMPONENTS]; + } + Display::Reconstruction(path) => { + if let Err(e) = crate::decoder::load_parameters(&mut session, &g, path) { + log::error!("failed to load the decoder: {e}"); + return; + } + let pixels = config.image_size * config.image_size; + planar = vec![0.0f32; 3 * pixels]; + colors_out = vec![0.0f32; pixels * 3]; + } + } + + ready.store(true, Ordering::Release); + + while let Ok(cmd) = rx.recv() { + let patches = match cmd { + Command::Submit(p) => p, + Command::Refit => { + refit_pending = true; + continue; + } + Command::Stop => break, + }; + + let start = Instant::now(); + session.set_input("patches", &patches); + session.step(); + session.wait(); + + if reconstructing { + session.read_output_by_index(0, &mut planar); + // [3, H, W] → [H * W, 3]. + let pixels = config.image_size * config.image_size; + for p in 0..pixels { + for c in 0..3 { + colors_out[p * 3 + c] = planar[c * pixels + p]; + } + } + } else { + session.read_output_by_index(0, &mut colors_out); + } + + if refit_pending { + // Refitting needs the full feature matrix, so this frame pays + // for the larger readback. It happens once at startup and then + // only on request. + session.read_output_by_index(1, &mut features_out); + basis = Basis::fit( + &features_out, + tokens, + config.hidden_size, + config.num_prefix_tokens(), + ); + apply_basis(&mut session, &basis); + refit_pending = false; + log::info!("refitted colour basis from live features"); + // The colours just read were produced by the old basis; redo + // the projection on the CPU so this frame is not displayed with + // a stale palette. + colors_out = basis.project(&features_out, tokens); + } + + let grid = FeatureGrid { + colors: colors_out.clone(), + grid: if reconstructing { + config.image_size + } else { + config.grid() + }, + prefix_tokens: if reconstructing { + 0 + } else { + config.num_prefix_tokens() + }, + latency_ms: start.elapsed().as_secs_f64() * 1000.0, + }; + if let Ok(mut slot) = latest.lock() { + *slot = Some(grid); + } + generation.fetch_add(1, Ordering::Release); + ready.store(true, Ordering::Release); + } + + log::info!("inference worker stopped"); +} + +fn apply_basis(session: &mut meganeura::Session, basis: &Basis) { + session.set_parameter("pca.weight", &basis.weight_matrix()); + session.set_parameter("pca.bias", &basis.bias_vector()); +} diff --git a/environment/publication-source/source-snapshot/src/lib.rs b/environment/publication-source/source-snapshot/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1efabc0503b6b9176776f480b8989a6d07cab93c --- /dev/null +++ b/environment/publication-source/source-snapshot/src/lib.rs @@ -0,0 +1,70 @@ +//! DINOv3 inference on Meta Quest, via Blade for graphics and Meganeura +//! for the network. +//! +//! The camera image is encoded to DINOv3 patch features and those features +//! are turned back into something viewable, so the user sees the world +//! through a DINO roundtrip. +//! +//! # Layout +//! +//! * [`dinov3`] — the encoder as a meganeura graph, plus its config. +//! * [`preprocess`] — image to patch tensor, with the flattening order the +//! folded patch-embedding matmul requires. +//! * [`weights`] — binding a HuggingFace checkpoint to graph parameters. +//! * [`bench`] — throughput measurement, shared by the desktop and +//! on-device entry points. +//! +//! # Sharing one GPU context +//! +//! The renderer and the network run on a *single* +//! `blade_graphics::Context`, created here and handed to meganeura through +//! `SessionConfig::gpu`. That is why this crate pins the same +//! blade-graphics revision meganeura does — two copies of the crate would +//! make the `Arc` types incompatible. It also means no +//! external-memory interop is needed: `Session::input_buffer` hands back a +//! `BufferPiece` a render pass can write to directly. + +pub mod bench; +#[cfg(target_os = "android")] +pub mod camera; +pub mod decoder; +pub mod dinov3; +pub mod inference; +pub mod pca; +pub mod preprocess; +pub mod render; +pub mod source; +pub mod weights; + +use std::sync::Arc; + +/// Create the GPU context that both the renderer and inference will share. +/// +/// `xr` stays `None` for headless compute (the benchmark); the XR path +/// fills in an `XrDesc` and everything downstream is unchanged. +pub fn init_context( + xr: Option, +) -> Result, blade_graphics::NotSupportedError> { + let context = unsafe { + blade_graphics::Context::init(blade_graphics::ContextDesc { + presentation: false, + xr, + ray_tracing: false, + // Validation layers are not present on a retail Quest, and + // they cost real time where we can least afford it. + validation: cfg!(debug_assertions) && !cfg!(target_os = "android"), + timing: false, + capture: false, + overlay: false, + device_id: None, + }) + }?; + let info = context.device_information(); + log::info!( + "GPU: {} ({}), driver {}", + info.device_name, + info.driver_name, + info.driver_info + ); + Ok(Arc::new(context)) +} diff --git a/environment/publication-source/source-snapshot/src/pca.rs b/environment/publication-source/source-snapshot/src/pca.rs new file mode 100644 index 0000000000000000000000000000000000000000..2fe39e5c6f42f86a449e188d12f9fef2a39d25cf --- /dev/null +++ b/environment/publication-source/source-snapshot/src/pca.rs @@ -0,0 +1,401 @@ +//! Turning 384-dimensional patch features into something a person can see. +//! +//! The first display mode is the classic DINO visualization: project patch +//! features onto their top three principal components and read those off as +//! RGB. It needs no trained decoder, costs one `[hidden, 3]` matmul, and is +//! semantically meaningful — patches of the same object land on the same +//! colour, which is precisely what the features encode. +//! +//! The basis is fitted **on device** from a captured frame rather than +//! shipped as an asset. Feature statistics depend on what the camera is +//! actually looking at, and a basis fitted on ImageNet-ish photos would +//! waste most of its dynamic range on a living room wall. +//! +//! Fitting uses power iteration with deflation. For three components out of +//! a few hundred tokens that is a handful of milliseconds on the CPU, and +//! it avoids pulling in a linear-algebra dependency for one job. + +use meganeura::{Graph, NodeId}; + +/// Number of principal components, one per colour channel. +pub const COMPONENTS: usize = 3; + +/// A fitted projection from feature space to RGB. +#[derive(Debug, Clone)] +pub struct Basis { + /// Feature-space mean, subtracted before projection. + pub mean: Vec, + /// Row-major `[COMPONENTS, dim]` — the top principal directions. + pub components: Vec, + /// Per-component scale mapping projections into roughly `[0, 1]`. + pub scale: [f32; COMPONENTS], + /// Per-component offset, applied after scaling. + pub offset: [f32; COMPONENTS], + pub dim: usize, +} + +impl Basis { + /// An identity-ish basis to display before the first fit completes: + /// three arbitrary orthogonal axes. Produces a picture, just not a + /// well-conditioned one. + pub fn placeholder(dim: usize) -> Self { + let mut components = vec![0.0; COMPONENTS * dim]; + for c in 0..COMPONENTS { + components[c * dim + c] = 1.0; + } + Self { + mean: vec![0.0; dim], + components, + scale: [1.0; COMPONENTS], + offset: [0.5; COMPONENTS], + dim, + } + } + + /// Fit from a `[tokens, dim]` feature matrix. + /// + /// `skip` drops the leading prefix tokens: CLS and register tokens are + /// not patches, they carry global rather than spatial information, and + /// including them skews the components away from what is being + /// displayed. + pub fn fit(features: &[f32], tokens: usize, dim: usize, skip: usize) -> Self { + assert_eq!(features.len(), tokens * dim, "feature matrix shape mismatch"); + assert!(skip < tokens, "nothing left after skipping {skip} tokens"); + let rows = tokens - skip; + let data = &features[skip * dim..]; + + // Centre. + let mut mean = vec![0.0f32; dim]; + for r in 0..rows { + for d in 0..dim { + mean[d] += data[r * dim + d]; + } + } + for m in &mut mean { + *m /= rows as f32; + } + let mut centred: Vec = (0..rows * dim) + .map(|i| data[i] - mean[i % dim]) + .collect(); + + let mut components = vec![0.0f32; COMPONENTS * dim]; + let mut projected = vec![0.0f32; COMPONENTS * rows]; + + for c in 0..COMPONENTS { + // Deterministic, non-degenerate start vector. A constant vector + // would be orthogonal to components that sum to zero, so vary it. + let mut v: Vec = (0..dim) + .map(|d| ((d * 2654435761usize) % 1024) as f32 / 1024.0 - 0.5) + .collect(); + normalize(&mut v); + + let mut scores = vec![0.0f32; rows]; + for _ in 0..48 { + // scores = X v ; v' = Xᵀ scores — power iteration on XᵀX + // without ever forming the dim×dim covariance matrix. + for r in 0..rows { + let row = ¢red[r * dim..(r + 1) * dim]; + scores[r] = row.iter().zip(&v).map(|(a, b)| a * b).sum(); + } + let mut next = vec![0.0f32; dim]; + for r in 0..rows { + let s = scores[r]; + let row = ¢red[r * dim..(r + 1) * dim]; + for d in 0..dim { + next[d] += s * row[d]; + } + } + if normalize(&mut next) < 1e-12 { + break; + } + v = next; + } + + // Final scores, then deflate so the next iteration finds the + // next-strongest direction. + for r in 0..rows { + let row = ¢red[r * dim..(r + 1) * dim]; + let s: f32 = row.iter().zip(&v).map(|(a, b)| a * b).sum(); + scores[r] = s; + projected[c * rows + r] = s; + } + for r in 0..rows { + let s = scores[r]; + for d in 0..dim { + centred[r * dim + d] -= s * v[d]; + } + } + components[c * dim..(c + 1) * dim].copy_from_slice(&v); + } + + // Map each component to [0, 1] using a robust range rather than + // min/max: a single outlier patch would otherwise flatten the whole + // image into a narrow band of colour. + let mut lo = [0.0f32; COMPONENTS]; + let mut span = [0.0f32; COMPONENTS]; + for c in 0..COMPONENTS { + let mut col: Vec = projected[c * rows..(c + 1) * rows].to_vec(); + col.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)); + lo[c] = col[(rows as f32 * 0.02) as usize]; + let hi = col[((rows as f32 * 0.98) as usize).min(rows - 1)]; + span[c] = hi - lo[c]; + } + + // A component carrying almost no variance relative to the leading + // one carries no visual information, and normalizing it to full + // range would amplify numerical noise into a psychedelic channel. + // This is not a contrived case: it is what a blank wall looks like. + // Map such a channel to flat mid-grey instead. + let dominant = span.iter().copied().fold(0.0f32, f32::max); + let floor = dominant * 1e-3; + let mut scale = [0.0f32; COMPONENTS]; + let mut offset = [0.5f32; COMPONENTS]; + for c in 0..COMPONENTS { + if span[c] > floor && span[c] > f32::MIN_POSITIVE { + scale[c] = 1.0 / span[c]; + offset[c] = -lo[c] / span[c]; + } + } + + Self { + mean, + components, + scale, + offset, + dim, + } + } + + /// The `[dim, COMPONENTS]` matrix the graph's projection matmul wants, + /// with the per-component scale folded in. + pub fn weight_matrix(&self) -> Vec { + let mut w = vec![0.0f32; self.dim * COMPONENTS]; + for c in 0..COMPONENTS { + for d in 0..self.dim { + w[d * COMPONENTS + c] = self.components[c * self.dim + d] * self.scale[c]; + } + } + w + } + + /// The matching bias. + /// + /// `(x - mean) @ W * scale + offset` folds into `x @ (W * scale) + b` + /// with `b = offset - (mean @ W) * scale`, saving a subtraction pass + /// over every token. + pub fn bias_vector(&self) -> Vec { + let mut b = [0.0f32; COMPONENTS]; + for c in 0..COMPONENTS { + let dot: f32 = (0..self.dim) + .map(|d| self.mean[d] * self.components[c * self.dim + d]) + .sum(); + b[c] = self.offset[c] - dot * self.scale[c]; + } + b.to_vec() + } + + /// CPU-side projection, for tests and for previewing a fit without a + /// GPU roundtrip. + pub fn project(&self, features: &[f32], tokens: usize) -> Vec { + let w = self.weight_matrix(); + let b = self.bias_vector(); + let mut out = vec![0.0f32; tokens * COMPONENTS]; + for t in 0..tokens { + for c in 0..COMPONENTS { + let mut acc = b[c]; + for d in 0..self.dim { + acc += features[t * self.dim + d] * w[d * COMPONENTS + c]; + } + out[t * COMPONENTS + c] = acc; + } + } + out + } +} + +fn normalize(v: &mut [f32]) -> f32 { + let norm = v.iter().map(|x| x * x).sum::().sqrt(); + if norm > 1e-12 { + for x in v.iter_mut() { + *x /= norm; + } + } + norm +} + +/// Append the colour projection to an encoder output. +/// +/// Declares `pca.weight` and `pca.bias` as parameters, so refitting the +/// basis is a `set_parameter` call rather than a graph rebuild. +/// +/// Returns the `[tokens, COMPONENTS]` colour node. Folding this into the +/// graph rather than projecting on the CPU keeps the per-frame readback at +/// `tokens * 3` floats instead of `tokens * 384` — about 3 KB rather than +/// 300 KB, which matters on a bus shared with the compositor. +pub fn add_projection(g: &mut Graph, features: NodeId, hidden: usize) -> NodeId { + let w = g.parameter("pca.weight", &[hidden, COMPONENTS]); + let b = g.parameter("pca.bias", &[COMPONENTS]); + let projected = g.matmul(features, w); + g.bias_add(projected, b) +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Features lying on a known plane must be recovered by the top two + /// components, with the projection spreading across the output range. + #[test] + fn recovers_a_planted_subspace() { + let dim = 32; + let tokens = 200; + let mut features = vec![0.0f32; tokens * dim]; + for t in 0..tokens { + let a = (t as f32 / tokens as f32) * 2.0 - 1.0; + let b = ((t * 7 % tokens) as f32 / tokens as f32) * 2.0 - 1.0; + for d in 0..dim { + // Two strong directions plus a much weaker third. + features[t * dim + d] = if d == 3 { + 5.0 * a + } else if d == 11 { + 4.0 * b + } else { + 0.01 * ((d as f32) * 0.1 + a) + }; + } + } + + let basis = Basis::fit(&features, tokens, dim, 0); + // The first two components should be dominated by dims 3 and 11. + let c0 = &basis.components[0..dim]; + let c1 = &basis.components[dim..2 * dim]; + let strongest = |c: &[f32]| { + c.iter() + .enumerate() + .max_by(|a, b| a.1.abs().partial_cmp(&b.1.abs()).unwrap()) + .unwrap() + .0 + }; + let (s0, s1) = (strongest(c0), strongest(c1)); + assert!( + (s0 == 3 && s1 == 11) || (s0 == 11 && s1 == 3), + "expected components along dims 3 and 11, got {s0} and {s1}" + ); + } + + #[test] + fn components_are_orthonormal() { + let dim = 24; + let tokens = 90; + let features: Vec = (0..tokens * dim) + .map(|i| ((i * 37 % 101) as f32 / 101.0 - 0.5) * (1.0 + (i % 5) as f32)) + .collect(); + let basis = Basis::fit(&features, tokens, dim, 0); + + for a in 0..COMPONENTS { + let va = &basis.components[a * dim..(a + 1) * dim]; + let norm: f32 = va.iter().map(|x| x * x).sum::().sqrt(); + assert!((norm - 1.0).abs() < 1e-3, "component {a} norm {norm}"); + for b in (a + 1)..COMPONENTS { + let vb = &basis.components[b * dim..(b + 1) * dim]; + let dot: f32 = va.iter().zip(vb).map(|(x, y)| x * y).sum(); + assert!(dot.abs() < 1e-2, "components {a},{b} not orthogonal: {dot}"); + } + } + } + + /// The folded weight/bias form must agree with an explicit + /// centre-project-scale-offset, since the graph only sees the folded one. + #[test] + fn folded_weights_match_explicit_form() { + let dim = 16; + let tokens = 60; + let features: Vec = (0..tokens * dim) + .map(|i| ((i * 13 % 97) as f32 / 97.0 - 0.5) * 3.0) + .collect(); + let basis = Basis::fit(&features, tokens, dim, 0); + let folded = basis.project(&features, tokens); + + for t in 0..tokens { + for c in 0..COMPONENTS { + let explicit: f32 = (0..dim) + .map(|d| { + (features[t * dim + d] - basis.mean[d]) * basis.components[c * dim + d] + }) + .sum::() + * basis.scale[c] + + basis.offset[c]; + let got = folded[t * COMPONENTS + c]; + assert!( + (got - explicit).abs() < 1e-3, + "token {t} component {c}: folded {got} vs explicit {explicit}" + ); + } + } + } + + /// The robust range should put the bulk of patches inside [0, 1], + /// otherwise the display is either washed out or clipped. + #[test] + fn projection_spans_the_display_range() { + let dim = 48; + let tokens = 300; + let features: Vec = (0..tokens * dim) + .map(|i| { + let t = (i / dim) as f32; + let d = (i % dim) as f32; + (t * 0.017 + d * 0.31).sin() * 2.0 + }) + .collect(); + let basis = Basis::fit(&features, tokens, dim, 0); + let out = basis.project(&features, tokens); + + for c in 0..COMPONENTS { + let vals: Vec = (0..tokens).map(|t| out[t * COMPONENTS + c]).collect(); + let inside = vals.iter().filter(|v| (0.0..=1.0).contains(*v)).count(); + let frac = inside as f32 / tokens as f32; + assert!(frac > 0.9, "component {c}: only {:.0}% inside [0,1]", frac * 100.0); + } + } + + /// A near-featureless scene — a blank wall — must not be amplified into + /// a noise field. Degenerate components go flat grey instead. + #[test] + fn degenerate_components_stay_neutral() { + let dim = 32; + let tokens = 120; + // Rank-1 data: only the first component carries any variance. + let mut features = vec![0.0f32; tokens * dim]; + for t in 0..tokens { + let a = t as f32 / tokens as f32; + for d in 0..dim { + features[t * dim + d] = a * (d as f32 * 0.05).cos(); + } + } + + let basis = Basis::fit(&features, tokens, dim, 0); + let out = basis.project(&features, tokens); + assert!(out.iter().all(|v| v.is_finite()), "projection produced non-finite values"); + + // Components 1 and 2 have no signal; every token should sit at the + // neutral value rather than spanning the range. + for c in 1..COMPONENTS { + let vals: Vec = (0..tokens).map(|t| out[t * COMPONENTS + c]).collect(); + let lo = vals.iter().copied().fold(f32::INFINITY, f32::min); + let hi = vals.iter().copied().fold(f32::NEG_INFINITY, f32::max); + assert!( + (hi - lo) < 1e-3 && (lo - 0.5).abs() < 1e-3, + "component {c} should be flat mid-grey, spans [{lo}, {hi}]" + ); + } + } + + #[test] + fn placeholder_is_usable_before_the_first_fit() { + let basis = Basis::placeholder(384); + let features = vec![0.25f32; 8 * 384]; + let out = basis.project(&features, 8); + assert_eq!(out.len(), 8 * COMPONENTS); + assert!(out.iter().all(|v| v.is_finite())); + } +} diff --git a/environment/publication-source/source-snapshot/src/preprocess.rs b/environment/publication-source/source-snapshot/src/preprocess.rs new file mode 100644 index 0000000000000000000000000000000000000000..73339a1e7d209697186f2ca7ac5922e9fe51b63d --- /dev/null +++ b/environment/publication-source/source-snapshot/src/preprocess.rs @@ -0,0 +1,191 @@ +//! Turning an image into the `"patches"` tensor the encoder graph wants. +//! +//! The graph folds DINOv3's patch-embedding Conv2d into a single matmul, +//! which means the flattening order here has to agree exactly with the +//! order the convolution weight was flattened in. PyTorch stores that +//! weight as `[out_channels, in_channels, kh, kw]`, so within one patch +//! the element order is **channel-major**: +//! +//! ```text +//! index = c * patch_size² + ky * patch_size + kx +//! ``` +//! +//! Get this wrong and the model still runs, producing confident nonsense +//! — so it is pinned down by tests below. + +use crate::dinov3::Config; + +/// ImageNet statistics from the model's `preprocessor_config.json`. +pub const IMAGE_MEAN: [f32; 3] = [0.485, 0.456, 0.406]; +pub const IMAGE_STD: [f32; 3] = [0.229, 0.224, 0.225]; + +/// Flatten an already-normalized CHW pixel tensor into patches. +/// +/// `pixels` is `[3, image_size, image_size]`, matching what HuggingFace's +/// image processor hands to the model as `pixel_values`. Taking this form +/// directly is what lets the desktop verifier feed the exact same tensor +/// as the reference implementation, keeping resize and normalization +/// differences out of a numerics comparison. +/// +/// Returns `[num_patches, patch_dim]` in row-major grid order. +pub fn patches_from_pixels_chw(pixels: &[f32], config: &Config) -> Vec { + let size = config.image_size; + let ps = config.patch_size; + let grid = config.grid(); + assert_eq!( + pixels.len(), + 3 * size * size, + "expected a [3, {size}, {size}] pixel tensor, got {} values", + pixels.len() + ); + + let plane = size * size; + let patch_area = ps * ps; + let mut out = vec![0.0f32; config.num_patches() * config.patch_dim()]; + + for gy in 0..grid { + for gx in 0..grid { + let patch = (gy * grid + gx) * config.patch_dim(); + for c in 0..3 { + for ky in 0..ps { + let src_row = c * plane + (gy * ps + ky) * size + gx * ps; + let dst_row = patch + c * patch_area + ky * ps; + out[dst_row..dst_row + ps].copy_from_slice(&pixels[src_row..src_row + ps]); + } + } + } + } + + out +} + +/// Flatten interleaved 8-bit RGB into patches, rescaling to `[0, 1]` and +/// applying the ImageNet normalization on the way. +/// +/// `rgb` is `[image_size, image_size, 3]` — the layout image decoders and +/// camera conversions naturally produce. No resizing happens here; the +/// caller supplies an image already at `config.image_size`. +pub fn patches_from_rgb8(rgb: &[u8], config: &Config) -> Vec { + let size = config.image_size; + let ps = config.patch_size; + let grid = config.grid(); + assert_eq!( + rgb.len(), + 3 * size * size, + "expected a [{size}, {size}, 3] RGB image, got {} bytes", + rgb.len() + ); + + let patch_area = ps * ps; + let mut out = vec![0.0f32; config.num_patches() * config.patch_dim()]; + + for gy in 0..grid { + for gx in 0..grid { + let patch = (gy * grid + gx) * config.patch_dim(); + for ky in 0..ps { + let y = gy * ps + ky; + for kx in 0..ps { + let x = gx * ps + kx; + let src = (y * size + x) * 3; + for c in 0..3 { + let v = rgb[src + c] as f32 / 255.0; + out[patch + c * patch_area + ky * ps + kx] = + (v - IMAGE_MEAN[c]) / IMAGE_STD[c]; + } + } + } + } + } + + out +} + +/// Reshape a `[out, 3, patch, patch]` Conv2d weight into the +/// `[patch_dim, out]` matrix the graph's patch-embedding matmul expects. +/// +/// The source is already contiguous in channel-major order per output +/// channel, so this is purely a transpose of a `[out, patch_dim]` view. +pub fn conv_weight_to_matmul(weight: &[f32], out_channels: usize, patch_dim: usize) -> Vec { + assert_eq!( + weight.len(), + out_channels * patch_dim, + "conv weight has {} values, expected {out_channels} * {patch_dim}", + weight.len() + ); + let mut m = vec![0.0f32; patch_dim * out_channels]; + for o in 0..out_channels { + for i in 0..patch_dim { + m[i * out_channels + o] = weight[o * patch_dim + i]; + } + } + m +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn chw_patch_layout_is_channel_major() { + let c = Config::vits16(); + // Encode each pixel's identity as its flat CHW index so the + // mapping is checkable by arithmetic. + let size = c.image_size; + let pixels: Vec = (0..3 * size * size).map(|i| i as f32).collect(); + let patches = patches_from_pixels_chw(&pixels, &c); + + let ps = c.patch_size; + let plane = size * size; + // Patch (gy=3, gx=5), channel 2, offset (ky=7, kx=11). + let (gy, gx, ch, ky, kx) = (3, 5, 2, 7, 11); + let got = patches[(gy * c.grid() + gx) * c.patch_dim() + ch * ps * ps + ky * ps + kx]; + let want = (ch * plane + (gy * ps + ky) * size + gx * ps + kx) as f32; + assert_eq!(got, want); + } + + #[test] + fn rgb8_and_chw_paths_agree() { + let c = Config::vits16(); + let size = c.image_size; + // Build an arbitrary but reproducible RGB image, then the + // equivalent normalized CHW tensor, and check both flatteners + // land on the same patch tensor. + let rgb: Vec = (0..3 * size * size).map(|i| (i % 251) as u8).collect(); + let mut chw = vec![0.0f32; 3 * size * size]; + for y in 0..size { + for x in 0..size { + for ch in 0..3 { + let v = rgb[(y * size + x) * 3 + ch] as f32 / 255.0; + chw[ch * size * size + y * size + x] = (v - IMAGE_MEAN[ch]) / IMAGE_STD[ch]; + } + } + } + + let from_rgb = patches_from_rgb8(&rgb, &c); + let from_chw = patches_from_pixels_chw(&chw, &c); + assert_eq!(from_rgb.len(), from_chw.len()); + let worst = from_rgb + .iter() + .zip(&from_chw) + .map(|(a, b)| (a - b).abs()) + .fold(0.0f32, f32::max); + assert!(worst < 1e-6, "paths disagree by {worst}"); + } + + #[test] + fn normalization_maps_midgray_near_zero() { + let c = Config::vits16(); + // 0.485*255 ≈ 124 is the red-channel mean, so red lands near 0. + let rgb = vec![124u8; 3 * c.image_size * c.image_size]; + let patches = patches_from_rgb8(&rgb, &c); + assert!(patches[0].abs() < 0.02, "red channel not centred: {}", patches[0]); + } + + #[test] + fn conv_weight_transpose_roundtrip() { + // [out=2, patch_dim=3] stored row-major becomes [3, 2]. + let w = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; + let m = conv_weight_to_matmul(&w, 2, 3); + assert_eq!(m, vec![1.0, 4.0, 2.0, 5.0, 3.0, 6.0]); + } +} diff --git a/environment/publication-source/source-snapshot/src/render.rs b/environment/publication-source/source-snapshot/src/render.rs new file mode 100644 index 0000000000000000000000000000000000000000..8ef5d8c662c8587c992876edb304dca4acdffada --- /dev/null +++ b/environment/publication-source/source-snapshot/src/render.rs @@ -0,0 +1,324 @@ +//! Drawing the coloured feature grid to an eye buffer. +//! +//! Deliberately tiny: a full-screen triangle and a `grid x grid x 3` float +//! buffer. The renderer runs at the headset's refresh rate regardless of +//! how slowly inference produces new grids, so the expensive part of the +//! frame is never on the display path. + +use blade_graphics as gpu; + +use crate::pca::COMPONENTS; + +/// Maximum eyes we allocate parameter slots for. +pub const MAX_EYES: usize = 2; + +#[repr(C)] +#[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] +struct Params { + scale: [f32; 2], + offset: [f32; 2], + grid: u32, + pad: [u32; 3], +} + +/// Where a flat overlay lands in one eye's clip space. +/// +/// Purely 2D. The only thing an eye's frustum contributes to a head-locked +/// image is where its axis sits and how wide the image should be — a scale +/// and an offset — so that is all this carries. +#[derive(Clone, Copy, Debug)] +pub struct EyeTransform { + pub scale: [f32; 2], + pub offset: [f32; 2], +} + +impl EyeTransform { + /// Fills the eye buffer exactly. Right for a flat window, wrong for a + /// headset, where it stretches the image over the whole field of view + /// and ignores the frustum's asymmetry. + pub const FULLSCREEN: Self = Self { + scale: [1.0, 1.0], + offset: [0.0, 0.0], + }; + + /// Fill an eye's field of view, centred on a given direction rather + /// than on the eye's axis. + /// + /// `centre_tan` is where the image's middle should sit, in tangent + /// units: `(x/-z, y/-z)` of the target direction expressed in the eye's + /// space. Zero is straight ahead and reproduces [`filling`]. + /// + /// This is how the image gets to stay put while the head moves. The + /// content is as old as the last completed inference — a tenth of a + /// second here — so labelling it with the current head pose tells the + /// compositor to compensate for nothing, and it slides around with the + /// head. Feeding the direction the camera was *pointing when the frame + /// was captured* moves the image opposite to head motion, which is what + /// world-locked looks like. + pub fn filling_at(fov: [f32; 4], centre_tan: [f32; 2]) -> Self { + let [left, right, up, down] = fov; + let (tan_l, tan_r) = (left.tan(), right.tan()); + let (tan_u, tan_d) = (up.tan(), down.tan()); + let (span_x, span_y) = (tan_r - tan_l, tan_u - tan_d); + Self { + // Same size as filling the buffer. + scale: [1.0, 1.0], + offset: [ + (2.0 * centre_tan[0] - (tan_r + tan_l)) / span_x, + (2.0 * centre_tan[1] - (tan_u + tan_d)) / span_y, + ], + } + } + + /// Fill an eye's field of view, recentred on its axis. + /// + /// The right default for passthrough parity: the system's own + /// passthrough maps these cameras across your whole view, so matching it + /// means spanning the frustum rather than inventing an angular size. + /// + /// Note this is *not* the same as filling the eye buffer. Headset frusta + /// are asymmetric and mirror between the eyes, so an image painted + /// edge-to-edge has its centre at a different angle in each eye, and the + /// two will not fuse. Spanning the frustum symmetrically about the axis + /// is what makes them agree. + pub fn filling(fov: [f32; 4]) -> Self { + let [left, right, up, down] = fov; + let half_tan = [ + (right.tan() - left.tan()) * 0.5, + (up.tan() - down.tan()) * 0.5, + ]; + Self::for_eye(fov, half_tan) + } + + /// Place an image into an eye whose frustum is `[left, right, up, down]` + /// radians, as OpenXR reports it. + /// + /// `half_tan` is the tangent of the image's half-angle on each axis. + /// Separate axes matter: the camera frame is squashed into a square for + /// the encoder, and giving x and y their true angular extents here is + /// what unsquashes it, so the view keeps the camera's full field + /// without looking stretched. + /// + /// A ray at angle θ from the view axis lands at clip + /// `(2·tanθ − (tanR + tanL)) / (tanR − tanL)`, so the quad's ±1 edges + /// map to a scale of `2·half_tan / (tanR − tanL)` about an offset of + /// `−(tanR + tanL) / (tanR − tanL)`. + /// + /// Headset frusta are asymmetric and differ between eyes, which is why + /// the offset is not zero and not shared: dropping it is what leaves the + /// two views unfusable. + pub fn for_eye(fov: [f32; 4], half_tan: [f32; 2]) -> Self { + let [left, right, up, down] = fov; + let (tan_l, tan_r) = (left.tan(), right.tan()); + let (tan_u, tan_d) = (up.tan(), down.tan()); + let (span_x, span_y) = (tan_r - tan_l, tan_u - tan_d); + Self { + scale: [ + 2.0 * half_tan[0] / span_x, + 2.0 * half_tan[1] / span_y, + ], + offset: [-(tan_r + tan_l) / span_x, -(tan_u + tan_d) / span_y], + } + } +} + +#[derive(blade_macros::ShaderData)] +struct ViewData { + params: gpu::BufferPiece, + cells: gpu::BufferPiece, +} + +/// Renders the latest feature grid full-screen. +pub struct GridView { + pipeline: gpu::RenderPipeline, + params_buf: gpu::Buffer, + cells_buf: gpu::Buffer, + grid: usize, +} + +impl GridView { + /// `color_format` must match the eye buffer being rendered into — + /// on an XR surface, `XrSurface::format()`. + pub fn new(context: &gpu::Context, color_format: gpu::TextureFormat, grid: usize) -> Self { + let shader = context.create_shader(gpu::ShaderDesc { + source: include_str!("shaders/grid_view.wgsl"), + naga_module: None, + }); + let data_layout = ::layout(); + let pipeline = context.create_render_pipeline(gpu::RenderPipelineDesc { + name: "grid-view", + data_layouts: &[&data_layout], + vertex: shader.at("vs_main"), + vertex_fetches: &[], + primitive: gpu::PrimitiveState::default(), + // The view covers every pixel, so there is nothing to depth-test + // against and no depth buffer to allocate. + depth_stencil: None, + fragment: Some(shader.at("fs_main")), + color_targets: &[gpu::ColorTargetState::from(color_format)], + multisample_state: gpu::MultisampleState::default(), + }); + + // One slot per eye: the projection differs between them, and both + // are in flight within a single frame's submission. + let params_buf = context.create_buffer(gpu::BufferDesc { + name: "grid-view-params", + size: (std::mem::size_of::() * MAX_EYES) as u64, + memory: gpu::Memory::Shared, + }); + let cells_buf = context.create_buffer(gpu::BufferDesc { + name: "grid-view-cells", + size: (grid * grid * COMPONENTS * std::mem::size_of::()) as u64, + memory: gpu::Memory::Shared, + }); + + let mut view = Self { + pipeline, + params_buf, + cells_buf, + grid, + }; + // Full-screen until the caller supplies per-eye transforms, which + // is right for a window and wrong for a headset. + for eye in 0..MAX_EYES { + view.set_transform(context, eye, EyeTransform::FULLSCREEN); + } + // A mid-grey field, so a failure to ever produce a result looks + // like "no data" rather than like a working black-and-nothing view. + view.upload(context, &vec![0.5; grid * grid * COMPONENTS]); + view + } + + /// Replace the displayed grid. `rgb` is `[grid * grid, 3]`, row-major. + pub fn upload(&mut self, context: &gpu::Context, rgb: &[f32]) { + let expected = self.grid * self.grid * COMPONENTS; + debug_assert_eq!(rgb.len(), expected, "grid payload is the wrong size"); + let n = rgb.len().min(expected); + unsafe { + std::ptr::copy_nonoverlapping(rgb.as_ptr(), self.cells_buf.data() as *mut f32, n); + } + context.sync_buffer(self.cells_buf); + } + + /// Set where the overlay lands in one eye. + pub fn set_transform(&mut self, context: &gpu::Context, eye: usize, t: EyeTransform) { + debug_assert!(eye < MAX_EYES); + unsafe { + let slot = (self.params_buf.data() as *mut Params).add(eye); + *slot = Params { + scale: t.scale, + offset: t.offset, + grid: self.grid as u32, + pad: [0; 3], + }; + } + context.sync_buffer(self.params_buf); + } + + /// Draw into an already-started render pass, using `eye`'s transform. + pub fn draw(&self, pass: &mut gpu::RenderCommandEncoder, eye: usize) { + let offset = (eye.min(MAX_EYES - 1) * std::mem::size_of::()) as u64; + let mut encoder = pass.with(&self.pipeline); + encoder.bind( + 0, + &ViewData { + params: self.params_buf.at(offset), + cells: self.cells_buf.into(), + }, + ); + encoder.draw(0, 6, 0, 1); + } + + pub fn destroy(mut self, context: &gpu::Context) { + context.destroy_buffer(self.cells_buf); + context.destroy_buffer(self.params_buf); + context.destroy_render_pipeline(&mut self.pipeline); + } +} + +/// Rotate a vector by a quaternion `[x, y, z, w]`. +fn rotate(q: [f32; 4], v: [f32; 3]) -> [f32; 3] { + let (qx, qy, qz, qw) = (q[0], q[1], q[2], q[3]); + // t = 2 * (q_vec × v); v' = v + qw * t + q_vec × t + let tx = 2.0 * (qy * v[2] - qz * v[1]); + let ty = 2.0 * (qz * v[0] - qx * v[2]); + let tz = 2.0 * (qx * v[1] - qy * v[0]); + [ + v[0] + qw * tx + qy * tz - qz * ty, + v[1] + qw * ty + qz * tx - qx * tz, + v[2] + qw * tz + qx * ty - qy * tx, + ] +} + +/// Where a direction that was straight ahead under `then` appears under +/// `now`, in tangent units suitable for [`EyeTransform::filling_at`]. +/// +/// Both quaternions are `[x, y, z, w]` in the same reference space. The +/// result is the image's centre after the head has moved, so a rotation to +/// the right pushes the content left — the image staying put in the world +/// while the view sweeps across it. +/// +/// Returns `None` when the old direction has swung behind the viewer, where +/// a tangent-plane shift stops meaning anything. +pub fn reprojection_offset(then: [f32; 4], now: [f32; 4]) -> Option<[f32; 2]> { + // Forward under the capture pose, brought into the current eye's space + // by the inverse of the current pose. + let forward = rotate(then, [0.0, 0.0, -1.0]); + let inverse_now = [-now[0], -now[1], -now[2], now[3]]; + let v = rotate(inverse_now, forward); + if v[2] >= -1e-3 { + return None; + } + Some([v[0] / -v[2], v[1] / -v[2]]) +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Straight ahead stays straight ahead when the head has not moved. + #[test] + fn no_motion_means_no_shift() { + let identity = [0.0, 0.0, 0.0, 1.0]; + let offset = reprojection_offset(identity, identity).unwrap(); + assert!(offset[0].abs() < 1e-6 && offset[1].abs() < 1e-6); + } + + /// Turning the head right must push the content left, so the image + /// appears to stay where it was in the world. + #[test] + fn turning_right_pushes_content_left() { + let identity = [0.0, 0.0, 0.0, 1.0]; + // +15 degrees about Y is a leftward yaw in a right-handed system + // looking down -Z, so -15 turns the view to the right. + let half = (-15.0f32).to_radians() * 0.5; + let turned_right = [0.0, half.sin(), 0.0, half.cos()]; + let offset = reprojection_offset(identity, turned_right).unwrap(); + assert!( + offset[0] < -0.1, + "expected the image to move left, got {offset:?}" + ); + // The magnitude should be tan(15 deg) = 0.268. + assert!((offset[0] + 15.0f32.to_radians().tan()).abs() < 1e-3); + assert!(offset[1].abs() < 1e-6, "yaw should not shift vertically"); + } + + /// Looking up must push the content down. + #[test] + fn looking_up_pushes_content_down() { + let identity = [0.0, 0.0, 0.0, 1.0]; + let half = 10.0f32.to_radians() * 0.5; + let looked_up = [half.sin(), 0.0, 0.0, half.cos()]; + let offset = reprojection_offset(identity, looked_up).unwrap(); + assert!(offset[1] < -0.1, "expected downward shift, got {offset:?}"); + assert!(offset[0].abs() < 1e-6); + } + + /// A view swung right round has nothing sensible to show. + #[test] + fn facing_away_has_no_offset() { + let identity = [0.0, 0.0, 0.0, 1.0]; + let behind = [0.0, 1.0, 0.0, 0.0]; + assert!(reprojection_offset(identity, behind).is_none()); + } +} diff --git a/environment/publication-source/source-snapshot/src/shaders/grid_view.wgsl b/environment/publication-source/source-snapshot/src/shaders/grid_view.wgsl new file mode 100644 index 0000000000000000000000000000000000000000..3955a4fb711c294d530a15bbb3cc8ce7c1433664 --- /dev/null +++ b/environment/publication-source/source-snapshot/src/shaders/grid_view.wgsl @@ -0,0 +1,73 @@ +// The feature grid, drawn as a head-locked 2D overlay. +// +// A quad in clip space with a per-eye scale and offset. No 3D: the content +// is flat and pinned to the head, so nothing here needs a view or a +// projection matrix. +// +// The per-eye transform is not optional decoration, though. A headset's +// frusta are asymmetric — the view axis is not at the centre of the eye +// buffer, and the two eyes differ — so painting identical pixels into both +// buffers puts the same content at different apparent angles and the views +// refuse to fuse. `offset` recentres on each eye's view axis; `scale` sizes +// the image to the angle the camera actually saw, instead of stretching it +// across the whole display and looking zoomed. + +struct Params { + scale: vec2, + offset: vec2, + grid: u32, + pad0: u32, + pad1: u32, + pad2: u32, +}; +var params: Params; +var cells: array; + +struct VsOut { + @builtin(position) position: vec4, + @location(0) uv: vec2, +}; + +@vertex +fn vs_main(@builtin(vertex_index) vi: u32) -> VsOut { + // Two triangles over the unit square. + var xs = array(-1.0, 1.0, -1.0, -1.0, 1.0, 1.0); + var ys = array(-1.0, -1.0, 1.0, 1.0, -1.0, 1.0); + let x = xs[vi]; + let y = ys[vi]; + + var out: VsOut; + out.position = vec4( + x * params.scale.x + params.offset.x, + y * params.scale.y + params.offset.y, + 0.0, + 1.0, + ); + // Blade uses a negative-height viewport, so clip +y is the top of the + // framebuffer. Row 0 of the grid is the top of the image, so v runs + // opposite to y. + out.uv = vec2(x * 0.5 + 0.5, 0.5 - y * 0.5); + return out; +} + +fn cell(ix: i32, iy: i32) -> vec3 { + let g = i32(params.grid); + let x = clamp(ix, 0, g - 1); + let y = clamp(iy, 0, g - 1); + let base = u32((y * g + x) * 3); + return vec3(cells[base], cells[base + 1u], cells[base + 2u]); +} + +@fragment +fn fs_main(in: VsOut) -> @location(0) vec4 { + let p = in.uv * f32(params.grid) - 0.5; + let corner = floor(p); + let frac = p - corner; + let ix = i32(corner.x); + let iy = i32(corner.y); + + let top = mix(cell(ix, iy), cell(ix + 1, iy), frac.x); + let bottom = mix(cell(ix, iy + 1), cell(ix + 1, iy + 1), frac.x); + let rgb = clamp(mix(top, bottom, frac.y), vec3(0.0), vec3(1.0)); + return vec4(rgb, 1.0); +} diff --git a/environment/publication-source/source-snapshot/src/source.rs b/environment/publication-source/source-snapshot/src/source.rs new file mode 100644 index 0000000000000000000000000000000000000000..4bd31ce8fc891eb754651bad8426073b1c4b6883 --- /dev/null +++ b/environment/publication-source/source-snapshot/src/source.rs @@ -0,0 +1,289 @@ +//! Where frames come from. +//! +//! The passthrough camera is not wired up yet, so this exists mainly as the +//! seam it will slot into: the XR loop pulls from a [`FrameSource`] and does +//! not care whether the pixels came from a camera or were made up. +//! +//! Until then [`TestPattern`] provides something with real spatial +//! structure. That matters more than it sounds — a flat or noisy image +//! makes every patch feature statistically identical, so the PCA colouring +//! would look plausible while proving nothing. A scene with distinct +//! regions shows immediately whether features are tracking content. + +/// A source of square RGB8 frames at the encoder's input resolution. +pub trait FrameSource { + /// Side length in pixels; must match `Config::image_size`. + fn size(&self) -> usize; + + /// The next frame as interleaved RGB8, `[size, size, 3]`, or `None` + /// when nothing new is available. + fn next_frame(&mut self) -> Option<&[u8]>; +} + +/// A moving synthetic scene: coloured discs drifting over a gradient, with +/// a checkerboard patch for high-frequency contrast. +/// +/// Deliberately built from a few large, distinctly-coloured regions, since +/// that is what DINO features separate well and therefore what makes the +/// PCA view legible while bringing the pipeline up. +pub struct TestPattern { + size: usize, + buf: Vec, + frame: u32, +} + +impl TestPattern { + pub fn new(size: usize) -> Self { + Self { + size, + buf: vec![0; size * size * 3], + frame: 0, + } + } + + fn render(&mut self) { + let size = self.size; + let t = self.frame as f32 * 0.02; + // Three discs on circular paths, each a saturated primary so the + // top principal components have something unambiguous to separate. + let discs = [ + (0.30 + 0.18 * t.cos(), 0.30 + 0.18 * t.sin(), 0.16, [230u8, 60, 50]), + (0.70 + 0.15 * (t * 0.7 + 2.0).cos(), 0.35 + 0.15 * (t * 0.7).sin(), 0.13, [60, 200, 90]), + (0.50 + 0.20 * (t * 0.5 + 4.0).sin(), 0.72 + 0.10 * (t * 0.9).cos(), 0.15, [70, 110, 235]), + ]; + + for y in 0..size { + let v = y as f32 / size as f32; + for x in 0..size { + let u = x as f32 / size as f32; + + // Background: a slow vertical gradient. + let mut rgb = [ + (40.0 + 60.0 * v) as u8, + (50.0 + 40.0 * (1.0 - v)) as u8, + (70.0 + 50.0 * v) as u8, + ]; + + // A checkerboard corner, for a region whose texture differs + // from everything else without its colour doing so. + if u > 0.72 && v > 0.72 { + let cell = ((x / 8) + (y / 8)) % 2; + let shade = if cell == 0 { 200 } else { 90 }; + rgb = [shade, shade, shade]; + } + + for &(cx, cy, r, color) in &discs { + let dx = u - cx; + let dy = v - cy; + if dx * dx + dy * dy < r * r { + rgb = color; + } + } + + let i = (y * size + x) * 3; + self.buf[i] = rgb[0]; + self.buf[i + 1] = rgb[1]; + self.buf[i + 2] = rgb[2]; + } + } + } +} + +impl FrameSource for TestPattern { + fn size(&self) -> usize { + self.size + } + + fn next_frame(&mut self) -> Option<&[u8]> { + self.render(); + self.frame = self.frame.wrapping_add(1); + Some(&self.buf) + } +} + +/// Centre-crop an interleaved RGBA image to a square and resample it down +/// to `size`, dropping alpha. +/// +/// Box-averaging rather than nearest: a patch embedding sees 16×16 pixels, +/// and point-sampling a 2560-wide screen down to 224 would alias hard +/// enough to change what the features encode. Cheap here — it runs once per +/// captured frame, not per patch. +pub fn square_downscale_rgba(rgba: &[u8], width: usize, height: usize, size: usize) -> Vec { + let side = width.min(height); + let x0 = (width - side) / 2; + let y0 = (height - side) / 2; + + let mut out = vec![0u8; size * size * 3]; + for oy in 0..size { + let sy0 = y0 + oy * side / size; + let sy1 = (y0 + (oy + 1) * side / size).max(sy0 + 1); + for ox in 0..size { + let sx0 = x0 + ox * side / size; + let sx1 = (x0 + (ox + 1) * side / size).max(sx0 + 1); + + let mut acc = [0u32; 3]; + let mut n = 0u32; + for sy in sy0..sy1.min(height) { + for sx in sx0..sx1.min(width) { + let i = (sy * width + sx) * 4; + acc[0] += rgba[i] as u32; + acc[1] += rgba[i + 1] as u32; + acc[2] += rgba[i + 2] as u32; + n += 1; + } + } + let n = n.max(1); + let o = (oy * size + ox) * 3; + for c in 0..3 { + out[o + c] = (acc[c] / n) as u8; + } + } + } + out +} + +/// Live screen capture. +/// +/// Exists mostly so the whole pipeline can be developed and demonstrated +/// without a headset: it is the same `FrameSource` contract the Quest +/// passthrough camera will implement, so the capture loop, colour handling, +/// and downscale are all exercised here first. +#[cfg(feature = "capture")] +pub struct ScreenCapture { + monitor: xcap::Monitor, + size: usize, + buf: Vec, +} + +#[cfg(feature = "capture")] +impl ScreenCapture { + /// Capture the monitor at `index`, or the primary one if out of range. + pub fn new(size: usize, index: usize) -> Result> { + let monitors = xcap::Monitor::all()?; + if monitors.is_empty() { + return Err("no monitors found".into()); + } + for (i, m) in monitors.iter().enumerate() { + log::info!( + "monitor {i}: {}x{}{}", + m.width().unwrap_or(0), + m.height().unwrap_or(0), + if i == index { " (selected)" } else { "" } + ); + } + let monitor = monitors + .into_iter() + .nth(index) + .ok_or("monitor index out of range")?; + Ok(Self { + monitor, + size, + buf: vec![128; size * size * 3], + }) + } +} + +#[cfg(feature = "capture")] +impl FrameSource for ScreenCapture { + fn size(&self) -> usize { + self.size + } + + fn next_frame(&mut self) -> Option<&[u8]> { + // A dropped frame is not worth failing over — the previous one is + // still displayable, and capture hiccups when windows change. + match self.monitor.capture_image() { + Ok(image) => { + let (w, h) = (image.width() as usize, image.height() as usize); + self.buf = square_downscale_rgba(&image.into_raw(), w, h, self.size); + Some(&self.buf) + } + Err(e) => { + log::warn!("screen capture failed: {e}"); + None + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn downscale_centre_crops_and_averages() { + // A 40×20 image: left half red, right half blue. The centre crop is + // the middle 20×20, which straddles the boundary evenly. + let (w, h) = (40usize, 20usize); + let mut rgba = vec![0u8; w * h * 4]; + for y in 0..h { + for x in 0..w { + let i = (y * w + x) * 4; + let c = if x < w / 2 { [255, 0, 0] } else { [0, 0, 255] }; + rgba[i..i + 3].copy_from_slice(&c); + rgba[i + 3] = 255; + } + } + + let out = square_downscale_rgba(&rgba, w, h, 4); + assert_eq!(out.len(), 4 * 4 * 3); + // Left column should be red, right column blue. + let px = |x: usize, y: usize| { + let i = (y * 4 + x) * 3; + [out[i], out[i + 1], out[i + 2]] + }; + assert_eq!(px(0, 0), [255, 0, 0], "left edge should be red"); + assert_eq!(px(3, 0), [0, 0, 255], "right edge should be blue"); + } + + #[test] + fn downscale_averages_rather_than_point_samples() { + // Alternating single-pixel columns must average to grey, not pick + // one extreme. Point sampling would give 0 or 255. + let (w, h) = (64usize, 64usize); + let mut rgba = vec![255u8; w * h * 4]; + for y in 0..h { + for x in 0..w { + let v = if x % 2 == 0 { 0 } else { 255 }; + let i = (y * w + x) * 4; + rgba[i..i + 3].copy_from_slice(&[v, v, v]); + } + } + let out = square_downscale_rgba(&rgba, w, h, 8); + for px in out.chunks_exact(3) { + assert!( + (100..=155).contains(&px[0]), + "expected mid-grey from averaging, got {}", + px[0] + ); + } + } + + #[test] + fn test_pattern_has_spatial_structure() { + let mut src = TestPattern::new(224); + let frame = src.next_frame().unwrap().to_vec(); + assert_eq!(frame.len(), 224 * 224 * 3); + + // A uniform image would make the whole exercise meaningless, so + // check there is real variation to encode. + let mean = frame.iter().map(|&b| b as f64).sum::() / frame.len() as f64; + let var = frame + .iter() + .map(|&b| (b as f64 - mean).powi(2)) + .sum::() + / frame.len() as f64; + assert!(var > 400.0, "test pattern is too flat: variance {var:.1}"); + } + + #[test] + fn test_pattern_animates() { + let mut src = TestPattern::new(64); + let a = src.next_frame().unwrap().to_vec(); + for _ in 0..20 { + src.next_frame(); + } + let b = src.next_frame().unwrap().to_vec(); + assert_ne!(a, b, "frames are identical; the scene is not moving"); + } +} diff --git a/environment/publication-source/source-snapshot/src/weights.rs b/environment/publication-source/source-snapshot/src/weights.rs new file mode 100644 index 0000000000000000000000000000000000000000..a0b7a2e4710b83532996a6a86fc3face691cec9e --- /dev/null +++ b/environment/publication-source/source-snapshot/src/weights.rs @@ -0,0 +1,172 @@ +//! Binding a HuggingFace DINOv3 checkpoint to the encoder graph's +//! parameters. +//! +//! Three shape conventions differ between the checkpoint and the graph, +//! and all three are handled here rather than in the graph: +//! +//! * `nn.Linear` stores `[out_features, in_features]`; meganeura's +//! `matmul` wants `[in, out]`. Every projection is transposed. +//! * The patch embedding is a 4D `[out, 3, k, k]` conv weight; it is +//! flattened to `[out, patch_dim]` and transposed. +//! * `cls_token` and `register_tokens` are separate parameters; the graph +//! declares one `prefix_tokens` matrix, assembled here. + +use meganeura::Session; +use meganeura::data::safetensors::SafeTensorsModel; + +use crate::dinov3::Config; +use crate::preprocess::conv_weight_to_matmul; + +type Error = Box; + +/// Checkpoints appear both with and without a `model.` prefix on the +/// encoder layers, depending on whether they were saved from +/// `DINOv3ViTModel` or from the bare backbone. Resolve whichever this one +/// uses once, up front, instead of guessing per tensor. +fn layer_prefix(model: &SafeTensorsModel) -> Result<&'static str, Error> { + let info = model.tensor_info(); + for candidate in ["layer.", "model.layer."] { + if info.keys().any(|k| k.starts_with(candidate)) { + return Ok(candidate); + } + } + Err(format!( + "no encoder layers found; checkpoint has {} tensors, e.g. {:?}", + info.len(), + info.keys().take(5).collect::>() + ) + .into()) +} + +/// Read a tensor under an optional `model.` prefix. +fn embedding_tensor(model: &SafeTensorsModel, name: &str) -> Result, Error> { + if model.tensor_info().contains_key(name) { + model.tensor_f32_auto(name) + } else { + model.tensor_f32_auto(&format!("model.{name}")) + } +} + +/// Upload every parameter the encoder graph declares. +/// +/// Fails loudly on a missing or mis-shaped tensor: a silently skipped +/// weight would leave a zero buffer and produce plausible-looking +/// garbage. +pub fn load_encoder( + session: &mut Session, + model: &SafeTensorsModel, + config: &Config, +) -> Result<(), Error> { + let hidden = config.hidden_size; + let prefix = layer_prefix(model)?; + log::info!("checkpoint layer prefix: {prefix:?}"); + + // --- Patch embedding: [out, 3, k, k] -> [patch_dim, out] --- + let conv = embedding_tensor(model, "embeddings.patch_embeddings.weight")?; + let expected = hidden * config.patch_dim(); + if conv.len() != expected { + return Err(format!( + "patch embedding has {} values, expected {expected} \ + (is the checkpoint's patch_size or hidden_size different?)", + conv.len() + ) + .into()); + } + session.set_parameter( + "embeddings.patch_embeddings.weight", + &conv_weight_to_matmul(&conv, hidden, config.patch_dim()), + ); + session.set_parameter( + "embeddings.patch_embeddings.bias", + &embedding_tensor(model, "embeddings.patch_embeddings.bias")?, + ); + + // --- Prefix tokens: CLS first, then the registers --- + // + // Order matters and is not arbitrary: the reference builds the + // sequence as cat([cls, registers, patches]), and RoPE identifies + // prefix tokens purely by their position at the front. + let cls = embedding_tensor(model, "embeddings.cls_token")?; + let registers = embedding_tensor(model, "embeddings.register_tokens")?; + if cls.len() != hidden { + return Err(format!("cls_token has {} values, expected {hidden}", cls.len()).into()); + } + if registers.len() != config.num_register_tokens * hidden { + return Err(format!( + "register_tokens has {} values, expected {} * {hidden}", + registers.len(), + config.num_register_tokens + ) + .into()); + } + let mut prefix_tokens = Vec::with_capacity(config.num_prefix_tokens() * hidden); + prefix_tokens.extend_from_slice(&cls); + prefix_tokens.extend_from_slice(®isters); + session.set_parameter("prefix_tokens", &prefix_tokens); + + // --- Encoder layers --- + for i in 0..config.num_hidden_layers { + let src = format!("{prefix}{i}"); + let dst = format!("layer.{i}"); + + for norm in ["norm1", "norm2"] { + for part in ["weight", "bias"] { + session.set_parameter( + &format!("{dst}.{norm}.{part}"), + &model.tensor_f32_auto(&format!("{src}.{norm}.{part}"))?, + ); + } + } + + // K has no bias — `key_bias: false` in the config. + for (proj, has_bias) in [ + ("q_proj", true), + ("k_proj", false), + ("v_proj", true), + ("o_proj", true), + ] { + session.set_parameter( + &format!("{dst}.attention.{proj}.weight"), + &model.tensor_f32_auto_transposed(&format!("{src}.attention.{proj}.weight"))?, + ); + if has_bias { + session.set_parameter( + &format!("{dst}.attention.{proj}.bias"), + &model.tensor_f32_auto(&format!("{src}.attention.{proj}.bias"))?, + ); + } + } + + for proj in ["up_proj", "down_proj"] { + session.set_parameter( + &format!("{dst}.mlp.{proj}.weight"), + &model.tensor_f32_auto_transposed(&format!("{src}.mlp.{proj}.weight"))?, + ); + session.set_parameter( + &format!("{dst}.mlp.{proj}.bias"), + &model.tensor_f32_auto(&format!("{src}.mlp.{proj}.bias"))?, + ); + } + + for ls in ["layer_scale1", "layer_scale2"] { + session.set_parameter( + &format!("{dst}.{ls}.lambda1"), + &model.tensor_f32_auto(&format!("{src}.{ls}.lambda1"))?, + ); + } + } + + // --- Final norm --- + for part in ["weight", "bias"] { + session.set_parameter( + &format!("norm.{part}"), + &embedding_tensor(model, &format!("norm.{part}"))?, + ); + } + + log::info!( + "loaded DINOv3 weights: {} layers, hidden {hidden}", + config.num_hidden_layers + ); + Ok(()) +} diff --git a/environment/publication-source/source-snapshot/tests/dinov3_ops.rs b/environment/publication-source/source-snapshot/tests/dinov3_ops.rs new file mode 100644 index 0000000000000000000000000000000000000000..7e911f1c20f4aaeec4c6e7f309bff6bd8aab7a47 --- /dev/null +++ b/environment/publication-source/source-snapshot/tests/dinov3_ops.rs @@ -0,0 +1,142 @@ +//! Numerical checks at the exact tensor shapes used by DINOv3. + +use meganeura::Graph; +use meganeura::train::{Mode, SessionConfig}; + +#[test] +fn full_attention_matches_cpu_at_dinov3_shape() { + let sequence = 201usize; + let heads = 6usize; + let head_dim = 64usize; + let hidden = heads * head_dim; + + let mut graph = Graph::new(); + let q_node = graph.input("q", &[sequence, hidden]); + let k_node = graph.input("k", &[sequence, hidden]); + let v_node = graph.input("v", &[sequence, hidden]); + let output = graph.full_attention( + q_node, + k_node, + v_node, + heads as u32, + heads as u32, + head_dim as u32, + ); + graph.set_outputs(vec![output]); + + let q: Vec = (0..sequence * hidden) + .map(|i| (i as f32 * 0.013).sin() * 0.2) + .collect(); + let k: Vec = (0..sequence * hidden) + .map(|i| (i as f32 * 0.017 + 0.3).cos() * 0.2) + .collect(); + let v: Vec = (0..sequence * hidden) + .map(|i| (i as f32 * 0.019 - 0.2).sin() * 0.2) + .collect(); + + let mut expected = vec![0.0f32; sequence * hidden]; + let scale = 1.0 / (head_dim as f32).sqrt(); + for query in 0..sequence { + for head in 0..heads { + let offset = head * head_dim; + let mut scores = vec![0.0f32; sequence]; + for key in 0..sequence { + scores[key] = (0..head_dim) + .map(|dimension| { + q[query * hidden + offset + dimension] + * k[key * hidden + offset + dimension] + }) + .sum::() + * scale; + } + let maximum = scores.iter().copied().fold(f32::NEG_INFINITY, f32::max); + let denominator: f32 = scores.iter().map(|score| (*score - maximum).exp()).sum(); + for dimension in 0..head_dim { + expected[query * hidden + offset + dimension] = scores + .iter() + .enumerate() + .map(|(key, score)| { + (*score - maximum).exp() * v[key * hidden + offset + dimension] + }) + .sum::() + / denominator; + } + } + } + + let gpu = dinovision::init_context(None).expect("GPU context"); + let (mut session, _) = meganeura::train::build( + &graph, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + session.set_input("q", &q); + session.set_input("k", &k); + session.set_input("v", &v); + session.step(); + session.wait(); + let actual = session.read_output(expected.len()); + let maximum_error = actual + .iter() + .zip(&expected) + .map(|(a, b)| (a - b).abs()) + .fold(0.0f32, f32::max); + assert!( + maximum_error < 2e-4, + "full attention differs by {maximum_error} at DINOv3 shape" + ); +} + +#[test] +fn trailing_layer_scale_matches_cpu_at_dinov3_shape() { + let tokens = 201usize; + let hidden = 384usize; + let mut graph = Graph::new(); + let input = graph.input("input", &[tokens, hidden]); + let gain = graph.input("gain", &[hidden]); + let transposed = graph.transpose(input); + let flat = graph.reshape(transposed, &[hidden * tokens]); + let scaled = graph.mul_per_channel(flat, gain, hidden as u32, tokens as u32); + let scaled = graph.reshape(scaled, &[hidden, tokens]); + let output = graph.transpose(scaled); + graph.set_outputs(vec![output]); + + let values: Vec = (0..tokens * hidden) + .map(|index| (index as f32 * 0.017).sin()) + .collect(); + let gains: Vec = (0..hidden) + .map(|index| 0.1 + index as f32 / hidden as f32) + .collect(); + let expected: Vec = values + .iter() + .enumerate() + .map(|(index, value)| value * gains[index % hidden]) + .collect(); + + let gpu = dinovision::init_context(None).expect("GPU context"); + let (mut session, _) = meganeura::train::build( + &graph, + SessionConfig { + mode: Mode::Inference, + gpu: Some(gpu), + ..Default::default() + }, + ); + session.set_input("input", &values); + session.set_input("gain", &gains); + session.step(); + session.wait(); + let actual = session.read_output(expected.len()); + let maximum_error = actual + .iter() + .zip(&expected) + .map(|(a, b)| (a - b).abs()) + .fold(0.0f32, f32::max); + assert!( + maximum_error < 1e-5, + "trailing LayerScale differs by {maximum_error}" + ); +} diff --git a/environment/publication-source/source-snapshot/tests/semantics.rs b/environment/publication-source/source-snapshot/tests/semantics.rs new file mode 100644 index 0000000000000000000000000000000000000000..9018880d165826e523f85b17348e3a4c2f1981dc --- /dev/null +++ b/environment/publication-source/source-snapshot/tests/semantics.rs @@ -0,0 +1,133 @@ +//! Do the features actually mean anything? +//! +//! The point of DINO features is that patches of the same thing land near +//! each other in feature space regardless of position, and patches of +//! different things do not. That property is what the PCA colouring +//! displays and what any downstream use would rely on, and it is +//! surprisingly sensitive to exactly the mistakes that are easy to make +//! here: a transposed projection, a mis-paired RoPE half, or a patch +//! flattening in the wrong channel order all leave the magnitudes looking +//! healthy while destroying the structure. +//! +//! So rather than compare against a reference dump — which would need +//! torch on the machine — this checks the property directly, using a scene +//! with known regions. +//! +//! Requires the checkpoint. Set `DINOVISION_WEIGHTS` to a +//! `model.safetensors`; without it the test reports itself skipped, since +//! failing for a missing asset would be noise. + +use dinovision::dinov3::Config; + +/// Cosine similarity, the metric DINO features are usually compared under. +fn cosine(a: &[f32], b: &[f32]) -> f32 { + let dot: f32 = a.iter().zip(b).map(|(x, y)| x * y).sum(); + let na: f32 = a.iter().map(|x| x * x).sum::().sqrt(); + let nb: f32 = b.iter().map(|x| x * x).sum::().sqrt(); + dot / (na * nb).max(f32::MIN_POSITIVE) +} + +/// A scene with four unambiguous regions, drawn as flat colour blocks so +/// the expected grouping is not a matter of opinion. Quadrants, at 224²: +/// top-left red, top-right green, bottom-left blue, bottom-right a fine +/// checkerboard (same mean colour as the background, different texture). +fn quadrant_scene(size: usize) -> Vec { + let mut rgb = vec![0u8; size * size * 3]; + let half = size / 2; + for y in 0..size { + for x in 0..size { + let px = match (x < half, y < half) { + (true, true) => [200, 40, 40], + (false, true) => [40, 180, 60], + (true, false) => [50, 70, 210], + (false, false) => { + let on = ((x / 4) + (y / 4)) % 2 == 0; + if on { [230, 230, 230] } else { [30, 30, 30] } + } + }; + let i = (y * size + x) * 3; + rgb[i..i + 3].copy_from_slice(&px); + } + } + rgb +} + +/// Index of the patch at grid position (gx, gy), skipping prefix tokens. +fn patch(features: &[f32], config: &Config, gx: usize, gy: usize) -> Vec { + let t = config.num_prefix_tokens() + gy * config.grid() + gx; + let h = config.hidden_size; + features[t * h..(t + 1) * h].to_vec() +} + +#[test] +fn features_group_by_content_not_position() { + let Ok(weights) = std::env::var("DINOVISION_WEIGHTS") else { + eprintln!("skipped: set DINOVISION_WEIGHTS to a model.safetensors to run this"); + return; + }; + let weights = std::path::PathBuf::from(weights); + if !weights.exists() { + eprintln!("skipped: {} does not exist", weights.display()); + return; + } + + let config = Config::vits16().at_resolution(224); + let gpu = dinovision::init_context(None).expect("GPU context"); + let (mut session, _) = dinovision::bench::build_encoder_session(gpu, &config, None); + let model = meganeura::data::safetensors::SafeTensorsModel::load(weights).expect("read weights"); + dinovision::weights::load_encoder(&mut session, &model, &config).expect("bind weights"); + + let rgb = quadrant_scene(config.image_size); + let patches = dinovision::preprocess::patches_from_rgb8(&rgb, &config); + session.set_input("patches", &patches); + session.step(); + session.wait(); + let features = session.read_output(config.num_tokens() * config.hidden_size); + assert!( + features.iter().all(|v| v.is_finite()), + "features contain non-finite values" + ); + + // Sample two well-separated patches inside each quadrant, staying away + // from the boundaries where receptive fields mix regions. + let g = config.grid(); + let q = g / 4; + let regions = [ + ("red", [(q, q), (q + 1, q + 1)]), + ("green", [(g - q - 1, q), (g - q - 2, q + 1)]), + ("blue", [(q, g - q - 1), (q + 1, g - q - 2)]), + ("checker", [(g - q - 1, g - q - 1), (g - q - 2, g - q - 2)]), + ]; + + // Within a region, two patches of the same material should be close. + let mut worst_within = 1.0f32; + for (name, pts) in ®ions { + let a = patch(&features, &config, pts[0].0, pts[0].1); + let b = patch(&features, &config, pts[1].0, pts[1].1); + let c = cosine(&a, &b); + eprintln!("within {name:>8}: {c:.3}"); + worst_within = worst_within.min(c); + } + + // Across regions, patches of different material should be further apart + // than any same-material pair. + let mut best_across = -1.0f32; + for i in 0..regions.len() { + for j in (i + 1)..regions.len() { + let a = patch(&features, &config, regions[i].1[0].0, regions[i].1[0].1); + let b = patch(&features, &config, regions[j].1[0].0, regions[j].1[0].1); + let c = cosine(&a, &b); + eprintln!("across {:>8}/{:<8}: {c:.3}", regions[i].0, regions[j].0); + best_across = best_across.max(c); + } + } + + eprintln!("worst within-region {worst_within:.3}, best across-region {best_across:.3}"); + assert!( + worst_within > best_across, + "features do not separate content: the least similar same-region pair \ + ({worst_within:.3}) scored below the most similar different-region pair \ + ({best_across:.3}). A scrambled patch order or transposed projection \ + looks exactly like this." + ); +} diff --git a/environment/publication-source/source-snapshot/tests/threading.rs b/environment/publication-source/source-snapshot/tests/threading.rs new file mode 100644 index 0000000000000000000000000000000000000000..c61090a643b30d1bc82bac694bdeef7be862f1b3 --- /dev/null +++ b/environment/publication-source/source-snapshot/tests/threading.rs @@ -0,0 +1,29 @@ +//! Compile-time constraints that dictate how inference is threaded. +//! +//! `blade_graphics::Context` is `Send + Sync` — it guards its queue, +//! memory manager, and XR session state behind mutexes — so an +//! `Arc` can be shared with a worker thread. +//! +//! `meganeura::Session` is **not** `Send`: it owns a +//! `blade_graphics::CommandEncoder`. The single offending field is +//! `ScratchBuffer::mapped`, a raw pointer into a persistently mapped +//! allocation — everything else is Vulkan handles, which are fine. (Rust has +//! no stable way to *assert* a negative, hence a comment not a test.) +//! +//! That is why [`dinovision::inference`] hands the worker an +//! `Arc` and has it construct the session in place. A one-line +//! `unsafe impl Send for ScratchBuffer` in blade lifts the constraint — +//! verified, and on the `command-encoder-send` branch there. + +fn assert_send() {} +fn assert_sync() {} + +#[test] +fn context_can_be_shared_across_threads() { + assert_send::(); + assert_sync::(); + // Buffer handles carry explicit `unsafe impl Send/Sync`, so GPU-side + // results can be published to the render thread by handle. + assert_send::(); + assert_sync::(); +} diff --git a/environment/publication-source/source-snapshot/tools/build_android_artifacts.ps1 b/environment/publication-source/source-snapshot/tools/build_android_artifacts.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..89a246106b4ca6d282ebb5181a931ddfbe8ea537 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/build_android_artifacts.ps1 @@ -0,0 +1,121 @@ +param( + [Parameter(Mandatory = $true)] + [string]$OutputDir, + [string]$AndroidSdk, + [string]$NdkRoot +) + +$ErrorActionPreference = 'Stop' +$repo = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path +if (-not $AndroidSdk) { + if (-not $env:LOCALAPPDATA) { throw 'pass -AndroidSdk when LOCALAPPDATA is unavailable' } + $AndroidSdk = Join-Path $env:LOCALAPPDATA 'Android\Sdk' +} +$sdk = (Resolve-Path $AndroidSdk).Path +if (-not $NdkRoot) { $NdkRoot = Join-Path $sdk 'ndk\27.0.12077973' } +$ndk = (Resolve-Path $NdkRoot).Path +$clang = Join-Path $ndk 'toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android34-clang.cmd' +$ar = Join-Path $ndk 'toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-ar.exe' +foreach ($tool in @($clang, $ar)) { + if (-not (Test-Path -LiteralPath $tool -PathType Leaf)) { throw "missing NDK tool: $tool" } +} +$sourceProperties = Get-Content -Raw -LiteralPath (Join-Path $ndk 'source.properties') +if ($sourceProperties -notmatch '(?m)^Pkg\.Revision\s*=\s*27\.') { + throw "DinoVision's API-34 camera build requires NDK r27; got $sourceProperties" +} + +$destination = [System.IO.Path]::GetFullPath($OutputDir) +if (Test-Path -LiteralPath $destination) { + if (@(Get-ChildItem -LiteralPath $destination -Force).Count -ne 0) { + throw "Refusing to merge Android build output into non-empty directory: $destination" + } +} else { + New-Item -ItemType Directory -Path $destination | Out-Null +} + +$env:ANDROID_HOME = $sdk +$env:ANDROID_SDK_ROOT = $sdk +$env:ANDROID_NDK_ROOT = $ndk +$env:ANDROID_NDK_HOME = $ndk +$env:CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER = $clang +$env:CC_aarch64_linux_android = $clang +$env:AR_aarch64_linux_android = $ar +$cargo = (Get-Command cargo).Source + +function Run-Cargo([string[]]$Arguments, [string]$Name) { + $process = Start-Process ` + -FilePath $cargo ` + -ArgumentList $Arguments ` + -NoNewWindow ` + -Wait ` + -PassThru ` + -RedirectStandardOutput (Join-Path $destination "$Name.stdout.log") ` + -RedirectStandardError (Join-Path $destination "$Name.stderr.log") + if ($process.ExitCode -ne 0) { + throw "$Name failed with code $($process.ExitCode)" + } +} + +Push-Location $repo +try { + Run-Cargo @( + 'build', '--locked', '--release', '--target', 'aarch64-linux-android', + '--example', 'bench', '--example', 'evaluate_decoder' + ) 'native-build' + Run-Cargo @('apk', 'build', '--release', '--package', 'dinovision-xr') 'apk-build' +} finally { + Pop-Location +} + +$built = [ordered]@{ + 'bench' = Join-Path $repo 'target\aarch64-linux-android\release\examples\bench' + 'evaluate_decoder' = Join-Path $repo 'target\aarch64-linux-android\release\examples\evaluate_decoder' + 'dinovision_xr.apk' = Join-Path $repo 'target\release\apk\dinovision_xr.apk' +} +$artifacts = @() +foreach ($entry in $built.GetEnumerator()) { + if (-not (Test-Path -LiteralPath $entry.Value -PathType Leaf)) { + throw "expected Android artifact is missing: $($entry.Value)" + } + $target = Join-Path $destination $entry.Key + Copy-Item -LiteralPath $entry.Value -Destination $target + $artifacts += [ordered]@{ + name = $entry.Key + bytes = (Get-Item -LiteralPath $target).Length + sha256 = (Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash.ToLowerInvariant() + } +} + +$buildTools = Get-ChildItem -LiteralPath (Join-Path $sdk 'build-tools') -Directory | + Sort-Object { [version]$_.Name } -Descending | + Select-Object -First 1 +$aapt = Join-Path $buildTools.FullName 'aapt.exe' +if (-not (Test-Path -LiteralPath $aapt -PathType Leaf)) { throw 'aapt.exe was not found' } +& $aapt dump badging (Join-Path $destination 'dinovision_xr.apk') | + Set-Content -LiteralPath (Join-Path $destination 'apk-badging.txt') -Encoding utf8 +if ($LASTEXITCODE -ne 0) { throw 'could not inspect the XR APK manifest' } +$badging = Get-Content -Raw -LiteralPath (Join-Path $destination 'apk-badging.txt') +if ($badging -notmatch "package: name='rust\.dinovision_xr'" -or + $badging -notmatch "launchable-activity: name='android\.app\.NativeActivity'") { + throw 'XR APK package/activity does not match the device harness defaults' +} + +$cargoApk = (Get-Command cargo-apk).Source +$record = [ordered]@{ + schema_version = 1 + completed_utc = [DateTime]::UtcNow.ToString('o') + target = 'aarch64-linux-android' + android_api = 34 + android_sdk = $sdk + ndk = $ndk + ndk_source_properties = $sourceProperties.Trim() + rustc = (& rustc --version --verbose) -join "`n" + cargo = (& $cargo --version --verbose) -join "`n" + cargo_apk_sha256 = (Get-FileHash -LiteralPath $cargoApk -Algorithm SHA256).Hash.ToLowerInvariant() + package = 'rust.dinovision_xr' + activity = 'android.app.NativeActivity' + artifacts = $artifacts +} +$record | ConvertTo-Json -Depth 6 | + Set-Content -LiteralPath (Join-Path $destination 'android-build.json') -Encoding utf8 +Write-Output "wrote checked Android artifacts to $destination" diff --git a/environment/publication-source/source-snapshot/tools/collect_artifact_metadata.ps1 b/environment/publication-source/source-snapshot/tools/collect_artifact_metadata.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..66bc2de3190cc8cbfa85556d7ee93290856618b0 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/collect_artifact_metadata.ps1 @@ -0,0 +1,156 @@ +param( + [Parameter(Mandatory = $true)] + [string]$OutputDir, + [string]$Model, + [string]$Decoder +) + +$ErrorActionPreference = 'Stop' +$git = 'C:\Portables\cmder\vendor\git-for-windows\cmd\git.exe' +$root = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path +$meganeura = (Resolve-Path (Join-Path $root '..\meganeura')).Path +$blade = (Resolve-Path (Join-Path $root '..\blade')).Path +$adbCandidates = @() +if ($env:LOCALAPPDATA) { + $adbCandidates += Join-Path $env:LOCALAPPDATA 'Android\Sdk\platform-tools\adb.exe' +} +if ($env:ANDROID_HOME) { + $adbCandidates += Join-Path $env:ANDROID_HOME 'platform-tools\adb.exe' +} +$adbCandidates = @($adbCandidates | Where-Object { Test-Path -LiteralPath $_ }) +$adb = if ($adbCandidates.Count -gt 0) { $adbCandidates[0] } else { $null } +$out = [System.IO.Path]::GetFullPath($OutputDir) +if (Test-Path -LiteralPath $out) { + if (@(Get-ChildItem -LiteralPath $out -Force).Count -ne 0) { + throw "Refusing to merge environment metadata into non-empty directory: $out" + } +} else { + New-Item -ItemType Directory -Path $out | Out-Null +} + +function Git-State([string]$repo) { + $revision = (& $git -C $repo rev-parse HEAD).Trim() + $branch = (& $git -C $repo branch --show-current).Trim() + $status = @(& $git -C $repo status --porcelain=v1) + [ordered]@{ + path = $repo + revision = $revision + branch = $branch + clean = $status.Count -eq 0 + status = $status + } +} + +$cargoMetadata = (& cargo metadata --format-version 1 --locked | ConvertFrom-Json) +$resolvedPackages = [ordered]@{} +foreach ($name in @('meganeura', 'blade-graphics')) { + $package = @($cargoMetadata.packages | Where-Object { $_.name -eq $name }) + $resolvedPackages[$name] = @( + $package | ForEach-Object { + [ordered]@{ + version = $_.version + source = $_.source + manifest_path = $_.manifest_path + } + } + ) +} + +$metadata = [ordered]@{ + schema_version = 1 + collected_utc = [DateTime]::UtcNow.ToString('o') + dinovision = Git-State $root + meganeura = Git-State $meganeura + blade_checkout = Git-State $blade + resolved_packages = $resolvedPackages + rustc = (& rustc --version --verbose) -join "`n" + cargo = (& cargo --version --verbose) -join "`n" + os = [System.Environment]::OSVersion.VersionString + android_ndk_root = $env:ANDROID_NDK_ROOT + android_ndks = if ($env:ANDROID_HOME) { + @( + Get-ChildItem -LiteralPath (Join-Path $env:ANDROID_HOME 'ndk') -Directory -ErrorAction SilentlyContinue | + Select-Object -ExpandProperty Name + ) + } else { @() } + nvidia_smi = if (Get-Command nvidia-smi -ErrorAction SilentlyContinue) { + (& nvidia-smi --query-gpu=name,driver_version --format=csv,noheader) -join "`n" + } else { $null } + adb = if ($adb) { (& $adb version) -join "`n" } else { $null } + model = $null + decoder = $null + quest_connected = $false +} + +# A Git revision alone is not sufficient while the experiment is being +# developed in a dirty tree. Preserve the exact tracked patch and hash every +# tracked or untracked, non-ignored source file. The paper freeze should be a +# clean commit; this fallback makes development runs auditable instead of +# silently attributing them to HEAD. +$workingPatch = Join-Path $out 'dinovision-working-tree.patch' +& $git -C $root diff --binary --no-ext-diff --output=$workingPatch HEAD +if ($LASTEXITCODE -ne 0) { throw 'could not preserve the DinoVision working-tree patch' } +$sourceFiles = @( + & $git -C $root ls-files --cached --others --exclude-standard | + Where-Object { $_ -and (Test-Path -LiteralPath (Join-Path $root $_)) } +) +$metadata.dinovision['working_patch_sha256'] = ( + Get-FileHash -LiteralPath $workingPatch -Algorithm SHA256 +).Hash.ToLowerInvariant() +$metadata.dinovision['source_files'] = @( + $sourceFiles | ForEach-Object { + $path = Join-Path $root $_ + [ordered]@{ + path = $_.Replace('\', '/') + bytes = (Get-Item -LiteralPath $path).Length + sha256 = (Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash.ToLowerInvariant() + } + } +) +$sourceSnapshot = Join-Path $out 'dinovision-source-snapshot' +foreach ($relative in $sourceFiles) { + $source = Join-Path $root $relative + $target = Join-Path $sourceSnapshot $relative + New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null + Copy-Item -LiteralPath $source -Destination $target +} + +foreach ($asset in @(@('model', $Model), @('decoder', $Decoder))) { + if ($asset[1] -and (Test-Path -LiteralPath $asset[1])) { + $file = Get-Item -LiteralPath $asset[1] + $metadata[$asset[0]] = [ordered]@{ + path = $file.FullName + bytes = $file.Length + sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $file.FullName).Hash.ToLowerInvariant() + } + } +} + +& cargo tree --locked | Set-Content -Encoding utf8 (Join-Path $out 'cargo-tree.txt') +Copy-Item -LiteralPath (Join-Path $root 'Cargo.lock') -Destination (Join-Path $out 'Cargo.lock') + +$deviceLines = if ($adb) { @(& $adb devices) } else { @() } +$connected = @($deviceLines | Select-Object -Skip 1 | Where-Object { $_ -match "`tdevice$" }) +if ($connected.Count -gt 0) { + $metadata.quest_connected = $true + & $adb shell getprop | Set-Content -Encoding utf8 (Join-Path $out 'quest-getprop.txt') + & $adb shell dumpsys thermalservice | Set-Content -Encoding utf8 (Join-Path $out 'quest-thermal.txt') + & $adb shell dumpsys battery | Set-Content -Encoding utf8 (Join-Path $out 'quest-battery.txt') + & $adb shell dumpsys power | Set-Content -Encoding utf8 (Join-Path $out 'quest-power.txt') + & $adb shell dumpsys SurfaceFlinger | Select-String -Pattern 'refresh|fps|Display' | + Set-Content -Encoding utf8 (Join-Path $out 'quest-display.txt') + $toggles = @( + 'raw_camera', 'mono', 'camera_half_fov_deg', + 'inference_interval_ms', 'submission_chunks', 'capture' + ) + $toggleState = [ordered]@{} + foreach ($toggle in $toggles) { + $path = "/data/local/tmp/dinovision/$toggle" + $value = (& $adb shell "if [ -e '$path' ]; then cat '$path' 2>/dev/null || echo ''; else echo ''; fi").Trim() + $toggleState[$toggle] = $value + } + $toggleState | ConvertTo-Json -Depth 4 | Set-Content -Encoding utf8 (Join-Path $out 'quest-runtime-toggles.json') +} + +$metadata | ConvertTo-Json -Depth 8 | Set-Content -Encoding utf8 (Join-Path $out 'metadata.json') +Write-Output "wrote metadata to $out" diff --git a/environment/publication-source/source-snapshot/tools/compare_f32.py b/environment/publication-source/source-snapshot/tools/compare_f32.py new file mode 100644 index 0000000000000000000000000000000000000000..3d22b1bc6a639adc6f4aefc80af5c1fc0a1f66be --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/compare_f32.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +"""Compare two raw little-endian f32 tensors and emit an auditable record.""" + +from __future__ import annotations + +import argparse +import array +import hashlib +import json +import math +import sys +from pathlib import Path + + +def read_tensor(path: Path) -> array.array[float]: + data = path.read_bytes() + if len(data) % 4: + raise SystemExit(f"{path} is not a whole number of f32 values") + values = array.array("f") + values.frombytes(data) + if sys.byteorder != "little": + values.byteswap() + return values + + +def sha256(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("reference", type=Path) + parser.add_argument("candidate", type=Path) + parser.add_argument("--output", required=True, type=Path) + parser.add_argument("--max-relative-l2", type=float) + parser.add_argument("--min-cosine", type=float) + parser.add_argument("--row-size", type=int) + parser.add_argument("--min-row-cosine", type=float) + args = parser.parse_args() + if args.min_row_cosine is not None and args.row_size is None: + raise SystemExit("--min-row-cosine requires --row-size") + + reference = read_tensor(args.reference) + candidate = read_tensor(args.candidate) + if len(reference) != len(candidate): + raise SystemExit( + f"length mismatch: {args.reference} has {len(reference)}, " + f"{args.candidate} has {len(candidate)}" + ) + + squared_error = 0.0 + squared_reference = 0.0 + squared_candidate = 0.0 + dot = 0.0 + absolute_error = 0.0 + max_absolute_error = -1.0 + max_absolute_index = 0 + for index, (expected, actual) in enumerate(zip(reference, candidate)): + difference = float(actual) - float(expected) + squared_error += difference * difference + squared_reference += float(expected) * float(expected) + squared_candidate += float(actual) * float(actual) + dot += float(expected) * float(actual) + absolute_error += abs(difference) + if abs(difference) > max_absolute_error: + max_absolute_error = abs(difference) + max_absolute_index = index + + relative_l2 = math.sqrt(squared_error) / max(math.sqrt(squared_reference), sys.float_info.min) + cosine = dot / max( + math.sqrt(squared_reference) * math.sqrt(squared_candidate), + sys.float_info.min, + ) + row_metrics = None + if args.row_size is not None: + if args.row_size <= 0 or len(reference) % args.row_size: + raise SystemExit("--row-size must be positive and divide the tensor length") + minimum_cosine = math.inf + minimum_cosine_row = 0 + maximum_relative_l2 = -math.inf + maximum_relative_l2_row = 0 + for row in range(len(reference) // args.row_size): + start = row * args.row_size + end = start + args.row_size + row_reference = reference[start:end] + row_candidate = candidate[start:end] + row_dot = sum(float(a) * float(b) for a, b in zip(row_reference, row_candidate)) + row_reference_squared = sum(float(value) ** 2 for value in row_reference) + row_candidate_squared = sum(float(value) ** 2 for value in row_candidate) + row_error_squared = sum( + (float(actual) - float(expected)) ** 2 + for expected, actual in zip(row_reference, row_candidate) + ) + row_cosine = row_dot / max( + math.sqrt(row_reference_squared) * math.sqrt(row_candidate_squared), + sys.float_info.min, + ) + row_relative_l2 = math.sqrt(row_error_squared) / max( + math.sqrt(row_reference_squared), sys.float_info.min + ) + if row_cosine < minimum_cosine: + minimum_cosine = row_cosine + minimum_cosine_row = row + if row_relative_l2 > maximum_relative_l2: + maximum_relative_l2 = row_relative_l2 + maximum_relative_l2_row = row + row_metrics = { + "row_size": args.row_size, + "rows": len(reference) // args.row_size, + "minimum_cosine": minimum_cosine, + "minimum_cosine_row": minimum_cosine_row, + "maximum_relative_l2": maximum_relative_l2, + "maximum_relative_l2_row": maximum_relative_l2_row, + } + checks = { + "max_relative_l2": ( + None + if args.max_relative_l2 is None + else relative_l2 <= args.max_relative_l2 + ), + "min_cosine": ( + None if args.min_cosine is None else cosine >= args.min_cosine + ), + "min_row_cosine": ( + None + if args.min_row_cosine is None + else row_metrics is not None + and row_metrics["minimum_cosine"] >= args.min_row_cosine + ), + } + passed = all(value is not False for value in checks.values()) + record = { + "schema_version": 1, + "reference": str(args.reference).replace("\\", "/"), + "reference_sha256": sha256(args.reference), + "candidate": str(args.candidate).replace("\\", "/"), + "candidate_sha256": sha256(args.candidate), + "elements": len(reference), + "relative_l2": relative_l2, + "cosine": cosine, + "mean_absolute_error": absolute_error / len(reference), + "max_absolute_error": max_absolute_error, + "max_absolute_index": max_absolute_index, + "thresholds": { + "max_relative_l2": args.max_relative_l2, + "min_cosine": args.min_cosine, + "min_row_cosine": args.min_row_cosine, + }, + "row_metrics": row_metrics, + "checks": checks, + "passed": passed, + } + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(record, indent=2) + "\n", encoding="utf-8") + row_text = ( + "" + if row_metrics is None + else f", minimum row cosine {row_metrics['minimum_cosine']:.9f}" + ) + print( + f"relative L2 {relative_l2:.6g}, cosine {cosine:.9f}{row_text}, " + f"max abs {max_absolute_error:.6g} at {max_absolute_index}: " + f"{'PASS' if passed else 'FAIL'}" + ) + if not passed: + raise SystemExit(1) + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/convert_decoder.py b/environment/publication-source/source-snapshot/tools/convert_decoder.py new file mode 100644 index 0000000000000000000000000000000000000000..95c8f823e2142712369b84c48d7eff565c257464 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/convert_decoder.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Convert DinoVision's runtime decoder.bin into named SafeTensors.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path + +import numpy as np +from safetensors.numpy import load_file, save_file + + +STAGES = (256, 128, 64, 32) +BLEND_STAGES = 2 + + +def sha256(path: Path) -> str: + hasher = hashlib.sha256() + with path.open("rb") as source: + for chunk in iter(lambda: source.read(1024 * 1024), b""): + hasher.update(chunk) + return hasher.hexdigest() + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--training", required=True, type=Path) + parser.add_argument("--input", type=Path) + parser.add_argument("--output", required=True, type=Path) + args = parser.parse_args() + + training = json.loads(args.training.read_text(encoding="utf-8")) + source = args.input or args.training.parent / "decoder.bin" + source_hash = sha256(source) + if source_hash != training["decoder_sha256"]: + raise SystemExit( + f"{source} has SHA-256 {source_hash}; training record expects " + f"{training['decoder_sha256']}" + ) + + flat = np.fromfile(source, dtype=" None: + nonlocal offset + count = int(np.prod(shape)) + end = offset + count + if end > len(flat): + raise SystemExit(f"{source} ends inside tensor {name}") + tensors[name] = flat[offset:end].reshape(shape).copy() + offset = end + + def block(name: str, in_channels: int, out_channels: int) -> None: + take(f"{name}.weight", (out_channels, in_channels, 3, 3)) + take(f"{name}.bias", (out_channels,)) + take(f"{name}.norm.weight", (out_channels,)) + take(f"{name}.norm.bias", (out_channels,)) + + in_channels = 384 + for index, out_channels in enumerate(STAGES): + block(f"dec.{index}", in_channels, out_channels) + if index < BLEND_STAGES: + block(f"dec.{index}b", out_channels, out_channels) + in_channels = out_channels + take("dec.out.weight", (3, in_channels, 3, 3)) + take("dec.out.bias", (3,)) + if offset != len(flat): + raise SystemExit(f"{source} has {len(flat) - offset} trailing f32 values") + + metadata = { + "format": "dinovision-decoder-v1", + "source_decoder_sha256": source_hash, + "model_sha256": training["model_sha256"], + "dataset_manifest_sha256": training["dataset_manifest_sha256"], + "encoder_layers": str(training["encoder_layers"]), + "image_size": str(training["image_size"]), + "seed": str(training["seed"]), + "objective": training["objective"], + } + args.output.parent.mkdir(parents=True, exist_ok=True) + save_file(tensors, args.output, metadata=metadata) + loaded = load_file(args.output) + for name, expected in tensors.items(): + if name not in loaded or not np.array_equal(expected, loaded[name]): + raise SystemExit(f"SafeTensors roundtrip changed tensor {name}") + print( + f"wrote {args.output}: {len(tensors)} named tensors, " + f"SHA-256 {sha256(args.output)}" + ) + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/dump_reference.py b/environment/publication-source/source-snapshot/tools/dump_reference.py new file mode 100644 index 0000000000000000000000000000000000000000..49b578009939236cdc9e81fb21cb2ce3eefc1a84 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/dump_reference.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python3 +"""Dump a DINOv3 reference forward pass for `cargo run --example verify`. + +Writes three files into the output directory: + + pixel_values.bin f32 [3, S, S] the preprocessed input tensor + features.bin f32 [tokens, 384] expected last_hidden_state + model.safetensors weights, in the graph's naming + +Dumping the *preprocessed* pixel tensor rather than an image is deliberate: +it keeps resize and normalization differences out of the comparison, so a +mismatch in `verify` is a mismatch in the graph, not in the resampling +filter. + +Saving the state dict here rather than downloading it in Rust also means +`verify` needs no Hub access and no license acceptance at run time. + + pip install torch transformers safetensors pillow numpy + huggingface-cli login # facebook/... is license-gated + python tools/dump_reference.py --out ref/ + +The weights are gated. Accept the DINOv3 license on the canonical model page +and authenticate with Hugging Face before running this script. +""" + +import argparse +import hashlib +import json +import pathlib + +import numpy as np +import torch +import transformers +from safetensors.torch import save_file +from transformers import AutoModel +from transformers.models.dinov3_vit.modeling_dinov3_vit import ( + apply_rotary_pos_emb, + eager_attention_forward, +) + +DEFAULT_MODEL = "facebook/dinov3-vits16-pretrain-lvd1689m" +IMAGE_MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32) +IMAGE_STD = np.array([0.229, 0.224, 0.225], dtype=np.float32) + + +def build_input(size: int, image: str | None) -> np.ndarray: + """Return a normalized f32 CHW tensor.""" + if image is not None: + from PIL import Image + + rgb = Image.open(image).convert("RGB").resize((size, size), Image.BILINEAR) + hwc = np.asarray(rgb, dtype=np.float32) / 255.0 + else: + # A smooth, deterministic pattern. Smooth matters: white noise makes + # every patch statistically identical, which would hide a bug in the + # patch ordering or in the position encoding. + ys, xs = np.mgrid[0:size, 0:size].astype(np.float32) + u, v = xs / size, ys / size + hwc = np.stack( + [ + 0.5 + 0.5 * np.sin(6.0 * u + 2.0 * v), + 0.5 + 0.5 * np.sin(4.0 * v - 3.0 * u * v), + 0.5 + 0.5 * np.cos(5.0 * u * v + u), + ], + axis=-1, + ).astype(np.float32) + + chw = ((hwc - IMAGE_MEAN) / IMAGE_STD).transpose(2, 0, 1) + return np.ascontiguousarray(chw, dtype=np.float32) + + +def main() -> None: + ap = argparse.ArgumentParser() + ap.add_argument("--out", default="ref", type=pathlib.Path) + ap.add_argument("--model", default=DEFAULT_MODEL) + ap.add_argument("--size", type=int, default=224) + ap.add_argument( + "--layers", + type=int, + default=12, + help="number of leading encoder layers to execute before the final norm", + ) + ap.add_argument("--image", default=None, help="optional real photo instead of a test pattern") + args = ap.parse_args() + + if args.size % 16: + raise SystemExit(f"--size {args.size} is not a multiple of the patch size (16)") + + args.out.mkdir(parents=True, exist_ok=True) + + model = AutoModel.from_pretrained(args.model, dtype=torch.float32).eval() + cfg = model.config + print( + f"{args.model}: {cfg.num_hidden_layers} layers, hidden {cfg.hidden_size}, " + f"{cfg.num_register_tokens} register tokens, gated_mlp={cfg.use_gated_mlp}" + ) + if cfg.use_gated_mlp: + raise SystemExit("the Rust graph implements the plain MLP only (ViT-S/B)") + if not 0 <= args.layers <= cfg.num_hidden_layers: + raise SystemExit( + f"--layers must be in [0, {cfg.num_hidden_layers}], got {args.layers}" + ) + + chw = build_input(args.size, args.image) + pixels = torch.from_numpy(chw)[None] + with torch.no_grad(): + hidden_states = model.embeddings(pixels) + embeddings = hidden_states[0].numpy().astype(np.float32) + position_embeddings = model.rope_embeddings(pixels) + first_layer = model.model.layer[0] + first_norm1 = first_layer.norm1(hidden_states) + first_q = first_layer.attention.q_proj(first_norm1) + first_k = first_layer.attention.k_proj(first_norm1) + first_v = first_layer.attention.v_proj(first_norm1) + tokens = first_q.shape[1] + heads = cfg.num_attention_heads + head_dim = cfg.hidden_size // heads + q_heads = first_q.view(1, tokens, heads, head_dim).transpose(1, 2) + k_heads = first_k.view(1, tokens, heads, head_dim).transpose(1, 2) + v_heads = first_v.view(1, tokens, heads, head_dim).transpose(1, 2) + q_rope, k_rope = apply_rotary_pos_emb( + q_heads, k_heads, *position_embeddings + ) + first_attention, _ = eager_attention_forward( + first_layer.attention, + q_rope, + k_rope, + v_heads, + None, + scaling=first_layer.attention.scaling, + ) + first_attention = first_attention.reshape(1, tokens, cfg.hidden_size) + first_attention_projected = first_layer.attention.o_proj(first_attention) + first_attention_scaled = first_layer.layer_scale1( + first_attention_projected + ) + first_residual = hidden_states + first_attention_scaled + first_norm2 = first_layer.norm2(first_residual) + first_mlp_up = first_layer.mlp.up_proj(first_norm2) + first_mlp_activated = first_layer.mlp.act_fn(first_mlp_up) + first_mlp_down = first_layer.mlp.down_proj(first_mlp_activated) + first_mlp_scaled = first_layer.layer_scale2(first_mlp_down) + first_output = first_residual + first_mlp_scaled + first_final_norm = model.norm(first_output) + for layer in model.model.layer[: args.layers]: + hidden_states = layer( + hidden_states, position_embeddings=position_embeddings + ) + features = model.norm(hidden_states)[0].numpy().astype(np.float32) + + grid = args.size // cfg.patch_size + expected_tokens = 1 + cfg.num_register_tokens + grid * grid + assert features.shape == (expected_tokens, cfg.hidden_size), features.shape + + (args.out / "pixel_values.bin").write_bytes(chw.tobytes()) + (args.out / "embeddings.bin").write_bytes( + np.ascontiguousarray(embeddings).tobytes() + ) + for name, tensor in { + "first-norm1.bin": first_norm1, + "first-q.bin": first_q, + "first-k.bin": first_k, + "first-v.bin": first_v, + "first-q-rope.bin": q_rope.transpose(1, 2).reshape( + 1, tokens, cfg.hidden_size + ), + "first-k-rope.bin": k_rope.transpose(1, 2).reshape( + 1, tokens, cfg.hidden_size + ), + "first-attention.bin": first_attention, + "first-attention-projected.bin": first_attention_projected, + "first-attention-scaled.bin": first_attention_scaled, + "first-residual.bin": first_residual, + "first-norm2.bin": first_norm2, + "first-mlp-up.bin": first_mlp_up, + "first-mlp-activated.bin": first_mlp_activated, + "first-mlp-down.bin": first_mlp_down, + "first-mlp-scaled.bin": first_mlp_scaled, + "first-output.bin": first_output, + "first-final-norm.bin": first_final_norm, + }.items(): + (args.out / name).write_bytes( + np.ascontiguousarray(tensor[0].numpy().astype(np.float32)).tobytes() + ) + (args.out / "features.bin").write_bytes(np.ascontiguousarray(features).tobytes()) + + # `save_file` rejects shared storage, which `state_dict()` can contain. + state = {k: v.contiguous().clone() for k, v in model.state_dict().items()} + save_file(state, str(args.out / "model.safetensors")) + + def sha256(path: pathlib.Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + local_model = pathlib.Path(args.model) + reference = { + "schema_version": 1, + "base_model": DEFAULT_MODEL if local_model.is_dir() else args.model, + "model_source": str(args.model), + "image_size": args.size, + "encoder_layers": args.layers, + "tokens": expected_tokens, + "hidden_size": cfg.hidden_size, + "torch_version": torch.__version__, + "transformers_version": transformers.__version__, + "numpy_version": np.__version__, + "pixel_values_sha256": sha256(args.out / "pixel_values.bin"), + "embeddings_sha256": sha256(args.out / "embeddings.bin"), + "features_sha256": sha256(args.out / "features.bin"), + "exported_model_sha256": sha256(args.out / "model.safetensors"), + } + if local_model.is_dir() and (local_model / "model.safetensors").is_file(): + reference["source_model_sha256"] = sha256( + local_model / "model.safetensors" + ) + (args.out / "reference.json").write_text( + json.dumps(reference, indent=2) + "\n", encoding="utf-8" + ) + + print( + f"wrote {args.out}/ — {args.layers} layers, {args.size}x{args.size}, " + f"{grid}x{grid} grid, {expected_tokens} tokens" + ) + print(f"features: mean {features.mean():+.4f} std {features.std():.4f}") + print(f"\nnow run: cargo run --release --example verify -- {args.out}") + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/extract_json_records.py b/environment/publication-source/source-snapshot/tools/extract_json_records.py new file mode 100644 index 0000000000000000000000000000000000000000..744cef271c3dd9163c9e8e3aec1fe4249b1068c7 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/extract_json_records.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""Extract prefixed JSON records from benchmark or logcat text files.""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--input", action="append", required=True, type=Path) + parser.add_argument("--marker", required=True) + parser.add_argument("--output", required=True, type=Path) + args = parser.parse_args() + + records: list[dict[str, object]] = [] + decoder = json.JSONDecoder() + for path in args.input: + for line_number, line in enumerate( + path.read_text(encoding="utf-8", errors="replace").splitlines(), start=1 + ): + marker_at = line.find(args.marker) + if marker_at < 0: + continue + payload = line[marker_at + len(args.marker) :].strip() + try: + record, consumed = decoder.raw_decode(payload) + except json.JSONDecodeError as error: + raise SystemExit(f"{path}:{line_number}: malformed record: {error}") from error + if payload[consumed:].strip(): + raise SystemExit(f"{path}:{line_number}: trailing text after JSON record") + if not isinstance(record, dict): + raise SystemExit(f"{path}:{line_number}: record is not a JSON object") + record["artifact_source"] = str(path).replace("\\", "/") + record["artifact_line"] = line_number + records.append(record) + + if not records: + raise SystemExit(f"no {args.marker!r} records found") + output = {"schema_version": 1, "marker": args.marker, "records": records} + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(output, indent=2) + "\n", encoding="utf-8") + print(f"wrote {args.output}: {len(records)} records") + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/make_correctness_frame.py b/environment/publication-source/source-snapshot/tools/make_correctness_frame.py new file mode 100644 index 0000000000000000000000000000000000000000..8a9402b20a1c567dabe606e02fe87f031eb86757 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/make_correctness_frame.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Generate the deterministic RGB8 frame used for host/device parity.""" + +from __future__ import annotations + +import argparse +import hashlib +from pathlib import Path + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--output", required=True, type=Path) + parser.add_argument("--size", type=int, default=224) + args = parser.parse_args() + if args.size <= 1 or args.size % 16: + raise SystemExit("--size must be greater than one and divisible by 16") + + pixels = bytearray() + center = (args.size - 1) / 2.0 + radius_squared = (args.size * 0.28) ** 2 + for y in range(args.size): + for x in range(args.size): + red = round(255 * x / (args.size - 1)) + green = round(255 * y / (args.size - 1)) + checker = 48 if ((x // 16) ^ (y // 16)) & 1 else 208 + in_circle = (x - center) ** 2 + (y - center) ** 2 < radius_squared + blue = 255 - checker if in_circle else checker + pixels.extend((red, green, blue)) + + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_bytes(pixels) + digest = hashlib.sha256(pixels).hexdigest() + print(f"wrote {args.output}: {len(pixels)} bytes, SHA-256 {digest}") + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/make_dataset_manifest.py b/environment/publication-source/source-snapshot/tools/make_dataset_manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..2f16b52350763fa7d7e3b3cd800a66cd42e2330f --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/make_dataset_manifest.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +"""Build a deterministic, leakage-checked DinoVision dataset manifest. + +Each --entry supplies SPLIT SOURCE GROUP PATH. PATH is resolved below --root. +All files in one capture session must share a GROUP, and a group may occur in +only one split. Identical bytes are rejected when they cross a split boundary. +Files from sibling directories are interleaved, so a limited training prefix +does not consist entirely of the lexicographically first class. + +Example: + python tools/make_dataset_manifest.py \ + --root data --output experiments/dataset.json \ + --entry train photo imagenette-train imagenette/train \ + --entry train capture room-a captures/room-a \ + --entry test capture room-b captures/room-b +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +from pathlib import Path + + +EXTENSIONS = {".jpeg", ".jpg", ".png", ".rgb"} + + +def digest(path: Path) -> str: + h = hashlib.sha256() + with path.open("rb") as f: + for chunk in iter(lambda: f.read(1024 * 1024), b""): + h.update(chunk) + return h.hexdigest() + + +def interleaved_images(directory: Path) -> list[Path]: + """Return a deterministic round-robin over leaf directories.""" + groups: dict[Path, list[Path]] = {} + for path in directory.rglob("*"): + if path.is_file() and path.suffix.lower() in EXTENSIONS: + groups.setdefault(path.parent, []).append(path) + ordered_groups = [sorted(groups[parent]) for parent in sorted(groups)] + result: list[Path] = [] + for index in range(max((len(group) for group in ordered_groups), default=0)): + result.extend(group[index] for group in ordered_groups if index < len(group)) + return result + + +def main() -> None: + ap = argparse.ArgumentParser() + ap.add_argument("--root", required=True, type=Path) + ap.add_argument("--output", required=True, type=Path) + ap.add_argument("--name", default="dinovision") + ap.add_argument( + "--entry", + nargs=4, + action="append", + metavar=("SPLIT", "SOURCE", "GROUP", "PATH"), + required=True, + ) + ap.add_argument( + "--provenance", + nargs=3, + action="append", + default=[], + metavar=("NAME", "URL", "SHA256"), + help="record an immutable source archive without downloading it", + ) + args = ap.parse_args() + + root = args.root.resolve() + output = args.output.resolve() + for name, _, sha256 in args.provenance: + if len(sha256) != 64 or any(c not in "0123456789abcdef" for c in sha256.lower()): + raise SystemExit(f"provenance {name} has an invalid SHA-256: {sha256}") + images: list[dict[str, object]] = [] + group_splits: dict[tuple[str, str], str] = {} + hash_entries: dict[str, dict[str, object]] = {} + + for split, source, group, relative in sorted(args.entry): + key = (source, group) + previous = group_splits.setdefault(key, split) + if previous != split: + raise SystemExit( + f"group {source}/{group} occurs in both {previous} and {split}" + ) + + directory = (root / relative).resolve() + try: + directory.relative_to(root) + except ValueError: + raise SystemExit(f"entry escapes --root: {directory}") from None + if not directory.is_dir(): + raise SystemExit(f"not a directory: {directory}") + paths = interleaved_images(directory) + if not paths: + raise SystemExit(f"no supported images below {directory}") + + for path in paths: + sha = digest(path) + old = hash_entries.get(sha) + if old is not None: + raise SystemExit( + "identical file occurs more than once: " + f"{old['path']} ({old['split']}) and {path} ({split})" + ) + item = { + "path": path.relative_to(root).as_posix(), + "split": split, + "source": source, + "group": group, + "sha256": sha, + "bytes": path.stat().st_size, + } + images.append(item) + hash_entries.setdefault(sha, item) + + try: + stored_root = Path(os.path.relpath(root, output.parent)).as_posix() + except ValueError: + stored_root = str(root) + manifest = { + "schema_version": 1, + "name": args.name, + "root": stored_root, + "provenance": [ + {"name": name, "url": url, "sha256": sha256} + for name, url, sha256 in args.provenance + ], + "images": images, + } + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8") + + counts: dict[str, int] = {} + for image in images: + counts[image["split"]] = counts.get(image["split"], 0) + 1 + print(f"wrote {output}: {len(images)} images, splits {counts}") + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/pull_quest_artifacts.ps1 b/environment/publication-source/source-snapshot/tools/pull_quest_artifacts.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..71ae609b89c5ea1f0be5c5c9ecd0a334d1ed7435 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/pull_quest_artifacts.ps1 @@ -0,0 +1,99 @@ +param( + [Parameter(Mandatory = $true)] + [string]$OutputDir +) + +$ErrorActionPreference = "Stop" + +function Relative-Path([string]$Base, [string]$Path) { + $basePath = [System.IO.Path]::GetFullPath($Base).TrimEnd([char[]]@('\', '/')) + $fullPath = [System.IO.Path]::GetFullPath($Path) + $prefix = $basePath + [System.IO.Path]::DirectorySeparatorChar + if (-not $fullPath.StartsWith($prefix, [System.StringComparison]::OrdinalIgnoreCase)) { + throw "$fullPath is not inside $basePath" + } + $fullPath.Substring($prefix.Length) +} + +$adbCandidates = @() +if ($env:LOCALAPPDATA) { + $adbCandidates += Join-Path $env:LOCALAPPDATA "Android\Sdk\platform-tools\adb.exe" +} +if ($env:ANDROID_HOME) { + $adbCandidates += Join-Path $env:ANDROID_HOME "platform-tools\adb.exe" +} +$adbCandidates = @($adbCandidates | Where-Object { Test-Path -LiteralPath $_ }) + +if ($adbCandidates.Count -eq 0) { + throw "adb.exe was not found under LOCALAPPDATA or ANDROID_HOME" +} +$adb = $adbCandidates[0] + +$devices = @(& $adb devices | Select-Object -Skip 1 | Where-Object { $_ -match "\tdevice$" }) +if ($devices.Count -ne 1) { + throw "Expected exactly one authorized device; found $($devices.Count). Check 'adb devices'." +} + +$destination = [System.IO.Path]::GetFullPath($OutputDir) +if (Test-Path -LiteralPath $destination) { + if (@(Get-ChildItem -LiteralPath $destination -Force).Count -ne 0) { + throw "Refusing to merge a recovery pull into non-empty directory: $destination" + } +} else { + New-Item -ItemType Directory -Path $destination | Out-Null +} + +$runtimeDir = Join-Path $destination "runtime" +$captureDir = Join-Path $destination "captures" +New-Item -ItemType Directory -Path $runtimeDir | Out-Null +New-Item -ItemType Directory -Path $captureDir | Out-Null + +$runtimeRemote = "/data/local/tmp/dinovision" +$capturesRemote = "/sdcard/Android/data/rust.dinovision_xr/files/captures" + +# adb pull is read-only on the headset. Pull the whole runtime directory first +# so unknown historical files are preserved rather than guessed at by name. +$runtimePresent = $false +& $adb shell "test -d $runtimeRemote" +if ($LASTEXITCODE -eq 0) { + $runtimePresent = $true + & $adb pull "$runtimeRemote/." $runtimeDir + if ($LASTEXITCODE -ne 0) { + throw "Failed to pull $runtimeRemote" + } +} + +$capturesPresent = $false +& $adb shell "test -d $capturesRemote" +if ($LASTEXITCODE -eq 0) { + $capturesPresent = $true + & $adb pull "$capturesRemote/." $captureDir + if ($LASTEXITCODE -ne 0) { + throw "Failed to pull $capturesRemote" + } +} + +$metadata = [ordered]@{ + schema_version = 1 + pulled_utc = [DateTime]::UtcNow.ToString("o") + device = (& $adb get-serialno).Trim() + product = (& $adb shell getprop ro.product.name).Trim() + model = (& $adb shell getprop ro.product.model).Trim() + build_fingerprint = (& $adb shell getprop ro.build.fingerprint).Trim() + runtime_directory_present = $runtimePresent + capture_directory_present = $capturesPresent + files = @( + Get-ChildItem -LiteralPath $destination -File -Recurse | ForEach-Object { + [ordered]@{ + path = (Relative-Path $destination $_.FullName).Replace("\", "/") + bytes = $_.Length + sha256 = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() + } + } + ) +} + +$manifestPath = Join-Path $destination "recovery_manifest.json" +$metadata | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $manifestPath -Encoding utf8 +Write-Host "Recovered $($metadata.files.Count) files to $destination" +Write-Host "Manifest: $manifestPath" diff --git a/environment/publication-source/source-snapshot/tools/run_cross_device_correctness.ps1 b/environment/publication-source/source-snapshot/tools/run_cross_device_correctness.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..4ae311badb7af7ab4f54a52ac2141857dabdd012 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/run_cross_device_correctness.ps1 @@ -0,0 +1,183 @@ +param( + [Parameter(Mandatory = $true)] + [string]$OutputDir, + [Parameter(Mandatory = $true)] + [string]$RecoveryManifest, + [Parameter(Mandatory = $true)] + [string]$Binary, + [Parameter(Mandatory = $true)] + [string]$CorrectnessRoot, + [Parameter(Mandatory = $true)] + [string]$HostSampleDir, + [Parameter(Mandatory = $true)] + [string]$Model, + [Parameter(Mandatory = $true)] + [string]$Decoder, + [int]$Layers = 3, + [int]$Size = 224 +) + +$ErrorActionPreference = 'Stop' +$repo = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path +$binaryPath = (Resolve-Path $Binary).Path +$rootPath = (Resolve-Path $CorrectnessRoot).Path +$hostSamples = (Resolve-Path $HostSampleDir).Path +$modelPath = (Resolve-Path $Model).Path +$decoderPath = (Resolve-Path $Decoder).Path +$recoveryPath = (Resolve-Path $RecoveryManifest).Path +$manifestPath = (Resolve-Path (Join-Path $rootPath 'manifests\correctness-224.json')).Path +$framePath = (Resolve-Path (Join-Path $rootPath 'input\frame.rgb')).Path +$destination = [System.IO.Path]::GetFullPath($OutputDir) +if (Test-Path -LiteralPath $destination) { + if (@(Get-ChildItem -LiteralPath $destination -Force).Count -ne 0) { + throw "Refusing to merge correctness output into non-empty directory: $destination" + } +} else { + New-Item -ItemType Directory -Path $destination | Out-Null +} + +$adbCandidates = @() +if ($env:LOCALAPPDATA) { + $adbCandidates += Join-Path $env:LOCALAPPDATA 'Android\Sdk\platform-tools\adb.exe' +} +if ($env:ANDROID_HOME) { + $adbCandidates += Join-Path $env:ANDROID_HOME 'platform-tools\adb.exe' +} +$adbCandidates = @($adbCandidates | Where-Object { Test-Path -LiteralPath $_ }) +if ($adbCandidates.Count -eq 0) { throw 'adb.exe was not found' } +$adb = $adbCandidates[0] +$devices = @(& $adb devices | Select-Object -Skip 1 | Where-Object { $_ -match "`tdevice$" }) +if ($devices.Count -ne 1) { throw "Expected one authorized device; found $($devices.Count)" } +$serial = (& $adb get-serialno).Trim() +$recovery = Get-Content -Raw -LiteralPath $recoveryPath | ConvertFrom-Json +if ($recovery.device -ne $serial) { + throw "Recovery manifest is for $($recovery.device), connected device is $serial" +} + +function Hash([string]$Path) { + (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant() +} + +$binaryHash = Hash $binaryPath +$modelHash = Hash $modelPath +$decoderHash = Hash $decoderPath +$hostQualityPath = Join-Path (Split-Path -Parent $hostSamples) 'quality.json' +if (-not (Test-Path -LiteralPath $hostQualityPath -PathType Leaf)) { + throw "host correctness record is missing: $hostQualityPath" +} +$hostQuality = Get-Content -Raw -LiteralPath $hostQualityPath | ConvertFrom-Json +if ($hostQuality.summary.count -ne 1 -or + $hostQuality.encoder_layers -ne $Layers -or + $hostQuality.image_size -ne $Size -or + $hostQuality.model_sha256 -ne $modelHash -or + $hostQuality.decoder_sha256 -ne $decoderHash -or + $hostQuality.manifest_sha256 -ne (Hash $manifestPath)) { + throw 'host correctness record does not match the requested fixed cell' +} +$stamp = [DateTime]::UtcNow.ToString('yyyyMMddTHHmmssZ') +$remoteRoot = "/data/local/tmp/dinovision-correctness/$stamp-$($decoderHash.Substring(0, 12))" +foreach ($subdirectory in @('', '/manifests', '/input', '/output')) { + & $adb shell "mkdir -p '$remoteRoot$subdirectory'" + if ($LASTEXITCODE -ne 0) { throw "could not create $remoteRoot$subdirectory" } +} + +$remoteFiles = [ordered]@{ + "$remoteRoot/evaluate_decoder" = $binaryPath + "$remoteRoot/model.safetensors" = $modelPath + "$remoteRoot/decoder.bin" = $decoderPath + "$remoteRoot/manifests/correctness-224.json" = $manifestPath + "$remoteRoot/input/frame.rgb" = $framePath +} +foreach ($entry in $remoteFiles.GetEnumerator()) { + & $adb push $entry.Value $entry.Key | Out-Null + if ($LASTEXITCODE -ne 0) { throw "could not push $($entry.Value)" } + $remoteHash = ((& $adb shell "sha256sum '$($entry.Key)'").Trim().Split(' ')[0]) + if ((Hash $entry.Value) -ne $remoteHash) { throw "hash mismatch for $($entry.Key)" } +} +& $adb shell "chmod 755 '$remoteRoot/evaluate_decoder'" +if ($LASTEXITCODE -ne 0) { throw 'could not mark evaluator executable' } + +& $adb shell dumpsys thermalservice | Set-Content -Encoding utf8 (Join-Path $destination 'before-thermal.txt') +& $adb shell dumpsys battery | Set-Content -Encoding utf8 (Join-Path $destination 'before-battery.txt') +& $adb shell dumpsys power | Set-Content -Encoding utf8 (Join-Path $destination 'before-power.txt') +$command = "cd '$remoteRoot' && RUST_LOG=warn ./evaluate_decoder " + + "--manifest manifests/correctness-224.json --model model.safetensors " + + "--decoder decoder.bin --split test --layers $Layers --size $Size " + + "--output output/quality.json --samples 1" +$oldErrorPreference = $ErrorActionPreference +try { + $ErrorActionPreference = 'Continue' + & $adb shell $command ` + 1> (Join-Path $destination 'device.stdout.log') ` + 2> (Join-Path $destination 'device.stderr.log') + $exitCode = $LASTEXITCODE +} finally { + $ErrorActionPreference = $oldErrorPreference +} +if ($exitCode -ne 0) { throw "device evaluator exited with code $exitCode" } + +$deviceOutput = Join-Path $destination 'device-output' +New-Item -ItemType Directory -Path $deviceOutput | Out-Null +& $adb pull "$remoteRoot/output/." $deviceOutput | Out-Null +if ($LASTEXITCODE -ne 0) { throw 'could not pull device correctness output' } +$deviceQualityPath = Join-Path $deviceOutput 'quality.json' +$deviceQuality = Get-Content -Raw -LiteralPath $deviceQualityPath | ConvertFrom-Json +if ($deviceQuality.summary.count -ne 1 -or + $deviceQuality.encoder_layers -ne $Layers -or + $deviceQuality.image_size -ne $Size -or + $deviceQuality.model_sha256 -ne $modelHash -or + $deviceQuality.decoder_sha256 -ne $decoderHash -or + $deviceQuality.manifest_sha256 -ne (Hash $manifestPath)) { + throw 'device correctness record does not match the pushed fixed cell' +} +& $adb shell dumpsys thermalservice | Set-Content -Encoding utf8 (Join-Path $destination 'after-thermal.txt') +& $adb shell dumpsys battery | Set-Content -Encoding utf8 (Join-Path $destination 'after-battery.txt') +& $adb shell dumpsys power | Set-Content -Encoding utf8 (Join-Path $destination 'after-power.txt') + +$deviceSamples = Join-Path $deviceOutput 'quality_samples' +$comparisons = Join-Path $destination 'comparisons' +New-Item -ItemType Directory -Path $comparisons | Out-Null +function Compare( + [string]$Name, + [double]$MaxRelativeL2, + [double]$MinCosine, + [int]$RowSize = 0, + [double]$MinRowCosine = 0.0 +) { + $arguments = @( + (Join-Path $hostSamples "0000-$Name.f32"), + (Join-Path $deviceSamples "0000-$Name.f32"), + '--output', (Join-Path $comparisons "$Name.json"), + '--max-relative-l2', "$MaxRelativeL2", + '--min-cosine', "$MinCosine" + ) + if ($RowSize -gt 0) { + $arguments += @('--row-size', "$RowSize", '--min-row-cosine', "$MinRowCosine") + } + & python (Join-Path $repo 'tools\compare_f32.py') @arguments + if ($LASTEXITCODE -ne 0) { throw "$Name comparison failed" } +} + +Compare 'patches' 0.0 0.999999999 +Compare 'encoder' 0.01 0.999 384 0.999 +Compare 'features' 0.01 0.999 +Compare 'reconstruction' 0.02 0.999 + +$metadata = [ordered]@{ + schema_version = 1 + completed_utc = [DateTime]::UtcNow.ToString('o') + device_serial = $serial + device_model = (& $adb shell getprop ro.product.model).Trim() + build_fingerprint = (& $adb shell getprop ro.build.fingerprint).Trim() + remote_root = $remoteRoot + encoder_layers = $Layers + image_size = $Size + binary_sha256 = $binaryHash + model_sha256 = $modelHash + decoder_sha256 = $decoderHash + manifest_sha256 = Hash $manifestPath + frame_sha256 = Hash $framePath + recovery_manifest_sha256 = Hash $recoveryPath +} +$metadata | ConvertTo-Json -Depth 5 | Set-Content -Encoding utf8 (Join-Path $destination 'correctness-metadata.json') +Write-Output "cross-device correctness passed; device files remain at $remoteRoot" diff --git a/environment/publication-source/source-snapshot/tools/run_decoder_matrix.ps1 b/environment/publication-source/source-snapshot/tools/run_decoder_matrix.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..b02eeff523e630329e4035e276076f5613773c56 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/run_decoder_matrix.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory = $true)] + [string]$Manifest, + [Parameter(Mandatory = $true)] + [string]$Model, + [Parameter(Mandatory = $true)] + [string]$OutputRoot, + [string[]]$Seeds = @('0', '1', '2'), + [int]$Steps = 12000, + [int]$Images = 2500, + [int]$Layers = 3, + [int]$Size = 224, + [string]$EvaluationSplit = "validation" +) + +$ErrorActionPreference = "Stop" +$repo = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +$manifestPath = (Resolve-Path $Manifest).Path +$modelPath = (Resolve-Path $Model).Path +$manifestHash = (Get-FileHash -LiteralPath $manifestPath -Algorithm SHA256).Hash.ToLowerInvariant() +$modelHash = (Get-FileHash -LiteralPath $modelPath -Algorithm SHA256).Hash.ToLowerInvariant() +$outputPath = [System.IO.Path]::GetFullPath($OutputRoot) +New-Item -ItemType Directory -Force -Path $outputPath | Out-Null +$cargo = (Get-Command cargo).Source +$seedValues = @( + $Seeds | ForEach-Object { $_ -split ',' } | ForEach-Object { + $value = 0L + if (-not [long]::TryParse($_.Trim(), [ref]$value) -or $value -lt 0) { + throw "invalid seed: $_" + } + $value + } +) +if ($seedValues.Count -eq 0 -or @($seedValues | Select-Object -Unique).Count -ne $seedValues.Count) { + throw 'provide at least one seed, without duplicates' +} + +function Run-Cargo( + [string[]]$Arguments, + [string]$Stdout, + [string]$Stderr, + [string]$LogLevel +) { + $env:RUST_LOG = $LogLevel + Push-Location $repo + $oldErrorPreference = $ErrorActionPreference + try { + # Windows PowerShell may wrap native stderr as ErrorRecord objects; + # Continue preserves the native exit code while the two streams are + # retained independently. + $ErrorActionPreference = "Continue" + & $cargo @Arguments 1> $Stdout 2> $Stderr + $exitCode = $LASTEXITCODE + } finally { + $ErrorActionPreference = $oldErrorPreference + Pop-Location + } + if ($exitCode -ne 0) { + throw "cargo exited with code $exitCode; see $Stdout and $Stderr" + } +} + +foreach ($seed in $seedValues) { + $runDir = Join-Path $outputPath "${Layers}l${Size}-seed${seed}" + New-Item -ItemType Directory -Force -Path $runDir | Out-Null + $decoder = Join-Path $runDir "decoder.bin" + $training = Join-Path $runDir "training.json" + $quality = Join-Path $runDir "quality-imagenette-$EvaluationSplit.json" + + if (-not ((Test-Path -LiteralPath $training) -and (Test-Path -LiteralPath $decoder))) { + Write-Output "training seed $seed at $(Get-Date -Format o)" + Run-Cargo ` + -Arguments @( + "run", "--release", "--example", "train_decoder", "--", + $manifestPath, $modelPath, "$Steps", "$Images", "$Layers", "$Size", "$seed", $runDir + ) ` + -Stdout (Join-Path $runDir "training.stdout.log") ` + -Stderr (Join-Path $runDir "training.stderr.log") ` + -LogLevel "info" + } else { + Write-Output "seed $seed training outputs already exist; preserving them" + } + + $record = Get-Content -Raw -LiteralPath $training | ConvertFrom-Json + if ( + $record.seed -ne $seed -or + $record.steps -ne $Steps -or + $record.requested_images -ne $Images -or + $record.encoder_layers -ne $Layers -or + $record.image_size -ne $Size -or + $record.dataset_manifest_sha256 -ne $manifestHash -or + $record.model_sha256 -ne $modelHash + ) { + throw "existing training record does not match requested cell: $training" + } + + if (-not (Test-Path -LiteralPath $quality)) { + Write-Output "evaluating seed $seed at $(Get-Date -Format o)" + Run-Cargo ` + -Arguments @( + "run", "--release", "--example", "evaluate_decoder", "--", + "--manifest", $manifestPath, + "--model", $modelPath, + "--decoder", $decoder, + "--split", $EvaluationSplit, + "--layers", "$Layers", + "--size", "$Size", + "--output", $quality, + "--samples", "12" + ) ` + -Stdout (Join-Path $runDir "evaluation.stdout.log") ` + -Stderr (Join-Path $runDir "evaluation.stderr.log") ` + -LogLevel "warn" + } else { + Write-Output "seed $seed quality output already exists; preserving it" + } + + $qualityRecord = Get-Content -Raw -LiteralPath $quality | ConvertFrom-Json + if ( + $qualityRecord.split -ne $EvaluationSplit -or + $qualityRecord.encoder_layers -ne $Layers -or + $qualityRecord.image_size -ne $Size -or + $qualityRecord.manifest_sha256 -ne $manifestHash -or + $qualityRecord.model_sha256 -ne $modelHash -or + $qualityRecord.decoder_sha256 -ne $record.decoder_sha256 + ) { + throw "quality record does not match its training cell: $quality" + } + + $safeTensors = Join-Path $runDir "decoder.safetensors" + if (-not (Test-Path -LiteralPath $safeTensors)) { + & python (Join-Path $repo "tools\convert_decoder.py") ` + --training $training ` + --input $decoder ` + --output $safeTensors + if ($LASTEXITCODE -ne 0) { + throw "decoder SafeTensors conversion failed for seed $seed" + } + } +} + +Write-Output "decoder matrix complete at $(Get-Date -Format o)" diff --git a/environment/publication-source/source-snapshot/tools/run_quest_bench.ps1 b/environment/publication-source/source-snapshot/tools/run_quest_bench.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..6118a62f717486619cc9c352a4a3968ba09092f2 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/run_quest_bench.ps1 @@ -0,0 +1,149 @@ +param( + [Parameter(Mandatory = $true)] + [string]$OutputDir, + [Parameter(Mandatory = $true)] + [string]$RecoveryManifest, + [string]$Binary = "target\aarch64-linux-android\release\examples\bench", + [ValidateSet("live-worn", "awake-unworn")] + [string]$Condition = "live-worn", + [int]$Processes = 3, + [int]$Iterations = 20, + [ValidateSet("full", "shapes")] + [string]$Suite = "full" +) + +$ErrorActionPreference = "Stop" +if ($Processes -lt 3) { throw "paper protocol requires at least three processes" } +if ($Iterations -lt 20) { throw "paper protocol requires at least 20 retained samples" } +$repo = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +$binaryPath = (Resolve-Path (Join-Path $repo $Binary)).Path +$recoveryPath = (Resolve-Path $RecoveryManifest).Path +$destination = [System.IO.Path]::GetFullPath($OutputDir) +if (Test-Path -LiteralPath $destination) { + if (@(Get-ChildItem -LiteralPath $destination -Force).Count -ne 0) { + throw "Refusing to merge benchmark output into non-empty directory: $destination" + } +} else { + New-Item -ItemType Directory -Path $destination | Out-Null +} + +$adbCandidates = @() +if ($env:LOCALAPPDATA) { + $adbCandidates += Join-Path $env:LOCALAPPDATA "Android\Sdk\platform-tools\adb.exe" +} +if ($env:ANDROID_HOME) { + $adbCandidates += Join-Path $env:ANDROID_HOME "platform-tools\adb.exe" +} +$adbCandidates = @($adbCandidates | Where-Object { Test-Path -LiteralPath $_ }) +if ($adbCandidates.Count -eq 0) { + throw "adb.exe was not found" +} +$adb = $adbCandidates[0] +$devices = @(& $adb devices | Select-Object -Skip 1 | Where-Object { $_ -match "\tdevice$" }) +if ($devices.Count -ne 1) { + throw "Expected exactly one authorized device; found $($devices.Count)" +} +$serial = (& $adb get-serialno).Trim() +$recovery = Get-Content -Raw -LiteralPath $recoveryPath | ConvertFrom-Json +if ($recovery.device -ne $serial) { + throw "Recovery manifest is for $($recovery.device), connected device is $serial" +} + +$binaryHash = (Get-FileHash -LiteralPath $binaryPath -Algorithm SHA256).Hash.ToLowerInvariant() +$remoteDir = "/data/local/tmp/dinovision" +$remoteBinary = "$remoteDir/bench-paper-$($binaryHash.Substring(0, 12))" +& $adb shell "mkdir -p $remoteDir" +if ($LASTEXITCODE -ne 0) { throw "could not create $remoteDir" } +& $adb push $binaryPath $remoteBinary +if ($LASTEXITCODE -ne 0) { throw "could not push benchmark binary" } +& $adb shell "chmod 755 $remoteBinary" +if ($LASTEXITCODE -ne 0) { throw "could not mark benchmark executable" } + +$remoteHash = (& $adb shell "sha256sum $remoteBinary").Trim().Split(" ")[0] +if ($binaryHash -ne $remoteHash) { + throw "pushed binary hash mismatch: host $binaryHash, device $remoteHash" +} + +$suiteEnvironment = if ($Suite -eq "shapes") { "DINOVISION_BENCH=shapes " } else { "" } +$remoteName = [System.IO.Path]::GetFileName($remoteBinary) +$command = "cd $remoteDir && RUST_LOG=info DINOVISION_WARMUPS=5 ${suiteEnvironment}./$remoteName $Iterations" + +function Capture-State([string]$Prefix) { + & $adb shell dumpsys thermalservice | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-thermal.txt") + & $adb shell dumpsys battery | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-battery.txt") + & $adb shell dumpsys power | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-power.txt") + & $adb shell dumpsys activity activities | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-activity.txt") + & $adb shell dumpsys SurfaceFlinger | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-surfaceflinger.txt") +} + +function Assert-Condition([string]$When) { + $power = (& $adb shell dumpsys power) -join "`n" + if ($power -notmatch 'mWakefulness=Awake') { + throw "Headset is not awake $When; requested condition is $Condition" + } + if ($Condition -eq 'live-worn') { + $activity = (& $adb shell dumpsys activity activities) -join "`n" + if ($activity -match 'SensorLockActivity') { + throw "Headset is not being worn $When (SensorLockActivity is resumed)" + } + } +} + +function Run-Process([string]$Name, [string]$RunCommand) { + Capture-State "$Name-before" + $process = Start-Process ` + -FilePath $adb ` + -ArgumentList @("shell", $RunCommand) ` + -NoNewWindow ` + -Wait ` + -PassThru ` + -RedirectStandardOutput (Join-Path $destination "$Name.stdout.log") ` + -RedirectStandardError (Join-Path $destination "$Name.stderr.log") + Capture-State "$Name-after" + if ($process.ExitCode -ne 0) { + throw "device benchmark $Name exited with code $($process.ExitCode)" + } +} + +# This process is retained as a stabilization diagnostic but excluded from +# aggregate results. It prevents the first retained process from receiving +# the entire device clock-ramp penalty. +Assert-Condition "before stabilization" +$warmupCommand = "cd $remoteDir && RUST_LOG=info DINOVISION_WARMUPS=5 ${suiteEnvironment}./$remoteName 5" +Run-Process "stabilization" $warmupCommand +for ($index = 0; $index -lt $Processes; $index++) { + Assert-Condition "before process $index" + Run-Process ("process-{0:d2}" -f $index) $command +} +Assert-Condition "after retained processes" + +$recordArguments = @( + (Join-Path $repo 'tools\extract_json_records.py'), + '--marker', 'DINOVISION_BENCH_JSON', + '--output', (Join-Path $destination 'benchmark-records.json') +) +for ($index = 0; $index -lt $Processes; $index++) { + $recordArguments += @('--input', (Join-Path $destination ("process-{0:d2}.stdout.log" -f $index))) +} +& python @recordArguments +if ($LASTEXITCODE -ne 0) { throw 'could not extract benchmark JSON records' } + +$metadata = [ordered]@{ + schema_version = 1 + completed_utc = [DateTime]::UtcNow.ToString("o") + condition = $Condition + suite = $Suite + processes = $Processes + warmups_per_process = 5 + retained_samples_per_workload = $Iterations + command = $command + binary = $binaryPath + binary_sha256 = $binaryHash + device_serial = $serial + device_model = (& $adb shell getprop ro.product.model).Trim() + build_fingerprint = (& $adb shell getprop ro.build.fingerprint).Trim() + recovery_manifest = $recoveryPath + recovery_manifest_sha256 = (Get-FileHash -LiteralPath $recoveryPath -Algorithm SHA256).Hash.ToLowerInvariant() +} +$metadata | ConvertTo-Json -Depth 4 | Set-Content -Encoding utf8 (Join-Path $destination "benchmark-metadata.json") +Write-Output "wrote Quest benchmark artifacts to $destination" diff --git a/environment/publication-source/source-snapshot/tools/run_xr_sweep.ps1 b/environment/publication-source/source-snapshot/tools/run_xr_sweep.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..94099da66beebdaf00c4f56d1ba4d4b7c098f378 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/run_xr_sweep.ps1 @@ -0,0 +1,269 @@ +param( + [Parameter(Mandatory = $true)] + [string]$OutputDir, + [Parameter(Mandatory = $true)] + [string]$RecoveryManifest, + [Parameter(Mandatory = $true)] + [string]$Apk, + [Parameter(Mandatory = $true)] + [string]$Model, + [Parameter(Mandatory = $true)] + [string]$Decoder, + # Fixed before device data: a deterministic permutation avoids making + # chunk count monotonic with startup/thermal drift. Summaries sort cells. + [int[]]$Chunks = @(4, 16, 1, 12, 2, 8), + [int]$InferenceIntervalMs = 0, + [int]$DurationSeconds = 90, + [string]$Package = 'rust.dinovision_xr', + [string]$Activity = 'android.app.NativeActivity' +) + +$ErrorActionPreference = 'Stop' +if ($DurationSeconds -lt 60) { + throw 'paper protocol requires at least 60 seconds per chunk setting' +} +if ($Chunks.Count -lt 2 -or @($Chunks | Where-Object { $_ -lt 1 }).Count -gt 0) { + throw 'provide at least two positive chunk settings' +} +if (@($Chunks | Select-Object -Unique).Count -ne $Chunks.Count) { + throw 'chunk settings must be unique because each setting owns one output cell' +} + +$repo = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path +$apkPath = (Resolve-Path $Apk).Path +$modelPath = (Resolve-Path $Model).Path +$decoderPath = (Resolve-Path $Decoder).Path +$recoveryPath = (Resolve-Path $RecoveryManifest).Path +$destination = [System.IO.Path]::GetFullPath($OutputDir) +if (Test-Path -LiteralPath $destination) { + if (@(Get-ChildItem -LiteralPath $destination -Force).Count -ne 0) { + throw "Refusing to merge XR output into non-empty directory: $destination" + } +} else { + New-Item -ItemType Directory -Path $destination | Out-Null +} + +$adbCandidates = @() +if ($env:LOCALAPPDATA) { + $adbCandidates += Join-Path $env:LOCALAPPDATA 'Android\Sdk\platform-tools\adb.exe' +} +if ($env:ANDROID_HOME) { + $adbCandidates += Join-Path $env:ANDROID_HOME 'platform-tools\adb.exe' +} +$adbCandidates = @($adbCandidates | Where-Object { Test-Path -LiteralPath $_ }) +if ($adbCandidates.Count -eq 0) { throw 'adb.exe was not found' } +$adb = $adbCandidates[0] +$devices = @(& $adb devices | Select-Object -Skip 1 | Where-Object { $_ -match "`tdevice$" }) +if ($devices.Count -ne 1) { throw "Expected one authorized device; found $($devices.Count)" } +$serial = (& $adb get-serialno).Trim() +$recovery = Get-Content -Raw -LiteralPath $recoveryPath | ConvertFrom-Json +if ($recovery.device -ne $serial) { + throw "Recovery manifest is for $($recovery.device), connected device is $serial" +} + +$remoteDir = '/data/local/tmp/dinovision' +$modelRemote = "$remoteDir/model.safetensors" +$decoderRemote = "$remoteDir/decoder.bin" +$toggleNames = @( + 'raw_camera', 'mono', 'camera_half_fov_deg', + 'inference_interval_ms', 'submission_chunks', 'capture' +) + +function Shell-Quote([string]$Value) { + if ($Value.Contains("'")) { throw 'toggle values may not contain a single quote' } + return "'$Value'" +} + +function Assert-LiveWorn([string]$When) { + $power = (& $adb shell dumpsys power) -join "`n" + if ($power -notmatch 'mWakefulness=Awake') { + throw "Headset is not awake $When" + } + $activityState = (& $adb shell dumpsys activity activities) -join "`n" + if ($activityState -match 'SensorLockActivity') { + throw "Headset is not being worn $When (SensorLockActivity is resumed)" + } +} + +function Capture-State([string]$Prefix) { + & $adb shell dumpsys thermalservice | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-thermal.txt") + & $adb shell dumpsys battery | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-battery.txt") + & $adb shell dumpsys power | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-power.txt") + & $adb shell dumpsys activity activities | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-activity.txt") + & $adb shell dumpsys SurfaceFlinger | Set-Content -Encoding utf8 (Join-Path $destination "$Prefix-surfaceflinger.txt") +} + +function Read-Toggle([string]$Name) { + $path = "$remoteDir/$Name" + $present = ((& $adb shell "if [ -e '$path' ]; then echo yes; else echo no; fi").Trim() -eq 'yes') + [ordered]@{ + present = $present + value = if ($present) { ((& $adb shell "cat '$path' 2>/dev/null") -join "`n").TrimEnd() } else { $null } + } +} + +function Write-Toggle([string]$Name, [string]$Value) { + $path = "$remoteDir/$Name" + $quoted = Shell-Quote $Value + & $adb shell "printf '%s' $quoted > '$path'" + if ($LASTEXITCODE -ne 0) { throw "could not write toggle $Name" } +} + +function Remove-Toggle([string]$Name) { + & $adb shell "rm -f -- '$remoteDir/$Name'" + if ($LASTEXITCODE -ne 0) { throw "could not remove toggle $Name" } +} + +function Remote-File-Present([string]$Path) { + return ((& $adb shell "if [ -f '$Path' ]; then echo yes; else echo no; fi").Trim() -eq 'yes') +} + +& $adb shell "mkdir -p '$remoteDir'" +if ($LASTEXITCODE -ne 0) { throw "could not create $remoteDir" } +$originalToggles = [ordered]@{} +foreach ($name in $toggleNames) { $originalToggles[$name] = Read-Toggle $name } +$originalToggles | ConvertTo-Json -Depth 5 | Set-Content -Encoding utf8 (Join-Path $destination 'preexisting-toggles.json') + +$backupDir = Join-Path $destination 'preexisting-runtime' +New-Item -ItemType Directory -Path $backupDir | Out-Null +$hadModel = Remote-File-Present $modelRemote +$hadDecoder = Remote-File-Present $decoderRemote +$oldModelHash = if ($hadModel) { ((& $adb shell "sha256sum '$modelRemote'").Trim().Split(' ')[0]) } else { $null } +$oldDecoderHash = if ($hadDecoder) { ((& $adb shell "sha256sum '$decoderRemote'").Trim().Split(' ')[0]) } else { $null } +if ($hadModel) { + & $adb pull $modelRemote (Join-Path $backupDir 'model.safetensors') | Out-Null + if ($LASTEXITCODE -ne 0 -or + (Get-FileHash -LiteralPath (Join-Path $backupDir 'model.safetensors') -Algorithm SHA256).Hash.ToLowerInvariant() -ne $oldModelHash) { + throw 'could not preserve the preexisting encoder exactly' + } +} +if ($hadDecoder) { + & $adb pull $decoderRemote (Join-Path $backupDir 'decoder.bin') | Out-Null + if ($LASTEXITCODE -ne 0 -or + (Get-FileHash -LiteralPath (Join-Path $backupDir 'decoder.bin') -Algorithm SHA256).Hash.ToLowerInvariant() -ne $oldDecoderHash) { + throw 'could not preserve the preexisting decoder exactly' + } +} + +$completed = $false +try { + Assert-LiveWorn 'before installation' + & $adb install -r $apkPath | Set-Content -Encoding utf8 (Join-Path $destination 'install.log') + if ($LASTEXITCODE -ne 0) { throw 'APK installation failed' } + & $adb shell pm grant $Package horizonos.permission.HEADSET_CAMERA + if ($LASTEXITCODE -ne 0) { throw 'HEADSET_CAMERA permission grant failed' } + + & $adb push $modelPath $modelRemote | Out-Null + if ($LASTEXITCODE -ne 0) { throw 'encoder push failed' } + & $adb push $decoderPath $decoderRemote | Out-Null + if ($LASTEXITCODE -ne 0) { throw 'decoder push failed' } + $modelHash = (Get-FileHash -LiteralPath $modelPath -Algorithm SHA256).Hash.ToLowerInvariant() + $decoderHash = (Get-FileHash -LiteralPath $decoderPath -Algorithm SHA256).Hash.ToLowerInvariant() + $remoteModelHash = ((& $adb shell "sha256sum '$modelRemote'").Trim().Split(' ')[0]) + $remoteDecoderHash = ((& $adb shell "sha256sum '$decoderRemote'").Trim().Split(' ')[0]) + if ($modelHash -ne $remoteModelHash -or $decoderHash -ne $remoteDecoderHash) { + throw 'pushed weight hash mismatch' + } + + # Stereo corrected-model runs only. Capture is disabled so this protocol + # never writes private camera frames. + foreach ($name in @('raw_camera', 'mono', 'capture')) { Remove-Toggle $name } + Write-Toggle 'inference_interval_ms' "$InferenceIntervalMs" + + foreach ($chunk in $Chunks) { + $name = "chunks-{0:d2}" -f $chunk + Write-Toggle 'submission_chunks' "$chunk" + Assert-LiveWorn "before $name" + Capture-State "$name-before" + & $adb shell am force-stop $Package + # logcat streams the existing ring buffer unless it is cleared. A stale + # DinoVision window from an earlier setting would otherwise be accepted + # as part of this cell and silently bias the aggregate. + & $adb logcat -c + if ($LASTEXITCODE -ne 0) { throw "could not clear logcat before $name" } + $stdout = Join-Path $destination "$name.logcat.log" + $stderr = Join-Path $destination "$name.logcat.stderr.log" + $logcat = Start-Process ` + -FilePath $adb ` + -ArgumentList @('logcat', '-v', 'epoch', 'dinovision:I', 'RustStdoutStderr:I', '*:S') ` + -WindowStyle Hidden ` + -PassThru ` + -RedirectStandardOutput $stdout ` + -RedirectStandardError $stderr + try { + Start-Sleep -Seconds 1 + & $adb shell am start -W -a android.intent.action.MAIN -c com.oculus.intent.category.VR -n "$Package/$Activity" | + Set-Content -Encoding utf8 (Join-Path $destination "$name-launch.log") + if ($LASTEXITCODE -ne 0) { throw "could not launch $name" } + Start-Sleep -Seconds $DurationSeconds + & $adb shell am force-stop $Package + Start-Sleep -Seconds 2 + } finally { + Stop-Process -Id $logcat.Id -Force -ErrorAction SilentlyContinue + $logcat.WaitForExit() + } + Capture-State "$name-after" + Assert-LiveWorn "after $name" + & python (Join-Path $repo 'tools\extract_json_records.py') ` + --input $stdout ` + --marker DINOVISION_APP_JSON ` + --output (Join-Path $destination "$name-records.json") + if ($LASTEXITCODE -ne 0) { throw "no valid application records for $name" } + } + + $metadata = [ordered]@{ + schema_version = 1 + completed_utc = [DateTime]::UtcNow.ToString('o') + condition = 'live-worn' + device_serial = $serial + device_model = (& $adb shell getprop ro.product.model).Trim() + build_fingerprint = (& $adb shell getprop ro.build.fingerprint).Trim() + package = $Package + activity = $Activity + chunks = $Chunks + order_policy = 'predeclared deterministic permutation before corrected device data' + inference_interval_ms = $InferenceIntervalMs + duration_seconds_per_setting = $DurationSeconds + apk_sha256 = (Get-FileHash -LiteralPath $apkPath -Algorithm SHA256).Hash.ToLowerInvariant() + model_sha256 = $modelHash + decoder_sha256 = $decoderHash + recovery_manifest = $recoveryPath + recovery_manifest_sha256 = (Get-FileHash -LiteralPath $recoveryPath -Algorithm SHA256).Hash.ToLowerInvariant() + } + $metadata | ConvertTo-Json -Depth 5 | Set-Content -Encoding utf8 (Join-Path $destination 'sweep-metadata.json') + $completed = $true +} finally { + & $adb shell am force-stop $Package 2>$null + foreach ($name in $toggleNames) { + $state = $originalToggles[$name] + if ($state.present) { Write-Toggle $name ([string]$state.value) } else { Remove-Toggle $name } + } + if ($hadModel) { + & $adb push (Join-Path $backupDir 'model.safetensors') $modelRemote | Out-Null + if ($LASTEXITCODE -ne 0 -or + ((& $adb shell "sha256sum '$modelRemote'").Trim().Split(' ')[0]) -ne $oldModelHash) { + throw 'failed to restore the preexisting encoder exactly' + } + } else { + & $adb shell "rm -f -- '$modelRemote'" + } + if ($hadDecoder) { + & $adb push (Join-Path $backupDir 'decoder.bin') $decoderRemote | Out-Null + if ($LASTEXITCODE -ne 0 -or + ((& $adb shell "sha256sum '$decoderRemote'").Trim().Split(' ')[0]) -ne $oldDecoderHash) { + throw 'failed to restore the preexisting decoder exactly' + } + } else { + & $adb shell "rm -f -- '$decoderRemote'" + } + foreach ($name in $toggleNames) { + $restored = Read-Toggle $name + $original = $originalToggles[$name] + if ($restored.present -ne $original.present -or + ($restored.present -and [string]$restored.value -ne [string]$original.value)) { + throw "failed to restore toggle $name exactly" + } + } +} + +if ($completed) { Write-Output "wrote live XR sweep to $destination" } diff --git a/environment/publication-source/source-snapshot/tools/stage_huggingface_artifact.ps1 b/environment/publication-source/source-snapshot/tools/stage_huggingface_artifact.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..4c8569ee50fcd78722b4aafca34a5435e74767ce --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/stage_huggingface_artifact.ps1 @@ -0,0 +1,316 @@ +param( + [Parameter(Mandatory = $true)] + [string]$OutputDir, + [Parameter(Mandatory = $true)] + [string]$RunsRoot, + [Parameter(Mandatory = $true)] + [string]$DatasetManifest, + [Parameter(Mandatory = $true)] + [string]$CorrectnessRoot, + [Parameter(Mandatory = $true)] + [string[]]$ReferenceRoots, + [Parameter(Mandatory = $true)] + [string]$EnvironmentDir, + [string]$PublicationEnvironmentDir, + [string]$AndroidBuildDir, + [string]$DeterminismRecord, + [string[]]$DeterminismRunDirs, + [string]$CrossDeviceDir, + [string]$BenchmarkDir, + [string]$XrDir, + [int[]]$Seeds = @(0, 1, 2), + [int]$SelectedSeed = 0, + [int]$Layers = 3, + [int]$Size = 224, + [string]$ExpectedDatasetManifestSha256 = '2071f89b2a7b077d7729641fc858e1225d057d11a797d16198c0d195d989bb89', + [string]$ExpectedCorrectnessManifestSha256 = '94b10d1640c3e09b3eecec8abea64ec0cdd128032ad60a0e31d246ac932b178f', + [string]$ExpectedCorrectnessFrameSha256 = 'b89c2000b8877bce4649610e490579eef1ada5b29867f7a773d88450549ad1a8' +) + +$ErrorActionPreference = 'Stop' +$repo = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path +$runs = (Resolve-Path $RunsRoot).Path +$manifest = (Resolve-Path $DatasetManifest).Path +$correctness = (Resolve-Path $CorrectnessRoot).Path +$environment = (Resolve-Path $EnvironmentDir).Path +$publicationEnvironment = if ($PublicationEnvironmentDir) { + (Resolve-Path $PublicationEnvironmentDir).Path +} else { $null } +$references = @($ReferenceRoots | ForEach-Object { (Resolve-Path $_).Path }) + +function File-Hash([string]$Path) { + (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant() +} + +function Relative-Path([string]$Base, [string]$Path) { + $basePath = [System.IO.Path]::GetFullPath($Base).TrimEnd([char[]]@('\', '/')) + $fullPath = [System.IO.Path]::GetFullPath($Path) + $prefix = $basePath + [System.IO.Path]::DirectorySeparatorChar + if (-not $fullPath.StartsWith($prefix, [System.StringComparison]::OrdinalIgnoreCase)) { + throw "$fullPath is not inside $basePath" + } + $fullPath.Substring($prefix.Length) +} + +if ((File-Hash $manifest) -ne $ExpectedDatasetManifestSha256) { + throw 'dataset manifest is not the frozen Imagenette manifest' +} +$correctnessManifest = Join-Path $correctness 'manifests\correctness-224.json' +$correctnessFrame = Join-Path $correctness 'input\frame.rgb' +if ((File-Hash $correctnessManifest) -ne $ExpectedCorrectnessManifestSha256) { + throw 'correctness manifest is not the frozen public manifest' +} +if ((File-Hash $correctnessFrame) -ne $ExpectedCorrectnessFrameSha256) { + throw 'correctness frame is not the frozen synthetic public frame' +} + +if ($Seeds.Count -lt 3 -or $Seeds -notcontains $SelectedSeed) { + throw 'publish at least three seeds and include the preselected seed' +} +$destination = [System.IO.Path]::GetFullPath($OutputDir) +if (Test-Path -LiteralPath $destination) { + if (@(Get-ChildItem -LiteralPath $destination -Force).Count -ne 0) { + throw "Refusing to merge a publication into non-empty directory: $destination" + } +} else { + New-Item -ItemType Directory -Path $destination | Out-Null +} + +function Copy-PublicFile([string]$Source, [string]$RelativeDestination) { + if (-not (Test-Path -LiteralPath $Source -PathType Leaf)) { + throw "required publication input is missing: $Source" + } + $target = Join-Path $destination $RelativeDestination + $parent = Split-Path -Parent $target + New-Item -ItemType Directory -Force -Path $parent | Out-Null + Copy-Item -LiteralPath $Source -Destination $target +} + +function Copy-DirectoryFiles( + [string]$Source, + [string]$RelativeDestination, + [string[]]$Patterns +) { + foreach ($pattern in $Patterns) { + Get-ChildItem -LiteralPath $Source -File -Filter $pattern | ForEach-Object { + Copy-PublicFile $_.FullName (Join-Path $RelativeDestination $_.Name) + } + } +} + +function Copy-PublicTree([string]$Source, [string]$RelativeDestination) { + if (-not (Test-Path -LiteralPath $Source -PathType Container)) { + throw "required publication directory is missing: $Source" + } + Get-ChildItem -LiteralPath $Source -Recurse -File | ForEach-Object { + $relative = Relative-Path $Source $_.FullName + Copy-PublicFile $_.FullName (Join-Path $RelativeDestination $relative) + } +} + +function Write-SanitizedJson( + [string]$Source, + [string]$RelativeDestination, + [string[]]$RemoveProperties +) { + if (-not (Test-Path -LiteralPath $Source -PathType Leaf)) { + throw "required publication input is missing: $Source" + } + $record = Get-Content -Raw -LiteralPath $Source | ConvertFrom-Json + foreach ($property in $RemoveProperties) { + $record.PSObject.Properties.Remove($property) + } + $target = Join-Path $destination $RelativeDestination + New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null + $json = $record | ConvertTo-Json -Depth 20 + if ($env:USERPROFILE) { + $json = $json.Replace($env:USERPROFILE, '') + $json = $json.Replace($env:USERPROFILE.Replace('\', '/'), '') + } + # Parse the transformed text before publication so path redaction cannot + # accidentally corrupt JSON escaping. + $json | ConvertFrom-Json | Out-Null + $json | Set-Content -LiteralPath $target -Encoding utf8 +} + +# Repository documentation and explicit source snapshots are the only trees +# copied recursively. Every experimental result is selected by exact filename +# or suffix; dataset photos and private headset capture trees are unreachable. +Get-ChildItem -LiteralPath (Join-Path $repo 'huggingface') -File | ForEach-Object { + Copy-PublicFile $_.FullName $_.Name +} + +$selectedDir = Join-Path $runs ("${Layers}l${Size}-seed${SelectedSeed}") +foreach ($name in @('decoder.bin', 'decoder.safetensors', 'training.json')) { + Copy-PublicFile (Join-Path $selectedDir $name) $name +} + +foreach ($seed in $Seeds) { + $runName = "${Layers}l${Size}-seed${seed}" + $runDir = Join-Path $runs $runName + foreach ($name in @( + 'decoder.bin', 'decoder.safetensors', 'training.json', + 'run-notes.json', + 'training.stdout.log', 'training.stderr.log', + 'evaluation.stdout.log', 'evaluation.stderr.log' + )) { + Copy-PublicFile (Join-Path $runDir $name) (Join-Path "replicates\$runName" $name) + } + Copy-PublicFile ` + (Join-Path $runDir 'quality-imagenette-validation.json') ` + (Join-Path 'quality' "$runName.json") +} +Copy-PublicFile (Join-Path $runs 'quality-summary.json') 'quality\summary.json' +Copy-PublicFile (Join-Path $runs 'quality-summary.md') 'quality\summary.md' +Copy-PublicFile (Join-Path $runs 'dataset-summary.json') 'manifests\dataset-summary.json' +Copy-PublicFile (Join-Path $runs 'dataset-summary.md') 'manifests\dataset-summary.md' + +Copy-PublicFile $manifest 'manifests\imagenette2-320.json' +Copy-PublicFile ` + $correctnessManifest ` + 'manifests\correctness-224.json' +Copy-PublicFile $correctnessFrame 'correctness\frame.rgb' +$hostCorrectness = Join-Path $correctness 'host-seed0' +Copy-PublicFile (Join-Path $hostCorrectness 'quality.json') 'correctness\host\quality.json' +Copy-DirectoryFiles ` + (Join-Path $hostCorrectness 'quality_samples') ` + 'correctness\host\quality_samples' ` + @('*.f32') + +foreach ($reference in $references) { + $name = Split-Path -Leaf $reference + # Reference tensors use .bin; the gated exported model has a distinct + # .safetensors suffix and is deliberately not selected. + Copy-DirectoryFiles $reference (Join-Path 'correctness\reference' $name) @('*.json', '*.bin') +} + +function Copy-EnvironmentSnapshot( + [string]$Source, + [string]$RelativeDestination +) { + Write-SanitizedJson ` + (Join-Path $Source 'metadata.json') ` + (Join-Path $RelativeDestination 'metadata.json') ` + @('android_ndk_root') + $publicMetadataPath = Join-Path $destination (Join-Path $RelativeDestination 'metadata.json') + $publicMetadata = Get-Content -Raw -LiteralPath $publicMetadataPath | ConvertFrom-Json + # The full source snapshot supersedes the local binary patch. The latter + # can retain deleted, machine-specific paths even after current files are + # portable, so do not publish it or a dangling hash for it. + $publicMetadata.dinovision.PSObject.Properties.Remove('working_patch_sha256') + $publicMetadata | ConvertTo-Json -Depth 20 | + Set-Content -LiteralPath $publicMetadataPath -Encoding utf8 + Copy-DirectoryFiles ` + $Source ` + $RelativeDestination ` + @('Cargo.lock', 'cargo-tree.txt') + Copy-PublicTree ` + (Join-Path $Source 'dinovision-source-snapshot') ` + (Join-Path $RelativeDestination 'source-snapshot') +} + +Copy-EnvironmentSnapshot $environment 'environment\training-source' +if ($publicationEnvironment) { + Copy-EnvironmentSnapshot $publicationEnvironment 'environment\publication-source' +} + +if ($AndroidBuildDir) { + $androidBuild = (Resolve-Path $AndroidBuildDir).Path + Write-SanitizedJson ` + (Join-Path $androidBuild 'android-build.json') ` + 'environment\android-build\android-build.json' ` + @() + foreach ($name in @( + 'apk-badging.txt', + 'apk-build.stdout.log', 'apk-build.stderr.log', + 'native-build.stdout.log', 'native-build.stderr.log' + )) { + Copy-PublicFile ` + (Join-Path $androidBuild $name) ` + (Join-Path 'environment\android-build' $name) + } +} + +if ($DeterminismRecord) { + Copy-PublicFile ` + (Resolve-Path $DeterminismRecord).Path ` + 'reproducibility\determinism.json' + if (-not $DeterminismRunDirs -or $DeterminismRunDirs.Count -lt 2) { + throw 'a determinism record requires at least two source run records' + } + foreach ($runDir in $DeterminismRunDirs) { + $resolvedRun = (Resolve-Path $runDir).Path + $runName = Split-Path -Leaf $resolvedRun + Copy-PublicFile ` + (Join-Path $resolvedRun 'training.json') ` + (Join-Path "reproducibility\runs\$runName" 'training.json') + } +} + +if ($CrossDeviceDir) { + $cross = (Resolve-Path $CrossDeviceDir).Path + Write-SanitizedJson ` + (Join-Path $cross 'correctness-metadata.json') ` + 'correctness\host-quest\metadata.json' ` + @('device_serial', 'remote_root', 'recovery_manifest_sha256') + Copy-DirectoryFiles (Join-Path $cross 'comparisons') 'correctness\host-quest\comparisons' @('*.json') + Copy-DirectoryFiles (Join-Path $cross 'device-output') 'correctness\host-quest\device-output' @('*.json') + Copy-DirectoryFiles ` + (Join-Path $cross 'device-output\quality_samples') ` + 'correctness\host-quest\device-output\quality_samples' ` + @('*.f32') +} + +if ($BenchmarkDir) { + $bench = (Resolve-Path $BenchmarkDir).Path + Write-SanitizedJson ` + (Join-Path $bench 'benchmark-metadata.json') ` + 'benchmarks\isolated\metadata.json' ` + @('device_serial', 'binary', 'recovery_manifest', 'recovery_manifest_sha256') + foreach ($name in @('benchmark-records.json', 'benchmark-summary.json', 'benchmark-summary.md')) { + Copy-PublicFile (Join-Path $bench $name) (Join-Path 'benchmarks\isolated' $name) + } +} + +if ($XrDir) { + $xr = (Resolve-Path $XrDir).Path + Write-SanitizedJson ` + (Join-Path $xr 'sweep-metadata.json') ` + 'benchmarks\live-xr\metadata.json' ` + @('device_serial', 'recovery_manifest', 'recovery_manifest_sha256') + Copy-DirectoryFiles $xr 'benchmarks\live-xr\records' @('chunks-*-records.json') + foreach ($name in @('xr-summary.json', 'xr-summary.md')) { + Copy-PublicFile (Join-Path $xr $name) (Join-Path 'benchmarks\live-xr' $name) + } +} + +$files = @( + Get-ChildItem -LiteralPath $destination -Recurse -File | + Sort-Object FullName | + ForEach-Object { + [ordered]@{ + path = (Relative-Path $destination $_.FullName).Replace('\', '/') + bytes = $_.Length + sha256 = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() + } + } +) +$encoderCheckpointSha256 = '4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d' +if (@($files | Where-Object { $_.sha256 -eq $encoderCheckpointSha256 }).Count -ne 0) { + throw 'the gated DINOv3 checkpoint must not be staged' +} +$imagePayloads = @($files | Where-Object { $_.path -match '\.(jpe?g|png)$' }) +if ($imagePayloads.Count -ne 0) { + throw "dataset or reconstruction images must not be staged: $($imagePayloads.path -join ', ')" +} +$manifestRecord = [ordered]@{ + schema_version = 1 + created_utc = [DateTime]::UtcNow.ToString('o') + selected_seed = $SelectedSeed + encoder_layers = $Layers + image_size = $Size + files = $files +} +$manifestRecord | ConvertTo-Json -Depth 6 | + Set-Content -LiteralPath (Join-Path $destination 'ARTIFACT_MANIFEST.json') -Encoding utf8 +Write-Output "staged $($files.Count) explicitly selected files in $destination" diff --git a/environment/publication-source/source-snapshot/tools/summarize_bench.py b/environment/publication-source/source-snapshot/tools/summarize_bench.py new file mode 100644 index 0000000000000000000000000000000000000000..c60e429b237762215ad409d3258f54fdaafae141 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/summarize_bench.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +"""Aggregate raw benchmark samples across fresh device processes.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import statistics +from collections import defaultdict +from pathlib import Path +from typing import Iterable + + +def distribution(values: Iterable[float]) -> dict[str, float]: + ordered = sorted(float(value) for value in values) + if not ordered: + raise SystemExit("cannot summarize an empty distribution") + if any(not math.isfinite(value) or value <= 0 for value in ordered): + raise SystemExit("timing samples must be finite and positive") + + def quantile(q: float) -> float: + at = q * (len(ordered) - 1) + lower = int(at) + upper = min(lower + 1, len(ordered) - 1) + return ordered[lower] + (ordered[upper] - ordered[lower]) * (at - lower) + + return { + "mean": statistics.fmean(ordered), + "median": quantile(0.5), + "p25": quantile(0.25), + "p75": quantile(0.75), + "min": ordered[0], + "max": ordered[-1], + } + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--records", required=True, type=Path) + parser.add_argument("--metadata", required=True, type=Path) + parser.add_argument("--output-json", required=True, type=Path) + parser.add_argument("--output-markdown", required=True, type=Path) + args = parser.parse_args() + + artifact = json.loads(args.records.read_text(encoding="utf-8-sig")) + metadata = json.loads(args.metadata.read_text(encoding="utf-8-sig")) + if int(metadata["processes"]) < 3: + raise SystemExit("paper protocol requires at least three processes") + expected_samples = int(metadata["retained_samples_per_workload"]) + if expected_samples < 20: + raise SystemExit("paper protocol requires at least 20 samples per process") + + grouped: dict[str, list[dict[str, object]]] = defaultdict(list) + for record in artifact.get("records", []): + if record.get("kind") != "dinovision_benchmark": + raise SystemExit("unexpected benchmark record kind") + samples = record.get("samples_ms", []) + if len(samples) != expected_samples: + raise SystemExit( + f"{record.get('label')} has {len(samples)} samples, expected {expected_samples}" + ) + computed = distribution(float(value) for value in samples) + for field, key in ( + ("median_ms", "median"), + ("p25_ms", "p25"), + ("p75_ms", "p75"), + ("min_ms", "min"), + ("max_ms", "max"), + ("mean_ms", "mean"), + ): + if not math.isclose( + float(record[field]), computed[key], rel_tol=0.0, abs_tol=1e-4 + ): + raise SystemExit( + f"{record.get('label')} has inconsistent {field}: " + f"{record[field]} vs {computed[key]} from raw samples" + ) + grouped[str(record["label"])].append(record) + + workloads: list[dict[str, object]] = [] + for label, records in sorted(grouped.items()): + if len(records) != int(metadata["processes"]): + raise SystemExit( + f"{label!r} occurs in {len(records)} processes, expected {metadata['processes']}" + ) + sources = {str(record.get("artifact_source")) for record in records} + if len(sources) != len(records): + raise SystemExit(f"{label!r} does not have one record per distinct process log") + macs = {int(record["macs"]) for record in records} + if len(macs) != 1: + raise SystemExit(f"{label!r} has inconsistent MAC counts") + mac_count = next(iter(macs)) + samples = [float(value) for record in records for value in record["samples_ms"]] + timings = distribution(samples) + process_medians = distribution(float(record["median_ms"]) for record in records) + median_ms = timings["median"] + workloads.append( + { + "label": label, + "macs": mac_count, + "processes": len(records), + "samples": len(samples), + "timing_ms": timings, + "process_median_ms": process_medians, + "median_gflops": (2.0 * mac_count) / (median_ms / 1000.0) / 1e9, + } + ) + + result = { + "schema_version": 1, + "benchmark_metadata": metadata, + "records_sha256": hashlib.sha256(args.records.read_bytes()).hexdigest(), + "workloads": workloads, + } + args.output_json.parent.mkdir(parents=True, exist_ok=True) + args.output_markdown.parent.mkdir(parents=True, exist_ok=True) + args.output_json.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8") + + lines = [ + "# Isolated Quest benchmark", + "", + f"Condition: `{metadata['condition']}`. Each workload has {metadata['processes']} processes x {expected_samples} retained samples after {metadata['warmups_per_process']} warmups/process.", + "", + "| Workload | Pooled median [IQR] (ms) | Process medians: median [min, max] (ms) | Pooled min-max (ms) | Median GFLOP/s |", + "|---|---:|---:|---:|---:|", + ] + for workload in workloads: + timing = workload["timing_ms"] + lines.append( + f"| {workload['label']} " + f"| {timing['median']:.2f} [{timing['p25']:.2f}, {timing['p75']:.2f}] " + f"| {workload['process_median_ms']['median']:.2f} " + f"[{workload['process_median_ms']['min']:.2f}, {workload['process_median_ms']['max']:.2f}] " + f"| {timing['min']:.2f}-{timing['max']:.2f} " + f"| {workload['median_gflops']:.1f} |" + ) + args.output_markdown.write_text("\n".join(lines) + "\n", encoding="utf-8") + print(f"wrote {args.output_json} and {args.output_markdown}") + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/summarize_dataset.py b/environment/publication-source/source-snapshot/tools/summarize_dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..dfc1f436652b2f4398fdfc2d110d541200e056e1 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/summarize_dataset.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +"""Summarize an immutable dataset manifest and its selected training prefix.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from collections import Counter, defaultdict +from pathlib import Path + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--manifest", required=True, type=Path) + parser.add_argument("--training-prefix", type=int, default=2500) + parser.add_argument( + "--class-component", + type=int, + default=2, + help="zero-based path component containing a class ID", + ) + parser.add_argument("--output-json", required=True, type=Path) + parser.add_argument("--output-markdown", required=True, type=Path) + args = parser.parse_args() + if args.training_prefix < 1 or args.class_component < 0: + raise SystemExit("prefix must be positive and class component non-negative") + + manifest_bytes = args.manifest.read_bytes() + manifest = json.loads(manifest_bytes) + if manifest.get("schema_version") != 1 or not manifest.get("images"): + raise SystemExit("unsupported or empty dataset manifest") + + split_counts: Counter[str] = Counter() + source_counts: dict[str, Counter[str]] = defaultdict(Counter) + group_splits: dict[tuple[str, str], str] = {} + hashes: set[str] = set() + paths: set[str] = set() + class_counts: dict[str, Counter[str]] = defaultdict(Counter) + train_entries: list[dict[str, object]] = [] + for image in manifest["images"]: + split = str(image["split"]) + source = str(image["source"]) + group = str(image["group"]) + path = str(image["path"]) + digest = str(image["sha256"]) + if path in paths or digest in hashes: + raise SystemExit(f"duplicate path or content in manifest: {path}") + paths.add(path) + hashes.add(digest) + key = (source, group) + previous = group_splits.setdefault(key, split) + if previous != split: + raise SystemExit(f"group {source}/{group} crosses {previous} and {split}") + parts = Path(path).parts + if len(parts) <= args.class_component: + raise SystemExit(f"{path} has no class component {args.class_component}") + class_id = parts[args.class_component] + split_counts[split] += 1 + source_counts[split][source] += 1 + class_counts[split][class_id] += 1 + if split == "train": + train_entries.append(image) + + if len(train_entries) < args.training_prefix: + raise SystemExit( + f"training split has {len(train_entries)} entries, fewer than prefix " + f"{args.training_prefix}" + ) + prefix_classes = Counter( + Path(str(image["path"])).parts[args.class_component] + for image in train_entries[: args.training_prefix] + ) + artifact = { + "schema_version": 1, + "dataset_name": manifest.get("name"), + "manifest_sha256": hashlib.sha256(manifest_bytes).hexdigest(), + "provenance": manifest.get("provenance", []), + "images": len(manifest["images"]), + "unique_content_hashes": len(hashes), + "groups": len(group_splits), + "split_counts": dict(sorted(split_counts.items())), + "source_counts_by_split": { + split: dict(sorted(counts.items())) + for split, counts in sorted(source_counts.items()) + }, + "class_counts_by_split": { + split: dict(sorted(counts.items())) + for split, counts in sorted(class_counts.items()) + }, + "selected_training_prefix": args.training_prefix, + "selected_training_prefix_class_counts": dict(sorted(prefix_classes.items())), + } + args.output_json.parent.mkdir(parents=True, exist_ok=True) + args.output_markdown.parent.mkdir(parents=True, exist_ok=True) + args.output_json.write_text(json.dumps(artifact, indent=2) + "\n", encoding="utf-8") + + lines = [ + "# Dataset summary", + "", + f"Manifest SHA-256: `{artifact['manifest_sha256']}`.", + "", + "| Split | Images | Classes | Sources |", + "|---|---:|---:|---|", + ] + for split, count in sorted(split_counts.items()): + lines.append( + f"| {split} | {count} | {len(class_counts[split])} " + f"| {', '.join(f'{source}: {n}' for source, n in sorted(source_counts[split].items()))} |" + ) + lines.extend( + [ + "", + f"The selected training prefix contains {args.training_prefix} images:", + "", + "| Class ID | Images |", + "|---|---:|", + ] + ) + lines.extend(f"| {name} | {count} |" for name, count in sorted(prefix_classes.items())) + args.output_markdown.write_text("\n".join(lines) + "\n", encoding="utf-8") + print(f"wrote {args.output_json} and {args.output_markdown}") + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/summarize_determinism.py b/environment/publication-source/source-snapshot/tools/summarize_determinism.py new file mode 100644 index 0000000000000000000000000000000000000000..e9e24ce7e62384ee7bbe4476426361885f74555d --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/summarize_determinism.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +"""Verify and summarize repeated deterministic decoder-training runs.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from datetime import UTC, datetime +from pathlib import Path + + +MATCH_FIELDS = ( + "dataset_manifest_sha256", + "requested_images", + "training_images", + "model_sha256", + "initialization", + "initialization_sha256", + "seed", + "image_size", + "encoder_layers", + "batch_size", + "steps", + "data_order", + "objective", + "optimizer", + "initial_learning_rate", + "final_learning_rate", + "decoder_parameters", + "final_l1", +) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as source: + for chunk in iter(lambda: source.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--run", action="append", required=True, type=Path) + parser.add_argument("--output", required=True, type=Path) + args = parser.parse_args() + if len(args.run) < 2: + raise SystemExit("at least two --run directories are required") + + records: list[tuple[Path, dict[str, object], str, str]] = [] + for directory in args.run: + training_path = directory / "training.json" + decoder_path = directory / "decoder.bin" + training = json.loads(training_path.read_text(encoding="utf-8-sig")) + decoder_hash = sha256(decoder_path) + if decoder_hash != training["decoder_sha256"]: + raise SystemExit(f"{decoder_path} disagrees with training.json") + records.append((directory, training, sha256(training_path), decoder_hash)) + + baseline = records[0][1] + for directory, training, _, _ in records[1:]: + differences = [field for field in MATCH_FIELDS if training[field] != baseline[field]] + if differences: + raise SystemExit(f"{directory} differs in deterministic fields: {differences}") + decoder_hashes = {record[3] for record in records} + if len(decoder_hashes) != 1: + raise SystemExit(f"decoder hashes differ: {sorted(decoder_hashes)}") + + output = { + "schema_version": 1, + "created_utc": datetime.now(UTC).isoformat(), + "purpose": "short deterministic replay; not a quality or throughput result", + "configuration": {field: baseline[field] for field in MATCH_FIELDS}, + "runs": [ + { + "name": directory.name, + "training_record_sha256": training_hash, + "decoder_sha256": decoder_hash, + } + for directory, _, training_hash, decoder_hash in records + ], + "all_decoder_bytes_identical": True, + "decoder_sha256": records[0][3], + } + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(output, indent=2) + "\n", encoding="utf-8") + print( + f"verified {len(records)} deterministic runs: " + f"decoder SHA-256 {records[0][3]}" + ) + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/summarize_quality.py b/environment/publication-source/source-snapshot/tools/summarize_quality.py new file mode 100644 index 0000000000000000000000000000000000000000..0f1908ce4c71b0ec0d6d998f165a733ab17bd343 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/summarize_quality.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 +"""Aggregate decoder training/evaluation JSON without manual transcription.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import statistics +from collections import defaultdict +from pathlib import Path + + +def mean_sd(values: list[float]) -> dict[str, float | None]: + if not values: + return {"mean": None, "sample_stddev": None} + return { + "mean": statistics.fmean(values), + "sample_stddev": statistics.stdev(values) if len(values) > 1 else None, + } + + +def display(value: dict[str, float | None], digits: int) -> str: + mean = value["mean"] + stddev = value["sample_stddev"] + assert mean is not None + return ( + f"{mean:.{digits}f}" + if stddev is None + else f"{mean:.{digits}f} ± {stddev:.{digits}f}" + ) + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--run-dir", action="append", required=True, type=Path) + parser.add_argument("--quality-name", default="quality-imagenette-validation.json") + parser.add_argument("--output-json", required=True, type=Path) + parser.add_argument("--output-markdown", required=True, type=Path) + parser.add_argument("--minimum-runs", type=int, default=3) + args = parser.parse_args() + if args.minimum_runs < 1: + raise SystemExit("--minimum-runs must be positive") + + runs: list[dict[str, object]] = [] + grouped: dict[tuple[object, ...], list[dict[str, object]]] = defaultdict(list) + for directory in args.run_dir: + training = json.loads((directory / "training.json").read_text(encoding="utf-8")) + quality = json.loads((directory / args.quality_name).read_text(encoding="utf-8")) + notes_path = directory / "run-notes.json" + notes = json.loads(notes_path.read_text(encoding="utf-8")) if notes_path.exists() else {} + checks = { + "decoder_hash": training["decoder_sha256"] == quality["decoder_sha256"], + "model_hash": training["model_sha256"] == quality["model_sha256"], + "manifest_hash": training["dataset_manifest_sha256"] + == quality["manifest_sha256"], + "layers": training["encoder_layers"] == quality["encoder_layers"], + "image_size": training["image_size"] == quality["image_size"], + } + if not all(checks.values()): + raise SystemExit(f"inconsistent run {directory}: {checks}") + run = { + "directory": str(directory).replace("\\", "/"), + "seed": training["seed"], + "encoder_layers": training["encoder_layers"], + "image_size": training["image_size"], + "training_images": training["training_images"], + "evaluation_images": quality["summary"]["count"], + "dataset": quality["dataset_name"], + "split": quality["split"], + "manifest_sha256": quality["manifest_sha256"], + "model_sha256": quality["model_sha256"], + "decoder_sha256": quality["decoder_sha256"], + "training_record_sha256": hashlib.sha256( + (directory / "training.json").read_bytes() + ).hexdigest(), + "quality_record_sha256": hashlib.sha256( + (directory / args.quality_name).read_bytes() + ).hexdigest(), + "training_seconds": training["training_seconds"], + # Interactive development runs are valid training/quality records, + # but their wall time is not a performance result. Timing is + # admitted only when the run notes opt in after documenting a + # controlled host state; absence of notes must fail closed. + "training_timing_valid": notes.get("training_timing_valid", False), + "final_training_l1": training["final_l1"], + "global_psnr_db": quality["summary"]["global_psnr_db"], + "median_image_psnr_db": quality["summary"]["psnr_db"]["median"], + "median_image_ssim": quality["summary"]["ssim"]["median"], + "median_image_mae": quality["summary"]["mae"]["median"], + } + runs.append(run) + key = ( + run["encoder_layers"], + run["image_size"], + run["dataset"], + run["split"], + run["manifest_sha256"], + run["model_sha256"], + ) + grouped[key].append(run) + + aggregates: list[dict[str, object]] = [] + for (layers, size, dataset, split, manifest_sha, model_sha), cell_runs in sorted( + grouped.items() + ): + cell_runs.sort(key=lambda run: int(run["seed"])) + seeds = [int(run["seed"]) for run in cell_runs] + if len(cell_runs) < args.minimum_runs: + raise SystemExit( + f"{layers}L/{size}/{dataset}/{split} has {len(cell_runs)} runs; " + f"require at least {args.minimum_runs}" + ) + if len(set(seeds)) != len(seeds): + raise SystemExit(f"duplicate seed in {layers}L/{size}/{dataset}/{split}: {seeds}") + training_counts = {int(run["training_images"]) for run in cell_runs} + evaluation_counts = {int(run["evaluation_images"]) for run in cell_runs} + if len(training_counts) != 1 or len(evaluation_counts) != 1: + raise SystemExit( + f"inconsistent sample counts in {layers}L/{size}/{dataset}/{split}" + ) + valid_training_times = [ + float(run["training_seconds"]) + for run in cell_runs + if run["training_timing_valid"] + ] + aggregate = { + "encoder_layers": layers, + "image_size": size, + "dataset": dataset, + "split": split, + "manifest_sha256": manifest_sha, + "model_sha256": model_sha, + "seeds": seeds, + "runs": len(cell_runs), + "training_images_per_run": cell_runs[0]["training_images"], + "evaluation_images_per_run": cell_runs[0]["evaluation_images"], + "global_psnr_db": mean_sd( + [float(run["global_psnr_db"]) for run in cell_runs] + ), + "median_image_psnr_db": mean_sd( + [float(run["median_image_psnr_db"]) for run in cell_runs] + ), + "median_image_ssim": mean_sd( + [float(run["median_image_ssim"]) for run in cell_runs] + ), + "median_image_mae": mean_sd( + [float(run["median_image_mae"]) for run in cell_runs] + ), + "valid_training_timing_runs": len(valid_training_times), + "training_seconds": mean_sd(valid_training_times), + } + aggregates.append(aggregate) + + artifact = {"schema_version": 1, "runs": runs, "aggregates": aggregates} + args.output_json.parent.mkdir(parents=True, exist_ok=True) + args.output_markdown.parent.mkdir(parents=True, exist_ok=True) + args.output_json.write_text(json.dumps(artifact, indent=2) + "\n", encoding="utf-8") + + lines = [ + "# Decoder quality summary", + "", + "Generated from immutable training and per-image evaluation JSON.", + "", + "| Encoder | Size | Seeds | Validation images/run | Global PSNR (dB) | Median-image PSNR (dB) | Median RGB SSIM | Median MAE |", + "|---:|---:|---:|---:|---:|---:|---:|---:|", + ] + for cell in aggregates: + lines.append( + f"| {cell['encoder_layers']}L | {cell['image_size']} | {cell['runs']} " + f"| {cell['evaluation_images_per_run']} " + f"| {display(cell['global_psnr_db'], 2)} " + f"| {display(cell['median_image_psnr_db'], 2)} " + f"| {display(cell['median_image_ssim'], 4)} " + f"| {display(cell['median_image_mae'], 4)} |" + ) + lines.extend( + [ + "", + "| Seed | Decoder SHA-256 | Training (s) | Final-batch train L1 | Global PSNR (dB) | Median RGB SSIM |", + "|---:|---|---:|---:|---:|---:|", + ] + ) + for run in sorted(runs, key=lambda item: (item["encoder_layers"], item["image_size"], item["seed"])): + training_seconds = ( + f"{float(run['training_seconds']):.1f}" + if run["training_timing_valid"] + else "excluded" + ) + lines.append( + f"| {run['seed']} | `{run['decoder_sha256']}` " + f"| {training_seconds} " + f"| {float(run['final_training_l1']):.5f} " + f"| {float(run['global_psnr_db']):.2f} " + f"| {float(run['median_image_ssim']):.4f} |" + ) + args.output_markdown.write_text("\n".join(lines) + "\n", encoding="utf-8") + print(f"wrote {args.output_json} and {args.output_markdown}") + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/summarize_xr.py b/environment/publication-source/source-snapshot/tools/summarize_xr.py new file mode 100644 index 0000000000000000000000000000000000000000..a0b18af43023341551bde503a5837eb79e700312 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/summarize_xr.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +"""Summarize retained live-XR JSON windows without manual transcription.""" + +from __future__ import annotations + +import argparse +import json +import math +from collections import defaultdict +from pathlib import Path +from typing import Iterable + + +def distribution(values: Iterable[float]) -> dict[str, float]: + ordered = sorted(float(value) for value in values) + if not ordered: + raise SystemExit("cannot summarize an empty distribution") + + def quantile(q: float) -> float: + at = q * (len(ordered) - 1) + lower = int(at) + upper = min(lower + 1, len(ordered) - 1) + return ordered[lower] + (ordered[upper] - ordered[lower]) * (at - lower) + + return { + "median": quantile(0.5), + "p25": quantile(0.25), + "p75": quantile(0.75), + "min": ordered[0], + "max": ordered[-1], + } + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--records", action="append", required=True, type=Path) + parser.add_argument("--discard-windows", type=int, default=2) + parser.add_argument("--expected-chunks", default="1,2,4,8,12,16") + parser.add_argument("--expected-interval-ms", type=int, default=0) + parser.add_argument("--output-json", required=True, type=Path) + parser.add_argument("--output-markdown", required=True, type=Path) + args = parser.parse_args() + if args.discard_windows < 0: + raise SystemExit("--discard-windows cannot be negative") + expected_chunks = { + int(value.strip()) for value in args.expected_chunks.split(",") if value.strip() + } + if not expected_chunks or min(expected_chunks) < 1: + raise SystemExit("--expected-chunks must contain positive integers") + + grouped: dict[tuple[int, int], list[dict[str, object]]] = defaultdict(list) + sources: list[dict[str, object]] = [] + for path in args.records: + artifact = json.loads(path.read_text(encoding="utf-8-sig")) + records = artifact.get("records", []) + if not records: + raise SystemExit(f"{path} contains no records") + for record in records: + if record.get("kind") != "dinovision_app_window": + raise SystemExit(f"{path} contains an unexpected record kind") + if record.get("raw_camera") is not False: + raise SystemExit(f"{path} is not a corrected-model run") + eye_rates = record.get("per_eye_update_hz", []) + eye_counts = record.get("per_eye_update_counts", []) + latency_samples = record.get("worker_latency_samples_ms", []) + if len(eye_rates) != 2 or len(eye_counts) != 2 or len(latency_samples) != 2: + raise SystemExit(f"{path} is not a stereo run") + seconds = float(record["window_seconds"]) + render_frames = int(record["render_frames"]) + if not math.isfinite(seconds) or seconds <= 0 or render_frames < 0: + raise SystemExit(f"{path} has an invalid reporting window") + if not math.isclose( + float(record["render_hz"]), render_frames / seconds, abs_tol=1e-4 + ): + raise SystemExit(f"{path} has inconsistent render rate/count") + for eye in range(2): + count = int(eye_counts[eye]) + if count < 0 or len(latency_samples[eye]) != count: + raise SystemExit(f"{path} eye {eye} latency/count mismatch") + if any( + not math.isfinite(float(value)) or float(value) <= 0 + for value in latency_samples[eye] + ): + raise SystemExit(f"{path} eye {eye} has invalid latency") + if not math.isclose(float(eye_rates[eye]), count / seconds, abs_tol=1e-4): + raise SystemExit(f"{path} eye {eye} has inconsistent rate/count") + key = (int(record["submission_chunks"]), int(record["inference_interval_ms"])) + grouped[key].append(record) + sources.append({"path": str(path).replace("\\", "/"), "records": len(records)}) + + observed_chunks = {chunks for chunks, _ in grouped} + observed_intervals = {interval for _, interval in grouped} + if observed_chunks != expected_chunks: + raise SystemExit( + f"observed chunk cells {sorted(observed_chunks)}, expected {sorted(expected_chunks)}" + ) + if observed_intervals != {args.expected_interval_ms}: + raise SystemExit( + f"observed intervals {sorted(observed_intervals)}, expected {args.expected_interval_ms}" + ) + + cells: list[dict[str, object]] = [] + for (chunks, interval), records in sorted(grouped.items()): + retained = records[args.discard_windows :] + if len(retained) < 10: + raise SystemExit( + f"chunks={chunks} has only {len(retained)} retained windows after " + f"discarding {args.discard_windows}; require at least 10" + ) + duration = sum(float(record["window_seconds"]) for record in retained) + render_frames = sum(int(record["render_frames"]) for record in retained) + eye_counts = [ + sum(int(record["per_eye_update_counts"][eye]) for record in retained) + for eye in range(2) + ] + latency_by_eye = [ + [ + float(sample) + for record in retained + for sample in record["worker_latency_samples_ms"][eye] + ] + for eye in range(2) + ] + pooled_latency = latency_by_eye[0] + latency_by_eye[1] + if not pooled_latency: + raise SystemExit(f"chunks={chunks} has no worker latency samples") + eye_rates = [count / duration for count in eye_counts] + cells.append( + { + "submission_chunks": chunks, + "inference_interval_ms": interval, + "discarded_windows": args.discard_windows, + "retained_windows": len(retained), + "retained_seconds": duration, + "render_submission_hz": render_frames / duration, + "per_eye_update_hz": eye_rates, + "minimum_eye_update_hz": min(eye_rates), + "window_render_hz": distribution( + float(record["render_hz"]) for record in retained + ), + "window_minimum_eye_hz": distribution( + float(record["min_eye_update_hz"]) for record in retained + ), + "worker_latency_ms": distribution(pooled_latency), + "worker_latency_samples": len(pooled_latency), + "per_eye_worker_latency_ms": [ + distribution(latency_by_eye[eye]) for eye in range(2) + ], + } + ) + + artifact = { + "schema_version": 1, + "sources": sources, + "discarded_initial_windows_per_cell": args.discard_windows, + "cells": cells, + } + args.output_json.parent.mkdir(parents=True, exist_ok=True) + args.output_markdown.parent.mkdir(parents=True, exist_ok=True) + args.output_json.write_text(json.dumps(artifact, indent=2) + "\n", encoding="utf-8") + + lines = [ + "# Live XR chunk sweep", + "", + "Rates are totals divided by retained wall time. Latency is worker wall time, not capture-to-photon latency.", + "", + "| Chunks | Retained (s) | Render submissions (Hz) | Eye 0 updates (Hz) | Eye 1 updates (Hz) | Lower eye (Hz) | Worker latency median [IQR] (ms) |", + "|---:|---:|---:|---:|---:|---:|---:|", + ] + for cell in cells: + latency = cell["worker_latency_ms"] + lines.append( + f"| {cell['submission_chunks']} | {cell['retained_seconds']:.1f} " + f"| {cell['render_submission_hz']:.2f} " + f"| {cell['per_eye_update_hz'][0]:.2f} " + f"| {cell['per_eye_update_hz'][1]:.2f} " + f"| {cell['minimum_eye_update_hz']:.2f} " + f"| {latency['median']:.2f} [{latency['p25']:.2f}, {latency['p75']:.2f}] |" + ) + args.output_markdown.write_text("\n".join(lines) + "\n", encoding="utf-8") + print(f"wrote {args.output_json} and {args.output_markdown}") + + +if __name__ == "__main__": + main() diff --git a/environment/publication-source/source-snapshot/tools/verify_huggingface_artifact.py b/environment/publication-source/source-snapshot/tools/verify_huggingface_artifact.py new file mode 100644 index 0000000000000000000000000000000000000000..b55e1341ff52615b9970cf3080796af0be0b4ff8 --- /dev/null +++ b/environment/publication-source/source-snapshot/tools/verify_huggingface_artifact.py @@ -0,0 +1,403 @@ +#!/usr/bin/env python3 +"""Fail-closed validation for the staged public DinoVision model artifact.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import os +from pathlib import Path + +from safetensors import safe_open + + +ENCODER_SHA256 = "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d" +DATASET_MANIFEST_SHA256 = ( + "2071f89b2a7b077d7729641fc858e1225d057d11a797d16198c0d195d989bb89" +) +CORRECTNESS_MANIFEST_SHA256 = ( + "94b10d1640c3e09b3eecec8abea64ec0cdd128032ad60a0e31d246ac932b178f" +) +CORRECTNESS_FRAME_SHA256 = ( + "b89c2000b8877bce4649610e490579eef1ada5b29867f7a773d88450549ad1a8" +) +QUALITY_SUMMARY_SHA256 = ( + "06d34ea8eff9d0bf50dbae467891347d7032bcd85b5080b45d381bca02ba4350" +) +DECODER_SHA256 = { + 0: "d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c", + 1: "1dbc2b99603604814e5d6f99f3a5ed765863c3e2db5012fd95d8bc87954879a6", + 2: "2085a6923760c0266c4f965db2014afd7cf4b7fcbde2c203d9e399c37fe2af67", +} +REFERENCE_EXPECTED = { + 0: (5.53577506954782e-07, 1.0, 1.0), + 1: (0.0007806134116510104, 1.0, 0.9999894), + 3: (0.001403442372470342, 0.9999995, 0.9999949), + 12: (0.002253213523752634, 0.9999975, 0.99999523), +} +DECODER_TENSOR_ORDER = ( + "dec.0.weight", "dec.0.bias", "dec.0.norm.weight", "dec.0.norm.bias", + "dec.0b.weight", "dec.0b.bias", "dec.0b.norm.weight", "dec.0b.norm.bias", + "dec.1.weight", "dec.1.bias", "dec.1.norm.weight", "dec.1.norm.bias", + "dec.1b.weight", "dec.1b.bias", "dec.1b.norm.weight", "dec.1b.norm.bias", + "dec.2.weight", "dec.2.bias", "dec.2.norm.weight", "dec.2.norm.bias", + "dec.3.weight", "dec.3.bias", "dec.3.norm.weight", "dec.3.norm.bias", + "dec.out.weight", "dec.out.bias", +) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as source: + for chunk in iter(lambda: source.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def read_json(path: Path) -> dict[str, object]: + return json.loads(path.read_text(encoding="utf-8-sig")) + + +def check_decoder(directory: Path, expected_seed: int) -> dict[str, object]: + training = read_json(directory / "training.json") + if int(training["seed"]) != expected_seed: + raise SystemExit(f"{directory} records seed {training['seed']}, expected {expected_seed}") + for field, expected in ( + ("dataset_manifest_sha256", DATASET_MANIFEST_SHA256), + ("model_sha256", ENCODER_SHA256), + ("encoder_layers", 3), + ("image_size", 224), + ("training_images", 2500), + ("batch_size", 8), + ("steps", 12000), + ("decoder_parameters", 2_012_547), + ): + if training[field] != expected: + raise SystemExit(f"{directory}/training.json {field} mismatch") + binary_hash = sha256(directory / "decoder.bin") + if binary_hash != training["decoder_sha256"] or binary_hash != DECODER_SHA256[expected_seed]: + raise SystemExit(f"{directory}/decoder.bin disagrees with training.json") + with safe_open(directory / "decoder.safetensors", framework="numpy") as tensors: + metadata = tensors.metadata() + names = list(tensors.keys()) + rebuilt = b"".join(tensors.get_tensor(name).tobytes(order="C") for name in DECODER_TENSOR_ORDER) + if set(names) != set(DECODER_TENSOR_ORDER) or metadata.get("source_decoder_sha256") != binary_hash: + raise SystemExit(f"{directory}/decoder.safetensors has invalid tensors or metadata") + if rebuilt != (directory / "decoder.bin").read_bytes(): + raise SystemExit(f"{directory}/decoder.safetensors is not an exact named representation") + for field, expected in ( + ("model_sha256", training["model_sha256"]), + ("dataset_manifest_sha256", training["dataset_manifest_sha256"]), + ("encoder_layers", str(training["encoder_layers"])), + ("image_size", str(training["image_size"])), + ("seed", str(expected_seed)), + ): + if metadata.get(field) != expected: + raise SystemExit(f"{directory}/decoder.safetensors metadata {field} mismatch") + return training + + +def check_source_snapshot(directory: Path) -> None: + metadata = read_json(directory / "metadata.json") + dinovision = metadata["dinovision"] + snapshot = directory / "source-snapshot" + expected = {entry["path"]: entry for entry in dinovision["source_files"]} + actual = { + path.relative_to(snapshot).as_posix(): path + for path in snapshot.rglob("*") + if path.is_file() + } + if set(expected) != set(actual): + raise SystemExit(f"source snapshot inventory mismatch in {directory}") + for name, path in actual.items(): + record = expected[name] + if path.stat().st_size != int(record["bytes"]) or sha256(path) != record["sha256"]: + raise SystemExit(f"source snapshot hash/size mismatch for {directory.name}/{name}") + if "working_patch_sha256" in dinovision or (directory / "dinovision-working-tree.patch").exists(): + raise SystemExit(f"source snapshot should not expose a machine-specific patch in {directory}") + if sha256(directory / "Cargo.lock") != sha256(snapshot / "Cargo.lock"): + raise SystemExit(f"Cargo.lock differs from source snapshot in {directory}") + + +def check_references(root: Path) -> None: + reference_root = root / "correctness" / "reference" + found: dict[int, Path] = {} + common_pixel_hash: str | None = None + for directory in reference_root.iterdir(): + if not directory.is_dir(): + continue + reference = read_json(directory / "reference.json") + verification = read_json(directory / "verification.json") + layers = int(reference["encoder_layers"]) + if layers in found: + raise SystemExit(f"duplicate {layers}-layer reference") + found[layers] = directory + if reference.get("source_model_sha256") != ENCODER_SHA256: + raise SystemExit(f"{directory} is not bound to the canonical checkpoint") + if verification.get("source_model_sha256") != ENCODER_SHA256: + raise SystemExit(f"{directory} verification lost the source checkpoint hash") + if verification["model_sha256"] != reference["exported_model_sha256"]: + raise SystemExit(f"{directory} verified a different exported checkpoint") + if int(verification["encoder_layers"]) != layers or not verification["passed"]: + raise SystemExit(f"{directory} has a failed or mislabeled verification") + pixel_hash = sha256(directory / "pixel_values.bin") + feature_hash = sha256(directory / "features.bin") + if pixel_hash != reference["pixel_values_sha256"]: + raise SystemExit(f"{directory}/pixel_values.bin hash mismatch") + if feature_hash != reference["features_sha256"]: + raise SystemExit(f"{directory}/features.bin hash mismatch") + if common_pixel_hash is None: + common_pixel_hash = pixel_hash + elif pixel_hash != common_pixel_hash: + raise SystemExit("reference depths do not use one identical pixel tensor") + expected_metric = REFERENCE_EXPECTED.get(layers) + if expected_metric is None: + raise SystemExit(f"unexpected reference depth {layers}") + for field, expected in zip( + ("relative_l2", "cls_cosine", "worst_patch_cosine"), expected_metric + ): + if not math.isclose(float(verification[field]), expected, abs_tol=1e-7): + raise SystemExit(f"{directory} {field} disagrees with the audited result") + stages = verification["stages"] + if len(stages) != 19: + raise SystemExit(f"{directory} should contain 19 checked stages") + for stage in stages: + reference_path = directory / stage["reference_file"] + meganeura_path = directory / stage["meganeura_file"] + if sha256(reference_path) != stage["reference_sha256"]: + raise SystemExit(f"reference stage hash mismatch: {reference_path}") + if sha256(meganeura_path) != stage["meganeura_sha256"]: + raise SystemExit(f"Meganeura stage hash mismatch: {meganeura_path}") + expected_bytes = int(stage["elements"]) * 4 + if reference_path.stat().st_size != expected_bytes or meganeura_path.stat().st_size != expected_bytes: + raise SystemExit(f"stage element count mismatch in {directory}") + final_stage = stages[-1] + if final_stage["name"] != "full encoder output": + raise SystemExit(f"{directory} does not end with the full encoder metric") + if final_stage["meganeura_sha256"] != verification["meganeura_features_sha256"]: + raise SystemExit(f"{directory} final output hash mismatch") + if set(found) != set(REFERENCE_EXPECTED): + raise SystemExit(f"expected reference depths {sorted(REFERENCE_EXPECTED)}, got {sorted(found)}") + + +def check_host_correctness(root: Path) -> None: + if sha256(root / "manifests" / "correctness-224.json") != CORRECTNESS_MANIFEST_SHA256: + raise SystemExit("fixed correctness manifest hash mismatch") + if sha256(root / "correctness" / "frame.rgb") != CORRECTNESS_FRAME_SHA256: + raise SystemExit("fixed correctness frame hash mismatch") + quality = read_json(root / "correctness" / "host" / "quality.json") + for field, expected in ( + ("manifest_sha256", CORRECTNESS_MANIFEST_SHA256), + ("model_sha256", ENCODER_SHA256), + ("decoder_sha256", DECODER_SHA256[0]), + ("encoder_layers", 3), + ("image_size", 224), + ): + if quality[field] != expected: + raise SystemExit(f"host correctness {field} mismatch") + if quality["summary"]["count"] != 1 or quality["images"][0]["sha256"] != CORRECTNESS_FRAME_SHA256: + raise SystemExit("host correctness record is not the fixed one-image cell") + sample_root = root / "correctness" / "host" / "quality_samples" + expected_sizes = { + "0000-encoder.f32": 201 * 384 * 4, + "0000-features.f32": 196 * 384 * 4, + "0000-patches.f32": 3 * 224 * 224 * 4, + "0000-reconstruction.f32": 3 * 224 * 224 * 4, + } + actual = {path.name: path.stat().st_size for path in sample_root.iterdir() if path.is_file()} + if actual != expected_sizes: + raise SystemExit(f"host correctness tensor inventory mismatch: {actual}") + + +def check_determinism(root: Path) -> None: + path = root / "reproducibility" / "determinism.json" + if not path.is_file(): + return + record = read_json(path) + if not record["all_decoder_bytes_identical"] or len(record["runs"]) < 2: + raise SystemExit("determinism replay did not establish identical decoders") + decoder_hash = record["decoder_sha256"] + for run in record["runs"]: + training_path = root / "reproducibility" / "runs" / run["name"] / "training.json" + if sha256(training_path) != run["training_record_sha256"]: + raise SystemExit(f"determinism training record hash mismatch: {run['name']}") + training = read_json(training_path) + if training["decoder_sha256"] != decoder_hash: + raise SystemExit(f"determinism decoder hash mismatch: {run['name']}") + configuration = record["configuration"] + if configuration["steps"] != 20 or configuration["training_images"] != 16: + raise SystemExit("determinism evidence is not the declared short replay") + if configuration["model_sha256"] != ENCODER_SHA256: + raise SystemExit("determinism replay used the wrong encoder") + + +def check_android_build(root: Path) -> None: + directory = root / "environment" / "android-build" + if not directory.is_dir(): + return + build = read_json(directory / "android-build.json") + if build["target"] != "aarch64-linux-android" or int(build["android_api"]) != 34: + raise SystemExit("Android build target mismatch") + if build["package"] != "rust.dinovision_xr" or build["activity"] != "android.app.NativeActivity": + raise SystemExit("Android package/activity mismatch") + artifacts = {entry["name"] for entry in build["artifacts"]} + if artifacts != {"bench", "evaluate_decoder", "dinovision_xr.apk"}: + raise SystemExit(f"Android build inventory mismatch: {artifacts}") + badging = (directory / "apk-badging.txt").read_text(encoding="utf-8-sig") + if "name='rust.dinovision_xr'" not in badging or "name='android.app.NativeActivity'" not in badging: + raise SystemExit("APK badging does not confirm the declared package/activity") + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--artifact", required=True, type=Path) + args = parser.parse_args() + root = args.artifact.resolve() + manifest_path = root / "ARTIFACT_MANIFEST.json" + manifest = read_json(manifest_path) + if ( + int(manifest["selected_seed"]) != 0 + or int(manifest["encoder_layers"]) != 3 + or int(manifest["image_size"]) != 224 + ): + raise SystemExit("artifact manifest does not describe the predeclared deployment cell") + + recorded = {entry["path"]: entry for entry in manifest["files"]} + actual = { + path.relative_to(root).as_posix(): path + for path in root.rglob("*") + if path.is_file() and path != manifest_path + } + if set(recorded) != set(actual): + raise SystemExit( + f"artifact manifest mismatch: missing={sorted(set(recorded) - set(actual))}, " + f"unrecorded={sorted(set(actual) - set(recorded))}" + ) + allowed_safetensors = { + "decoder.safetensors", + "replicates/3l224-seed0/decoder.safetensors", + "replicates/3l224-seed1/decoder.safetensors", + "replicates/3l224-seed2/decoder.safetensors", + } + for name, path in actual.items(): + record = recorded[name] + digest = sha256(path) + if path.stat().st_size != int(record["bytes"]) or digest != record["sha256"]: + raise SystemExit(f"artifact manifest hash/size mismatch for {name}") + if digest == ENCODER_SHA256: + raise SystemExit("the gated DINOv3 checkpoint is present") + if path.suffix.lower() in {".jpg", ".jpeg", ".png"}: + raise SystemExit(f"image payload must not be public: {name}") + if path.suffix.lower() == ".safetensors" and name not in allowed_safetensors: + raise SystemExit(f"unexpected SafeTensors payload: {name}") + if path.name.lower() == "model.safetensors": + raise SystemExit(f"exported or gated base checkpoint must not be staged: {name}") + + selected_seed = int(manifest["selected_seed"]) + selected = check_decoder(root, selected_seed) + replicate_records = [] + for directory in sorted((root / "replicates").iterdir()): + seed = int(directory.name.rsplit("seed", 1)[1]) + replicate_records.append(check_decoder(directory, seed)) + seeds = sorted(int(record["seed"]) for record in replicate_records) + if seeds != [0, 1, 2]: + raise SystemExit(f"expected replicate seeds [0, 1, 2], got {seeds}") + selected_replicate = next(record for record in replicate_records if record["seed"] == selected_seed) + if selected_replicate["decoder_sha256"] != selected["decoder_sha256"]: + raise SystemExit("root decoder is not the preselected replicate") + for name in ("decoder.bin", "decoder.safetensors", "training.json"): + if sha256(root / name) != sha256(root / "replicates" / "3l224-seed0" / name): + raise SystemExit(f"root {name} is not byte-identical to selected replicate") + + quality_path = root / "quality" / "summary.json" + if sha256(quality_path) != QUALITY_SUMMARY_SHA256: + raise SystemExit("quality summary hash is not the audited three-seed record") + quality = read_json(quality_path) + if len(quality["runs"]) != 3 or quality["aggregates"][0]["runs"] != 3: + raise SystemExit("quality summary is not the required three-run aggregate") + if sorted(int(run["seed"]) for run in quality["runs"]) != seeds: + raise SystemExit("quality and decoder replicate seeds differ") + aggregate = quality["aggregates"][0] + for field, expected in ( + ("encoder_layers", 3), + ("image_size", 224), + ("manifest_sha256", DATASET_MANIFEST_SHA256), + ("model_sha256", ENCODER_SHA256), + ("training_images_per_run", 2500), + ("evaluation_images_per_run", 3925), + ("valid_training_timing_runs", 0), + ): + if aggregate[field] != expected: + raise SystemExit(f"quality aggregate {field} mismatch") + for run in quality["runs"]: + seed = int(run["seed"]) + run_name = f"3l224-seed{seed}" + training_path = root / "replicates" / run_name / "training.json" + quality_record_path = root / "quality" / f"{run_name}.json" + if sha256(training_path) != run["training_record_sha256"]: + raise SystemExit(f"quality summary training hash mismatch for seed {seed}") + if sha256(quality_record_path) != run["quality_record_sha256"]: + raise SystemExit(f"quality summary record hash mismatch for seed {seed}") + record = read_json(quality_record_path) + for field, expected in ( + ("manifest_sha256", DATASET_MANIFEST_SHA256), + ("model_sha256", ENCODER_SHA256), + ("decoder_sha256", DECODER_SHA256[seed]), + ("encoder_layers", 3), + ("image_size", 224), + ("split", "validation"), + ): + if record[field] != expected: + raise SystemExit(f"quality seed {seed} {field} mismatch") + if record["summary"]["count"] != 3925 or len(record["images"]) != 3925: + raise SystemExit(f"quality seed {seed} is not the complete held-out split") + if not math.isclose(record["summary"]["global_psnr_db"], run["global_psnr_db"]): + raise SystemExit(f"quality seed {seed} global PSNR mismatch") + + if sha256(root / "manifests" / "imagenette2-320.json") != DATASET_MANIFEST_SHA256: + raise SystemExit("dataset manifest is not the frozen Imagenette manifest") + dataset_summary = read_json(root / "manifests" / "dataset-summary.json") + if dataset_summary["manifest_sha256"] != DATASET_MANIFEST_SHA256: + raise SystemExit("dataset summary is not bound to the frozen manifest") + + check_host_correctness(root) + check_references(root) + source_directories = { + path.name: path + for path in (root / "environment").iterdir() + if path.is_dir() and path.name.endswith("-source") + } + if set(source_directories) != {"training-source", "publication-source"}: + raise SystemExit(f"source snapshot inventory mismatch: {sorted(source_directories)}") + for directory in source_directories.values(): + check_source_snapshot(directory) + check_determinism(root) + check_android_build(root) + + if sha256(root / "DINOv3-LICENSE.md") != "25d122eb8f5b880fd23c736fb6ea8018ee45c12237e00b8a86d14c653904999e": + raise SystemExit("included DINOv3 agreement hash mismatch") + readme = (root / "README.md").read_text(encoding="utf-8-sig") + if "**Built with DINOv3**" not in readme: + raise SystemExit("prominent DINOv3 attribution is missing") + + user_profile = os.environ.get("USERPROFILE") + if user_profile: + needles = { + user_profile.lower().encode(), + user_profile.replace("\\", "/").lower().encode(), + } + for name, path in actual.items(): + if any(needle in path.read_bytes().lower() for needle in needles): + raise SystemExit(f"unredacted user-profile path in {name}") + + total_bytes = sum(path.stat().st_size for path in actual.values()) + print( + f"artifact valid: {len(actual)} payload files, {total_bytes} bytes, " + f"selected seed {selected_seed}, replicates {seeds}" + ) + + +if __name__ == "__main__": + main() diff --git a/environment/training-source/Cargo.lock b/environment/training-source/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..d977280a171f65aa0327b289cceed2c4f2d7c8f7 --- /dev/null +++ b/environment/training-source/Cargo.lock @@ -0,0 +1,6011 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-activity" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" +dependencies = [ + "android-properties", + "bitflags 2.13.1", + "cc", + "jni", + "libc", + "log", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "num_enum 0.7.6", + "thiserror 2.0.19", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" +dependencies = [ + "android_log-sys", + "env_filter 0.1.4", + "log", +] + +[[package]] +name = "annotate-snippets" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +dependencies = [ + "anstyle", + "unicode-width", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "arc-swap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "ash-window" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52bca67b61cb81e5553babde81b8211f713cb6db79766f80168f3e5f40ea6c82" +dependencies = [ + "ash", + "raw-window-handle 0.6.2", + "raw-window-metal", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.4", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.4", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.4", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "annotate-snippets", + "bitflags 2.13.1", + "cexpr", + "clang-sys", + "itertools", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.3", + "shlex 1.3.0", + "syn 2.0.119", +] + +[[package]] +name = "bit-set" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2f926cc3060f09db9ebc5b52823d85268d24bb917e472c0c4bea35780a7d" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blade-graphics" +version = "0.8.4" +source = "git+https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac" +dependencies = [ + "ash", + "ash-window", + "bitflags 2.13.1", + "bytemuck", + "codespan-reporting", + "glow", + "gpu-alloc", + "gpu-alloc-ash", + "hidden-trait", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "mint", + "naga", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", + "objc2-ui-kit 0.3.2", + "once_cell", + "openxr", + "raw-window-handle 0.6.2", + "slab", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "blade-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27142319e2f4c264581067eaccb9f80acccdde60d8b4bf57cc50cd3152f109ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.4", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.13.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex 2.0.1", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-expr" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb693542bcafa528e198be0ebd9d3632ca5b7c93dbe7237460e199910835997c" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "num-traits", +] + +[[package]] +name = "clang-sys" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation", + "core-graphics-types", + "libc", + "objc", +] + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "cookie-factory" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dashmap" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.19", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dinovision" +version = "0.1.0" +dependencies = [ + "blade-graphics", + "blade-macros", + "bytemuck", + "env_logger", + "half", + "image", + "log", + "meganeura", + "serde", + "serde_json", + "sha2", + "winit", + "xcap", +] + +[[package]] +name = "dinovision-android" +version = "0.1.0" +dependencies = [ + "android-activity", + "android_logger", + "dinovision", + "log", +] + +[[package]] +name = "dinovision-xr" +version = "0.1.0" +dependencies = [ + "android-activity", + "android_logger", + "blade-graphics", + "dinovision", + "log", + "ndk-glue", + "openxr", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +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 0.61.2", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "dot-generator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aaac7ada45f71873ebce336491d1c1bc4a7c8042c7cea978168ad59e805b871" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "dot-structures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cfcded997a93eb31edd639361fa33fd229a8784e953b37d71035fe3890b7b" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "drm" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 0.38.44", +] + +[[package]] +name = "drm" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a41816e58f47f49acfd956651055ddcf137c4882c2098c30c448817af21183a" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "bytemuck_derive", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 1.1.4", +] + +[[package]] +name = "drm-ffi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690" +dependencies = [ + "drm-sys", + "rustix 1.1.4", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8e1361066d91f5ffccff060a3c3be9c3ecde15be2959c1937595f7a82a9f8" +dependencies = [ + "libc", + "linux-raw-sys 0.9.4", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "egglog" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2e053dcef2cd92b0dee0acfad08d83a98c1c1e55b4c55b8eefa2c0e3f4d055" +dependencies = [ + "chrono", + "clap", + "csv", + "dyn-clone", + "egglog-add-primitive", + "egglog-ast", + "egglog-bridge", + "egglog-core-relations", + "egglog-numeric-id", + "egglog-reports", + "egraph-serialize", + "env_logger", + "hashbrown 0.16.1", + "im-rc", + "indexmap", + "log", + "mimalloc", + "num", + "ordered-float", + "rayon", + "rustc-hash 2.1.3", + "serde_json", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-add-primitive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea7ffb4d889c382918cfa139256f2a4d3f46de6e08d9c071e33543393bd3663" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "egglog-ast" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c67f2aa84cdabd48b266cff0ad4bc6d4cb4386ca51d8c8d93e089f182bc162b" +dependencies = [ + "ordered-float", +] + +[[package]] +name = "egglog-bridge" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaf9e5c5f59f5edb456367dd1e7e30fe5ecfd5b434954ec7ad2d90b3169d9a2f" +dependencies = [ + "anyhow", + "dyn-clone", + "egglog-core-relations", + "egglog-numeric-id", + "egglog-reports", + "egglog-union-find", + "hashbrown 0.16.1", + "indexmap", + "log", + "num-rational", + "once_cell", + "ordered-float", + "petgraph", + "rayon", + "smallvec", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-concurrency" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5cf71f21545d7b14aceb21e51fdc16b1077e5063df03d57253fc13f098ea2cd" +dependencies = [ + "arc-swap", + "egglog-numeric-id", + "rayon", + "smallvec", +] + +[[package]] +name = "egglog-core-relations" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d477debbbe77c0fb24df98c37560cce6b8dcd8d05918a009926204cbf13c73" +dependencies = [ + "anyhow", + "bumpalo", + "crossbeam", + "crossbeam-queue", + "dashmap", + "dyn-clone", + "egglog-concurrency", + "egglog-numeric-id", + "egglog-reports", + "egglog-union-find", + "fixedbitset", + "hashbrown 0.16.1", + "indexmap", + "log", + "num", + "once_cell", + "petgraph", + "rand 0.9.5", + "rayon", + "rustc-hash 2.1.3", + "smallvec", + "thiserror 2.0.19", + "web-time", +] + +[[package]] +name = "egglog-numeric-id" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b207a4ee3241bc8c84bb314d8c6802fa4974c4742a9b1af5e7646ec6ddb5ae5" +dependencies = [ + "rayon", +] + +[[package]] +name = "egglog-reports" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a58e0caea9c3d0fe0486245784f579645576f3b4a8be97fb5828655b281208" +dependencies = [ + "clap", + "hashbrown 0.16.1", + "indexmap", + "rustc-hash 2.1.3", + "serde", + "serde_json", + "web-time", +] + +[[package]] +name = "egglog-union-find" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175f8e99129dcdac7f96b12cc4703c4145bb74a1a53accc46073a19ace10b9f9" +dependencies = [ + "crossbeam", + "egglog-concurrency", + "egglog-numeric-id", +] + +[[package]] +name = "egraph-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0977732fb537ace6f8c15ce160ebdda78b6502b4866d3b904e4fe752e2be4702" +dependencies = [ + "graphviz-rust", + "indexmap", + "once_cell", + "ordered-float", + "serde", + "serde_json", +] + +[[package]] +name = "either" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_filter" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" +dependencies = [ + "anstream", + "anstyle", + "env_filter 2.0.0", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" + +[[package]] +name = "futures-io" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "futures-sink" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" + +[[package]] +name = "futures-task" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" + +[[package]] +name = "futures-util" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gbm" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a" +dependencies = [ + "bitflags 2.13.1", + "drm 0.14.1", + "drm-fourcc", + "gbm-sys", + "libc", + "wayland-backend", + "wayland-server", +] + +[[package]] +name = "gbm-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13a5f2acc785d8fb6bf6b7ab6bfb0ef5dad4f4d97e8e70bb8e470722312f76f" +dependencies = [ + "libc", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasm-bindgen", +] + +[[package]] +name = "gl" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45cf04b2726f02df5508c6de726acdc90cdf97ac771a9a0ffd8ba10a6e696bf9" +dependencies = [ + "bitflags 2.13.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-ash" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643756f08ef6def813c776199e4766596395a4c6530373c9a4374a64de2f53a1" +dependencies = [ + "ash", + "gpu-alloc-types", + "tinyvec", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bbed164dd10ed526c2e4fe3e721ca4a71c61730e5aafac6844b417b3227058" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "graphviz-rust" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee83cefff83c5dd5f34c603145f4e8d478e70cc17873049b6a36eeaf37b250a" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "into-attr-derive", + "pest", + "pest_derive", + "rand 0.9.5", + "tempfile", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hf-hub" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "629d8f3bbeda9d148036d6b0de0a3ab947abd08ce90626327fc3547a49d59d97" +dependencies = [ + "dirs", + "http", + "indicatif", + "libc", + "log", + "rand 0.9.5", + "reqwest", + "serde", + "serde_json", + "thiserror 2.0.19", + "ureq", + "windows-sys 0.60.2", +] + +[[package]] +name = "hidden-trait" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ed9e850438ac849bec07e7d09fbe9309cbd396a5988c30b010580ce08860df" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "http" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 1.0.9", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[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 = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[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 = "im-rc" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + +[[package]] +name = "into-attr" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b48c537e49a709e678caec3753a7dba6854661a1eaa27675024283b3f8b376" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "into-attr-derive" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecac7c1ae6cd2c6a3a64d1061a8bdc7f52ff62c26a831a2301e54c1b5d70d5b1" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jiff" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +dependencies = [ + "defmt", +] + +[[package]] +name = "jiff-static" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.19", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" +dependencies = [ + "cc", +] + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "bitflags 2.13.1", + "libc", + "plain", + "redox_syscall 0.9.1", +] + +[[package]] +name = "libspa" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2909f3be29d674e7f10604aff18d1bbe1bb03c4cd61c8a8ba19c0b1d162f7d4e" +dependencies = [ + "bitflags 2.13.1", + "cc", + "cookie-factory", + "libc", + "libspa-sys", + "nom 8.0.0", + "rustix 1.1.4", + "system-deps", +] + +[[package]] +name = "libspa-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69ad52764fca54818486f3cf75afec844d1f1a1568c24dcee25d41b1ab007dda" +dependencies = [ + "bindgen", + "cc", + "system-deps", +] + +[[package]] +name = "libwayshot-xcap" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8a46e4d016ef464e386e4970f5415fe0939c2d63abe0c2f539c05ef88c5fe5" +dependencies = [ + "drm 0.15.0", + "gbm", + "gl", + "image", + "khronos-egl", + "memmap2", + "rustix 1.1.4", + "thiserror 2.0.19", + "tracing", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-wlr", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[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 = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "meganeura" +version = "0.2.0" +dependencies = [ + "blade-graphics", + "blade-macros", + "bytemuck", + "egglog", + "flate2", + "half", + "hf-hub", + "log", + "naga", + "oxionnx-core", + "oxionnx-proto", + "ron", + "safetensors", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mimalloc" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + +[[package]] +name = "mio" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +dependencies = [ + "libc", + "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 = "naga" +version = "29.0.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb#78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.13.1", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror 2.0.19", + "unicode-ident", +] + +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags 1.3.2", + "jni-sys 0.3.1", + "ndk-sys 0.4.1+23.1.7779620", + "num_enum 0.5.11", + "raw-window-handle 0.5.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.13.1", + "jni-sys 0.3.1", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum 0.7.6", + "raw-window-handle 0.6.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-glue" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" +dependencies = [ + "libc", + "log", + "ndk 0.7.0", + "ndk-context", + "ndk-macro", + "ndk-sys 0.4.1+23.1.7779620", + "once_cell", + "parking_lot", +] + +[[package]] +name = "ndk-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive 0.7.6", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", + "objc2-cloud-kit 0.3.2", + "objc2-core-data 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-av-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478ae33fcac9df0a18db8302387c666b8ef08a3e2d62b510ca4fc278a384b6c0" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "objc2 0.6.4", + "objc2-avf-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-image-io", + "objc2-media-toolbox", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-avf-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be" +dependencies = [ + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2" +dependencies = [ + "dispatch2", + "objc2 0.6.4", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-core-audio-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "libc", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "libc", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-io-surface", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-media" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ec576860167a15dd9fce7fbee7512beb4e31f532159d3482d1f9c6caedf31d" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "dispatch2", + "objc2 0.6.4", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-video", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-image-io" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b0446e98cf4a784cc7a0177715ff317eeaa8463841c616cfc78aa4f953c4ea" +dependencies = [ + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-media-toolbox" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd9fdde720df3da7046bb9097811000c1e7ab5cd579fa89d96b27d56781fb30" +dependencies = [ + "objc2 0.6.4", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-core-media", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit 0.2.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "openxr" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2d6934d2508f94fd4cbda6c2a326f111f60ce59fd9136df6d478564397dd40" +dependencies = [ + "libc", + "libloading", + "ndk-context", + "openxr-sys", +] + +[[package]] +name = "openxr-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f10e7e38c47f2175fc39363713b656db899fa0b4a14341029702cbdfa6f44d05" +dependencies = [ + "libc", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "orbclient" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" +dependencies = [ + "libc", + "libredox", +] + +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", + "rand 0.8.7", + "serde", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "oxionnx-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e993c5ce626b2ba751efa1c0c1e6b95c7dacc092174363a2aa6f55f3feee7c7f" +dependencies = [ + "half", + "hashbrown 0.17.1", +] + +[[package]] +name = "oxionnx-proto" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e80cf809f319ae19ef5e80a8b50a0afc2859da77cb182646d31633f75615ff" +dependencies = [ + "half", + "oxionnx-core", + "thiserror 2.0.19", + "tracing", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df728be843c7070fab6ab7c328c4e9e9d78e23bf749c0669c86ee7ebfa050a2" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2dd6fc3b26b3462ee188aac870f5a41d398f1cd5e2408d16531bd71c9591fd" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a7a9205cfb6f596a9e8b689c0a15f9ceb7a1aafae7aaf788150ac65b29975b6" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pest_meta" +version = "2.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85abd351c0de1e8384fc791a0737111a350394937e92b956b743dac12429f57c" +dependencies = [ + "pest", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", + "serde", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pipewire" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8585aba8a52ad74ccc633b8e293c1dc4277976bd5d510b925533f34fd6685f38" +dependencies = [ + "bitflags 2.13.1", + "libc", + "libspa", + "libspa-sys", + "pipewire-sys", + "rustix 1.1.4", +] + +[[package]] +name = "pipewire-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2089f245b548723e60325773c27f586b7a2372c79ea941b246cd0d654706adc" +dependencies = [ + "bindgen", + "libspa-sys", + "system-deps", +] + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "portable-atomic" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.13+spec-1.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.3", + "rustls", + "socket2", + "thiserror 2.0.19", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" +dependencies = [ + "bytes", + "getrandom 0.4.3", + "lru-slab", + "rand 0.10.2", + "rand_pcg", + "ring", + "rustc-hash 2.1.3", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.19", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.61.2", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +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.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +dependencies = [ + "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "serde", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e8caa82e31bb98fee12fa8f051c94a6aa36b07cddb03f0d4fc558988360ff1" +dependencies = [ + "cocoa", + "core-graphics", + "objc", + "raw-window-handle 0.6.2", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "redox_syscall" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07507be7b4a5f9f26eeb41eeaebb1f5a7ff29dfb29739facc21d35bf8b11c21e" +dependencies = [ + "bitflags 2.13.1", +] + +[[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 2.0.19", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots 1.0.9", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.13.1", + "serde", + "serde_derive", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "safetensors" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44560c11236a6130a46ce36c836a62936dc81ebf8c36a37947423571be0e55b6" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +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 = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.13.1", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "socks" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" +dependencies = [ + "byteorder", + "libc", + "winapi", +] + +[[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.1", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "system-deps" +version = "7.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +dependencies = [ + "thiserror-impl 2.0.19", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "1.1.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.4", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime 0.6.11", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.13+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.4", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.13.1", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "socks", + "url", + "webpki-roots 0.26.11", +] + +[[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 = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wayland-backend" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016ccf01d1c58b6f8999612813e17c9b2390f7d70671428869913310f83f54b8" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073" +dependencies = [ + "bitflags 2.13.1", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.13.1", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0" +dependencies = [ + "proc-macro2", + "quick-xml 0.41.0", + "quote", +] + +[[package]] +name = "wayland-server" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde9c29be0f723a573977de51ee455bf3dfa03652730a74f9dd3b337e374d75" +dependencies = [ + "bitflags 2.13.1", + "downcast-rs", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "libc", + "log", + "memoffset", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.9", +] + +[[package]] +name = "webpki-roots" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[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.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winit" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.13.1", + "block2 0.5.1", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk 0.9.0", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit 0.2.2", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle 0.6.2", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +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 = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 1.1.4", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcap" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b31c7f57ddfb14983525d9149eaed160de7d3973aaa546f3e19eb3394122b6b" +dependencies = [ + "dispatch2", + "image", + "libwayshot-xcap", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-av-foundation", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-media", + "objc2-core-video", + "objc2-foundation 0.3.2", + "percent-encoding", + "pipewire", + "rand 0.10.2", + "scopeguard", + "serde", + "thiserror 2.0.19", + "url", + "widestring", + "windows", + "xcb", + "zbus", +] + +[[package]] +name = "xcb" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4c580d8205abb0a5cf4eb7e927bd664e425b6c3263f9c5310583da96970cf6" +dependencies = [ + "bitflags 1.3.2", + "libc", + "quick-xml 0.30.0", +] + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.13.1", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[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 2.0.119", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe18fb60dc696039e738717b76eaea21e7a4489bbb1885020b43c94236d7e98a" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix 1.1.4", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow 1.0.4", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe96480bed92df2b442a1a30df364e12d08eed03aeb061f2b8dc6afb2be91119" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e" +dependencies = [ + "serde", + "winnow 1.0.4", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[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 2.0.119", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + +[[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 2.0.119", +] + +[[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.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] + +[[package]] +name = "zvariant" +version = "5.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee2a0bcd2a907786a456fff45aaaaf54c9ba5f50b71ae9ec1a4edd200c94911" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow 1.0.4", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a708216a18780796770bfe3f4739c7c83a3e8f789b755534bbbc06e4e23e12" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.119", + "winnow 1.0.4", +] diff --git a/environment/training-source/cargo-tree.txt b/environment/training-source/cargo-tree.txt new file mode 100644 index 0000000000000000000000000000000000000000..650b01df5dbdf6355abf48d37c149a7dd4b06379 --- /dev/null +++ b/environment/training-source/cargo-tree.txt @@ -0,0 +1,450 @@ +dinovision v0.1.0 (C:\Code\dinovision) +├── blade-graphics v0.8.4 (https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6) +│ ├── ash v0.38.0+1.3.281 +│ │ └── libloading v0.8.9 +│ │ └── windows-link v0.2.1 +│ ├── ash-window v0.13.0 +│ │ ├── ash v0.38.0+1.3.281 (*) +│ │ └── raw-window-handle v0.6.2 +│ ├── bitflags v2.13.1 +│ │ └── serde_core v1.0.229 +│ ├── bytemuck v1.25.2 +│ │ └── bytemuck_derive v1.11.0 (proc-macro) +│ │ ├── proc-macro2 v1.0.107 +│ │ │ └── unicode-ident v1.0.24 +│ │ ├── quote v1.0.47 +│ │ │ └── proc-macro2 v1.0.107 (*) +│ │ └── syn v2.0.119 +│ │ ├── proc-macro2 v1.0.107 (*) +│ │ ├── quote v1.0.47 (*) +│ │ └── unicode-ident v1.0.24 +│ ├── codespan-reporting v0.13.1 +│ │ ├── termcolor v1.4.1 +│ │ │ └── winapi-util v0.1.11 +│ │ │ └── windows-sys v0.61.2 +│ │ │ └── windows-link v0.2.1 +│ │ └── unicode-width v0.2.2 +│ ├── gpu-alloc v0.6.2 +│ │ ├── bitflags v2.13.1 (*) +│ │ └── gpu-alloc-types v0.3.1 +│ │ └── bitflags v2.13.1 (*) +│ ├── gpu-alloc-ash v0.7.1 +│ │ ├── ash v0.38.0+1.3.281 (*) +│ │ ├── gpu-alloc-types v0.3.1 (*) +│ │ └── tinyvec v1.12.0 +│ │ └── tinyvec_macros v0.1.1 +│ ├── hidden-trait v0.1.2 (proc-macro) +│ │ ├── proc-macro2 v1.0.107 (*) +│ │ ├── quote v1.0.47 (*) +│ │ └── syn v1.0.109 +│ │ ├── proc-macro2 v1.0.107 (*) +│ │ ├── quote v1.0.47 (*) +│ │ └── unicode-ident v1.0.24 +│ ├── log v0.4.33 +│ ├── mint v0.5.9 +│ ├── naga v29.0.0 (https://github.com/gfx-rs/wgpu?rev=78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb#78b4dfd0) +│ │ ├── arrayvec v0.7.8 +│ │ ├── bit-set v0.10.0 +│ │ │ └── bit-vec v0.9.1 +│ │ ├── bitflags v2.13.1 (*) +│ │ ├── cfg-if v1.0.4 +│ │ ├── codespan-reporting v0.13.1 (*) +│ │ ├── half v2.7.1 +│ │ │ ├── cfg-if v1.0.4 +│ │ │ ├── num-traits v0.2.19 +│ │ │ │ └── libm v0.2.16 +│ │ │ │ [build-dependencies] +│ │ │ │ └── autocfg v1.5.1 +│ │ │ └── zerocopy v0.8.55 +│ │ │ └── zerocopy-derive v0.8.55 (proc-macro) +│ │ │ ├── proc-macro2 v1.0.107 (*) +│ │ │ ├── quote v1.0.47 (*) +│ │ │ └── syn v2.0.119 (*) +│ │ ├── hashbrown v0.16.1 +│ │ │ ├── allocator-api2 v0.2.21 +│ │ │ ├── equivalent v1.0.2 +│ │ │ ├── foldhash v0.2.0 +│ │ │ └── serde_core v1.0.229 +│ │ ├── indexmap v2.14.0 +│ │ │ ├── equivalent v1.0.2 +│ │ │ ├── hashbrown v0.17.1 +│ │ │ │ ├── allocator-api2 v0.2.21 +│ │ │ │ ├── equivalent v1.0.2 +│ │ │ │ └── foldhash v0.2.0 +│ │ │ └── serde_core v1.0.229 +│ │ ├── libm v0.2.16 +│ │ ├── log v0.4.33 +│ │ ├── num-traits v0.2.19 (*) +│ │ ├── once_cell v1.21.4 +│ │ ├── rustc-hash v1.1.0 +│ │ ├── spirv v0.4.0+sdk-1.4.341.0 +│ │ │ └── bitflags v2.13.1 (*) +│ │ ├── thiserror v2.0.19 +│ │ │ └── thiserror-impl v2.0.19 (proc-macro) +│ │ │ ├── proc-macro2 v1.0.107 (*) +│ │ │ ├── quote v1.0.47 (*) +│ │ │ └── syn v3.0.3 +│ │ │ ├── proc-macro2 v1.0.107 (*) +│ │ │ ├── quote v1.0.47 (*) +│ │ │ └── unicode-ident v1.0.24 +│ │ └── unicode-ident v1.0.24 +│ │ [build-dependencies] +│ │ └── cfg_aliases v0.2.2 +│ ├── once_cell v1.21.4 +│ ├── openxr v0.19.0 +│ │ ├── libc v0.2.189 +│ │ ├── libloading v0.8.9 (*) +│ │ └── openxr-sys v0.11.0 +│ │ └── libc v0.2.189 +│ ├── raw-window-handle v0.6.2 +│ └── slab v0.4.12 +├── blade-macros v0.3.0 (proc-macro) +│ ├── proc-macro2 v1.0.107 (*) +│ ├── quote v1.0.47 (*) +│ └── syn v2.0.119 (*) +├── bytemuck v1.25.2 (*) +├── half v2.7.1 (*) +├── log v0.4.33 +└── meganeura v0.2.0 (C:\Code\meganeura) + ├── blade-graphics v0.8.4 (https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6) (*) + ├── blade-macros v0.3.0 (proc-macro) (*) + ├── bytemuck v1.25.2 (*) + ├── egglog v2.0.0 + │ ├── clap v4.6.4 + │ │ ├── clap_builder v4.6.2 + │ │ │ ├── anstream v1.0.0 + │ │ │ │ ├── anstyle v1.0.14 + │ │ │ │ ├── anstyle-parse v1.0.0 + │ │ │ │ │ └── utf8parse v0.2.2 + │ │ │ │ ├── anstyle-query v1.1.5 + │ │ │ │ │ └── windows-sys v0.61.2 (*) + │ │ │ │ ├── anstyle-wincon v3.0.11 + │ │ │ │ │ ├── anstyle v1.0.14 + │ │ │ │ │ ├── once_cell_polyfill v1.70.2 + │ │ │ │ │ └── windows-sys v0.61.2 (*) + │ │ │ │ ├── colorchoice v1.0.5 + │ │ │ │ ├── is_terminal_polyfill v1.70.2 + │ │ │ │ └── utf8parse v0.2.2 + │ │ │ ├── anstyle v1.0.14 + │ │ │ ├── clap_lex v1.1.0 + │ │ │ └── strsim v0.11.1 + │ │ └── clap_derive v4.6.4 (proc-macro) + │ │ ├── heck v0.5.0 + │ │ ├── proc-macro2 v1.0.107 (*) + │ │ ├── quote v1.0.47 (*) + │ │ └── syn v3.0.3 (*) + │ ├── csv v1.4.0 + │ │ ├── csv-core v0.1.13 + │ │ │ └── memchr v2.8.3 + │ │ ├── itoa v1.0.18 + │ │ ├── ryu v1.0.23 + │ │ └── serde_core v1.0.229 + │ ├── dyn-clone v1.0.20 + │ ├── egglog-add-primitive v2.0.0 (proc-macro) + │ │ ├── quote v1.0.47 (*) + │ │ └── syn v2.0.119 (*) + │ ├── egglog-ast v2.0.0 + │ │ └── ordered-float v5.3.0 + │ │ ├── num-traits v0.2.19 (*) + │ │ └── serde v1.0.229 + │ │ ├── serde_core v1.0.229 + │ │ └── serde_derive v1.0.229 (proc-macro) + │ │ ├── proc-macro2 v1.0.107 (*) + │ │ ├── quote v1.0.47 (*) + │ │ └── syn v3.0.3 (*) + │ ├── egglog-bridge v2.0.0 + │ │ ├── anyhow v1.0.104 + │ │ ├── dyn-clone v1.0.20 + │ │ ├── egglog-core-relations v2.0.0 + │ │ │ ├── anyhow v1.0.104 + │ │ │ ├── bumpalo v3.20.3 + │ │ │ ├── crossbeam v0.8.4 + │ │ │ │ ├── crossbeam-channel v0.5.16 + │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ ├── crossbeam-deque v0.8.7 + │ │ │ │ │ ├── crossbeam-epoch v0.9.20 + │ │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ ├── crossbeam-epoch v0.9.20 (*) + │ │ │ │ ├── crossbeam-queue v0.3.13 + │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ ├── crossbeam-queue v0.3.13 (*) + │ │ │ ├── dashmap v6.2.1 + │ │ │ │ ├── cfg-if v1.0.4 + │ │ │ │ ├── crossbeam-utils v0.8.22 + │ │ │ │ ├── hashbrown v0.14.5 + │ │ │ │ ├── lock_api v0.4.14 + │ │ │ │ │ └── scopeguard v1.2.0 + │ │ │ │ ├── once_cell v1.21.4 + │ │ │ │ └── parking_lot_core v0.9.12 + │ │ │ │ ├── cfg-if v1.0.4 + │ │ │ │ ├── smallvec v1.15.2 + │ │ │ │ └── windows-link v0.2.1 + │ │ │ ├── dyn-clone v1.0.20 + │ │ │ ├── egglog-concurrency v2.0.0 + │ │ │ │ ├── arc-swap v1.9.2 + │ │ │ │ │ └── rustversion v1.0.23 (proc-macro) + │ │ │ │ ├── egglog-numeric-id v2.0.0 + │ │ │ │ │ └── rayon v1.12.0 + │ │ │ │ │ ├── either v1.17.0 + │ │ │ │ │ └── rayon-core v1.13.0 + │ │ │ │ │ ├── crossbeam-deque v0.8.7 (*) + │ │ │ │ │ └── crossbeam-utils v0.8.22 + │ │ │ │ ├── rayon v1.12.0 (*) + │ │ │ │ └── smallvec v1.15.2 + │ │ │ ├── egglog-numeric-id v2.0.0 (*) + │ │ │ ├── egglog-reports v2.0.0 + │ │ │ │ ├── clap v4.6.4 (*) + │ │ │ │ ├── hashbrown v0.16.1 (*) + │ │ │ │ ├── indexmap v2.14.0 (*) + │ │ │ │ ├── rustc-hash v2.1.3 + │ │ │ │ ├── serde v1.0.229 (*) + │ │ │ │ ├── serde_json v1.0.151 + │ │ │ │ │ ├── indexmap v2.14.0 (*) + │ │ │ │ │ ├── itoa v1.0.18 + │ │ │ │ │ ├── memchr v2.8.3 + │ │ │ │ │ ├── serde_core v1.0.229 + │ │ │ │ │ └── zmij v1.0.23 + │ │ │ │ └── web-time v1.1.0 + │ │ │ ├── egglog-union-find v2.0.0 + │ │ │ │ ├── crossbeam v0.8.4 (*) + │ │ │ │ ├── egglog-concurrency v2.0.0 (*) + │ │ │ │ └── egglog-numeric-id v2.0.0 (*) + │ │ │ ├── fixedbitset v0.5.7 + │ │ │ ├── hashbrown v0.16.1 (*) + │ │ │ ├── indexmap v2.14.0 (*) + │ │ │ ├── log v0.4.33 + │ │ │ ├── num v0.4.3 + │ │ │ │ ├── num-bigint v0.4.8 + │ │ │ │ │ ├── num-integer v0.1.46 + │ │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ ├── num-complex v0.4.6 + │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ ├── num-integer v0.1.46 (*) + │ │ │ │ ├── num-iter v0.1.46 + │ │ │ │ │ ├── num-integer v0.1.46 (*) + │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ ├── num-rational v0.4.2 + │ │ │ │ │ ├── num-bigint v0.4.8 (*) + │ │ │ │ │ ├── num-integer v0.1.46 (*) + │ │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ │ └── num-traits v0.2.19 (*) + │ │ │ ├── once_cell v1.21.4 + │ │ │ ├── petgraph v0.8.3 + │ │ │ │ ├── fixedbitset v0.5.7 + │ │ │ │ ├── hashbrown v0.15.5 + │ │ │ │ │ └── foldhash v0.1.5 + │ │ │ │ └── indexmap v2.14.0 (*) + │ │ │ ├── rand v0.9.5 + │ │ │ │ ├── rand_chacha v0.9.0 + │ │ │ │ │ ├── ppv-lite86 v0.2.21 + │ │ │ │ │ │ └── zerocopy v0.8.55 (*) + │ │ │ │ │ └── rand_core v0.9.5 + │ │ │ │ │ └── getrandom v0.3.4 + │ │ │ │ │ └── cfg-if v1.0.4 + │ │ │ │ └── rand_core v0.9.5 (*) + │ │ │ ├── rayon v1.12.0 (*) + │ │ │ ├── rustc-hash v2.1.3 + │ │ │ ├── smallvec v1.15.2 + │ │ │ ├── thiserror v2.0.19 (*) + │ │ │ └── web-time v1.1.0 + │ │ ├── egglog-numeric-id v2.0.0 (*) + │ │ ├── egglog-reports v2.0.0 (*) + │ │ ├── egglog-union-find v2.0.0 (*) + │ │ ├── hashbrown v0.16.1 (*) + │ │ ├── indexmap v2.14.0 (*) + │ │ ├── log v0.4.33 + │ │ ├── num-rational v0.4.2 (*) + │ │ ├── once_cell v1.21.4 + │ │ ├── ordered-float v5.3.0 (*) + │ │ ├── petgraph v0.8.3 (*) + │ │ ├── rayon v1.12.0 (*) + │ │ ├── smallvec v1.15.2 + │ │ ├── thiserror v2.0.19 (*) + │ │ └── web-time v1.1.0 + │ ├── egglog-core-relations v2.0.0 (*) + │ ├── egglog-numeric-id v2.0.0 (*) + │ ├── egglog-reports v2.0.0 (*) + │ ├── egraph-serialize v0.3.0 + │ │ ├── graphviz-rust v0.9.8 + │ │ │ ├── dot-generator v0.2.0 + │ │ │ │ └── dot-structures v0.1.2 + │ │ │ ├── dot-structures v0.1.2 + │ │ │ ├── into-attr v0.1.1 + │ │ │ │ └── dot-structures v0.1.2 + │ │ │ ├── into-attr-derive v0.2.1 (proc-macro) + │ │ │ │ ├── dot-generator v0.2.0 (*) + │ │ │ │ ├── dot-structures v0.1.2 + │ │ │ │ ├── into-attr v0.1.1 (*) + │ │ │ │ ├── quote v1.0.47 (*) + │ │ │ │ └── syn v1.0.109 (*) + │ │ │ ├── pest v2.8.8 + │ │ │ │ ├── memchr v2.8.3 + │ │ │ │ └── ucd-trie v0.1.7 + │ │ │ ├── pest_derive v2.8.8 (proc-macro) + │ │ │ │ ├── pest v2.8.8 (*) + │ │ │ │ └── pest_generator v2.8.8 + │ │ │ │ ├── pest v2.8.8 (*) + │ │ │ │ ├── pest_meta v2.8.8 + │ │ │ │ │ └── pest v2.8.8 (*) + │ │ │ │ ├── proc-macro2 v1.0.107 (*) + │ │ │ │ ├── quote v1.0.47 (*) + │ │ │ │ └── syn v2.0.119 (*) + │ │ │ ├── rand v0.9.5 (*) + │ │ │ └── tempfile v3.27.0 + │ │ │ ├── fastrand v2.5.0 + │ │ │ ├── getrandom v0.4.3 + │ │ │ │ └── cfg-if v1.0.4 + │ │ │ ├── once_cell v1.21.4 + │ │ │ └── windows-sys v0.61.2 (*) + │ │ ├── indexmap v2.14.0 (*) + │ │ ├── once_cell v1.21.4 + │ │ ├── ordered-float v5.3.0 (*) + │ │ ├── serde v1.0.229 (*) + │ │ └── serde_json v1.0.151 (*) + │ ├── env_logger v0.11.11 + │ │ ├── anstream v1.0.0 (*) + │ │ ├── anstyle v1.0.14 + │ │ ├── env_filter v2.0.0 + │ │ │ ├── log v0.4.33 + │ │ │ └── regex v1.13.1 + │ │ │ ├── aho-corasick v1.1.4 + │ │ │ │ └── memchr v2.8.3 + │ │ │ ├── memchr v2.8.3 + │ │ │ ├── regex-automata v0.4.16 + │ │ │ │ ├── aho-corasick v1.1.4 (*) + │ │ │ │ ├── memchr v2.8.3 + │ │ │ │ └── regex-syntax v0.8.11 + │ │ │ └── regex-syntax v0.8.11 + │ │ ├── jiff v0.2.35 + │ │ │ └── jiff-core v0.1.0 + │ │ └── log v0.4.33 + │ ├── hashbrown v0.16.1 (*) + │ ├── im-rc v15.1.0 + │ │ ├── bitmaps v2.1.0 + │ │ │ └── typenum v1.20.1 + │ │ ├── rand_core v0.6.4 + │ │ ├── rand_xoshiro v0.6.0 + │ │ │ └── rand_core v0.6.4 + │ │ ├── sized-chunks v0.6.5 + │ │ │ ├── bitmaps v2.1.0 (*) + │ │ │ └── typenum v1.20.1 + │ │ └── typenum v1.20.1 + │ │ [build-dependencies] + │ │ └── version_check v0.9.5 + │ ├── indexmap v2.14.0 (*) + │ ├── log v0.4.33 + │ ├── mimalloc v0.1.52 + │ │ └── libmimalloc-sys v0.1.49 + │ │ [build-dependencies] + │ │ └── cc v1.4.0 + │ │ ├── find-msvc-tools v0.1.9 + │ │ └── shlex v2.0.1 + │ ├── num v0.4.3 (*) + │ ├── ordered-float v5.3.0 (*) + │ ├── rayon v1.12.0 (*) + │ ├── rustc-hash v2.1.3 + │ ├── serde_json v1.0.151 (*) + │ ├── thiserror v2.0.19 (*) + │ └── web-time v1.1.0 + │ [build-dependencies] + │ └── chrono v0.4.45 + │ └── num-traits v0.2.19 + │ [build-dependencies] + │ └── autocfg v1.5.1 + ├── flate2 v1.1.9 + │ ├── crc32fast v1.5.0 + │ │ └── cfg-if v1.0.4 + │ └── miniz_oxide v0.8.9 + │ ├── adler2 v2.0.1 + │ └── simd-adler32 v0.3.10 + ├── half v2.7.1 (*) + ├── log v0.4.33 + ├── naga v29.0.0 (https://github.com/gfx-rs/wgpu?rev=78b4dfd0cb1ef5ed208fefe80ae2f855db3609bb#78b4dfd0) (*) + ├── oxionnx-core v0.1.4 + │ ├── half v2.7.1 (*) + │ └── hashbrown v0.17.1 (*) + ├── oxionnx-proto v0.1.4 + │ ├── half v2.7.1 (*) + │ ├── oxionnx-core v0.1.4 (*) + │ ├── thiserror v2.0.19 (*) + │ └── tracing v0.1.44 + │ ├── pin-project-lite v0.2.17 + │ ├── tracing-attributes v0.1.31 (proc-macro) + │ │ ├── proc-macro2 v1.0.107 (*) + │ │ ├── quote v1.0.47 (*) + │ │ └── syn v2.0.119 (*) + │ └── tracing-core v0.1.36 + │ └── once_cell v1.21.4 + ├── ron v0.8.1 + │ ├── base64 v0.21.7 + │ ├── bitflags v2.13.1 (*) + │ ├── serde v1.0.229 (*) + │ └── serde_derive v1.0.229 (proc-macro) (*) + ├── safetensors v0.4.5 + │ ├── serde v1.0.229 (*) + │ └── serde_json v1.0.151 (*) + ├── serde v1.0.229 (*) + ├── serde_json v1.0.151 (*) + ├── tracing v0.1.44 (*) + └── tracing-subscriber v0.3.23 + ├── nu-ansi-term v0.50.3 + │ └── windows-sys v0.61.2 (*) + ├── sharded-slab v0.1.7 + │ └── lazy_static v1.5.0 + ├── smallvec v1.15.2 + ├── thread_local v1.1.10 + │ └── cfg-if v1.0.4 + ├── tracing-core v0.1.36 (*) + └── tracing-log v0.2.0 + ├── log v0.4.33 + ├── once_cell v1.21.4 + └── tracing-core v0.1.36 (*) +[dev-dependencies] +├── env_logger v0.11.11 (*) +├── image v0.25.10 +│ ├── bytemuck v1.25.2 (*) +│ ├── byteorder-lite v0.1.0 +│ ├── moxcms v0.8.1 +│ │ ├── num-traits v0.2.19 (*) +│ │ └── pxfm v0.1.30 +│ ├── num-traits v0.2.19 (*) +│ ├── png v0.18.1 +│ │ ├── bitflags v2.13.1 (*) +│ │ ├── crc32fast v1.5.0 (*) +│ │ ├── fdeflate v0.3.7 +│ │ │ └── simd-adler32 v0.3.10 +│ │ ├── flate2 v1.1.9 (*) +│ │ └── miniz_oxide v0.8.9 (*) +│ ├── zune-core v0.5.1 +│ └── zune-jpeg v0.5.15 +│ └── zune-core v0.5.1 +├── serde v1.0.229 (*) +├── serde_json v1.0.151 (*) +├── sha2 v0.10.9 +│ ├── cfg-if v1.0.4 +│ ├── cpufeatures v0.2.17 +│ └── digest v0.10.7 +│ ├── block-buffer v0.10.4 +│ │ └── generic-array v0.14.7 +│ │ └── typenum v1.20.1 +│ │ [build-dependencies] +│ │ └── version_check v0.9.5 +│ └── crypto-common v0.1.7 +│ ├── generic-array v0.14.7 (*) +│ └── typenum v1.20.1 +└── winit v0.30.13 + ├── bitflags v2.13.1 (*) + ├── cursor-icon v1.2.0 + ├── dpi v0.1.2 + ├── raw-window-handle v0.6.2 + ├── smol_str v0.2.2 + ├── tracing v0.1.44 (*) + ├── unicode-segmentation v1.13.3 + └── windows-sys v0.52.0 + └── windows-targets v0.52.6 + └── windows_x86_64_msvc v0.52.6 + [build-dependencies] + └── cfg_aliases v0.2.2 diff --git a/environment/training-source/metadata.json b/environment/training-source/metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..6d991b726a6b603496cadbfcda6758146963be00 --- /dev/null +++ b/environment/training-source/metadata.json @@ -0,0 +1,385 @@ +{ + "schema_version": 1, + "collected_utc": "2026-08-02T03:30:43.4082684Z", + "dinovision": { + "path": "C:\\Code\\dinovision", + "revision": "66caef824dc53c96b60e1c7382f004300428079d", + "branch": "main", + "clean": false, + "status": [ + " M .cargo/config.toml", + " M .gitignore", + " M Cargo.lock", + " M Cargo.toml", + " M README.md", + " M REPORT.md", + " M android-xr/src/lib.rs", + " M android/src/lib.rs", + " M examples/bench.rs", + " M examples/train_decoder.rs", + " M examples/verify.rs", + " M src/bench.rs", + " M src/decoder.rs", + " M src/dinov3.rs", + " M tools/dump_reference.py", + "?? examples/common/", + "?? examples/evaluate_decoder.rs", + "?? experiments/", + "?? huggingface/", + "?? tests/dinov3_ops.rs", + "?? tools/build_android_artifacts.ps1", + "?? tools/collect_artifact_metadata.ps1", + "?? tools/compare_f32.py", + "?? tools/convert_decoder.py", + "?? tools/extract_json_records.py", + "?? tools/make_correctness_frame.py", + "?? tools/make_dataset_manifest.py", + "?? tools/pull_quest_artifacts.ps1", + "?? tools/run_cross_device_correctness.ps1", + "?? tools/run_decoder_matrix.ps1", + "?? tools/run_quest_bench.ps1", + "?? tools/run_xr_sweep.ps1", + "?? tools/stage_huggingface_artifact.ps1", + "?? tools/summarize_bench.py", + "?? tools/summarize_dataset.py", + "?? tools/summarize_quality.py", + "?? tools/summarize_xr.py" + ], + "source_files": [ + { + "path": "examples/common/mod.rs", + "bytes": 9570, + "sha256": "97872bb9c929ec510f76cf04ed6643bb063f181d6e7181524b5d80c3d9cc8439" + }, + { + "path": "examples/evaluate_decoder.rs", + "bytes": 19279, + "sha256": "787b705331097ed8963a4d3569f94f72db0e3fb9fffd65ecc17488eb9f2cd1e5" + }, + { + "path": "experiments/AUDIT.md", + "bytes": 4945, + "sha256": "f3a2326e3e18e3937a074a4c69ec173ca911afbc1cc5064d87cec26d63108c2f" + }, + { + "path": "experiments/README.md", + "bytes": 7613, + "sha256": "dfd4018c60965d425a365a4886bf269daaf29801fcef68ed7c6cf960340b8b37" + }, + { + "path": "huggingface/DINOv3-LICENSE.md", + "bytes": 7503, + "sha256": "25d122eb8f5b880fd23c736fb6ea8018ee45c12237e00b8a86d14c653904999e" + }, + { + "path": "huggingface/NOTICE.md", + "bytes": 883, + "sha256": "28b2cce3512b7c4d31d6ce435d338aeef9ee29839b198afbf414ec1c02ff3743" + }, + { + "path": "huggingface/README.md", + "bytes": 5358, + "sha256": "1f03054b826a7136367452913a67e829473fc9fd9e69eb44248d1f09222ea571" + }, + { + "path": "tests/dinov3_ops.rs", + "bytes": 4680, + "sha256": "1ff11a6db0cbccc422a0058a7a5d7e775dba357106cc3e8af3e23f315960387f" + }, + { + "path": "tools/build_android_artifacts.ps1", + "bytes": 4980, + "sha256": "97eedc24b8fc7e4baeb0faa0c023d57cda5d75d7ba9f9f1a04868d3563d8201b" + }, + { + "path": "tools/collect_artifact_metadata.ps1", + "bytes": 6601, + "sha256": "4574dea9d7ec0a7f87d9439b7fbc03e78a3a407bbb3ec53edeca5c0b61853f95" + }, + { + "path": "tools/compare_f32.py", + "bytes": 6380, + "sha256": "828f71146de6ac26aa40df27cec1170c0af4030c9d87cce87c5138c22d78e137" + }, + { + "path": "tools/convert_decoder.py", + "bytes": 3286, + "sha256": "962853f90e35a726d2f69f0f6fba2da4071efc12e8c3f200f695178a0377b9b6" + }, + { + "path": "tools/extract_json_records.py", + "bytes": 1927, + "sha256": "c5b8027cb6c8b1f57623c7543be0ce2925ad3e340c2a1bb510b3fa9f3c66cd3a" + }, + { + "path": "tools/make_correctness_frame.py", + "bytes": 1302, + "sha256": "87aacc02d8ae4b875fc3d519cd02f487c4187ebbcb7a752bbfddaf2f1bec7a28" + }, + { + "path": "tools/make_dataset_manifest.py", + "bytes": 4991, + "sha256": "d48f07f60af6c00edda4a8533e4ee5a265a924d2d6451898a8b0932e29343a11" + }, + { + "path": "tools/pull_quest_artifacts.ps1", + "bytes": 3202, + "sha256": "eda42f889f2a884cf82eec03375608212a7f50f2c8c0fbc2a7de6529afba2626" + }, + { + "path": "tools/run_cross_device_correctness.ps1", + "bytes": 6833, + "sha256": "1eb0d95bac5b6808bdd982d2c7047a096442e8a8973ab516538fc746a42c9fff" + }, + { + "path": "tools/run_decoder_matrix.ps1", + "bytes": 5352, + "sha256": "1f95ff681375b334dde39bab509c087321e6c531a9be04f47d65348dea9ccaef" + }, + { + "path": "tools/run_quest_bench.ps1", + "bytes": 6501, + "sha256": "0b6966cbcd06109ddee85e5a0746468ffe3932cd3748c0b4b4743eb23e1b34cf" + }, + { + "path": "tools/run_xr_sweep.ps1", + "bytes": 10711, + "sha256": "73853e9647a029ef0ea7b0190eaa757ee96b10ea80110aa5b731280eb0eaf8a4" + }, + { + "path": "tools/stage_huggingface_artifact.ps1", + "bytes": 9571, + "sha256": "7bb2fa6c4716fdd183c57ef0da743a306ad1d383083093c009032d7859bf1b3e" + }, + { + "path": "tools/summarize_bench.py", + "bytes": 5935, + "sha256": "94e4b431dad735c1233764018e43fafcfca194ccf75bfa6f14a159adeac17c12" + }, + { + "path": "tools/summarize_dataset.py", + "bytes": 4905, + "sha256": "cc9e1d1f6c36a5e792194ca7d77ef14674d3eed591994070d6c277786f26d144" + }, + { + "path": "tools/summarize_quality.py", + "bytes": 8713, + "sha256": "4fa1965d098029b85e5224c44fcb209f9771734ef25d559a9807d77489f80f98" + }, + { + "path": "tools/summarize_xr.py", + "bytes": 8249, + "sha256": "f78e44b7f1e81cb7b3d35e366b75fb464d6d76c84c23879e10f458794b4a640c" + }, + { + "path": ".cargo/config.toml", + "bytes": 226, + "sha256": "e7bf454f82c0d679e1bafc31028f74b20994b063fa3e5e86e1339430b05cc47c" + }, + { + "path": ".gitignore", + "bytes": 212, + "sha256": "5de7d69c3185414fd51c15aa33e4d104d6b7c1771431d97cae3920897b79a646" + }, + { + "path": "Cargo.lock", + "bytes": 148764, + "sha256": "d63a639b6af43b0fc1020ada5178902d30978ca51d555f2ea5417927582cbc49" + }, + { + "path": "Cargo.toml", + "bytes": 2382, + "sha256": "4bc34588dca13c3430b2432b19b585c95e739b68e7f959abe8f280f35d79428c" + }, + { + "path": "LICENSE", + "bytes": 1094, + "sha256": "602d42a30c16d186e3da4f12fc1eeab2dfc24a6e79da878c63a3ff234c0358e6" + }, + { + "path": "README.md", + "bytes": 17245, + "sha256": "e71dc7dbef867dc9cf7e15bfc0fef603627dd8f855a9af3721f8bb14835638b0" + }, + { + "path": "REPORT.md", + "bytes": 12167, + "sha256": "1fa8109553226482eaa59eb080ba9cb2a5901106948cec6430381e10a1a4d149" + }, + { + "path": "android-xr/Cargo.toml", + "bytes": 2854, + "sha256": "1df860091562bb35a2432930acb801a68b9688563b2d450d40a74ea2dc6c3131" + }, + { + "path": "android-xr/src/lib.rs", + "bytes": 36602, + "sha256": "dc39d9f6393482d325ec69fba83d0d846a76ddb8328164766d9445d74f981f52" + }, + { + "path": "android/Cargo.toml", + "bytes": 1630, + "sha256": "953097f02a122c40cc714c861862f4afc422e00ee99e46100c4cc6db5f254755" + }, + { + "path": "android/src/lib.rs", + "bytes": 2474, + "sha256": "31baa9646d8af738ebef870bb964e9d033625fcb198d014526665698bc19f969" + }, + { + "path": "examples/bench.rs", + "bytes": 1803, + "sha256": "15577b6f3b2f3e1b28eaf228eb81897ceaa0c237181d24baa2a067de7819a0be" + }, + { + "path": "examples/preview.rs", + "bytes": 5638, + "sha256": "f0beb2e9e0b2a1ddc2d681028a68843a6e570b2972a91b61c10b1d88f0e70c97" + }, + { + "path": "examples/train_decoder.rs", + "bytes": 16719, + "sha256": "cf9bb19634e9a08a6e98c8d536101095d841ed616b6272f0e013bfb5b86d7f10" + }, + { + "path": "examples/verify.rs", + "bytes": 22762, + "sha256": "241d70da7320526fa89fca9cb209cf839df398e051b9b26ccfe3ca5ca93073b7" + }, + { + "path": "examples/viewer.rs", + "bytes": 10350, + "sha256": "b5d655c664f0d929c78d57d4daded61f0746ed885504b7a02b013f6389ab4df6" + }, + { + "path": "src/bench.rs", + "bytes": 17678, + "sha256": "3bf99e83e2e8854730b34b5b0801172126c3f616371592d159b2ceb00405a35f" + }, + { + "path": "src/camera.rs", + "bytes": 28374, + "sha256": "93472c94e6d8ce5122b4c7db2731106c7102593cbb4bf444e7bbe9e08aa7b086" + }, + { + "path": "src/decoder.rs", + "bytes": 13220, + "sha256": "feee813cc1a8839d3ce374189e313d4f9c8ba5a087b0ab872fd570da156264b6" + }, + { + "path": "src/dinov3.rs", + "bytes": 20328, + "sha256": "09bcaad52dbeafe2992a1f7386d6444baae38a8f65a6f4c3a76266a0ec44145e" + }, + { + "path": "src/inference.rs", + "bytes": 13643, + "sha256": "2c8205c9771cfd1848e49ff4eef40492d6c4860b88fdef1e6467d5b520f1b961" + }, + { + "path": "src/lib.rs", + "bytes": 2547, + "sha256": "6b8ad76beffca29d94dcb5aa629f3f65c167c9c52fc8611e2ae48fb129a9cd64" + }, + { + "path": "src/pca.rs", + "bytes": 15878, + "sha256": "252f09f61486e333e0df8ddf34b167ee4de0c2861a7d9169c007061884fa2405" + }, + { + "path": "src/preprocess.rs", + "bytes": 7193, + "sha256": "69a13c6ee542763df8368839f6ae6ab9e082c3e25548b1f53219028c370561b5" + }, + { + "path": "src/render.rs", + "bytes": 13166, + "sha256": "31a0393b5caffff5e248a6fff89988d6368cf0de553491d43574748b16c8a779" + }, + { + "path": "src/shaders/grid_view.wgsl", + "bytes": 2490, + "sha256": "8406eba77ec27f055169edd00d540aeec18dd3c08733d8d9a7f0b2c479cb7869" + }, + { + "path": "src/source.rs", + "bytes": 10284, + "sha256": "11b38e9a06a7090cf2a9864b65eb46c96e429dbdb008b17f104172f0ec5e751d" + }, + { + "path": "src/weights.rs", + "bytes": 6404, + "sha256": "aa69dd605c691246fbe4cf00282aa25e0834681b713e47bfd6ef30369f98547f" + }, + { + "path": "tests/semantics.rs", + "bytes": 5790, + "sha256": "9cf2b851fd96adb9b754ebaeea315f6de02e7bf9f21d3d10b67fd376f28a80f1" + }, + { + "path": "tests/threading.rs", + "bytes": 1352, + "sha256": "df85acc70c20081aa337d7c97f4df9c513c8fd4c42e2aa2d7e798688ce5e3333" + }, + { + "path": "tools/dump_reference.py", + "bytes": 9405, + "sha256": "81fc39d70a6c381c1e5f871563672ea96818ff88995472f6ddb68cf35734ef29" + } + ] + }, + "meganeura": { + "path": "C:\\Code\\meganeura", + "revision": "0c0192a9414de45148086af64f610684e7a98743", + "branch": "android-cross-compile", + "clean": true, + "status": [ + + ] + }, + "blade_checkout": { + "path": "C:\\Code\\blade", + "revision": "1aa9d04a192b095533b2e5441ec658b2bafe056d", + "branch": "command-encoder-send", + "clean": true, + "status": [ + + ] + }, + "resolved_packages": { + "meganeura": [ + { + "version": "0.2.0", + "source": null, + "manifest_path": "C:\\Code\\meganeura\\Cargo.toml" + } + ], + "blade-graphics": [ + { + "version": "0.8.4", + "source": "git+https://github.com/kvark/blade?rev=ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac#ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac", + "manifest_path": "C:\\Users\\kvark\\.cargo\\git\\checkouts\\blade-26bd638d88226de3\\ba0fb5a\\blade-graphics\\Cargo.toml" + } + ] + }, + "rustc": "rustc 1.95.0 (59807616e 2026-04-14)\nbinary: rustc\ncommit-hash: 59807616e1fa2540724bfbac14d7976d7e4a3860\ncommit-date: 2026-04-14\nhost: x86_64-pc-windows-msvc\nrelease: 1.95.0\nLLVM version: 22.1.2", + "cargo": "cargo 1.95.0 (f2d3ce0bd 2026-03-21)\nrelease: 1.95.0\ncommit-hash: f2d3ce0bd7f24a49f8f72d9000448f8838c4e850\ncommit-date: 2026-03-21\nhost: x86_64-pc-windows-msvc\nlibgit2: 1.9.2 (sys:0.20.4 vendored)\nlibcurl: 8.15.0-DEV (sys:0.4.83+curl-8.15.0 vendored ssl:Schannel)\nos: Windows 10.0.26200 (Windows 11 Core) [64-bit]", + "os": "Microsoft Windows NT 10.0.26200.0", + "android_ndks": [ + "23.2.8568313", + "27.0.12077973" + ], + "nvidia_smi": "NVIDIA GeForce RTX 3050, 591.86", + "adb": "Android Debug Bridge version 1.0.41\nVersion 35.0.2-12147458\nInstalled as C:\\Users\\kvark\\AppData\\Local\\Android\\Sdk\\platform-tools\\adb.exe\nRunning on Windows 10.0.26200", + "model": { + "path": "C:\\tmp\\dinovision-assets\\model.safetensors", + "bytes": 86406384, + "sha256": "4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d" + }, + "decoder": { + "path": "C:\\tmp\\dinovision-runs-corrected-v2\\3l224-seed0\\decoder.bin", + "bytes": 8050188, + "sha256": "d2b34b2133b27c253e353af574d15627f2f7cfd6c87f3130e7541f3122a7ec5c" + }, + "quest_connected": false +} diff --git a/environment/training-source/source-snapshot/.cargo/config.toml b/environment/training-source/source-snapshot/.cargo/config.toml new file mode 100644 index 0000000000000000000000000000000000000000..91648b19c2c12ef74e184905d125184fee8eef87 --- /dev/null +++ b/environment/training-source/source-snapshot/.cargo/config.toml @@ -0,0 +1,3 @@ +# Host-specific Android SDK/NDK paths do not belong in a reproducible source +# tree. `tools/build_android_artifacts.ps1` validates NDK r27 and injects the +# target linker and compiler environment for both Cargo and cargo-apk. diff --git a/environment/training-source/source-snapshot/.gitignore b/environment/training-source/source-snapshot/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..18e9bfc9313306a77dbf3c9ebaa36de2890bab9d --- /dev/null +++ b/environment/training-source/source-snapshot/.gitignore @@ -0,0 +1,11 @@ +/target +/artifacts + +# Reference dumps from tools/dump_reference.py — weights and tensor blobs, +# tens of megabytes, and regenerable. +/ref +*.safetensors +*.bin + +# Compiled meganeura execution plans +*.plan diff --git a/environment/training-source/source-snapshot/android-xr/Cargo.toml b/environment/training-source/source-snapshot/android-xr/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..9fcda6477acb8bdfff2e696b686aa5305e6173b8 --- /dev/null +++ b/environment/training-source/source-snapshot/android-xr/Cargo.toml @@ -0,0 +1,83 @@ +[package] +name = "dinovision-xr" +version = "0.1.0" +publish = false +edition = "2024" + +[lib] +name = "dinovision_xr" +path = "src/lib.rs" +crate-type = ["cdylib"] + +[target.'cfg(target_os = "android")'.dependencies] +dinovision = { path = ".." } +blade-graphics = { version = "0.8.4", git = "https://github.com/kvark/blade", rev = "ba0fb5a6f2b5462c3e5796f8ce06b3b3d580adac" } +openxr = "0.19" +android-activity = { version = "0.6", features = ["native-activity"] } +android_logger = "0.14" +ndk-glue = "0.7" +log = "0.4" + +[package.metadata.android] +build_targets = ["aarch64-linux-android"] +# libopenxr_loader.so lives here; blade's examples ship the same set. +runtime_libs = "../../blade/examples-android/libs" +label = "DinoVision" + +[package.metadata.android.sdk] +# 34 is what Meta requires for the Passthrough Camera API, and NDK r27 is +# what has `ACameraManager_getTagFromName` for finding their vendor tags. +min_sdk_version = 34 +target_sdk_version = 34 + +[package.metadata.android.signing.release] +path = "../../blade/examples-android/keystore/debug.keystore" +keystore_password = "android" +key_alias = "androiddebugkey" +key_password = "android" + +# Without these, Horizon OS assumes controllers are mandatory and blocks +# launch behind a "controllers required" system dialog +# (LaunchCheckControllerRequiredDialogActivity). The app takes no input at +# all, so declaring optional hand tracking is the honest way to say so. +[[package.metadata.android.uses_feature]] +name = "oculus.software.handtracking" +required = false + +[[package.metadata.android.uses_permission]] +name = "com.oculus.permission.HAND_TRACKING" + +# Passthrough camera. Declaring these is necessary but not sufficient — +# HEADSET_CAMERA is a runtime permission, so it also has to be granted: +# adb shell pm grant rust.dinovision_xr horizonos.permission.HEADSET_CAMERA +[[package.metadata.android.uses_permission]] +name = "horizonos.permission.HEADSET_CAMERA" + +[[package.metadata.android.uses_permission]] +name = "android.permission.CAMERA" + +[[package.metadata.android.uses_feature]] +name = "android.hardware.camera2.any" +required = false + +[package.metadata.android.application] +label = "DinoVision" + +[[package.metadata.android.application.meta_data]] +name = "com.oculus.vr.focusaware" +value = "true" + +[package.metadata.android.application.activity] +label = "DinoVision" +theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" +config_changes = "density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode" +launch_mode = "singleTask" +orientation = "landscape" +resizeable_activity = false + +[[package.metadata.android.application.activity.intent_filter]] +actions = ["android.intent.action.MAIN"] +categories = [ + "com.oculus.intent.category.VR", + "android.intent.category.LAUNCHER", +] diff --git a/environment/training-source/source-snapshot/android/Cargo.toml b/environment/training-source/source-snapshot/android/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..af16c0c81adb8e4d4f1d51d75e90d9a44d90c1be --- /dev/null +++ b/environment/training-source/source-snapshot/android/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "dinovision-android" +version = "0.1.0" +publish = false +edition = "2024" + +[lib] +name = "dinobench" +path = "src/lib.rs" +crate-type = ["cdylib"] + +[target.'cfg(target_os = "android")'.dependencies] +dinovision = { path = ".." } +android-activity = { version = "0.6", features = ["native-activity"] } +android_logger = "0.14" +log = "0.4" + +[package.metadata.android] +build_targets = ["aarch64-linux-android"] +label = "DinoVision Bench" + +[package.metadata.android.sdk] +# API 30 matches the NDK clang wrapper configured in ../.cargo/config.toml. +# The passthrough-camera phase needs 34, and NDK r26+ to go with it. +min_sdk_version = 30 +target_sdk_version = 30 + +[package.metadata.android.signing.release] +path = "../../blade/examples-android/keystore/debug.keystore" +keystore_password = "android" +key_alias = "androiddebugkey" +key_password = "android" + +[package.metadata.android.application] +label = "DinoVision Bench" + +# Deliberately a plain 2D Android app, not a VR one: the benchmark answers +# a pure compute question, so there is no reason to drag OpenXR, a +# stereo swapchain, or the compositor into the measurement. It launches as +# a flat panel on the headset and logs to logcat. +[package.metadata.android.application.activity] +label = "DinoVision Bench" +config_changes = "density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode" +launch_mode = "singleTask" +orientation = "landscape" + +[[package.metadata.android.application.activity.intent_filter]] +actions = ["android.intent.action.MAIN"] +categories = ["android.intent.category.LAUNCHER"] diff --git a/environment/training-source/source-snapshot/android/src/lib.rs b/environment/training-source/source-snapshot/android/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d1b37df179f274a93e6af87c217b0ee05e30dadd --- /dev/null +++ b/environment/training-source/source-snapshot/android/src/lib.rs @@ -0,0 +1,75 @@ +//! On-device benchmark entry point. +//! +//! A deliberately plain Android app: no OpenXR, no swapchain, no camera. +//! The only question it answers is how fast the Adreno runs a DINOv3 +//! forward pass under meganeura, and mixing in the XR compositor would +//! only add noise to that. +//! +//! ```text +//! cargo apk run --manifest-path android/Cargo.toml --release --no-logcat +//! adb logcat -v time | grep -E "dinovision|RustStdoutStderr" +//! ``` +//! +//! The run is one-shot: results go to logcat and the process stays alive so +//! the launcher does not report a crash. + +#![cfg(target_os = "android")] + +use android_activity::{AndroidApp, MainEvent, PollEvent}; + +#[unsafe(no_mangle)] +fn android_main(app: AndroidApp) { + android_logger::init_once( + android_logger::Config::default() + .with_max_level(log::LevelFilter::Info) + .with_tag("dinovision"), + ); + + // Vulkan initialization can fail on a device we have not accounted for; + // a panic here would be reported as an opaque crash, so log the reason. + std::panic::set_hook(Box::new(|info| { + log::error!("panic: {info}"); + })); + + log::info!("=== dinovision benchmark ==="); + match std::panic::catch_unwind(run) { + Ok(()) => log::info!("=== benchmark complete ==="), + Err(_) => log::error!("=== benchmark aborted ==="), + } + + // Stay responsive to the lifecycle instead of returning, which Android + // treats as the activity dying. + loop { + app.poll_events(Some(std::time::Duration::from_millis(500)), |event| { + if let PollEvent::Main(MainEvent::Destroy) = event { + std::process::exit(0); + } + }); + } +} + +fn run() { + let gpu = match dinovision::init_context(None) { + Ok(gpu) => gpu, + Err(e) => { + log::error!("GPU context init failed: {e:?}"); + return; + } + }; + + let iters = std::env::var("DINOVISION_ITERS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(20); + log::info!( + "timing protocol: {} warmups, {iters} retained samples", + std::env::var("DINOVISION_WARMUPS").unwrap_or_else(|_| "5".into()) + ); + let results = dinovision::bench::run_all(gpu, iters); + + log::info!("---- summary ----"); + for t in &results { + log::info!("{t}"); + log::info!("DINOVISION_BENCH_JSON {}", t.json_line()); + } +}