simvx.graphics.scene_adapter¶
Adapter to bridge SceneTree nodes to Renderer submissions.
Module Contents¶
Classes¶
Bridges SceneTree to Renderer (Vulkan). |
Functions¶
|
Data¶
API¶
- simvx.graphics.scene_adapter.__all__¶
[‘SceneAdapter’]
- simvx.graphics.scene_adapter.log¶
‘getLogger(…)’
- simvx.graphics.scene_adapter.find_all_outside_subviewports(root: simvx.core.Node, node_type: type) list[source]¶
find_allthat does NOT descend intoSubViewportsubtrees.A SubViewport’s children render into the viewport’s own offscreen target (driven by
SubViewportManager), so a main-pass collection must not also pick them up: a plainroot.find_allwould double-submit them (aMultiMeshInstance3Dinside a SubViewport would draw in both the main pass and the offscreen pass). Mirrors the SubViewport boundary in_collect_nodes. The root itself is never skipped, so collecting a SubViewport’s own contents (root == that SubViewport) still works; nested SubViewports are pruned.
- class simvx.graphics.scene_adapter.SceneAdapter(engine: simvx.graphics.engine_surface.EngineSurface, renderer: Any)[source]¶
Bridges SceneTree to Renderer (Vulkan).
Responsibilities:
Register meshes with the GPU
Convert materials to Vulkan format
Traverse scene tree and submit instances
Initialization
- property offload_coordinator: Any[source]¶
The D8 :class:
SRUOffloadCoordinator, orNone(single-GPU/unopted).Built once, lazily, from
engine.multi_device: a coordinator exists only when that manager reports an active multi-device renderer. On every single-GPU box (and any box that did not opt in) this isNone, so the SRU recording seam’scoordinator is Nonebranch keeps the path byte-identical to today.
- plan_sru_offload(srus: list, *, sru_id: Any = None, cost: Any = None) None[source]¶
Compute this frame’s per-SRU device routes (no-op without a coordinator).
Called once per frame on the ORDERED SRU list (producer-first) before the SRUs are recorded, so the per-SRU :meth:
render_to_target/- Meth:
render_sru_from_plancan look up their route. Pure decision work; no Vulkan. On the single-GPU / unopted path there is no coordinator and this returns immediately, leaving every SRU on the primary (today’s path).
sru_id/costaccessors are forwarded to the coordinator for the synchronous path, whose ordered items are live SubViewport nodes rather than :class:SubViewportSRUplans.
- register_mesh(mesh: Any) Any | None[source]¶
Register mesh with Vulkan engine, return MeshHandle.
Returns None if the mesh has no vertex data (skipped gracefully).
- register_skinned_mesh(mesh: Any) Any | None[source]¶
Register skinned mesh with Vulkan engine, return MeshHandle.
Returns None if the mesh has no vertex data.
- submit_scene(tree: simvx.core.SceneTree, *, submit_lights: bool = True, submit_2d: bool = True) None[source]¶
Walk scene tree and submit instances to renderer.
Performs a single tree traversal to collect all renderable node types, then passes the pre-collected lists to individual submission methods.
Gracefully handles scenes with no Camera3D (e.g. editor UI-only scenes) by skipping 3D submission while still processing 2D overlays.
submit_lightsis False for offscreen scene-render units (SubViewport / reflection-probe faces): the engine keeps a single shared light SSBO, so in the single-submit multi-scene frame only one light set can survive. The main scene owns it; offscreen SRUs render with the main scene’s lights (a known limitation). Skipping the upload also keeps the main scene’s light buffer intact without a re-submit.submit_2dis False for a RenderView SRU: it re-submits the MAIN tree (already submitted this frame), and the 2D overlay submits are per-frame APPENDS to shared renderer lists (particles, tilemap layers, 2D lights), so running them a second time would double that content in the main pass. A RenderView captures the 3D world only.
- resolve_2d_textures(root: simvx.core.Node) None[source]¶
Resolve Sprite2D / NinePatchRect textures under
root.The item-pipeline RTT-2D collector needs a SubViewport subtree’s sprite
_texture_idpopulated BEFORE it captureson_draw(a sprite whose texture is still-1emits nothing, so the collected item view would be empty and stay cached empty –_texture_idis not a Property, so it fires no invalidation). The main pass resolves its own sprites insubmit_sceneAFTER the item collection runs, and that walk prunes SubViewports anyway – so a SubViewport’s 2D sprites are resolved here, from the viewport’s own root. Idempotent: an already-resolved sprite (_texture_id >= 0) and a live SubViewport source are both skipped.
- render_to_target(cmd, target, tree: simvx.core.SceneTree, *, camera=None, screen_size: tuple[float, float] | None = None, draw2d_ops: list | None = None, item_2d: tuple | None = None, sru_id: int = 0, submit_2d: bool = True, occlusion: Any = None) None[source]¶
Record one offscreen scene-render unit (SRU) into the shared command buffer.
Single-submit slice model (no per-scene
begin_frame/ submit / wait): the offscreen scene’s instances are submitted into an isolated list, a contiguous slice of the shared transform SSBO is reserved for them, their transforms are written into that slice, and their draws are recorded with absolutefirst_instanceindices into the same primarycmdthat the main frame uses. The main scene’s per-frame submission lists are saved and restored around this call so its base-0 slice is untouched: the whole frame still ends in exactly ONEvkQueueSubmit.The offscreen colour target is written here and sampled by the main pass later in the same command buffer;
RenderTargetleaves it inSHADER_READ_ONLY_OPTIMAL(its end-of-pass store + image-layout transition is an in-cmd barrier), so the within-frame write-then-sample ordering is valid without any queue wait.Args: cmd: The frame’s primary Vulkan command buffer (from pre_render). target: Offscreen render target with begin_pass/end_pass/width/height/ready. tree: SceneTree (or _SubTreeView) to render. camera: Optional camera override (e.g. probe face / editor orbit camera). screen_size: Optional 2D screen size override (for 2D viewport rendering). draw2d_ops: Pre-extracted Draw2D ops to render as a 2D overlay. sru_id: Stable identity of this SRU (SubViewport node id / probe-face id), used to key the frustum visibility cache so SRUs never collide. submit_2d: Forwarded to :meth:
submit_scene. False for a RenderView SRU, whose re-submit of the already-submitted MAIN tree must not append the tree’s 2D overlays into the shared per-frame lists a second time (they would double in the main pass). occlusion: Optional per-view :class:~.renderer.view_occlusion.ViewOcclusionbundle (use_occlusion=Trueon the node). When given, the SRU’s transforms upload their AABBs and the view’s own two-phase Hi-Z cull is recorded before its colour pass, so the SRU render draws from the culled indirect batches.None(the default) records exactly the historical un-culled SRU.
- render_sru_from_plan(cmd, sru) None[source]¶
Record one SubViewport SRU from an OWNED packet plan (pipelined render thread).
The render-thread counterpart of :meth:
render_to_target: instead of walking the live tree (illegal on the render thread, the main thread owns it) it replays a :class:~.renderer.render_packet.SubViewportSRUsnapshot captured on the main thread by :meth:SubViewportManager.build_srus.It isolates the renderer’s main-scene per-frame instance lists + viewport (already installed from the packet for the main pass), binds the SRU’s OWNED instances + single camera viewport, reserves a slice of the shared transform SSBO, writes those transforms, records
render_scene_contentinto the SRU’s offscreen target with absolutefirst_instanceindices, overlays the SRU’s isolated Draw2D ops, and restores the main-scene state. The whole frame still ends in onevkQueueSubmit; the offscreen colour write is made visible to the main pass’s later sample by the render target’s end-of-pass layout transition (same asrender_to_target).
- snapshot_sru(tree: simvx.core.SceneTree, *, camera=None, screen_size: tuple[float, float] | None = None) tuple[list, list, Any, Any, list, list][source]¶
Submit an offscreen SRU’s scene into isolated lists and return OWNED copies.
The CPU-only, no-GPU counterpart of :meth:
render_to_target: it sets the same tree overrides (viewport rect / camera / screen size), runssubmit_sceneinto temporarily-isolated per-frame lists, then copies the resulting opaque / skinned instances and the SRU camera’s view + projection matrices, and restores the renderer + tree state. No slice reservation, no transform upload, no draw recording happens here: that is the render thread’s job from the returned plan. Used by- Meth:
SubViewportManager.build_srusto packetise SubViewports.
Returns
(instances, skinned_instances, camera_view, camera_proj, multimesh_blocks, billboard_submissions)where the instance lists, MultiMesh blocks, and billboard rows own copies of their transform / joint arrays and the matrices are owned copies (orNonefor a 2D-only SRU with no 3D camera viewport).