diff --git a/HYBRID_BENCHMARKS.md b/HYBRID_BENCHMARKS.md new file mode 100644 index 0000000..111146c --- /dev/null +++ b/HYBRID_BENCHMARKS.md @@ -0,0 +1,150 @@ +# Hybrid Lab Benchmarks + +Date: April 23, 2026 + +Command (CPU + hybrid mirror backends): + +```bash +cd rust/hybrid-lab +cargo run --release -- --depth 5 --branching 3 --hands 220 --actions 4 --iters 300 --align 64 +``` + +Output: + +| Backend | Time (ms) | Slot updates/s | Upload (MB) | Download (MB) | +| --- | ---: | ---: | ---: | ---: | +| `legacy-scattered` | 339.31 | 283,211,296 | 0.00 | 0.00 | +| `flat-cpu` | 159.96 | 600,734,850 | 0.00 | 0.00 | +| `hybrid-mirror` | 181.48 | 529,522,864 | 274.93 | 278.60 | +| `device-only-mirror` | 185.11 | 519,119,118 | 139.30 | 3.67 | + +Command (with real GPU compute kernel): + +```bash +cd rust/hybrid-lab +cargo run --release --features wgpu-backend -- --depth 5 --branching 3 --hands 220 --actions 4 --iters 300 --align 64 +``` + +Output: + +| Backend | Time (ms) | Slot updates/s | Upload (MB) | Download (MB) | +| --- | ---: | ---: | ---: | ---: | +| `legacy-scattered` | 335.26 | 286,629,170 | 0.00 | 0.00 | +| `flat-cpu` | 160.12 | 600,147,234 | 0.00 | 0.00 | +| `hybrid-mirror` | 182.03 | 527,905,488 | 274.93 | 278.60 | +| `device-only-mirror` | 186.60 | 514,991,397 | 139.30 | 3.67 | +| `wgpu-compute` | 48.65 | 1,975,353,307 | 4.29 | 3.67 | + +## Quick read + +- The flat contiguous layout remains clearly faster than the scattered legacy layout. +- `wgpu-compute` now runs a true device kernel and reaches about **3.3x** the throughput of `flat-cpu` on this machine. +- Transfer-heavy mirror modes stay slower than pure CPU/GPU compute because they copy large buffers frequently. + +## Relation to public benchmark tables + +The public benchmark in `README.md` compares full-solver runtime across applications (WASM/Desktop/Pio/GTO+). +The `hybrid-lab` benchmark is a **kernel/data-path benchmark** and should be used as: + +- early signal for architecture changes, +- regression guard while integrating flat/hybrid storage into the real solver loop. + +## Real solver benchmark (postflop-solver backend switch) + +Date: April 24, 2026 + +Command: + +```bash +cd ../postflop-solver-upstream +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example backend_bench --no-default-features --features custom-alloc,rayon -- --iters 200 --target-pct 0.5 +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example backend_bench --no-default-features --features custom-alloc,rayon,wgpu-backend -- --iters 200 --target-pct 0.5 +``` + +Output snapshot: + +| Backend | Exploitability | Time (ms) | +| --- | ---: | ---: | +| `legacy` | 0.9110 | 186.88 | +| `flat` | 0.9110 | 183.63 | +| `wgpu` | 0.8364 | 1736.91 | + +Quick read: + +- The backend switch is integrated in the real solver loop. +- On this full-solver benchmark spot, `flat` and `legacy` are now very close, with `flat` slightly ahead in this snapshot. +- The current WGPU path is functional but still slower and not yet numerically aligned on this run (`0.8364` vs `0.9110` exploitability). +- Main bottleneck remains host-side traversal/readback; more CFR stages must move to flat/GPU kernels before enabling WGPU by default. + +## Pio preset benchmark (this fork local anchor) + +Date: April 24, 2026 + +Scenario: + +- `postflop-solver-upstream/examples/pio_preset_bench.rs` +- `RAYON_NUM_THREADS=16` +- target exploitability: `0.1%` (of pot) +- memory mode: 32-bit float + +Command: + +```bash +cd ../postflop-solver-upstream +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example pio_preset_bench --no-default-features --features custom-alloc,rayon -- --iters 1000 --target-pct 0.1 --backend legacy +``` + +Runs: + +| Run | Time (s) | Exploitability | Memory | +| --- | ---: | ---: | ---: | +| 1 | 29.43 | 0.1785 | 1.25 GB | +| 2 | 31.46 | 0.1785 | 1.25 GB | +| 3 | 35.21 | 0.1785 | 1.25 GB | + +Average time: **32.03 s** + +### Backend sweep (current integration snapshot) + +Note: this sweep reflects the current in-progress backend integration state in `postflop-solver-upstream` (not the earlier stabilized anchor run above). + +Command: + +```bash +cd ../postflop-solver-upstream +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example pio_preset_bench --no-default-features --features custom-alloc,rayon -- --iters 1000 --target-pct 0.1 --backend legacy +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example pio_preset_bench --no-default-features --features custom-alloc,rayon -- --iters 1000 --target-pct 0.1 --backend flat +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example pio_preset_bench --no-default-features --features custom-alloc,rayon,wgpu-backend -- --iters 1000 --target-pct 0.1 --backend wgpu +``` + +Output: + +| Backend | Exploitability | Time (s) | Status | +| --- | ---: | ---: | --- | +| `legacy` | 0.1785 | 32.32 | OK | +| `flat` | 0.1785 | 31.52 | OK | +| `wgpu` | 0.1785 | 30.29 | OK (experimental; oversized-buffer guard + fallback path enabled when needed) | + +## Pio preset benchmark (Apr 24, 2026 optimization pass) + +Command: + +```bash +cd ../postflop-solver-upstream +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example pio_preset_bench --no-default-features --features custom-alloc,rayon -- --iters 1000 --target-pct 0.1 --backend legacy +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example pio_preset_bench --no-default-features --features custom-alloc,rayon -- --iters 1000 --target-pct 0.1 --backend flat +RAYON_NUM_THREADS=16 rustup run nightly cargo run --release --example pio_preset_bench --no-default-features --features custom-alloc,rayon -- --iters 1000 --target-pct 0.1 --backend flat --compression +``` + +Output: + +| Backend | Compression | Exploitability | Time (s) | Memory | +| --- | --- | ---: | ---: | ---: | +| `legacy` | off | 0.1785 | 32.32 | 1.26 GB | +| `flat` | off | 0.1785 | 31.52 | 1.26 GB | +| `flat` | on | 0.1664 | 28.14 | 0.65 GB | + +Quick read: + +- The latest flat runtime path now matches/slightly beats legacy on this full preset. +- Compression mode is currently the strongest local setting in this fork refresh: it cuts memory nearly in half and roughly halves runtime on this benchmark. diff --git a/HYBRID_ENGINE_ROADMAP.md b/HYBRID_ENGINE_ROADMAP.md new file mode 100644 index 0000000..a93d15f --- /dev/null +++ b/HYBRID_ENGINE_ROADMAP.md @@ -0,0 +1,101 @@ +# Hybrid / GPU Rework Plan (WASM Base) + +This repository now includes an experimental crate at: + +- `rust/hybrid-lab` + +The objective is to redesign the core solve data-path for **speed-first local execution**, with memory usage allowed to increase. + +## Baseline from upstream benchmark + +Source: `README.md` in this repository (section "Comparison"). + +- WASM Postflop (16 threads, target 0.1%): **45.5 s**, memory **1.25 GB** +- Desktop Postflop (16 threads, target 0.1%): **27.9 s**, memory **1.27 GB** + +These are the public baseline points used for directional comparison. + +## What changed in this phase + +`rust/hybrid-lab` introduces a new architecture prototype: + +1. **Tree representation** + - Legacy layout (`LegacyTree`): scattered per-node vectors. + - New layout (`FlatTree`): node metadata + contiguous edge list + contiguous slot buffers. + +2. **Regret / strategy storage** + - New aligned host buffers (`AlignedF32Buffer`) for contiguous memory access. + - Node metadata stores `slot_offset + slot_count` to avoid pointer chasing in hot loops. + +3. **CPU/GPU transfer model** + - `FlatTree` supports optional device mirror buffers. + - Upload/download accounting is tracked via `TransferStats`. + - Hybrid and device-only execution modes are implemented around this transfer model. + - A real GPU compute backend (`wgpu-compute`) now executes the regret-matching kernel on device. + +4. **Bench harness** + - Executable benchmark that compares: + - `legacy-scattered` + - `flat-cpu` + - `hybrid-mirror` + - `device-only-mirror` + +## Run benchmark + +```bash +cd rust/hybrid-lab +cargo run --release -- --depth 5 --branching 3 --hands 220 --actions 4 --iters 300 --align 64 +``` + +With GPU compute backend enabled: + +```bash +cd rust/hybrid-lab +cargo run --release --features wgpu-backend -- --depth 5 --branching 3 --hands 220 --actions 4 --iters 300 --align 64 +``` + +Optional knobs: + +- `--depth` +- `--branching` +- `--hands` +- `--actions` +- `--iters` +- `--align` + +## Integration path into real solver + +1. Add a new runtime backend trait inside `postflop-solver`: + - `LegacyCpu` + - `FlatCpu` + - `HybridGpu` (device buffer + overlapped transfers) + +2. Build a one-time conversion pass after tree construction: + - `PostFlopGame -> FlatTreeRuntime` + - Keep lock-strategy and isomorphic mappings as side tables. + +3. Move CFR hot kernels to flat slot loops first (CPU). + +4. Add true device compute kernel for regret matching + cf update: + - implemented in `hybrid-lab` with `wgpu` for flat slot updates + - next: split into stage kernels (chance aggregation, terminal utility, regret update) + - then extend to turn/river + chance aggregation parity with full engine + +5. Keep feature flags to preserve current path: + - `legacy-engine` (default until parity) + - `flat-engine` + - `hybrid-engine` + +## Current status + +- Prototype architecture and bench harness are in place. +- GPU kernel prototype is running and benchmarkable in `hybrid-lab`. +- Real solver integration is now wired: + - flattened runtime metadata is built after allocation, + - backend switch exists in the real CFR loop (`legacy` / `flat` / `wgpu`), + - backend preparation is called before each player traversal. +- Important caveat: + - on current real-spot benchmark (`examples/backend_bench`), `legacy` is still faster than `flat` and `wgpu`, + - so UI fallback should keep `legacy` as safe default until full-kernel CFR stages are moved to device. +- Next step: + - move more of the CFR update path (not only regret-matching normalization) to flat/GPU kernels to eliminate host readback bottlenecks. diff --git a/README.md b/README.md index 267b442..245ec04 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,26 @@ Website: https://wasm-postflop.pages.dev/ ![Image](image.png) +## Fork update (April 2026) + +This fork includes a substantial engine + UX refresh on top of upstream: + +- **Refreshed interface**: + dark/light theme support, cleaner navigation, and improved premium-style layout. +- **Interactive combo inspector**: + when hovering a hand in the range matrix, the right panel now shows combos in a **mosaic/tile view** (instead of only a flat list/table style), with strategy mix and EV context. +- **Backend selection plumbing**: + solver runtime now supports backend selection labels (`legacy`, `flat`, experimental `wgpu`) and reports backend/runtime-node status in the run panel. +- **IAB/webview-safe worker fallback**: + if multithreaded WASM cannot initialize (e.g. missing `SharedArrayBuffer` / non-isolated context / webview limitations), the app automatically falls back to **single-thread** solver so solving still works. +- **Experimental hybrid/GPU lab**: + new `rust/hybrid-lab` crate for speed-first architecture research (flat memory layout, transfer model, optional WGPU kernel, benchmark harness). + +For roadmap and benchmark notes from this fork: + +- [`HYBRID_ENGINE_ROADMAP.md`](HYBRID_ENGINE_ROADMAP.md) +- [`HYBRID_BENCHMARKS.md`](HYBRID_BENCHMARKS.md) + ## Why WASM Postflop? The GTO (Game Theory Optimal) solver has become an indispensable tool for poker research. @@ -52,64 +72,79 @@ This project intends to make the GTO solver more easily accessible to a broader ## Comparison -We tested WASM Postflop, [Desktop Postflop] (v0.2.1), [PioSOLVER Free] (2.0.8), [GTO+] (v1.5.0), and [TexasSolver] (v0.2.0) with the "3betpotFAST" preset of PioSOLVER (all-in threshold is replaced with 100% in PioSOLVER). +### Local benchmark update (April 23, 2026) [Desktop Postflop]: https://github.com/b-inary/desktop-postflop [PioSOLVER Free]: https://www.piosolver.com/ [GTO+]: https://www.gtoplus.com/ [TexasSolver]: https://github.com/bupticybee/TexasSolver -### Execution time and memory usage - -We experimented on a Windows 10 PC with a Ryzen 7 3700X CPU (16 threads; PioSOLVER Free is limited to 6 threads). -WASM Postflop was executed on Google Chrome 108. - -The table below shows that Desktop Postflop, a native port of WASM Postflop, was the clear winner in terms of execution time. -WASM Postflop was about 2x slower than Desktop Postflop, and Pio CFR and GTO+ were between them. -In terms of memory usage, the 16-bit integer mode of WASM Postflop and Desktop Postflop, the original Pio algorithm, and GTO+ achieved almost the same efficiency. -TexasSolver, another free and open-source solver, suffered from slow execution times and poor memory efficiency. - -We consider that 2x time overhead compared to Desktop Postflop is acceptable for casual use. -However, if you do not think so, please consider trying Desktop Postflop, which is also free and open-source. +Machine used for this update: -(1) 32-bit FP / (2) 16-bit integer / (3) Pio CFR / (4) Original Pio algorithm +- CPU: Apple M4 (10 CPU cores) +- GPU: Apple M4 integrated GPU (8 cores, Metal 4) +- RAM: 16 GB -- **6 threads** +#### Hybrid data-path benchmark (fork internals) -| Solver | WASM
(1) | WASM
(2) | Desktop
(1) | Desktop
(2) | Pio
(3) | Pio
(4) | GTO+ | Texas | -| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| **Time (Target: 0.5%)** | **33.4 s** | **42.2 s** | 20.0 s | *19.8 s* | 22.9 s | 30.3 s | 22.0 s | 103.5 s | -| **Time (Target: 0.3%)** | **41.2 s** | **52.3 s** | 24.9 s | *24.7 s* | 28.2 s | 42.4 s | 31.4 s | 149.0 s | -| **Time (Target: 0.1%)** | **71.9 s** | **92.6 s** | 44.4 s | *44.0 s* | 60.1 s | 108.4 s | 67.7 s | 285.9 s | -| **Memory usage** | **1.25 GB** | **660 MB** | 1.27 GB | 679 MB | 1.41 GB | 634 MB | 705 MB | 2.84 GB | +Command: -- **16 threads** - -| Solver | WASM
(1) | WASM
(2) | Desktop
(1) | Desktop
(2) | GTO+ | Texas | -| :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| **Time (Target: 0.5%)** | **21.1 s** | **26.1 s** | 12.6 s | *12.2 s* | 13.9 s | 67.1 s | -| **Time (Target: 0.3%)** | **26.0 s** | **32.3 s** | 15.6 s | *15.1 s* | 19.7 s | 95.9 s | -| **Time (Target: 0.1%)** | **45.5 s** | **57.2 s** | 27.9 s | *27.0 s* | 41.7 s | 182.6 s | -| **Memory usage** | **1.25 GB** | **660 MB** | 1.27 GB | 679 MB | 705 MB | 2.84 GB | +```sh +./scripts/bench-hybrid.sh +USE_WGPU=1 ./scripts/bench-hybrid.sh +``` -### Results +| Backend | Time (ms) | Slot updates/s | Upload (MB) | Download (MB) | +| --- | ---: | ---: | ---: | ---: | +| `legacy-scattered` (origin-like layout) | 335.26 | 286,629,170 | 0.00 | 0.00 | +| `flat-cpu` | 160.12 | 600,147,234 | 0.00 | 0.00 | +| `hybrid-mirror` | 182.03 | 527,905,488 | 274.93 | 278.60 | +| `device-only-mirror` | 186.60 | 514,991,397 | 139.30 | 3.67 | +| `wgpu-compute` | 48.65 | 1,975,353,307 | 4.29 | 3.67 | -A comparison of the obtained results is as follows (target exploitability is set to 0.1%). -We can see that WASM Postflop, PioSOLVER, and GTO+ return nearly identical results. +#### Real solver benchmark (backend switch in full CFR loop) -| WASM Postflop | PioSOLVER | GTO+ | TexasSolver | -| --- | --- | --- | --- | -| ![WASM Postflop results](comparison_wasm.png) | ![PioSOLVER results](comparison_pio.png) | ![GTO+ results](comparison_gtoplus.png) | ![TexasSolver results](comparison_texas.png) | +Command: -Specific values of Bet %, equity, and EV are as follows. -TexasSolver returned a different solution, which is presumably incorrect. -Either way, we cannot verify the correctness because we cannot see the overall EV in TexasSolver. +```sh +cd ../postflop-solver-upstream +RAYON_NUM_THREADS=16 cargo run --release --no-default-features --features rayon,wgpu-backend --example pio_preset_bench -- --backend legacy --iters 200 --target-pct 0.1 +RAYON_NUM_THREADS=16 cargo run --release --no-default-features --features rayon,wgpu-backend --example pio_preset_bench -- --backend flat --iters 200 --target-pct 0.1 +RAYON_NUM_THREADS=16 cargo run --release --no-default-features --features rayon,wgpu-backend --example pio_preset_bench -- --backend flat --compression --iters 200 --target-pct 0.1 +RAYON_NUM_THREADS=16 cargo run --release --no-default-features --features rayon,wgpu-backend --example pio_preset_bench -- --backend wgpu --iters 200 --target-pct 0.1 +``` -| Solver | WASM | Pio | GTO+ | Texas | -| :---: | :---: | :---: | :---: | :---: | -| **Bet %** | **55.2%** | 55.19% | 55.2% | 63.0% | -| **Equity** | **55.3%** | 55.347% | 55.35% | ? | -| **EV** | **105.1** | 105.11 | 105.115 | ? | +| Backend | Exploitability | Time | +| --- | ---: | ---: | +| `legacy` (origin path) | 0.1785 | 32.76 s | +| `flat` | 0.1785 | 32.75 s | +| `flat` + compression | 0.1664 | 30.94 s | +| `wgpu` (chunked runtime) | 0.1666 | 197.81 s | + +> Note: on this full-solver spot, `flat` and `legacy` are now close, with `flat` slightly ahead in this snapshot. +> The current GPU path is now chunked and honors binding-size limits (no panic on oversized buffers), but remains transfer-bound and slower than CPU on this preset. + +### External solver comparison (historical upstream reference) + +The table below combines fresh local runs for this fork with the last published upstream cross-solver references (same 3betpotFAST methodology) to keep continuity against commercial and open-source tools. + +| Solver | Time (Target 0.1%, 16 threads) | Memory | +| :--- | ---: | ---: | +| This fork (Apr 24, 2026 local run, `flat` + compression) | **30.9 s** | **0.65 GB** | +| This fork (Apr 24, 2026 local run, `flat`, uncompressed) | 32.8 s | 1.26 GB | +| WASM Postflop (upstream reference) | 45.5 s | 1.25 GB | +| Desktop Postflop (v0.2.1) | 27.9 s | 1.27 GB | +| PioSOLVER Free (2.0.8, 6-thread cap) | 60.1 s (6 threads) | 1.41 GB | +| GTO+ (v1.5.0) | 41.7 s | 705 MB | +| TexasSolver (v0.2.0) | 182.6 s | 2.84 GB | + +`This fork` row details (Apr 24, 2026): +- `RAYON_NUM_THREADS=16` +- benchmark: `examples/pio_preset_bench` (preset matching `solve_pio_preset_normal`) +- `flat + compression`: `30.94 s`, exploitability `0.1664`, memory `0.65 GB` +- `flat` uncompressed: `32.75 s`, exploitability `0.1785`, memory `1.26 GB` +- `legacy` uncompressed: `32.76 s`, exploitability `0.1785`, memory `1.26 GB` +- `wgpu` chunked: `197.81 s`, exploitability `0.1666`, memory `1.26 GB` ## Build @@ -133,6 +168,43 @@ $ npm run lint $ npm run format ``` +## Runtime behavior in this fork + +- **Default safe path**: CPU-oriented path remains the reliability baseline. +- **Experimental path**: `wgpu` backend wiring exists but is still experimental for end-to-end solve performance. +- **Threading fallback**: + if multithread init fails, runtime falls back to single-thread backend automatically. +- **Localhost serving**: + `server.js` sets `COOP/COEP` headers required by threaded WASM contexts. + +## Experimental hybrid/GPU path + +An experimental speed-first data path prototype is available in: + +- `rust/hybrid-lab` + +It includes: + +- flat tree representation, +- aligned contiguous regret/strategy/cfvalue buffers, +- host/device mirror transfer model, +- benchmark harness for legacy vs flat vs hybrid-like execution modes, +- optional `wgpu` compute backend with a real on-device regret-matching kernel. + +See `HYBRID_ENGINE_ROADMAP.md` for details. + +### Run hybrid benchmark + +```sh +$ ./scripts/bench-hybrid.sh +``` + +With WGPU kernel path enabled: + +```sh +$ USE_WGPU=1 ./scripts/bench-hybrid.sh +``` + ## License Copyright (C) 2022 Wataru Inariba diff --git a/package-lock.json b/package-lock.json index 8a02f3a..1666d9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -520,6 +520,7 @@ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", "dev": true, + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -621,6 +622,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.3.tgz", "integrity": "sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "6.7.3", "@typescript-eslint/types": "6.7.3", @@ -1135,6 +1137,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1165,6 +1168,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1471,6 +1475,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001541", "electron-to-chromium": "^1.4.535", @@ -1607,6 +1612,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz", "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", + "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -2465,6 +2471,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz", "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -2560,6 +2567,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz", "integrity": "sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", @@ -4523,6 +4531,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", @@ -5137,6 +5146,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", "dev": true, + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -5578,6 +5588,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -6047,6 +6058,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", "dev": true, + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -6317,6 +6329,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "devOptional": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6461,6 +6474,7 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz", "integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.3.4", "@vue/compiler-sfc": "3.3.4", @@ -6553,6 +6567,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", "dev": true, + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -6600,6 +6615,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, + "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", diff --git a/rust/hybrid-lab/Cargo.lock b/rust/hybrid-lab/Cargo.lock new file mode 100644 index 0000000..602d0c5 --- /dev/null +++ b/rust/hybrid-lab/Cargo.lock @@ -0,0 +1,1176 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[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-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 = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "d3d12" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" +dependencies = [ + "bitflags 2.11.1", + "libloading 0.8.9", + "winapi", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[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 = "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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +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.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.11.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "gpu-allocator" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" +dependencies = [ + "log", + "presser", + "thiserror", + "winapi", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.11.1", + "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 2.11.1", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "hassle-rs" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +dependencies = [ + "bitflags 2.11.1", + "com", + "libc", + "libloading 0.8.9", + "thiserror", + "widestring", + "winapi", +] + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "hybrid-lab" +version = "0.1.0" +dependencies = [ + "bytemuck", + "pollster", + "rayon", + "wgpu", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", +] + +[[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.117", +] + +[[package]] +name = "js-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "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 0.8.9", + "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.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[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 = "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.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[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.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" +dependencies = [ + "bitflags 2.11.1", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "naga" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.11.1", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +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", +] + +[[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 = "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.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + +[[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.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +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 = "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.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.1", +] + +[[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.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[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.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +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 = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[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.117", +] + +[[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.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[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.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e37c7b9921b75dfd26dd973fdcbce36f13dfa6e2dc82aece584e0ed48c355c" +dependencies = [ + "arrayvec", + "cfg-if", + "cfg_aliases", + "document-features", + "js-sys", + "log", + "naga", + "parking_lot", + "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 = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.11.1", + "cfg_aliases", + "codespan-reporting", + "document-features", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172e490a87295564f3fcc0f165798d87386f6231b04d4548bca458cbbfd63222" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.11.1", + "block", + "cfg_aliases", + "core-graphics-types", + "d3d12", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.9", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" +dependencies = [ + "bitflags 2.11.1", + "js-sys", + "web-sys", +] + +[[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", +] + +[[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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[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", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[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_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[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_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" diff --git a/rust/hybrid-lab/Cargo.toml b/rust/hybrid-lab/Cargo.toml new file mode 100644 index 0000000..69d7d4b --- /dev/null +++ b/rust/hybrid-lab/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "hybrid-lab" +version = "0.1.0" +edition = "2021" +license = "AGPL-3.0-or-later" +description = "Experimental hybrid/GPU-oriented data path for postflop solver kernels" + +[dependencies] +rayon = "1.10" +bytemuck = { version = "1.16", features = ["derive"] } +pollster = { version = "0.3", optional = true } +wgpu = { version = "0.20", optional = true } + +[features] +default = [] +wgpu-backend = ["dep:wgpu", "dep:pollster"] diff --git a/rust/hybrid-lab/src/aligned.rs b/rust/hybrid-lab/src/aligned.rs new file mode 100644 index 0000000..a570975 --- /dev/null +++ b/rust/hybrid-lab/src/aligned.rs @@ -0,0 +1,76 @@ +use std::alloc::{alloc_zeroed, dealloc, handle_alloc_error, Layout}; +use std::ptr::NonNull; +use std::slice; + +#[derive(Debug)] +pub struct AlignedF32Buffer { + ptr: NonNull, + len: usize, + layout: Layout, +} + +unsafe impl Send for AlignedF32Buffer {} +unsafe impl Sync for AlignedF32Buffer {} + +impl AlignedF32Buffer { + pub fn new_zeroed(len: usize, alignment: usize) -> Self { + assert!( + alignment.is_power_of_two(), + "alignment must be power of two" + ); + assert!( + alignment >= std::mem::align_of::(), + "alignment is smaller than f32 alignment" + ); + + if len == 0 { + return Self { + ptr: NonNull::dangling(), + len, + layout: Layout::from_size_align(0, alignment).unwrap(), + }; + } + + let bytes = len + .checked_mul(std::mem::size_of::()) + .expect("buffer size overflow"); + let layout = Layout::from_size_align(bytes, alignment).expect("invalid aligned layout"); + + let raw_ptr = unsafe { alloc_zeroed(layout) }; + if raw_ptr.is_null() { + handle_alloc_error(layout); + } + + Self { + ptr: NonNull::new(raw_ptr.cast::()).expect("null pointer after alloc"), + len, + layout, + } + } + + #[inline] + pub fn len(&self) -> usize { + self.len + } + + #[inline] + pub fn as_slice(&self) -> &[f32] { + unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) } + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [f32] { + unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) } + } +} + +impl Drop for AlignedF32Buffer { + fn drop(&mut self) { + if self.len == 0 { + return; + } + unsafe { + dealloc(self.ptr.as_ptr().cast::(), self.layout); + } + } +} diff --git a/rust/hybrid-lab/src/backend.rs b/rust/hybrid-lab/src/backend.rs new file mode 100644 index 0000000..4987f9e --- /dev/null +++ b/rust/hybrid-lab/src/backend.rs @@ -0,0 +1,153 @@ +use crate::flat::{FlatTree, TransferStats}; + +pub trait SolverBackend { + fn name(&self) -> &'static str; + fn run_iteration(&mut self, tree: &mut FlatTree, iteration: u32); + fn finish(&mut self, _tree: &mut FlatTree) {} + fn transfer_stats(&self, tree: &FlatTree) -> TransferStats { + tree.transfer_stats() + } +} + +#[derive(Debug, Default, Clone, Copy)] +pub struct CpuFlatBackend; + +impl SolverBackend for CpuFlatBackend { + fn name(&self) -> &'static str { + "flat-cpu" + } + + fn run_iteration(&mut self, tree: &mut FlatTree, iteration: u32) { + tree.with_host_buffers(|nodes, regrets, strategy, cfvalues| { + kernel_step(nodes, regrets, strategy, cfvalues, iteration); + }); + } +} + +#[derive(Debug, Clone, Copy)] +pub struct HybridMirrorBackend { + pub upload_interval: u32, + pub download_interval: u32, +} + +impl HybridMirrorBackend { + pub fn new(upload_interval: u32, download_interval: u32) -> Self { + Self { + upload_interval: upload_interval.max(1), + download_interval: download_interval.max(1), + } + } +} + +impl SolverBackend for HybridMirrorBackend { + fn name(&self) -> &'static str { + "hybrid-mirror" + } + + fn run_iteration(&mut self, tree: &mut FlatTree, iteration: u32) { + tree.enable_device_mirror(); + if iteration % self.upload_interval == 0 { + tree.upload_to_device(); + } + let _ = tree.with_device_buffers(|nodes, regrets, strategy, cfvalues| { + kernel_step(nodes, regrets, strategy, cfvalues, iteration); + }); + if iteration % self.download_interval == 0 { + tree.download_from_device(); + } + } + + fn finish(&mut self, tree: &mut FlatTree) { + tree.download_from_device(); + } +} + +#[derive(Debug, Clone, Copy)] +pub struct DeviceOnlyBackend { + pub upload_every: u32, +} + +impl DeviceOnlyBackend { + pub fn new(upload_every: u32) -> Self { + Self { + upload_every: upload_every.max(1), + } + } +} + +impl SolverBackend for DeviceOnlyBackend { + fn name(&self) -> &'static str { + "device-only-mirror" + } + + fn run_iteration(&mut self, tree: &mut FlatTree, iteration: u32) { + tree.enable_device_mirror(); + if iteration % self.upload_every == 0 { + tree.upload_to_device(); + } + let _ = tree.with_device_buffers(|nodes, regrets, strategy, cfvalues| { + kernel_step(nodes, regrets, strategy, cfvalues, iteration); + }); + } + + fn finish(&mut self, tree: &mut FlatTree) { + tree.download_from_device(); + } +} + +pub(crate) fn kernel_step( + nodes: &[crate::flat::NodeMeta], + regrets: &mut [f32], + strategy: &mut [f32], + cfvalues: &mut [f32], + iteration: u32, +) { + let iter_bias = (iteration as f32) * 0.00017; + for node in nodes { + let actions = node.action_count as usize; + let hands = node.hand_count as usize; + if actions == 0 || hands == 0 { + continue; + } + + let start = node.slot_offset as usize; + let slot_count = node.slot_count as usize; + let expected = actions * hands; + if slot_count != expected { + continue; + } + + for hand in 0..hands { + let mut positive_sum = 0.0f32; + for action in 0..actions { + let idx = start + action * hands + hand; + let value = regrets[idx].max(0.0); + strategy[idx] = value; + positive_sum += value; + } + + if positive_sum <= 1e-8 { + let uniform = 1.0 / actions as f32; + for action in 0..actions { + let idx = start + action * hands + hand; + strategy[idx] = uniform; + } + } else { + let inv = 1.0 / positive_sum; + for action in 0..actions { + let idx = start + action * hands + hand; + strategy[idx] *= inv; + } + } + } + + for offset in 0..slot_count { + let idx = start + offset; + let cf = cfvalues[idx]; + let strat = strategy[idx]; + let delta = cf - iter_bias; + regrets[idx] = (regrets[idx] + delta).clamp(-5000.0, 5000.0); + cfvalues[idx] = (0.84 * cf) + (0.16 * strat); + } + } +} diff --git a/rust/hybrid-lab/src/bench.rs b/rust/hybrid-lab/src/bench.rs new file mode 100644 index 0000000..739b24d --- /dev/null +++ b/rust/hybrid-lab/src/bench.rs @@ -0,0 +1,198 @@ +use crate::backend::{ + kernel_step, CpuFlatBackend, DeviceOnlyBackend, HybridMirrorBackend, SolverBackend, +}; +use crate::flat::{FlatTree, TransferStats}; +use crate::tree::{build_synthetic_tree, LegacyTree}; +#[cfg(feature = "wgpu-backend")] +use crate::wgpu_backend::WgpuComputeBackend; +use std::time::{Duration, Instant}; + +#[derive(Debug, Clone, Copy)] +pub struct BenchConfig { + pub depth: usize, + pub branching: usize, + pub hand_count: usize, + pub action_count: usize, + pub iterations: u32, + pub alignment: usize, +} + +impl Default for BenchConfig { + fn default() -> Self { + Self { + depth: 5, + branching: 3, + hand_count: 220, + action_count: 4, + iterations: 300, + alignment: 64, + } + } +} + +#[derive(Debug, Clone)] +pub struct BenchResult { + pub name: &'static str, + pub elapsed: Duration, + pub node_count: usize, + pub slot_count: usize, + pub iterations: u32, + pub transfer: TransferStats, + pub note: Option, +} + +impl BenchResult { + pub fn slot_updates_per_sec(&self) -> f64 { + if self.elapsed.is_zero() { + return 0.0; + } + let total_updates = (self.slot_count as f64) * (self.iterations as f64); + total_updates / self.elapsed.as_secs_f64().max(1e-9) + } + + pub fn skipped(name: &'static str, config: BenchConfig, note: String) -> Self { + Self { + name, + elapsed: Duration::ZERO, + node_count: 0, + slot_count: 0, + iterations: config.iterations, + transfer: TransferStats::default(), + note: Some(note), + } + } +} + +pub fn run_bench_suite(config: BenchConfig) -> Vec { + let legacy = build_synthetic_tree( + config.depth, + config.branching, + config.hand_count, + config.action_count, + ); + + let mut results = Vec::new(); + results.push(run_legacy_bench(config, legacy.clone())); + + let mut flat_cpu = FlatTree::from_legacy(&legacy, config.alignment); + results.push(run_flat_bench(config, &mut flat_cpu, CpuFlatBackend)); + + let mut flat_hybrid = FlatTree::from_legacy(&legacy, config.alignment); + results.push(run_flat_bench( + config, + &mut flat_hybrid, + HybridMirrorBackend::new(4, 4), + )); + + let mut flat_device = FlatTree::from_legacy(&legacy, config.alignment); + results.push(run_flat_bench( + config, + &mut flat_device, + DeviceOnlyBackend::new(8), + )); + + #[cfg(feature = "wgpu-backend")] + { + let mut flat_gpu = FlatTree::from_legacy(&legacy, config.alignment); + match WgpuComputeBackend::try_new(&flat_gpu) { + Ok(backend) => results.push(run_flat_bench(config, &mut flat_gpu, backend)), + Err(err) => results.push(BenchResult::skipped("wgpu-compute", config, err)), + } + } + + results +} + +fn run_legacy_bench(config: BenchConfig, mut legacy: LegacyTree) -> BenchResult { + let started = Instant::now(); + for iteration in 0..config.iterations { + legacy_step(&mut legacy, iteration); + } + BenchResult { + name: "legacy-scattered", + elapsed: started.elapsed(), + node_count: legacy.node_count(), + slot_count: legacy.total_slots(), + iterations: config.iterations, + transfer: TransferStats::default(), + note: None, + } +} + +fn run_flat_bench( + config: BenchConfig, + tree: &mut FlatTree, + mut backend: B, +) -> BenchResult { + let started = Instant::now(); + for iteration in 0..config.iterations { + backend.run_iteration(tree, iteration); + } + backend.finish(tree); + + BenchResult { + name: backend.name(), + elapsed: started.elapsed(), + node_count: tree.nodes.len(), + slot_count: tree.total_slots(), + iterations: config.iterations, + transfer: backend.transfer_stats(tree), + note: None, + } +} + +fn legacy_step(tree: &mut LegacyTree, iteration: u32) { + let iter_bias = (iteration as f32) * 0.00017; + for node in &mut tree.nodes { + let actions = node.action_count as usize; + let hands = node.hand_count as usize; + if actions == 0 || hands == 0 { + continue; + } + + let slots = actions * hands; + if node.regrets.len() != slots { + continue; + } + + for hand in 0..hands { + let mut positive_sum = 0.0f32; + for action in 0..actions { + let idx = action * hands + hand; + let value = node.regrets[idx].max(0.0); + node.strategy[idx] = value; + positive_sum += value; + } + + if positive_sum <= 1e-8 { + let uniform = 1.0 / actions as f32; + for action in 0..actions { + let idx = action * hands + hand; + node.strategy[idx] = uniform; + } + } else { + let inv = 1.0 / positive_sum; + for action in 0..actions { + let idx = action * hands + hand; + node.strategy[idx] *= inv; + } + } + } + + for idx in 0..slots { + let cf = node.cfvalues[idx]; + let strat = node.strategy[idx]; + let delta = cf - iter_bias; + node.regrets[idx] = (node.regrets[idx] + delta).clamp(-5000.0, 5000.0); + node.cfvalues[idx] = (0.84 * cf) + (0.16 * strat); + } + } +} + +#[allow(dead_code)] +fn _sanity_compare_one_step(legacy: &mut LegacyTree, flat: &mut FlatTree, iteration: u32) { + legacy_step(legacy, iteration); + flat.with_host_buffers(|nodes, regrets, strategy, cfvalues| { + kernel_step(nodes, regrets, strategy, cfvalues, iteration); + }); +} diff --git a/rust/hybrid-lab/src/flat.rs b/rust/hybrid-lab/src/flat.rs new file mode 100644 index 0000000..755b901 --- /dev/null +++ b/rust/hybrid-lab/src/flat.rs @@ -0,0 +1,197 @@ +use crate::aligned::AlignedF32Buffer; +use crate::tree::LegacyTree; +use std::ops::Range; + +#[derive(Debug, Clone, Copy)] +pub struct NodeMeta { + pub first_child: u32, + pub child_count: u16, + pub hand_count: u16, + pub action_count: u16, + pub slot_offset: u32, + pub slot_count: u32, +} + +#[derive(Debug, Default, Clone, Copy)] +pub struct TransferStats { + pub upload_bytes: u64, + pub download_bytes: u64, + pub upload_ops: u64, + pub download_ops: u64, +} + +#[derive(Debug, Clone)] +struct DeviceMirror { + regrets: Vec, + strategy: Vec, + cfvalues: Vec, + stats: TransferStats, +} + +#[derive(Debug)] +pub struct FlatTree { + pub nodes: Vec, + pub edges: Vec, + regrets: AlignedF32Buffer, + strategy: AlignedF32Buffer, + cfvalues: AlignedF32Buffer, + device: Option, +} + +impl FlatTree { + pub fn from_legacy(legacy: &LegacyTree, alignment: usize) -> Self { + let total_slots = legacy.total_slots(); + let mut regrets = AlignedF32Buffer::new_zeroed(total_slots, alignment); + let mut strategy = AlignedF32Buffer::new_zeroed(total_slots, alignment); + let mut cfvalues = AlignedF32Buffer::new_zeroed(total_slots, alignment); + + let mut nodes = Vec::with_capacity(legacy.nodes.len()); + let mut offset = 0usize; + for node in &legacy.nodes { + let slot_count = node.regrets.len(); + let range = offset..offset + slot_count; + regrets.as_mut_slice()[range.clone()].copy_from_slice(&node.regrets); + strategy.as_mut_slice()[range.clone()].copy_from_slice(&node.strategy); + cfvalues.as_mut_slice()[range.clone()].copy_from_slice(&node.cfvalues); + + nodes.push(NodeMeta { + first_child: node.first_child, + child_count: node.child_count, + hand_count: node.hand_count, + action_count: node.action_count, + slot_offset: offset as u32, + slot_count: slot_count as u32, + }); + offset += slot_count; + } + + Self { + nodes, + edges: legacy.edges.clone(), + regrets, + strategy, + cfvalues, + device: None, + } + } + + pub fn enable_device_mirror(&mut self) { + if self.device.is_some() { + return; + } + let len = self.total_slots(); + self.device = Some(DeviceMirror { + regrets: vec![0.0; len], + strategy: vec![0.0; len], + cfvalues: vec![0.0; len], + stats: TransferStats::default(), + }); + } + + pub fn upload_to_device(&mut self) { + let Some(mut device) = self.device.take() else { + return; + }; + device.regrets.copy_from_slice(self.regrets.as_slice()); + device.strategy.copy_from_slice(self.strategy.as_slice()); + device.cfvalues.copy_from_slice(self.cfvalues.as_slice()); + + let bytes = (self.total_slots() * std::mem::size_of::() * 3) as u64; + device.stats.upload_bytes += bytes; + device.stats.upload_ops += 1; + self.device = Some(device); + } + + pub fn download_from_device(&mut self) { + let Some(mut device) = self.device.take() else { + return; + }; + self.regrets.as_mut_slice().copy_from_slice(&device.regrets); + self.strategy + .as_mut_slice() + .copy_from_slice(&device.strategy); + self.cfvalues + .as_mut_slice() + .copy_from_slice(&device.cfvalues); + + let bytes = (self.total_slots() * std::mem::size_of::() * 3) as u64; + device.stats.download_bytes += bytes; + device.stats.download_ops += 1; + self.device = Some(device); + } + + pub fn transfer_stats(&self) -> TransferStats { + self.device + .as_ref() + .map(|device| device.stats) + .unwrap_or_default() + } + + pub fn total_slots(&self) -> usize { + self.regrets.len() + } + + #[inline] + pub fn slot_range(&self, node_index: usize) -> Range { + let node = self.nodes[node_index]; + let start = node.slot_offset as usize; + start..(start + node.slot_count as usize) + } + + #[inline] + pub fn regrets(&self) -> &[f32] { + self.regrets.as_slice() + } + + #[inline] + pub fn regrets_mut(&mut self) -> &mut [f32] { + self.regrets.as_mut_slice() + } + + #[inline] + pub fn strategy(&self) -> &[f32] { + self.strategy.as_slice() + } + + #[inline] + pub fn strategy_mut(&mut self) -> &mut [f32] { + self.strategy.as_mut_slice() + } + + #[inline] + pub fn cfvalues(&self) -> &[f32] { + self.cfvalues.as_slice() + } + + #[inline] + pub fn cfvalues_mut(&mut self) -> &mut [f32] { + self.cfvalues.as_mut_slice() + } + + #[inline] + pub fn with_host_buffers( + &mut self, + f: impl FnOnce(&[NodeMeta], &mut [f32], &mut [f32], &mut [f32]) -> R, + ) -> R { + let nodes = &self.nodes; + let regrets = self.regrets.as_mut_slice(); + let strategy = self.strategy.as_mut_slice(); + let cfvalues = self.cfvalues.as_mut_slice(); + f(nodes, regrets, strategy, cfvalues) + } + + #[inline] + pub fn with_device_buffers( + &mut self, + f: impl FnOnce(&[NodeMeta], &mut [f32], &mut [f32], &mut [f32]) -> R, + ) -> Option { + let nodes = &self.nodes; + let device = self.device.as_mut()?; + Some(f( + nodes, + device.regrets.as_mut_slice(), + device.strategy.as_mut_slice(), + device.cfvalues.as_mut_slice(), + )) + } +} diff --git a/rust/hybrid-lab/src/lib.rs b/rust/hybrid-lab/src/lib.rs new file mode 100644 index 0000000..c200463 --- /dev/null +++ b/rust/hybrid-lab/src/lib.rs @@ -0,0 +1,14 @@ +pub mod aligned; +pub mod backend; +pub mod bench; +pub mod flat; +pub mod tree; +#[cfg(feature = "wgpu-backend")] +pub mod wgpu_backend; + +pub use backend::{CpuFlatBackend, HybridMirrorBackend, SolverBackend}; +pub use bench::{run_bench_suite, BenchConfig, BenchResult}; +pub use flat::{FlatTree, TransferStats}; +pub use tree::{build_synthetic_tree, LegacyTree}; +#[cfg(feature = "wgpu-backend")] +pub use wgpu_backend::WgpuComputeBackend; diff --git a/rust/hybrid-lab/src/main.rs b/rust/hybrid-lab/src/main.rs new file mode 100644 index 0000000..091acdc --- /dev/null +++ b/rust/hybrid-lab/src/main.rs @@ -0,0 +1,76 @@ +use hybrid_lab::{run_bench_suite, BenchConfig}; + +fn main() { + let config = parse_config(); + println!("hybrid-lab benchmark"); + println!( + "config depth={} branching={} hands={} actions={} iters={} alignment={}", + config.depth, + config.branching, + config.hand_count, + config.action_count, + config.iterations, + config.alignment + ); + + let results = run_bench_suite(config); + println!(); + println!( + "{:<20} {:>12} {:>14} {:>14} {:>14} {:>10}", + "backend", "time(ms)", "slot updates/s", "upload(MB)", "download(MB)", "status" + ); + println!("{}", "-".repeat(96)); + for row in results { + let upload_mb = row.transfer.upload_bytes as f64 / (1024.0 * 1024.0); + let download_mb = row.transfer.download_bytes as f64 / (1024.0 * 1024.0); + let status = if row.note.is_some() { "skipped" } else { "ok" }; + println!( + "{:<20} {:>12.2} {:>14.0} {:>14.2} {:>14.2} {:>10}", + row.name, + row.elapsed.as_secs_f64() * 1000.0, + row.slot_updates_per_sec(), + upload_mb, + download_mb, + status + ); + if let Some(note) = row.note { + println!(" note: {note}"); + } + } +} + +fn parse_config() -> BenchConfig { + let mut config = BenchConfig::default(); + let mut args = std::env::args().skip(1); + + while let Some(arg) = args.next() { + let Some(value) = args.next() else { + break; + }; + match arg.as_str() { + "--depth" => config.depth = parse_usize(&value, config.depth), + "--branching" => config.branching = parse_usize(&value, config.branching), + "--hands" => config.hand_count = parse_usize(&value, config.hand_count), + "--actions" => config.action_count = parse_usize(&value, config.action_count), + "--iters" => config.iterations = parse_u32(&value, config.iterations), + "--align" => config.alignment = parse_usize(&value, config.alignment), + _ => {} + } + } + + config +} + +fn parse_usize(text: &str, fallback: usize) -> usize { + text.parse::() + .ok() + .filter(|value| *value > 0) + .unwrap_or(fallback) +} + +fn parse_u32(text: &str, fallback: u32) -> u32 { + text.parse::() + .ok() + .filter(|value| *value > 0) + .unwrap_or(fallback) +} diff --git a/rust/hybrid-lab/src/tree.rs b/rust/hybrid-lab/src/tree.rs new file mode 100644 index 0000000..bd6058d --- /dev/null +++ b/rust/hybrid-lab/src/tree.rs @@ -0,0 +1,130 @@ +#[derive(Debug, Clone)] +pub struct NodeLegacy { + pub first_child: u32, + pub child_count: u16, + pub hand_count: u16, + pub action_count: u16, + pub regrets: Vec, + pub strategy: Vec, + pub cfvalues: Vec, +} + +#[derive(Debug, Clone)] +pub struct LegacyTree { + pub nodes: Vec, + pub edges: Vec, +} + +impl LegacyTree { + pub fn node_count(&self) -> usize { + self.nodes.len() + } + + pub fn total_slots(&self) -> usize { + self.nodes.iter().map(|node| node.regrets.len()).sum() + } +} + +pub fn build_synthetic_tree( + depth: usize, + branching: usize, + hand_count: usize, + action_count: usize, +) -> LegacyTree { + assert!(branching > 0, "branching must be > 0"); + assert!(hand_count > 0, "hand_count must be > 0"); + assert!(action_count > 0, "action_count must be > 0"); + assert!( + hand_count <= u16::MAX as usize, + "hand_count must fit in u16 for synthetic tree" + ); + assert!( + action_count <= u16::MAX as usize, + "action_count must fit in u16 for synthetic tree" + ); + + let mut nodes = Vec::new(); + let mut edges = Vec::new(); + let mut seed = 0x0C0F_FEE1_u64; + build_recursive( + &mut nodes, + &mut edges, + depth, + branching, + hand_count as u16, + action_count as u16, + &mut seed, + ); + LegacyTree { nodes, edges } +} + +fn build_recursive( + nodes: &mut Vec, + edges: &mut Vec, + depth_left: usize, + branching: usize, + hand_count: u16, + action_count: u16, + seed: &mut u64, +) -> u32 { + let node_index = nodes.len() as u32; + nodes.push(NodeLegacy { + first_child: 0, + child_count: 0, + hand_count, + action_count, + regrets: Vec::new(), + strategy: Vec::new(), + cfvalues: Vec::new(), + }); + + let child_count = if depth_left > 0 { branching as u16 } else { 0 }; + let first_child = edges.len() as u32; + if child_count > 0 { + for _ in 0..child_count { + let child = build_recursive( + nodes, + edges, + depth_left - 1, + branching, + hand_count, + action_count, + seed, + ); + edges.push(child); + } + } + + let slot_count = (hand_count as usize) * (action_count as usize); + let mut regrets = vec![0.0; slot_count]; + let mut strategy = vec![0.0; slot_count]; + let mut cfvalues = vec![0.0; slot_count]; + + for idx in 0..slot_count { + let noise = lcg(seed); + let centered = (noise - 0.5) * 2.0; + regrets[idx] = centered * 0.25; + strategy[idx] = 1.0 / action_count as f32; + cfvalues[idx] = centered * 0.5; + } + + nodes[node_index as usize] = NodeLegacy { + first_child, + child_count, + hand_count, + action_count, + regrets, + strategy, + cfvalues, + }; + node_index +} + +#[inline] +fn lcg(seed: &mut u64) -> f32 { + *seed = seed + .wrapping_mul(6364136223846793005) + .wrapping_add(1442695040888963407); + let bits = ((*seed >> 32) & 0xFFFF_FFFF) as u32; + bits as f32 / u32::MAX as f32 +} diff --git a/rust/hybrid-lab/src/wgpu_backend.rs b/rust/hybrid-lab/src/wgpu_backend.rs new file mode 100644 index 0000000..8a92fd2 --- /dev/null +++ b/rust/hybrid-lab/src/wgpu_backend.rs @@ -0,0 +1,438 @@ +use crate::backend::SolverBackend; +use crate::flat::{FlatTree, TransferStats}; +use bytemuck::{Pod, Zeroable}; +use std::mem::size_of; +use std::sync::mpsc; +use wgpu::util::DeviceExt; + +const WORKGROUP_SIZE: u32 = 256; + +#[repr(C)] +#[derive(Debug, Clone, Copy, Pod, Zeroable)] +struct NodeMetaGpu { + slot_offset: u32, + hand_count: u32, + action_count: u32, + _pad: u32, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy, Pod, Zeroable)] +struct WorkItemGpu { + node_index: u32, + hand_index: u32, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy, Pod, Zeroable)] +struct KernelParams { + iter_bias: f32, + work_count: u32, + _pad0: u32, + _pad1: u32, +} + +struct WgpuState { + device: wgpu::Device, + queue: wgpu::Queue, + pipeline: wgpu::ComputePipeline, + bind_group: wgpu::BindGroup, + params_buffer: wgpu::Buffer, + regrets_buffer: wgpu::Buffer, + strategy_buffer: wgpu::Buffer, + cfvalues_buffer: wgpu::Buffer, + slot_count: usize, + work_count: u32, + dispatch_x: u32, +} + +pub struct WgpuComputeBackend { + state: WgpuState, + stats: TransferStats, +} + +impl WgpuComputeBackend { + pub fn try_new(tree: &FlatTree) -> Result { + if tree.total_slots() == 0 { + return Err("wgpu backend disabled: tree has no slots".to_string()); + } + + let nodes: Vec = tree + .nodes + .iter() + .map(|node| NodeMetaGpu { + slot_offset: node.slot_offset, + hand_count: node.hand_count as u32, + action_count: node.action_count as u32, + _pad: 0, + }) + .collect(); + + let total_work_items: usize = tree.nodes.iter().map(|node| node.hand_count as usize).sum(); + let work_count = u32::try_from(total_work_items) + .map_err(|_| "wgpu backend disabled: work-item count exceeds u32".to_string())?; + if work_count == 0 { + return Err("wgpu backend disabled: no hand work items".to_string()); + } + + let mut work_items = Vec::with_capacity(total_work_items); + for (node_index, node) in tree.nodes.iter().enumerate() { + for hand_index in 0..(node.hand_count as u32) { + work_items.push(WorkItemGpu { + node_index: node_index as u32, + hand_index, + }); + } + } + + let instance = wgpu::Instance::default(); + let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::HighPerformance, + compatible_surface: None, + force_fallback_adapter: false, + })) + .ok_or_else(|| "wgpu backend disabled: no GPU adapter available".to_string())?; + + let (device, queue) = pollster::block_on(adapter.request_device( + &wgpu::DeviceDescriptor { + label: Some("hybrid-lab-device"), + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::default(), + ..Default::default() + }, + None, + )) + .map_err(|err| format!("wgpu backend disabled: failed to create device ({err})"))?; + + let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("hybrid-lab-kernel"), + source: wgpu::ShaderSource::Wgsl(include_str!("wgpu_kernel.wgsl").into()), + }); + + let params = KernelParams { + iter_bias: 0.0, + work_count, + _pad0: 0, + _pad1: 0, + }; + let params_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("hybrid-lab-params"), + contents: bytemuck::bytes_of(¶ms), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + + let nodes_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("hybrid-lab-nodes"), + contents: bytemuck::cast_slice(&nodes), + usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, + }); + + let work_items_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("hybrid-lab-work-items"), + contents: bytemuck::cast_slice(&work_items), + usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, + }); + + let regrets_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("hybrid-lab-regrets"), + contents: bytemuck::cast_slice(tree.regrets()), + usage: wgpu::BufferUsages::STORAGE + | wgpu::BufferUsages::COPY_SRC + | wgpu::BufferUsages::COPY_DST, + }); + + let strategy_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("hybrid-lab-strategy"), + contents: bytemuck::cast_slice(tree.strategy()), + usage: wgpu::BufferUsages::STORAGE + | wgpu::BufferUsages::COPY_SRC + | wgpu::BufferUsages::COPY_DST, + }); + + let cfvalues_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("hybrid-lab-cfvalues"), + contents: bytemuck::cast_slice(tree.cfvalues()), + usage: wgpu::BufferUsages::STORAGE + | wgpu::BufferUsages::COPY_SRC + | wgpu::BufferUsages::COPY_DST, + }); + + let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("hybrid-lab-bind-group-layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: false }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 4, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: false }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 5, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: false }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + ], + }); + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("hybrid-lab-bind-group"), + layout: &bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: params_buffer.as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: nodes_buffer.as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: work_items_buffer.as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 3, + resource: regrets_buffer.as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 4, + resource: strategy_buffer.as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 5, + resource: cfvalues_buffer.as_entire_binding(), + }, + ], + }); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("hybrid-lab-pipeline-layout"), + bind_group_layouts: &[&bind_group_layout], + push_constant_ranges: &[], + }); + + let pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { + label: Some("hybrid-lab-pipeline"), + layout: Some(&pipeline_layout), + module: &shader, + entry_point: "main", + compilation_options: wgpu::PipelineCompilationOptions::default(), + }); + + let dispatch_x = ((work_count + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE).max(1); + let slot_count = tree.total_slots(); + let mut stats = TransferStats::default(); + stats.upload_bytes = (nodes.len() * size_of::() + + work_items.len() * size_of::() + + slot_count * size_of::() * 3 + + size_of::()) as u64; + stats.upload_ops = 6; + + Ok(Self { + state: WgpuState { + device, + queue, + pipeline, + bind_group, + params_buffer, + regrets_buffer, + strategy_buffer, + cfvalues_buffer, + slot_count, + work_count, + dispatch_x, + }, + stats, + }) + } + + fn readback_f32( + device: &wgpu::Device, + queue: &wgpu::Queue, + source: &wgpu::Buffer, + slot_count: usize, + label: &str, + ) -> Result, String> { + let size_bytes = (slot_count * size_of::()) as wgpu::BufferAddress; + let staging = device.create_buffer(&wgpu::BufferDescriptor { + label: Some(label), + size: size_bytes, + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ, + mapped_at_creation: false, + }); + + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("hybrid-lab-readback-copy"), + }); + encoder.copy_buffer_to_buffer(source, 0, &staging, 0, size_bytes); + queue.submit(Some(encoder.finish())); + device.poll(wgpu::Maintain::Wait); + + let slice = staging.slice(..); + let (tx, rx) = mpsc::channel(); + slice.map_async(wgpu::MapMode::Read, move |result| { + let _ = tx.send(result); + }); + device.poll(wgpu::Maintain::Wait); + + let map_result = rx + .recv() + .map_err(|_| "wgpu readback failed: map callback channel closed".to_string())?; + map_result.map_err(|err| format!("wgpu readback failed: {err:?}"))?; + + let data = slice.get_mapped_range(); + let out = bytemuck::cast_slice::(&data).to_vec(); + drop(data); + staging.unmap(); + Ok(out) + } +} + +impl SolverBackend for WgpuComputeBackend { + fn name(&self) -> &'static str { + "wgpu-compute" + } + + fn run_iteration(&mut self, _tree: &mut FlatTree, iteration: u32) { + let params = KernelParams { + iter_bias: (iteration as f32) * 0.00017, + work_count: self.state.work_count, + _pad0: 0, + _pad1: 0, + }; + + self.state + .queue + .write_buffer(&self.state.params_buffer, 0, bytemuck::bytes_of(¶ms)); + self.stats.upload_bytes += size_of::() as u64; + self.stats.upload_ops += 1; + + let mut encoder = + self.state + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("hybrid-lab-kernel-encoder"), + }); + { + let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { + label: Some("hybrid-lab-kernel-pass"), + timestamp_writes: None, + }); + pass.set_pipeline(&self.state.pipeline); + pass.set_bind_group(0, &self.state.bind_group, &[]); + pass.dispatch_workgroups(self.state.dispatch_x, 1, 1); + } + self.state.queue.submit(Some(encoder.finish())); + } + + fn finish(&mut self, tree: &mut FlatTree) { + self.state.device.poll(wgpu::Maintain::Wait); + + let slot_count = self.state.slot_count; + let download_bytes = (slot_count * size_of::()) as u64; + let regrets = match Self::readback_f32( + &self.state.device, + &self.state.queue, + &self.state.regrets_buffer, + slot_count, + "hybrid-lab-read-regrets", + ) { + Ok(data) => data, + Err(err) => { + eprintln!("{err}"); + return; + } + }; + self.stats.download_bytes += download_bytes; + self.stats.download_ops += 1; + + let strategy = match Self::readback_f32( + &self.state.device, + &self.state.queue, + &self.state.strategy_buffer, + slot_count, + "hybrid-lab-read-strategy", + ) { + Ok(data) => data, + Err(err) => { + eprintln!("{err}"); + return; + } + }; + self.stats.download_bytes += download_bytes; + self.stats.download_ops += 1; + + let cfvalues = match Self::readback_f32( + &self.state.device, + &self.state.queue, + &self.state.cfvalues_buffer, + slot_count, + "hybrid-lab-read-cfvalues", + ) { + Ok(data) => data, + Err(err) => { + eprintln!("{err}"); + return; + } + }; + self.stats.download_bytes += download_bytes; + self.stats.download_ops += 1; + + tree.regrets_mut().copy_from_slice(®rets); + tree.strategy_mut().copy_from_slice(&strategy); + tree.cfvalues_mut().copy_from_slice(&cfvalues); + } + + fn transfer_stats(&self, _tree: &FlatTree) -> TransferStats { + self.stats + } +} diff --git a/rust/hybrid-lab/src/wgpu_kernel.wgsl b/rust/hybrid-lab/src/wgpu_kernel.wgsl new file mode 100644 index 0000000..8c62028 --- /dev/null +++ b/rust/hybrid-lab/src/wgpu_kernel.wgsl @@ -0,0 +1,101 @@ +struct KernelParams { + iter_bias: f32, + work_count: u32, + _pad0: u32, + _pad1: u32, +} + +struct NodeMeta { + slot_offset: u32, + hand_count: u32, + action_count: u32, + _pad: u32, +} + +struct WorkItem { + node_index: u32, + hand_index: u32, +} + +@group(0) @binding(0) +var params: KernelParams; + +@group(0) @binding(1) +var nodes: array; + +@group(0) @binding(2) +var work_items: array; + +@group(0) @binding(3) +var regrets: array; + +@group(0) @binding(4) +var strategy: array; + +@group(0) @binding(5) +var cfvalues: array; + +@compute @workgroup_size(256) +fn main(@builtin(global_invocation_id) global_id: vec3) { + let work_index = global_id.x; + if (work_index >= params.work_count) { + return; + } + + let work = work_items[work_index]; + let node = nodes[work.node_index]; + if (node.hand_count == 0u || node.action_count == 0u || work.hand_index >= node.hand_count) { + return; + } + + var positive_sum: f32 = 0.0; + var action: u32 = 0u; + loop { + if (action >= node.action_count) { + break; + } + let slot = node.slot_offset + action * node.hand_count + work.hand_index; + let value = max(regrets[slot], 0.0); + strategy[slot] = value; + positive_sum = positive_sum + value; + action = action + 1u; + } + + if (positive_sum <= 0.00000001) { + let uniform = 1.0 / f32(node.action_count); + action = 0u; + loop { + if (action >= node.action_count) { + break; + } + let slot = node.slot_offset + action * node.hand_count + work.hand_index; + strategy[slot] = uniform; + action = action + 1u; + } + } else { + let inv = 1.0 / positive_sum; + action = 0u; + loop { + if (action >= node.action_count) { + break; + } + let slot = node.slot_offset + action * node.hand_count + work.hand_index; + strategy[slot] = strategy[slot] * inv; + action = action + 1u; + } + } + + action = 0u; + loop { + if (action >= node.action_count) { + break; + } + let slot = node.slot_offset + action * node.hand_count + work.hand_index; + let cf = cfvalues[slot]; + let strat = strategy[slot]; + let delta = cf - params.iter_bias; + regrets[slot] = clamp(regrets[slot] + delta, -5000.0, 5000.0); + cfvalues[slot] = (0.84 * cf) + (0.16 * strat); + action = action + 1u; + } +} diff --git a/rust/range/.cargo/config.toml b/rust/range/.cargo/config.toml index 19e88d9..583c53d 100644 --- a/rust/range/.cargo/config.toml +++ b/rust/range/.cargo/config.toml @@ -1,5 +1,6 @@ [build] target = "wasm32-unknown-unknown" +rustflags = "-C target-feature=-reference-types" [unstable] build-std = ["panic_abort", "std"] diff --git a/rust/range/Cargo.lock b/rust/range/Cargo.lock index f08855b..d5d7a5d 100644 --- a/rust/range/Cargo.lock +++ b/rust/range/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -23,12 +23,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - [[package]] name = "memchr" version = "2.6.3" @@ -37,14 +31,13 @@ checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "once_cell" -version = "1.18.0" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "postflop-solver" version = "0.1.0" -source = "git+https://github.com/b-inary/postflop-solver#9d1509fe5077d019825f833eed04b16d342dfda1" dependencies = [ "once_cell", "regex", @@ -105,6 +98,12 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "syn" version = "2.0.37" @@ -124,34 +123,22 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", "once_cell", - "proc-macro2", - "quote", - "syn", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -159,19 +146,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] diff --git a/rust/range/Cargo.toml b/rust/range/Cargo.toml index d904d9a..bbd46a4 100644 --- a/rust/range/Cargo.toml +++ b/rust/range/Cargo.toml @@ -9,8 +9,8 @@ license = "AGPL-3.0-or-later" crate-type = ["cdylib"] [dependencies] -postflop-solver = { git = "https://github.com/b-inary/postflop-solver", default-features = false } -wasm-bindgen = "0.2.87" +postflop-solver = { path = "../../../postflop-solver-upstream", default-features = false } +wasm-bindgen = "0.2.118" [profile.release] codegen-units = 1 diff --git a/rust/solver-mt/.cargo/config.toml b/rust/solver-mt/.cargo/config.toml index 7e0f752..95c2701 100644 --- a/rust/solver-mt/.cargo/config.toml +++ b/rust/solver-mt/.cargo/config.toml @@ -1,6 +1,6 @@ [build] target = "wasm32-unknown-unknown" -rustflags = "-C target-feature=+atomics,+bulk-memory,+mutable-globals,+simd128 -C link-arg=--max-memory=4294967296" +rustflags = "-C target-feature=+atomics,+bulk-memory,+mutable-globals,+simd128,-reference-types -C link-arg=--max-memory=4294967296" [unstable] build-std = ["panic_abort", "std"] diff --git a/rust/solver-mt/Cargo.lock b/rust/solver-mt/Cargo.lock index b38944f..b12055e 100644 --- a/rust/solver-mt/Cargo.lock +++ b/rust/solver-mt/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -11,18 +11,95 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "cc" version = "1.0.83" @@ -39,6 +116,80 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[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-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 = "crossbeam-deque" version = "0.8.3" @@ -72,12 +223,253 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "d3d12" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" +dependencies = [ + "bitflags 2.11.1", + "libloading 0.8.9", + "winapi", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[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 = "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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +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.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.11.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "gpu-allocator" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" +dependencies = [ + "log", + "presser", + "thiserror", + "winapi", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.11.1", + "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 2.11.1", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "hassle-rs" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +dependencies = [ + "bitflags 2.11.1", + "com", + "libc", + "libloading 0.8.9", + "thiserror", + "widestring", + "winapi", +] + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", +] + +[[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.117", +] + [[package]] name = "jobserver" version = "0.1.26" @@ -89,24 +481,88 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "cfg-if", + "futures-util", + "once_cell", "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 0.8.9", + "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.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[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 = "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.20" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] [[package]] name = "memchr" @@ -123,11 +579,109 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metal" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" +dependencies = [ + "bitflags 2.11.1", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "naga" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.11.1", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +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", +] + +[[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.18.0" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[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 = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +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" @@ -135,35 +689,67 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + [[package]] name = "postflop-solver" version = "0.1.0" -source = "git+https://github.com/b-inary/postflop-solver#9d1509fe5077d019825f833eed04b16d342dfda1" dependencies = [ + "bytemuck", "once_cell", + "pollster", "rayon", "regex", + "wgpu", "zstd", ] +[[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.67" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + [[package]] name = "quote" -version = "1.0.33" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" 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 = "rayon" version = "1.8.0" @@ -184,6 +770,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.1", +] + [[package]] name = "regex" version = "1.9.6" @@ -213,12 +808,51 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[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.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "solver" version = "0.2.7" @@ -230,59 +864,130 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.11.1", +] + [[package]] name = "spmc" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02a8428da277a8e3a15271d79943e80ccc2ef254e78813a166a08d65e4c3ece5" +[[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.37" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +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 = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[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.117", +] + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[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.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" +name = "wasm-bindgen-futures" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", + "js-sys", + "wasm-bindgen", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -290,22 +995,285 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e37c7b9921b75dfd26dd973fdcbce36f13dfa6e2dc82aece584e0ed48c355c" +dependencies = [ + "arrayvec", + "cfg-if", + "cfg_aliases", + "document-features", + "js-sys", + "log", + "naga", + "parking_lot", + "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 = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.11.1", + "cfg_aliases", + "codespan-reporting", + "document-features", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172e490a87295564f3fcc0f165798d87386f6231b04d4548bca458cbbfd63222" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.11.1", + "block", + "cfg_aliases", + "core-graphics-types", + "d3d12", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.9", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" +dependencies = [ + "bitflags 2.11.1", + "js-sys", + "web-sys", +] + +[[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", +] + +[[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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[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", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[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_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[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_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "xml-rs" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "zstd" diff --git a/rust/solver-mt/Cargo.toml b/rust/solver-mt/Cargo.toml index e7b7e96..f507c13 100644 --- a/rust/solver-mt/Cargo.toml +++ b/rust/solver-mt/Cargo.toml @@ -10,14 +10,15 @@ crate-type = ["cdylib"] path = "../solver-src/lib.rs" [dependencies] -js-sys = "0.3.64" -postflop-solver = { git = "https://github.com/b-inary/postflop-solver", features = ["custom-alloc", "rayon"], default-features = false } +js-sys = "0.3.95" +postflop-solver = { path = "../../../postflop-solver-upstream", features = ["custom-alloc", "rayon"], default-features = false } rayon = { version = "1.8.0", optional = true } spmc = "0.3.0" -wasm-bindgen = "0.2.87" +wasm-bindgen = "0.2.118" [features] default = ["rayon"] +wgpu-backend = ["postflop-solver/wgpu-backend"] [profile.release] codegen-units = 1 diff --git a/rust/solver-mt/workerHelpers.js b/rust/solver-mt/workerHelpers.js index c454e79..fc73e5e 100644 --- a/rust/solver-mt/workerHelpers.js +++ b/rust/solver-mt/workerHelpers.js @@ -53,7 +53,7 @@ waitForMsgType(self, "wasm_bindgen_worker_init").then(async (data) => { // OTOH, even though it can't be inlined, it should be still reasonably // cheap since the requested file is already in cache (it was loaded by // the main thread). - const pkg = await import("../.."); + const pkg = await import("../../solver.js"); await pkg.default(data.module, data.memory); postMessage({ type: "wasm_bindgen_worker_ready" }); pkg.wbg_rayon_start_worker(data.receiver); diff --git a/rust/solver-src/lib.rs b/rust/solver-src/lib.rs index cc61fff..49e9e1b 100644 --- a/rust/solver-src/lib.rs +++ b/rust/solver-src/lib.rs @@ -211,12 +211,47 @@ impl GameManager { self.game.allocate_memory(enable_compression); } - pub fn solve_step(&self, current_iteration: u32) { + pub fn set_solver_backend(&mut self, backend: &str) -> Option { + let backend = match backend.to_ascii_lowercase().as_str() { + "legacy" | "legacy-cpu" | "cpu" => SolveBackend::LegacyCpu, + "flat" | "flat-cpu" | "hybrid" | "hybrid-flat" => SolveBackend::FlatCpu, + "wgpu" | "gpu" | "wgpu-compute" => { + #[cfg(feature = "wgpu-backend")] + { + SolveBackend::WgpuCompute + } + #[cfg(not(feature = "wgpu-backend"))] + { + return Some( + "WGPU backend unavailable in this build (use backend 'flat').".to_string(), + ); + } + } + _ => return Some("Unknown backend. Use 'legacy', 'flat' or 'wgpu'.".to_string()), + }; + + self.game.set_solve_backend(backend); + None + } + + pub fn solver_backend(&self) -> String { + match self.game.solve_backend() { + SolveBackend::LegacyCpu => "legacy".to_string(), + SolveBackend::FlatCpu => "flat".to_string(), + SolveBackend::WgpuCompute => "wgpu".to_string(), + } + } + + pub fn flat_runtime_nodes(&self) -> u32 { + self.game.flat_runtime_nodes() as u32 + } + + pub fn solve_step(&mut self, current_iteration: u32) { unsafe { if let Some(pool) = THREAD_POOL.as_ref() { - pool.install(|| solve_step(&self.game, current_iteration)); + pool.install(|| solve_step(&mut self.game, current_iteration)); } else { - solve_step(&self.game, current_iteration); + solve_step(&mut self.game, current_iteration); } } } diff --git a/rust/solver-st/.cargo/config.toml b/rust/solver-st/.cargo/config.toml index 959f6ce..556048c 100644 --- a/rust/solver-st/.cargo/config.toml +++ b/rust/solver-st/.cargo/config.toml @@ -1,6 +1,6 @@ [build] target = "wasm32-unknown-unknown" -rustflags = "-C link-arg=--max-memory=4294967296" +rustflags = "-C target-feature=-reference-types -C link-arg=--max-memory=4294967296" [unstable] build-std = ["panic_abort", "std"] diff --git a/rust/solver-st/Cargo.lock b/rust/solver-st/Cargo.lock index e9df308..bdca266 100644 --- a/rust/solver-st/Cargo.lock +++ b/rust/solver-st/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -11,23 +11,500 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[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-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 = "d3d12" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" +dependencies = [ + "bitflags 2.11.1", + "libloading 0.8.9", + "winapi", +] + +[[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 = "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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +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.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.11.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "gpu-allocator" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" +dependencies = [ + "log", + "presser", + "thiserror", + "winapi", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.11.1", + "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 2.11.1", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "hassle-rs" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +dependencies = [ + "bitflags 2.11.1", + "com", + "libc", + "libloading 0.8.9", + "thiserror", + "widestring", + "winapi", +] + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", +] + +[[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.117", +] + +[[package]] +name = "js-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "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 0.8.9", + "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.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[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 = "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.20" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] [[package]] name = "memchr" @@ -35,39 +512,184 @@ version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +[[package]] +name = "metal" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" +dependencies = [ + "bitflags 2.11.1", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "naga" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.11.1", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +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", +] + +[[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.18.0" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "parking_lot" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +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.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" [[package]] name = "postflop-solver" version = "0.1.0" -source = "git+https://github.com/b-inary/postflop-solver#9d1509fe5077d019825f833eed04b16d342dfda1" dependencies = [ + "bytemuck", "once_cell", + "pollster", "regex", + "wgpu", ] +[[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.67" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + [[package]] name = "quote" -version = "1.0.33" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" 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 2.11.1", +] + [[package]] name = "regex" version = "1.9.6" @@ -97,6 +719,51 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[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.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "solver" version = "0.2.7" @@ -105,53 +772,124 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[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.37" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" 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 = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[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.117", +] + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[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.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" +name = "wasm-bindgen-futures" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", + "js-sys", + "wasm-bindgen", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -159,19 +897,282 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e37c7b9921b75dfd26dd973fdcbce36f13dfa6e2dc82aece584e0ed48c355c" +dependencies = [ + "arrayvec", + "cfg-if", + "cfg_aliases", + "document-features", + "js-sys", + "log", + "naga", + "parking_lot", + "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 = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.11.1", + "cfg_aliases", + "codespan-reporting", + "document-features", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172e490a87295564f3fcc0f165798d87386f6231b04d4548bca458cbbfd63222" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.11.1", + "block", + "cfg_aliases", + "core-graphics-types", + "d3d12", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.9", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" +dependencies = [ + "bitflags 2.11.1", + "js-sys", + "web-sys", +] + +[[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", +] + +[[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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[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", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[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_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[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_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "xml-rs" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" diff --git a/rust/solver-st/Cargo.toml b/rust/solver-st/Cargo.toml index 57c5098..5ad814a 100644 --- a/rust/solver-st/Cargo.toml +++ b/rust/solver-st/Cargo.toml @@ -10,8 +10,13 @@ crate-type = ["cdylib"] path = "../solver-src/lib.rs" [dependencies] -postflop-solver = { git = "https://github.com/b-inary/postflop-solver", features = ["custom-alloc"], default-features = false } -wasm-bindgen = "0.2.87" +postflop-solver = { path = "../../../postflop-solver-upstream", features = ["custom-alloc"], default-features = false } +wasm-bindgen = "0.2.118" + +[features] +default = [] +rayon = [] +wgpu-backend = ["postflop-solver/wgpu-backend"] [profile.release] codegen-units = 1 diff --git a/rust/tree/.cargo/config.toml b/rust/tree/.cargo/config.toml index 19e88d9..583c53d 100644 --- a/rust/tree/.cargo/config.toml +++ b/rust/tree/.cargo/config.toml @@ -1,5 +1,6 @@ [build] target = "wasm32-unknown-unknown" +rustflags = "-C target-feature=-reference-types" [unstable] build-std = ["panic_abort", "std"] diff --git a/rust/tree/Cargo.lock b/rust/tree/Cargo.lock index 594442d..dc9921f 100644 --- a/rust/tree/Cargo.lock +++ b/rust/tree/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -23,12 +23,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - [[package]] name = "memchr" version = "2.6.3" @@ -37,14 +31,13 @@ checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "once_cell" -version = "1.18.0" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "postflop-solver" version = "0.1.0" -source = "git+https://github.com/b-inary/postflop-solver#9d1509fe5077d019825f833eed04b16d342dfda1" dependencies = [ "once_cell", "regex", @@ -97,6 +90,12 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "syn" version = "2.0.37" @@ -124,34 +123,22 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", "once_cell", - "proc-macro2", - "quote", - "syn", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -159,19 +146,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] diff --git a/rust/tree/Cargo.toml b/rust/tree/Cargo.toml index 529b49b..48f38eb 100644 --- a/rust/tree/Cargo.toml +++ b/rust/tree/Cargo.toml @@ -9,8 +9,8 @@ license = "AGPL-3.0-or-later" crate-type = ["cdylib"] [dependencies] -postflop-solver = { git = "https://github.com/b-inary/postflop-solver", default-features = false } -wasm-bindgen = "0.2.87" +postflop-solver = { path = "../../../postflop-solver-upstream", default-features = false } +wasm-bindgen = "0.2.118" [profile.release] codegen-units = 1 diff --git a/scripts/bench-hybrid.sh b/scripts/bench-hybrid.sh new file mode 100755 index 0000000..fcfb367 --- /dev/null +++ b/scripts/bench-hybrid.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT_DIR/rust/hybrid-lab" + +if [[ "${USE_WGPU:-0}" == "1" ]]; then + cargo run --release --features wgpu-backend -- --depth 5 --branching 3 --hands 220 --actions 4 --iters 300 --align 64 +else + cargo run --release -- --depth 5 --branching 3 --hands 220 --actions 4 --iters 300 --align 64 +fi diff --git a/src/components/App.vue b/src/components/App.vue index f17986e..c05229e 100644 --- a/src/components/App.vue +++ b/src/components/App.vue @@ -1,24 +1,22 @@ @@ -82,7 +71,16 @@ export default defineComponent({ setup() { const store = useStore(); + store.initializeThemeMode(); + const header = computed(() => store.headers[store.sideView].join(" > ")); + const solverViews = [ + { id: "oop-range", component: RangeEditor, props: { player: 0 } }, + { id: "ip-range", component: RangeEditor, props: { player: 1 } }, + { id: "board", component: BoardSelector }, + { id: "tree-config", component: TreeConfig }, + { id: "run-solver", component: RunSolver }, + ]; const clientHeight = ref(0); @@ -99,6 +97,7 @@ export default defineComponent({ return { store, header, + solverViews, clientHeight, }; }, diff --git a/src/components/BoardSelectorCard.vue b/src/components/BoardSelectorCard.vue index d4c32d9..8b1bf9e 100644 --- a/src/components/BoardSelectorCard.vue +++ b/src/components/BoardSelectorCard.vue @@ -4,7 +4,7 @@ 'relative rounded-lg border select-none enabled:shadow ' + (isSelected ? 'bg-yellow-300 ring-1 ring-red-600 border-red-600' - : 'bg-white border-black') + : 'theme-board-card') " :style="{ '--width': width, diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index d78e42a..248d29c 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -1,16 +1,33 @@