Files
CFDManager/rust/README.md
T
NotBigGhostandClaude Opus 5 d7881496b0 Сверка документации с кодом: исправлены расхождения
Сплошная проверка документов против дерева. Код не менялся.

docs/rust_vs_cpp.md — числа, снятые с чужого каталога сборки:
- «775 МБ исходников зависимостей» и «10 пакетов в графе C++» получены
  на build/, сконфигурированном из другого дерева (его _deps содержит
  262 МБ nlohmann_json, который проект не объявляет). На деле девять
  объявленных репозиториев дают ~400 МБ исходников;
- пакетов в графе Rust 82, а не 76 (cargo tree по текущему Cargo.lock);
- итог по строкам 2976/494, а не 2962/492: строка «меш» устарела на 17
  строк игнорируемого диагностического теста, тесты в модулях — 176;
- «перевес почти весь в Vulkan-слое» — на деле 346 из 542 (64 %), из них
  305 на Context и Swapchain; остальное приходится на меш, редактор и
  приложение;
- «ни один замер не даёт разницы в порядок величины» неверно:
  инкрементальная release — 52.3 против 4.4 с, это 11.9x;
- граней с пятью и более вершинами в plane.obj 119, а не 121;
- из Catch2 перенесены все три случая, и добавлено ещё два, а не
  «три перенесены дословно»;
- деструктор Renderer::Impl — 22 строки, а не тридцать;
- путевых зависимостей у порта две: assets/meshes с откатом на текущий
  каталог и pipeline_cache.bin рядом с бинарём;
- граф целей CMake ацикличен, цикл существует на уровне исходников —
  именно поэтому CMake и молчит.

rust/README.md:
- объявленный rust-version = "1.82" недостижим: залоченные egui,
  egui-winit и epaint 0.36.1 требуют 1.95;
- перечни зависимостей крейтов были неполны, приведены целиком;
- build.rs читает ../../../shaders, а не ../../shaders;
- тесты не «чистая математика»: тесты загрузчика читают файлы из
  assets/meshes и требуют клон репозитория;
- assets/ порту никто не копирует, он находит корневую копию сам;
- те же поправки про цикл в CMake и про момент ожидания простоя.

README.md:
- панель называется Mesh, а не «Mesh load»;
- пресета clang-cl не существует, компилятор пресеты не фиксируют;
- версии Vulkan SDK и компиляторов сборкой не проверяются;
- Buffer и Image перечислены среди рабочих модулей vk/, хотя ими не
  пользуется никто.

docs/theory/solver_2x_sdf/README.md:
- предлагался несуществующий переключатель cfg.collision="bgk" и реестр
  операторов get; тот же файл двумя разделами ниже говорит, что оператор
  зафиксирован.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 14:11:06 +03:00

