You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf(renderer3d): InstantiatePlane collapses identical plane primitives into one instanced draw (#679) (#685)
* perf(renderer3d): add InstantiatePlane to collapse identical plane primitives into one instanced draw (#679)
`CreatePlane` primitives previously bypassed the instancing path so a per-tile
terrain (40k planes / 9 materials) produced 11k+ draw calls. `InstantiatePlane`
mirrors `InstantiateModel` for primitives: every instance that shares the same
source plane renders through a single instanced draw call -- ~9 draws for a
9-material terrain regardless of tile count.
- New `instantiate_plane(source_plane_id) -> u32` engine method backed by a
per-source-plane pool (`PlaneInstancePool`) over the existing
`instanced_meshes` map. Pool grows with `next_power_of_two` capacity, dirty
flush re-uploads once per frame.
- `set_object_position` / rotation / scale and `remove_object` dispatch to the
pool first; `add_object_to_scene` resolves an instance handle to its source
plane so the existing scene API works unchanged.
- Scene filtering for plane-instance pools: a pool only draws when its source
plane is in the current scene.
- New FFI export `goud_renderer3d_instantiate_plane` and schema entry; codegen
regenerated all 9 SDK wrappers.
- 4 new tests: 10k tiles collapse to 1 instanced draw; per-instance transforms
+ remove keep the pool dense; two source planes -> two draw calls; current
scene gates the pool.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(renderer3d): cascade plane-instance pool teardown + skip avoidable clone (#679 review)
Addresses code-quality, security, and spec review feedback on the
InstantiatePlane PR:
- Removing the source plane via destroy_object now tears down its pool
(frees GPU buffers, invalidates every instance handle) so a future
object id reusing the same value cannot route into a stale pool.
- flush_dirty_plane_instance_pools no longer clones the live
instances Vec on the steady-state in-place upload path; uses a
split-borrow with a SAFETY-commented unsafe slice plus a persistent
scratch buffer for the dirty-id list. Grow path uses mem::take/swap
to pad without cloning.
- instantiate_plane drops the .expect() panic; lookup falls back
to None gracefully and reserves the object id only after the
pool lookup succeeds.
- New regression test test_remove_source_plane_cascades_pool_teardown
asserts pool teardown + handle invalidation when the source plane
is destroyed.
- FFI doc + schema doc explain interaction with set_static_batching_enabled,
set_instancing_enabled, and set_min_instances_for_batching for primitives
and InstantiatePlane (spec ask 3 of #679). All SDK wrappers regenerated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(tests): split plane-instance tests into sibling file (#679 CI)
scripts/check-rs-line-limit.sh enforces a 500-line cap on .rs files. The
new plane-instance tests pushed renderer3d/tests.rs to 615 lines, which
made CI's `Rust File Line Limit` job fail. Moved the 5 plane-instance
tests into a sibling `tests_plane_instances.rs` so both files stay under
the cap. No test logic changed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(ffi): re-export goud_renderer3d_instantiate_plane from renderer3d/mod.rs (#679 CI)
The Lua codegen imports `crate::ffi::renderer3d::goud_renderer3d_instantiate_plane`,
which requires it to be re-exported from `ffi/renderer3d/mod.rs` like its
sibling primitive exports. Added it to the `pub use primitives::{...}` list
so `cargo check --workspace --all-targets` (the Preflight CI gate) passes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: ignore .claude/scheduled_tasks.lock runtime artifact
This file is a per-machine lockfile created by Claude Code's ScheduleWakeup
runtime; it should not be tracked in git.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* perf(renderer3d): drop redundant clones + unsafe in plane-instance pool (#679 review)
Addresses Claude PR review warnings on #685:
- W1: source.vertices.clone() now happens only when creating a new pool
(the else branch). Previously it ran on every instantiate_plane call,
costing ~39_991 redundant Vec<f32> allocations during a 40k-tile setup
over 9 source planes.
- W2: replace the unsafe split-borrow + raw pointer slice in
flush_dirty_plane_instance_pools' in-place update path with a safe
field-disjoint borrow. NLL proves self.instanced_meshes and self.backend
don't overlap; the SAFETY comment is no longer needed.
- W3: FFI doc on goud_renderer3d_instantiate_plane now spells out that
the source plane itself still costs one per-object draw on top of the
instanced draw, and recommends frustum exclusion or first-tile reuse.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(ts-web-sdk): add instantiatePlane stub to satisfy IGoudGame (#679 CI)
The web TypeScript SDK doesn't have a real backend for renderer3d, so
codegen/gen_ts_web.py emits hardcoded stubs returning 0/false for every
3D method. The IGoudGame interface requires instantiatePlane (added in
this PR), so the web GoudGame class needs a matching stub or TS2420
fails the wasm build.
Added the stub next to instantiateModel; regenerated all SDKs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: codegen/goud_sdk.schema.json
+14Lines changed: 14 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -5055,6 +5055,17 @@
5055
5055
],
5056
5056
"returns": "u32"
5057
5057
},
5058
+
{
5059
+
"name": "instantiatePlane",
5060
+
"doc": "Creates an instanced plane that shares geometry with a source plane (issue #679). All instances of the same source plane render through one instanced draw call regardless of setStaticBatchingEnabled / setInstancingEnabled / setMinInstancesForBatching (those flags govern non-instanced primitives and skinned models, not plane-instance pools). Use one source plane per material to draw multiple materials. Destroying the source plane cascades: the pool is freed and existing instance handles are invalidated.",
0 commit comments