diff --git a/RUST.md b/RUST.md index 33d4a20..f36ca11 100644 --- a/RUST.md +++ b/RUST.md @@ -37,19 +37,36 @@ session spending an afternoon on them again. ## Where things stand (2026-09-04) - **Done**: E0 (toolchain), E1 (Masonry on android-view, which found the - keyboard gap), I0a, I0b (iris builds on a pinned nightly and runs), I1 - (parley + glyph atlas). -- **Next**: **I2** — iris on android-view. E1 says the first thing to - answer there is why the editor gets keystrokes but no autocorrect or - suggestions, since that is the constraint the framework decision turns - on. **E2** (a transcript in Masonry) can go in parallel in another - session. + keyboard gap — now explained, see below), I0a, I0b (iris builds on a + pinned nightly and runs), I1 (parley + glyph atlas). +- **E1's keyboard gap is Masonry's `as_input_connection` returning `None` + (a TODO), not android-view or `EditorInfo`.** android-view's own demo + implements the `InputConnection` trait over a parley editor and gets + real Gboard suggestions on this emulator — screenshotted 2026-09-04. + android-view's `accesskit_android` adapter also has a reproducible abort + (a client detaching, not attaching, is the trigger) — see E1 below for + both, with the mitigation iris/I4 needs to carry. +- **Blocking, found 2026-09-04, before I2 can be called done**: iris's + texture pipeline asks every device, unconditionally, for + `VK_EXT_descriptor_indexing` ("bindless" binding arrays) — and a + sourced check says a real share of Android hardware does not have it, + not just the emulator's software renderer. See "iris's binding array + does not survive real Android hardware" under the iris track for the + measurement, the sources, and the recommended fix (generalize the + glyph atlas to images, the same way I1 already did for text). Not yet + implemented; a design decision to confirm before iris's render core + changes. +- **Next**: decide on the atlas-based image fix above, then **I2** — + iris on android-view. **E2** (a transcript in Masonry) can go in + parallel in another session. - **Not started**: `client-core`, which is item 1 of the recommendation below and does not depend on the framework choice. Nothing has been built for it, and it is not one of the numbered boxes — worth picking up in a session that wants work independent of the emulator. -- **The app itself is untouched.** Everything so far is in `iris/` and in - the rigs; nothing under `app/` or `server/` has changed. +- **The app itself is untouched.** Everything so far is in `iris/`, in + `rigs/gpu-probe` (a headless wgpu/Vulkan feature probe, pushable to a + device with no APK — see the binding-array section), and in the other + rigs; nothing under `app/` or `server/` has changed. - **Changed outside this repo**, both in `emulator-tools` and both pushed: `avd_serial` now validates its cache by asking the device its AVD name rather than by checking the serial is still attached (a recycled port @@ -851,6 +868,97 @@ step measured. nightly gates — `portable_simd` (the old glyph compositing) and `gen_blocks` (the deleted line iterator). **Eleven left.** +### iris's binding array does not survive real Android hardware (found 2026-09-04) + +Iris asked, of the "unknown number of images" case — a transcript with an +unbounded number of attached screenshots — whether iris's approach even +works on a phone, since her recollection was that mobile does not support +it. Checked rather than assumed, and the recollection is right, with +sources rather than a guess. + +**What iris does today.** Every texture — every `Image` widget +(`src/widget/image.rs`) and every glyph atlas page — gets its own +permanent slot in one array via `Textures::add` +(`core/src/primitive/texture.rs:65`), and both the `TEXTURE` and `GLYPH` +primitives sample it by `view_idx` into `binding_array>` +at `core/src/render/shader.wgsl:56`, sized by `UiLimits::default` — 100,000 +textures, 1,000 samplers (`core/src/render/mod.rs:347`). That needs three +wgpu features: `TEXTURE_BINDING_ARRAY`, +`SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING`, +`PARTIALLY_BOUND_BINDING_ARRAY` — Vulkan's `VK_EXT_descriptor_indexing` +("bindless"), promoted to core in 1.2. So a transcript with an unbounded +number of images is exactly the case that grows this array without bound, +one permanent slot per image. + +**Measured first on the emulator, and it fails outright.** A rig +(`rigs/gpu-probe`, a plain executable with no window, pushed with `adb +push` and run from `/data/local/tmp` — no APK needed to ask a device what +it supports) asks `wgpu::Adapter::request_device` for exactly iris's +features and limits. Against the emulator's guest Vulkan — both +SwiftShader (`vk_swiftshader_icd.json`) and lavapipe (`lvp_icd.json`, +cold-booted) — `request_device` **fails**: `Unsupported features were +requested: TEXTURE_BINDING_ARRAY | +SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING | +PARTIALLY_BOUND_BINDING_ARRAY`. A second, raw query through `ash` +(`rigs/gpu-probe/src/vk.rs`, bypassing wgpu) shows lavapipe's +`vkGetPhysicalDeviceFeatures2` actually reporting all seven descriptor- +indexing sub-features as `true` at device api version 1.3 — so on this +software renderer wgpu-hal's own feature detection is being more +conservative than the driver, for a reason not chased further (a likely +instance-version negotiation gap, since `VK_EXT_descriptor_indexing` was +only promoted to core at 1.2 and wgpu-hal's own `Instance::init` may be +requesting less). That part is an emulator/wgpu-hal question and not the +finding that matters. + +**The finding that matters is about real phones, not the emulator, and it +is sourced rather than recalled.** The **Android Vulkan Profile 2025** — +Google and Khronos's current baseline, covering **80.1% of active +Vulkan-capable Android devices** as of October 2025 +([developer.android.com/ndk/guides/graphics/android-vulkan-profile](https://developer.android.com/ndk/guides/graphics/android-vulkan-profile)) +— does **not** require `VK_EXT_descriptor_indexing` or any descriptor- +indexing feature. It requires `shaderSampledImageArrayDynamicIndexing` +(indexing an array of samplers by a value uniform across the invocation — +Vulkan 1.0 baseline, unrelated to bindless) and stops there; the same is +true of the 2021 and 2022 profiles. On the hardware side, Arm's own +developer documentation states **"`VK_EXT_descriptor_indexing` is +supported on all Valhall and 5th Gen GPUs"** +([developer.arm.com/mobile-graphics-and-gaming/vulkan-api-best-practices-on-arm-gpus](https://developer.arm.com/mobile-graphics-and-gaming/vulkan-api-best-practices-on-arm-gpus)) — +Mali generations from roughly 2019 (Mali-G77) onward, named affirmatively +with no claim made for Bifrost, Midgard or Utgard, which are still common +in budget and older Android phones still in use. So this is not a +software-renderer artifact: a real, currently-shipping share of the +Android fleet lacks the feature iris's texture pipeline asks for +unconditionally, and the newest official baseline does not promise it +either. (A crates.io/search-engine claim of "1% support on Android" for +this extension was checked against its cited source, an Arm blog post, +and was not actually there — that number does not appear anywhere primary +and should not be repeated; the 80.1%-baseline-excludes-it finding above +is the one with an attributable source.) + +**Recommendation, not yet implemented.** iris already solved the +identical problem for text in I1: the glyph atlas +(`core/src/render/atlas.rs`) packs many small rasters into a handful of +shared 1024×1024 pages and samples them by UV offset, so **text needs +none of the three features above** — only ordinary single-texture +sampling. The same technique generalizes to images: route an `Image` +widget through a shared atlas when it is small enough to pack (thumbnails, +downscaled attachment previews, avatars, icons), and fall back to one +ordinary, non-array texture bind group — selected per batched draw call +the way every immediate-mode 2D renderer already does — for anything too +large to atlas well (a photo opened at full resolution). Either path is +plain Vulkan 1.0 / GLES texture sampling, so it removes the descriptor- +indexing requirement from iris's device request entirely, which is also +what would make the emulator work regardless of the wgpu-hal question +above: a device that never asks for the feature cannot be refused for +lacking it. This is a change to iris's rendering core — the shader's +binding group layout, `Textures`, the texture and glyph primitives, and +`ui/painter.rs` — so it is written here as a recommendation rather than +started, per the project's rule to confirm a load-bearing design change +before making it. **It should be resolved before I2 is called done**, +since I2's pass condition is the phone, not just the emulator, and this +is exactly the kind of thing that passes on a desktop GPU and fails +silently on real hardware. + - [ ] **I2 — iris on android-view.** An `android-view` surface as a second backend beside winit: `wgpu` on the view's surface (GLES here, see the Vulkan section; Vulkan on the phone), touch as pointer events, @@ -895,9 +1003,12 @@ re-derived: 5. Run the existing rigs rather than inventing new ones: `ui-sandbox.sh` for a server with fixtures, `transcript-bench.sh` for the scroll baseline, `ui-trace` for anything positional, `emu up` for the - emulator, and `iris/run-headless.sh EXAMPLE --shot PNG` for an iris - example on this displayless machine. The Vulkan section below says how - to get a Vulkan path in the emulator when a `wgpu` backend needs one. + emulator, `iris/run-headless.sh EXAMPLE --shot PNG` for an iris + example on this displayless machine, and `rigs/gpu-probe` to ask a + device (this VM, the emulator, or a real phone over `adb push`) what + `wgpu` features and limits it actually has before building anything on + the assumption it does. The Vulkan section below says how to get a + Vulkan path in the emulator when a `wgpu` backend needs one. 6. **Bound anything heavy at the moment you start it.** An emulator or a long build gets a deadline — `timeout`, or a watchdog scoped to the pid you just started — rather than a plan to stop it later. Scope it to diff --git a/rigs/gpu-probe/.gitignore b/rigs/gpu-probe/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/rigs/gpu-probe/.gitignore @@ -0,0 +1 @@ +target diff --git a/rigs/gpu-probe/Cargo.lock b/rigs/gpu-probe/Cargo.lock new file mode 100644 index 0000000..f7e41e2 --- /dev/null +++ b/rigs/gpu-probe/Cargo.lock @@ -0,0 +1,1188 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[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 = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[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.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0e56a716f1e132ff6bf4bdac1c944a3fcdc1cae65f70a4a2a1ac3b401d2d1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", +] + +[[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 = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +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-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags", + "core-foundation", + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[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.5", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[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 = "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 = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-allocator" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" +dependencies = [ + "ash", + "hashbrown 0.16.1", + "log", + "presser", + "thiserror", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags", +] + +[[package]] +name = "gpu-probe" +version = "0.1.0" +dependencies = [ + "ash", + "pollster", + "wgpu", +] + +[[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.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", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "indexmap" +version = "2.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[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 = "js-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +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 = "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 = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[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.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "metal" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7047791b5bc903b8cd963014b355f71dc9864a9a0b727057676c1dcae5cbc15" +dependencies = [ + "bitflags", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "naga" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "618f667225063219ddfc61251087db8a9aec3c3f0950c916b614e403486f1135" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "hexf-parse", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash", + "spirv", + "thiserror", + "unicode-ident", +] + +[[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 = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "ordered-float" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c9e0d9b23589f26070720bac724174bfec1083e82f7854cdd0267518343c0" +dependencies = [ + "num-traits", +] + +[[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", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[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 = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[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.5", +] + +[[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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[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 = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasm-bindgen" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cb534d5ffd109c7d1135f34cdae29e60eab94855a625dcfe1705f8bc7ad79f" +dependencies = [ + "arrayvec", + "bitflags", + "bytemuck", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "28.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23f4642f53f666adcfd2d3218ab174d1e6681101aef18696b90cbe64d1c10f9" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87b7b696b918f337c486bf93142454080a32a37832ba8a31e4f48221890047da" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b251c331f84feac147de3c4aa3aa45112622a95dd7ee1b74384fa0458dbd79" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ca976e72b2c9964eb243e281f6ce7f14a514e409920920dcda12ae40febaae" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "28.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d6cb474beb218824dcc9e1ce679d973f719262789bfb27407da560cac20eeb" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags", + "block", + "bytemuck", + "cfg-if", + "cfg_aliases", + "core-graphics-types", + "glow", + "glutin_wgl_sys", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.16.1", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows", + "windows-core", +] + +[[package]] +name = "wgpu-types" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e18308757e594ed2cd27dddbb16a139c42a683819d32a2e0b1b0167552f5840c" +dependencies = [ + "bitflags", + "bytemuck", + "js-sys", + "log", + "web-sys", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[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.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[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 = "xml-rs" +version = "0.8.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" + +[[package]] +name = "zerocopy" +version = "0.8.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] diff --git a/rigs/gpu-probe/Cargo.toml b/rigs/gpu-probe/Cargo.toml new file mode 100644 index 0000000..bc6fc8d --- /dev/null +++ b/rigs/gpu-probe/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "gpu-probe" +version = "0.1.0" +edition = "2024" + +# Deliberately its own crate rather than a member of iris's workspace: the +# vendored `iris/` tree is meant to stay reconcilable with the iris/iris +# repository, and this is a rig belonging to ai-app. + +[dependencies] +# Pinned to what iris asks for, so the answer is about iris rather than +# about a different wgpu. +wgpu = "28.0.0" +pollster = "0.4.0" +# Queried directly, because wgpu and `cmd gpu vkjson` disagreed about +# descriptor indexing in the emulator and only the raw call says which is +# right. +ash = "0.38" diff --git a/rigs/gpu-probe/src/main.rs b/rigs/gpu-probe/src/main.rs new file mode 100644 index 0000000..1643e6b --- /dev/null +++ b/rigs/gpu-probe/src/main.rs @@ -0,0 +1,154 @@ +//! Ask a device whether it can give iris the GPU it asks for. +//! +//! iris's renderer binds every texture it has drawn as one binding array and +//! indexes it non-uniformly from the shader, which needs descriptor indexing +//! and a very large per-stage binding-array limit (101,000 elements: 100,000 +//! textures and 1,000 samplers, `UiLimits::default`). Those are ordinary on a +//! desktop and not obviously available on a phone, so this reports what the +//! adapter offers before anything is built on the assumption. +//! +//! It runs as a plain executable with no window and no APK, because +//! `request_adapter` needs no surface -- so it can be pushed to a device with +//! `adb push` and run from `/data/local/tmp`, which is far cheaper than an +//! app. What it therefore cannot answer is anything about presenting to a +//! surface; that is the Android backend's own problem. + +mod vk; + +use wgpu::*; + +/// What `iris/src/default/render.rs` asks `request_device` for. +fn iris_features() -> Features { + Features::TEXTURE_BINDING_ARRAY + | Features::PARTIALLY_BOUND_BINDING_ARRAY + | Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING +} + +/// `UiLimits::default()`: 100,000 textures + 1,000 samplers. +const IRIS_MAX_BINDING_ARRAY: u32 = 101_000; +const IRIS_MAX_BINDING_ARRAY_SAMPLERS: u32 = 1_000; + +fn main() { + vk::report(); + + let instance = Instance::new(&InstanceDescriptor { + backends: Backends::from_env().unwrap_or(Backends::PRIMARY), + ..Default::default() + }); + + let adapters = pollster::block_on(instance.enumerate_adapters(Backends::all())); + println!("adapters: {}", adapters.len()); + for adapter in &adapters { + let info = adapter.get_info(); + println!( + " {:?} {} ({:?})", + info.backend, info.name, info.device_type + ); + } + + let Some(adapter) = pollster::block_on(instance.request_adapter(&RequestAdapterOptions { + power_preference: PowerPreference::default(), + compatible_surface: None, + force_fallback_adapter: false, + })) + .ok() else { + println!("\nNO ADAPTER"); + std::process::exit(1); + }; + + let info = adapter.get_info(); + println!( + "\nchosen: {:?} {} ({:?})", + info.backend, info.name, info.device_type + ); + println!("driver: {} {}", info.driver, info.driver_info); + + let have = adapter.features(); + println!("\nfeatures iris requires:"); + let mut missing = Features::empty(); + for f in iris_features().iter() { + let ok = have.contains(f); + println!( + " {:60} {}", + format!("{f:?}"), + if ok { "yes" } else { "NO" } + ); + if !ok { + missing |= f; + } + } + + let limits = adapter.limits(); + println!("\nlimits iris requires:"); + for (name, want, got) in [ + ( + "max_binding_array_elements_per_shader_stage", + IRIS_MAX_BINDING_ARRAY, + limits.max_binding_array_elements_per_shader_stage, + ), + ( + "max_binding_array_sampler_elements_per_shader_stage", + IRIS_MAX_BINDING_ARRAY_SAMPLERS, + limits.max_binding_array_sampler_elements_per_shader_stage, + ), + ] { + println!( + " {name:52} want {want:>7} have {got:>7} {}", + if got >= want { "ok" } else { "TOO SMALL" } + ); + } + println!( + " {:52} want {:>7} have {:>7}", + "max_buffer_size (iris asks 1<<30)", + 1u64 << 30, + limits.max_buffer_size + ); + + // The question that actually matters: does the device iris builds come + // back, or does wgpu refuse it? + let mut wanted = Limits { + max_binding_array_elements_per_shader_stage: IRIS_MAX_BINDING_ARRAY, + max_binding_array_sampler_elements_per_shader_stage: IRIS_MAX_BINDING_ARRAY_SAMPLERS, + max_buffer_size: 1 << 30, + ..Default::default() + }; + match pollster::block_on(adapter.request_device(&DeviceDescriptor { + required_features: iris_features(), + required_limits: wanted.clone(), + ..Default::default() + })) { + Ok(_) => println!("\nIRIS DEVICE: ok"), + Err(e) => println!("\nIRIS DEVICE: FAILED -- {e}"), + } + + // If it failed, say how far down it has to be turned before it works, so + // the report names a number to design against rather than just "no". + if missing.is_empty() { + for cap in [ + limits.max_binding_array_elements_per_shader_stage, + 1024, + 128, + 16, + ] { + if cap >= IRIS_MAX_BINDING_ARRAY { + continue; + } + wanted.max_binding_array_elements_per_shader_stage = cap; + wanted.max_binding_array_sampler_elements_per_shader_stage = + cap.min(IRIS_MAX_BINDING_ARRAY_SAMPLERS); + let ok = pollster::block_on(adapter.request_device(&DeviceDescriptor { + required_features: iris_features(), + required_limits: wanted.clone(), + ..Default::default() + })) + .is_ok(); + println!( + " binding array capped at {cap:>7}: {}", + if ok { "ok" } else { "no" } + ); + if ok { + break; + } + } + } +} diff --git a/rigs/gpu-probe/src/vk.rs b/rigs/gpu-probe/src/vk.rs new file mode 100644 index 0000000..0d4ec6a --- /dev/null +++ b/rigs/gpu-probe/src/vk.rs @@ -0,0 +1,108 @@ +//! The raw Vulkan half of the probe. +//! +//! wgpu reports a feature only after a chain of its own decisions -- which +//! physical device, which API version, which extension list -- so "wgpu says +//! no" and "the driver says no" are different claims. This asks +//! `vkGetPhysicalDeviceFeatures2` itself and prints the inputs to that chain, +//! so a disagreement can be attributed rather than guessed at. + +use ash::{Entry, vk}; +use std::ffi::CStr; + +pub fn report() { + let entry = match unsafe { Entry::load() } { + Ok(e) => e, + Err(e) => { + println!("\nraw vulkan: cannot load loader -- {e}"); + return; + } + }; + + let instance_version = match unsafe { entry.try_enumerate_instance_version() } { + Ok(Some(v)) => v, + Ok(None) => vk::API_VERSION_1_0, + Err(e) => { + println!("\nraw vulkan: enumerate_instance_version failed -- {e}"); + return; + } + }; + println!("\nraw vulkan:"); + println!(" loader instance version: {}", ver(instance_version)); + + // Ask for the highest instance version the loader admits to: wgpu clamps + // the device version by the instance's, so an instance created at 1.0 + // makes a 1.3 device look like 1.0. + let app_info = vk::ApplicationInfo::default().api_version(instance_version); + let create = vk::InstanceCreateInfo::default().application_info(&app_info); + let instance = match unsafe { entry.create_instance(&create, None) } { + Ok(i) => i, + Err(e) => { + println!(" create_instance failed -- {e}"); + return; + } + }; + + let devices = unsafe { instance.enumerate_physical_devices() }.unwrap_or_default(); + for phd in devices { + let props = unsafe { instance.get_physical_device_properties(phd) }; + let name = unsafe { CStr::from_ptr(props.device_name.as_ptr()) }; + println!(" device: {}", name.to_string_lossy()); + println!(" device api version: {}", ver(props.api_version)); + + let exts = + unsafe { instance.enumerate_device_extension_properties(phd) }.unwrap_or_default(); + let has_ext = exts.iter().any(|e| { + (unsafe { CStr::from_ptr(e.extension_name.as_ptr()) }) == c"VK_EXT_descriptor_indexing" + }); + println!(" VK_EXT_descriptor_indexing advertised: {has_ext}"); + println!(" device extensions: {}", exts.len()); + + let mut indexing = vk::PhysicalDeviceDescriptorIndexingFeatures::default(); + let mut features2 = vk::PhysicalDeviceFeatures2::default().push_next(&mut indexing); + unsafe { instance.get_physical_device_features2(phd, &mut features2) }; + + for (name, v) in [ + ( + "shaderSampledImageArrayNonUniformIndexing", + indexing.shader_sampled_image_array_non_uniform_indexing, + ), + ( + "descriptorBindingSampledImageUpdateAfterBind", + indexing.descriptor_binding_sampled_image_update_after_bind, + ), + ( + "shaderStorageImageArrayNonUniformIndexing", + indexing.shader_storage_image_array_non_uniform_indexing, + ), + ( + "descriptorBindingStorageImageUpdateAfterBind", + indexing.descriptor_binding_storage_image_update_after_bind, + ), + ( + "shaderStorageBufferArrayNonUniformIndexing", + indexing.shader_storage_buffer_array_non_uniform_indexing, + ), + ( + "descriptorBindingStorageBufferUpdateAfterBind", + indexing.descriptor_binding_storage_buffer_update_after_bind, + ), + ( + "descriptorBindingPartiallyBound", + indexing.descriptor_binding_partially_bound, + ), + ] { + println!(" {name:48} {}", if v != 0 { "yes" } else { "NO" }); + } + } + + unsafe { instance.destroy_instance(None) }; +} + +fn ver(v: u32) -> String { + format!( + "{}.{}.{}", + vk::api_version_major(v), + vk::api_version_minor(v), + vk::api_version_patch(v) + ) +}