Сверка документации с кодом: исправлены расхождения

Сплошная проверка документов против дерева. Код не менялся.

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>
This commit is contained in:
2026-09-16 14:11:06 +03:00
co-authored by Claude Opus 5
parent fe5ca7f936
commit d7881496b0
4 changed files with 101 additions and 56 deletions
+38 -20
View File
@@ -10,7 +10,9 @@
## Требования
* Rust 1.82+ (проверялось на 1.97.1)
* 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`
@@ -24,8 +26,10 @@ cargo build --release
```
Запускать можно из любого каталога. Шейдеры вшиты в исполняемый файл на этапе сборки,
а `assets/meshes` ищется подъёмом по предкам от самого бинаря — в отличие от
C++-версии, которой нужен запуск из её собственного каталога.
а `assets/meshes` ищется подъёмом по предкам от самого бинаря и только затем — от
текущего каталога; в отличие от C++-версии, которой нужен запуск из её собственного
каталога. В отличие от неё же, `assets/` никуда не копируется: порт находит копию в
корне репозитория, поднимаясь от `target/<профиль>/`.
Рядом с исполняемым файлом создаётся `pipeline_cache.bin` — сериализованный
`VkPipelineCache`, он перечитывается при следующем запуске. Файл одноразовый: если
@@ -45,21 +49,34 @@ C++-версии, которой нужен запуск из её собств
cargo test
```
Чистая математика без видеокарты: габариты меша, сварка вершин, чтение `Cube.obj`,
пространство отсечения камеры. Тесты живут прямо в модулях (`#[cfg(test)] mod tests`),
отдельной цели под них нет.
Видеокарта не нужна: габариты меша, сварка вершин (три случая), чтение `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
crates/simv-vk/ весь Vulkan + build.rs (GLSL → SPIR-V) → ash, gpu-allocator,
egui-ash-renderer
crates/simv-editor/ камера, ввод, панели → egui
crates/simv-app/ App и точка входа → всё вышеперечисленное
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 живёт в одном месте» — здесь проверяет
@@ -67,7 +84,7 @@ crates/simv-app/ App и точка входа
так что нарушить границу нельзя даже по невнимательности.
Шейдеры общие с C++-версией: `build.rs` крейта `simv-vk` компилирует
`../../shaders/editor/*.{vert,frag}` тем же `glslangValidator -V --target-env vulkan1.3`
`../../../shaders/editor/*.{vert,frag}` тем же `glslangValidator -V --target-env vulkan1.3`
и кладёт SPIR-V в `OUT_DIR`, откуда он попадает в бинарь через `include_bytes!`.
## Чем отличается от C++-версии
@@ -78,15 +95,16 @@ Dear ImGui на C++, что обесценило бы сравнение.
Внутри отличия сведены в отдельный документ, здесь только самые заметные:
* **`App` живёт в исполняемом крейте**, а не в `simv-core`. В C++ граф целей цикличен
(`core::App` владеет `vk::Renderer`, `vk::Renderer` принимает `core::Window&`), и
держится это лишь на том, что `simv_vk` не линкует `simv_core`, а видит его заголовки.
Cargo цикл между крейтами отвергает.
* **`App` живёт в исполняемом крейте**, а не в `simv-core`. В C++ цикличны исходники
(`core::App` владеет `vk::Renderer`, `vk::Renderer` принимает `core::Window&`), тогда
как граф целей CMake ацикличен — потому CMake и молчит: `simv_vk` не линкует
`simv_core`, а лишь видит его заголовки, и символы `Window` находятся при сборке
исполняемого файла. Cargo такую схему отвергает.
* **Состояние сцены возвращается из замыкания интерфейса**, а не ставится сеттерами.
Замыкание вызывается из метода рендерера, поэтому трогать рендерер оттуда нельзя.
* **Загруженный меш выгружается на видеокарту после кадра**, а не из середины записи
команд, как в C++, где колбэк панели дёргает `vkDeviceWaitIdle` уже после захвата
образа цепочки показа.
* **Загруженный меш выгружается на видеокарту после кадра**, а не изнутри него, как в
C++, где колбэк панели дёргает `vkDeviceWaitIdle` уже после захвата образа цепочки
показа — хотя запись команд там ещё не началась, `vkBeginCommandBuffer` идёт позже.
* **`Buffer` и `Image` задействованы.** В C++ обе обёртки собираются в цель `simv_vk`, но
ими не пользуется никто.
* **Нет pImpl.** Приватные поля модуля дают ту же изоляцию, ради которой в C++ заведён