114 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SimVulcan на Rust
Порт редактора `SimVulcan` с C++20 на Rust. Делает то же самое: орбитальная камера над
тремя опорными плоскостями сетки, цветные оси XYZ, загрузка `.obj` и три режима
отображения модели. Тот же Vulkan 1.3 с динамическим рендерингом и synchronization2,
те же шейдеры.
Существует ради сравнения: обе версии лежат в репозитории рядом и собираются
независимо. Разбор различий с цифрами — в [`../docs/rust_vs_cpp.md`](../docs/rust_vs_cpp.md).
## Требования
* Rust 1.95+ (проверялось на 1.97.1). В `Cargo.toml` объявлено `rust-version = "1.82"`,
но это значение недостижимо: залоченные `egui`, `egui-winit` и `epaint` 0.36.1 сами
требуют 1.95, и на 1.82 Cargo обрывается на разрешении зависимостей
* Vulkan SDK 1.3.290+ — нужен только `glslangValidator` для сборки шейдеров
(ищется в `%VULKAN_SDK%\Bin`, затем в `PATH`)
* Драйвер Vulkan 1.3 с `fillModeNonSolid`
## Сборка и запуск
```sh
cd rust
cargo build --release
./target/release/SimVulcan
```
Запускать можно из любого каталога. Шейдеры вшиты в исполняемый файл на этапе сборки,
а `assets/meshes` ищется подъёмом по предкам от самого бинаря и только затем — от
текущего каталога; в отличие от C++-версии, которой нужен запуск из её собственного
каталога. В отличие от неё же, `assets/` никуда не копируется: порт находит копию в
корне репозитория, поднимаясь от `target/<профиль>/`.
Рядом с исполняемым файлом создаётся `pipeline_cache.bin` — сериализованный
`VkPipelineCache`, он перечитывается при следующем запуске. Файл одноразовый: если
конвейеры повели себя странно, его можно удалить.
Слой валидации Khronos запрашивается во всех конфигурациях, включая `--release`, — как
и в C++-версии. Если слоя нет, приложение об этом предупредит и пойдёт дальше.
**Для работы над кодом собирайте `cargo build` без `--release`.** В профиле выпуска стоит
`lto = "thin"`, и правка одной строки заставляет заново оптимизировать и слинковать весь
бинарь: 52 секунды против 5 в отладочной сборке. Замеры — в
[`../docs/rust_vs_cpp.md`](../docs/rust_vs_cpp.md).
## Тесты
```sh
cargo test
```
Видеокарта не нужна: габариты меша, сварка вершин (три случая), чтение `Cube.obj` и его
путь ошибки, пространство отсечения камеры и ограничители наклона и приближения,
разбор категорий журнала — тринадцать тестов плюс один помеченный `#[ignore]`
диагностический, тот самый, которым получена таблица расхождения загрузчиков. Чистой
математикой это, впрочем, не является: тесты загрузчика читают настоящие файлы из
`assets/meshes` через `$CARGO_MANIFEST_DIR`, поэтому им нужен рабочий клон репозитория.
Тесты живут прямо в модулях (`#[cfg(test)] mod tests`), отдельной цели под них нет.
## Раскладка
Пять крейтов повторяют карту целей CMake из корня репозитория:
Ниже перечислены сторонние зависимости; вдобавок каждый крейт зависит от тех крейтов
рабочего пространства, что указаны в скобках.
```
crates/simv-core/ журнал с категориями, окно → log, chrono, winit
crates/simv-mesh/ чтение .obj, сварка, габариты → glam, tobj, log, thiserror
(+ simv-core)
crates/simv-vk/ весь Vulkan + build.rs → ash, ash-window, raw-window-handle,
(GLSL → SPIR-V) gpu-allocator, egui, egui-winit,
egui-ash-renderer, winit, glam,
bytemuck, log, thiserror
(+ simv-core, simv-mesh)
crates/simv-editor/ камера, ввод, панели → egui, glam, log
(+ simv-core, simv-mesh)
crates/simv-app/ App и точка входа → четыре крейта выше
+ egui, winit, glam, log, anyhow
```
Главный инвариант проекта — «весь Vulkan живёт в одном месте» — здесь проверяет
компилятор: у `simv-mesh` и `simv-editor` в зависимостях нет ни `ash`, ни `simv-vk`,
так что нарушить границу нельзя даже по невнимательности.
Шейдеры общие с C++-версией: `build.rs` крейта `simv-vk` компилирует
`../../../shaders/editor/*.{vert,frag}` тем же `glslangValidator -V --target-env vulkan1.3`
и кладёт SPIR-V в `OUT_DIR`, откуда он попадает в бинарь через `include_bytes!`.
## Чем отличается от C++-версии
Снаружи — почти ничем, кроме внешнего вида панелей: вместо Dear ImGui взят **egui**.
Причина: крейт `imgui` — это биндинги, и сборка всё равно тянула бы за собой исходники
Dear ImGui на C++, что обесценило бы сравнение.
Внутри отличия сведены в отдельный документ, здесь только самые заметные:
* **`App` живёт в исполняемом крейте**, а не в `simv-core`. В C++ цикличны исходники
(`core::App` владеет `vk::Renderer`, `vk::Renderer` принимает `core::Window&`), тогда
как граф целей CMake ацикличен — потому CMake и молчит: `simv_vk` не линкует
`simv_core`, а лишь видит его заголовки, и символы `Window` находятся при сборке
исполняемого файла. Cargo такую схему отвергает.
* **Состояние сцены возвращается из замыкания интерфейса**, а не ставится сеттерами.
Замыкание вызывается из метода рендерера, поэтому трогать рендерер оттуда нельзя.
* **Загруженный меш выгружается на видеокарту после кадра**, а не изнутри него, как в
C++, где колбэк панели дёргает `vkDeviceWaitIdle` уже после захвата образа цепочки
показа — хотя запись команд там ещё не началась, `vkBeginCommandBuffer` идёт позже.
* **`Buffer` и `Image` задействованы.** В C++ обе обёртки собираются в цель `simv_vk`, но
ими не пользуется никто.
* **Нет pImpl.** Приватные поля модуля дают ту же изоляцию, ради которой в C++ заведён
`struct Renderer::Impl`.
* **Цикл событий принадлежит winit.** `ShouldClose`/`PollEvents` заменены методами
`ApplicationHandler`.