Skip to documentation
SLOP

tiny.sdfii.Engine

Reference tiny.sdfii Engine

Defined in tiny.sdfii.

API (128)

Actions

Public operations.

Types and contracts

Public types and contracts.

No direct callersNo direct callstiny.sdfiiEngine
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: fun/sdfii/src/engine/system/ui/command.zig:20

zig
pub const ActivationEvent = struct {    sequence: u64,    frame_index: u64,    root_id: u64,    widget_id: u64,    action: []const u8,};

Source: fun/sdfii/src/engine/system/ui/command.zig:101

zig
pub const Command = union(enum) {    publish_surface: SurfacePublish,    publish_native_surface: NativeSurfacePublish,    retract_surface: u64,    pointer_event: PointerEvent,    scroll_event: ScrollEvent,    key_event: KeyEvent,    text_event: TextEvent,    text_selection_event: TextSelectionUpdate,};

Source: fun/sdfii/src/engine/system/ui/command.zig:8

zig
pub const PointerEventKind = enum(u8) {    move,    down,    up,};

Source: fun/sdfii/src/engine/system/ui/command.zig:28

zig
pub const TextEditEvent = struct {    sequence: u64,    frame_index: u64,    root_id: u64,    widget_id: u64,    kind: TextEditKind,    text: []const u8,};

Source: fun/sdfii/src/engine/system/ui/command.zig:37

zig
pub const TextPointEvent = struct {    sequence: u64,    frame_index: u64,    root_id: u64,    widget_id: u64,    kind: PointerEventKind,    x: f32,    y: f32,    local_x: f32,    local_y: f32,    anchor_x: f32,    anchor_y: f32,    anchor_local_x: f32,    anchor_local_y: f32,};

Source: fun/sdfii/src/engine/system/ui/command.zig:53

zig
pub const TextSelectionUpdate = struct {    root_id: u64,    widget_id: u64,    cursor_visible: bool,    cursor_byte_offset: usize,    selection_active: bool,    selection_anchor_byte_offset: usize,    selection_focus_byte_offset: usize,};

Source: fun/sdfii/src/engine/system/ui/ownership/capacity.zig:49

zig
pub const Capacity = struct {    surfaces: usize,    placements: usize,    surface: surface.Capacity,    entries_offset: usize,    entries_bytes: usize,    placements_offset: usize,    placements_bytes: usize,    clone_offset: usize,    clone_stride: usize,    clone_bytes: usize,    storage_bytes: usize,    pub fn derive(limits: Limits) DeriveError!Capacity {        if (limits.surfaces == 0) return error.InvalidSurfaceLimit;        const placement_count = std.math.add(usize, limits.surfaces, 1) catch            return error.CapacityOverflow;        const surface_capacity = try surface.Capacity.derive(limits.surface);        const entries = try placed(Entry, 0, limits.surfaces);        const placements = try placed(surface.Placement, entries.end, placement_count);        const clone_offset = try aligned(placements.end, surface.storage_alignment);        const clone_stride = try aligned(surface_capacity.storage_bytes, surface.storage_alignment);        const clone_bytes = std.math.mul(usize, placement_count, clone_stride) catch            return error.CapacityOverflow;        const storage_bytes = std.math.add(usize, clone_offset, clone_bytes) catch            return error.CapacityOverflow;        return .{            .surfaces = limits.surfaces,            .placements = placement_count,            .surface = surface_capacity,            .entries_offset = entries.start,            .entries_bytes = entries.bytes,            .placements_offset = placements.start,            .placements_bytes = placements.bytes,            .clone_offset = clone_offset,            .clone_stride = clone_stride,            .clone_bytes = clone_bytes,            .storage_bytes = storage_bytes,        };    }};

Source: fun/sdfii/src/engine/system/ui/ownership/capacity.zig:27

zig
pub const Limits = struct {    surfaces: usize = default_surface_count,    surface: surface.Limits = .{        .nodes = default_nodes_per_surface,        .runs = default_runs_per_surface,        .styles = default_styles_per_surface,        .images = default_images_per_surface,        .image_pixels = default_image_pixels_per_surface,        .semantic_bytes = default_semantic_bytes_per_surface,    },};

Source: fun/sdfii/src/engine/system/ui/ownership/capacity.zig:14

zig
pub const SurfaceState = struct {    revision: u64,    tree: *const gui.model.UiSurfaceTree,    images: gui.model.UiImageSet,};

Source: fun/sdfii/src/engine/system/ui/ownership/store.zig:12

zig
pub const Status = struct {    capacity: capacity_mod.Capacity,    surface_count: usize,    free_surfaces: usize,    free_placements: usize,};
Called byCallsNo direct callersprivate; no linkfun.sdfii.src.backend.accy.executorbindprivate; no linkfun.sdfii.src.backend.accy.executorcapabilitiesprivate; no linkfun.sdfii.src.ffi.types.CompiledArtifactSummaryfromprivate; no linkfun.sdfii.src.ffi.typesbackendKindFromRawprivate; no linkfun.sdfii.src.ffi.typesboolFromFlagEnginebindAcousticExecutor
Static calls · unresolved targets: 0 · external targets: 5.
Called byCallsNo direct callsprivate; no linkfun.sdfii.src.engine.enginecaptureCommittedFrameProductsprivate; no linkfun.sdfii.src.engine.engineexpectActiveSceneAgreementEnginecurrentQueryRevision
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callstest; no linkfun.sdfii.src.engine.abi.scene.testtest: push scene low-level API replac...tiny.guipaint.Compositordeinittiny.quicconnection.Connectiondeinitprivate sourcelib.quic.src.properties.tls.DecoderTotalitypropertytiny.sqlhistory.repairrepair+11 moreEnginedeinit
Static calls · unresolved targets: 0 · external targets: 19.
Called byCallsprivate; no linkfun.sdfii.src.engine.abi.physicspreparePhysicsVjpTestSceneprivate; no linkfun.sdfii.src.engine.stepframeEngineframeStep
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersEngineinitFallibleEngineinit
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsEngineinitEngineinitFallible
Static calls · unresolved targets: 5 · external targets: 9.
Called byCallsNo direct callsprivate; no linkfun.sdfii.src.engine.system.scene.transactioncompileEngineinvalidateSceneDerivations
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallsNo direct callsprivate; no linkfun.sdfii.src.engine.enginepublishRawDeviceEventForTestEnginepublishInputCommand
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callsprivate; no linkfun.sdfii.src.engine.enginepublishInputCaptureSurfaceForTestEnginepublishUiSurface
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callsprivate; no linkfun.sdfii.src.engine.enginecaptureCommittedFrameProductsEnginereadRenderFrame
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callsprivate; no linkfun.sdfii.src.engine.enginecaptureCommittedFrameProductsprivate; no linkfun.sdfii.src.engine.engineexpectActiveSceneAgreementEnginereadRenderRuntime
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callstest; no linkfun.sdfii.src.engine.abi.scene.testtest: push scene low-level API replac...EnginereadSceneEditPublished
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callsprivate; no linkfun.sdfii.src.engine.enginecaptureCommittedFrameProductsprivate; no linkfun.sdfii.src.engine.engineexpectActiveSceneAgreementEnginereadSceneRuntime
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callstest; no linkfun.sdfii.src.engine.abi.scene.testtest: push scene low-level API replac...EnginesceneEditRevision
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersprivate; no linkfun.sdfii.src.engine.engineencodeMaterialBlobEngineupsertEntityMaterial
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsprivate; no linkfun.sdfii.src.engine.enginestepInputCaptureFrameForTestprivate; no linkfun.sdfii.src.engine.stepworldEngineworldStep
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest; no linkfun.sdfii.src.engine.system.ui.ownership.capa...test: SDFII UI surface store capacity...test; no linkfun.sdfii.src.engine.system.ui.ownership.capa...test: SDFII UI surface store capacity...private; no linkfun.sdfii.src.engine.system.ui.ownership.capa...alignedprivate; no linkfun.sdfii.src.engine.system.ui.ownership.capa...placedEngine.UiCapacityderive
Static calls · unresolved targets: 0 · external targets: 1.

Source: fun/sdfii/src/engine/system/ui/ownership/store.zig:10

zig
pub const StoreError = surface.CloneError || error{SurfaceStoreFull};

Source: fun/sdfii/src/engine/system/world/dirty.zig:8

zig
pub const edits_column: u32 = 803;

Source: fun/sdfii/src/engine/system/world/dirty.zig:6

zig
pub const material_column: u32 = 801;

Source: fun/sdfii/src/engine/system/world/dirty.zig:7

zig
pub const scene_resource_column: u32 = 802;

Source: fun/sdfii/src/engine/system/world/dirty.zig:5

zig
pub const shape_column: u32 = 800;

Source: fun/sdfii/src/engine/engine.zig

zig
const std = @import("std");const Self = @This();const WorldStore = @import("sdfii_world").store;const WorldSave = @import("sdfii_world").save;const sdfii_assets = @import("sdfii_assets");const AssetRegistry = sdfii_assets.registry;const ShapeAsset = sdfii_assets.ShapeAsset;const asset_reload = sdfii_assets.hot_reload;const SceneArtifact = @import("sdfii_scene").artifact;const Compiler = @import("sdfii_scene").compiler;const ScenePublish = @import("sdfii_scene").publish;const SceneRuntime = @import("sdfii_scene").runtime;const SceneOwnership = @import("sdfii_scene").ownership;const QueryService = @import("sdfii_query").service;const Raymarch = @import("sdfii_raymarch");const BackendExecutor = @import("sdfii_backend").executor;const BackendRuntime = @import("sdfii_backend").runtime;const Router = @import("sdfii_backend").router;const BehaviorRuntime = @import("system/root.zig").behavior.runtime;const Schema = @import("sdfii_world").schema;const WorldCommands = @import("sdfii_world").commands;const types = @import("sdfii_ffi").types;const runtime_shape = @import("system/root.zig").shape;const shape_api = runtime_shape.api;const shape_binding = runtime_shape.binding;const runtime_world = @import("system/root.zig").world;const world_dirty = runtime_world.dirty;const world_session = runtime_world.session;const WorldPlaySession = world_session.PlaySession;const PhysicsRuntime = @import("sdfii_physics").runtime;const PhysicsWorld = @import("sdfii_physics").world;const curve = @import("rig").curve;const AnimationRuntime = @import("system/root.zig").animation.runtime;const ControllerComponent = @import("system/root.zig").animation.controller;const InputRuntime = @import("system/root.zig").input.runtime;const UiInputBindings = @import("system/root.zig").input.binding.Bindings;const Ui = @import("system/root.zig").ui;const AudioRuntime = @import("system/root.zig").audio.runtime;const CommandSink = @import("command/root.zig").sink;const frame_mod = @import("sdfii_frame");const FrameClock = frame_mod.time;const InputState = frame_mod.input;const frame_system = @import("system/root.zig").frame;const runtime_render = @import("system/root.zig").render;const render_config = runtime_render.config;const step = @import("step.zig");const PhysicsScratch = @import("system/root.zig").physics.scratch.Store;pub const HandlerRegistry = BehaviorRuntime.HandlerRegistry;pub const ScenePublication = SceneRuntime.Publication;pub const InputCommand = InputRuntime.Command;pub const ClientInputSnapshot = InputRuntime.ClientSnapshot;pub const RenderRuntimeSnapshot = BackendRuntime.Snapshot;pub const RenderFrameView = BackendRuntime.FrameView;pub const RenderFrameRgba8State = BackendRuntime.Rgba8State;pub const SceneRuntimeSnapshot = SceneRuntime.Snapshot;pub const SceneAuthoringGap = SceneRuntime.AuthoringGap;pub const UiPointerEventKind = Ui.PointerEventKind;pub const UiSurface = Ui.UiSurface;pub const UiSurfaceTree = Ui.UiSurfaceTree;pub const UiCommand = Ui.Command;pub const UiPublishedFrame = Ui.UiPublishedFrame;pub const UiActivationEvent = Ui.ActivationEvent;pub const UiTextEditEvent = Ui.TextEditEvent;pub const UiTextPointEvent = Ui.TextPointEvent;pub const UiTextSelectionUpdate = Ui.TextSelectionUpdate;pub const UiLimits = Ui.Limits;pub const UiCapacity = Ui.Capacity;pub const UiStorageStatus = Ui.StorageStatus;pub const UiStorageExhaustion = Ui.StorageExhaustion;pub const UiSurfaceState = Ui.SurfaceState;pub const AudioCommand = AudioRuntime.Command;pub const AudioAssetKind = AudioRuntime.AssetKind;pub const AudioPlaybackMode = AudioRuntime.PlaybackMode;pub const AudioPlaybackState = AudioRuntime.PlaybackState;pub const AudioOutputKind = AudioRuntime.OutputKind;pub const AudioListenerPose = AudioRuntime.ListenerPose;pub const AudioAsset = AudioRuntime.Asset;pub const AudioTransport = AudioRuntime.Transport;pub const AudioOutput = AudioRuntime.Output;pub const AudioRuntimeSnapshot = AudioRuntime.Snapshot;pub const AudioPlaybackSnapshot = AudioRuntime.PlaybackSnapshot;pub const PhysicsScratchLimits = struct {    program_nodes: usize,};pub const Limits = struct {    entity_capacity: u32,    physics_scratch: PhysicsScratchLimits,    ui: UiLimits = .{},};pub const PhysicsScratchCapacity = PhysicsScratch.Capacity;pub const PhysicsScratchStatus = @import("system/root.zig").physics.scratch.Status;pub const AudioEmitterAcousticsSnapshot = AudioRuntime.EmitterAcousticsSnapshot;pub const PhysicsStepContext = struct {    frame_index: u64 = 0,    dt_s: f64 = 0,    collision_revision: u64 = 0,    collision_published: ?*const Compiler.PublishedRevision = null,};pub const PhysicsRuntimeSnapshot = struct {    synced_revision: u64 = 0,    fixed_step_count: u32 = 0,    step_ns: u64 = 0,    body_pose_count: usize = 0,    contact_count: usize = 0,};pub const BehaviorRuntimeSnapshot = struct {    step_ns: u64 = 0,    executed_component_count: usize = 0,    counter_after: i64 = 0,};pub const DIRTY_COL_SHAPE: u32 = world_dirty.shape_column;pub const DIRTY_COL_MATERIAL: u32 = world_dirty.material_column;pub const DIRTY_COL_SCENE_RESOURCE: u32 = world_dirty.scene_resource_column;pub const DIRTY_COL_EDITS: u32 = world_dirty.edits_column;pub const CurrentPublishedScene = struct {    value: Compiler.PublishedRevision = .{},    has_value: bool = false,    pub fn ptr(self: *const CurrentPublishedScene) ?*const Compiler.PublishedRevision {        return if (self.has_value) &self.value else null;    }};allocator: std.mem.Allocator,artifact_allocator: std.mem.Allocator,world: WorldStore,assets: AssetRegistry = .{},compiler: Compiler = .{},queries: QueryService = .{},backend: Router = .{},renderer: BackendRuntime.Runtime,scene: SceneRuntime.Runtime,input: InputRuntime.Runtime = .{},ui_input_bindings: UiInputBindings = .{},ui: Ui.Runtime,audio: AudioRuntime.Runtime,compiled_artifact: ?SceneArtifact.CompiledArtifact = null,handler_registry: HandlerRegistry = .{},pixel_buffer: ?[]types.FramePixel = null,graphics_buffer: ?[]u8 = null,pixel_width: u32 = 0,pixel_height: u32 = 0,render_preference: types.BackendPreference = .auto,requested_backend: types.BackendKind = .none,render_style: BackendExecutor.RenderStyle = .{},render_palette: []BackendExecutor.PaletteColor = &.{},graphics_requested: bool = false,last_compile_tick: u64 = 0,last_diagnostics: types.FrameDiagnostics = .{},last_frame_context: frame_mod.FrameContext = .{},frame_history: frame_mod.history.History = .{},frame_allocations: frame_mod.allocator.Telemetry = .{},play_session: ?WorldPlaySession = null,scene_compile: SceneOwnership.CompileDomain,collision_compile: SceneOwnership.CompileDomain,artifact_arena: std.heap.ArenaAllocator,physics_scratch: PhysicsScratch,clock: FrameClock = .{},last_input: InputState = .{},behavior: BehaviorRuntime = .{},physics: PhysicsRuntime = .{},animation: AnimationRuntime = .{},physics_snapshot: PhysicsRuntimeSnapshot = .{},behavior_snapshot: BehaviorRuntimeSnapshot = .{},last_task_run: step.TaskRun = .{},phase_count: usize = 0,pub fn init(allocator: std.mem.Allocator, limits: Limits) Self {    return initFallible(allocator, limits) catch unreachable;}pub fn initFallible(allocator: std.mem.Allocator, limits: Limits) !Self {    var world = try WorldStore.init(allocator, limits.entity_capacity);    errdefer world.deinit();    var physics_scratch = try PhysicsScratch.init(allocator, .{        .bodies = world.entities.capacity,        .program_nodes = limits.physics_scratch.program_nodes,    });    errdefer physics_scratch.deinit(allocator);    var ui_runtime = try Ui.Runtime.init(allocator, limits.ui);    errdefer ui_runtime.deinit();    var self = Self{        .allocator = allocator,        .artifact_allocator = allocator,        .world = world,        .backend = Router.initWithAllocator(allocator),        .renderer = BackendRuntime.Runtime.init(allocator),        .scene = SceneRuntime.Runtime.init(allocator),        .ui = ui_runtime,        .audio = AudioRuntime.Runtime.init(allocator),        .scene_compile = SceneOwnership.CompileDomain.init(allocator),        .collision_compile = SceneOwnership.CompileDomain.init(allocator),        .artifact_arena = std.heap.ArenaAllocator.init(allocator),        .physics_scratch = physics_scratch,    };    self.physics_scratch.activate();    self.world.markEngineOwned();    self.initDirtyTracking();    return self;}pub fn deinit(self: *Self) void {    render_config.deinit(self);    self.audio.deinit();    self.ui.deinit();    self.ui_input_bindings.deinit(self.allocator);    self.scene.deinit();    self.renderer.deinit();    self.handler_registry.deinit(self.allocator);    self.queries.deinitPushed(self.allocator);    self.backend.deinit();    self.artifact_arena.deinit();    self.animation.deinit(self.allocator);    self.physics.deinit(self.allocator);    self.behavior.deinit(self.allocator);    if (self.play_session) |*session| {        session.deinit();        self.play_session = null;    }    self.physics_scratch.deinit(self.allocator);    self.collision_compile.deinit();    self.scene_compile.deinit();    self.assets.deinit(self.allocator);    self.world.deinit();}pub fn bindShapeAsset(self: *Self, entity: WorldStore.EntityId, asset_id: []const u8) !void {    try shape_api.bindAsset(self, entity, asset_id);}pub fn bindShapeParam(self: *Self, entity: WorldStore.EntityId, param_name: []const u8, value: f32) !void {    try shape_api.bindParam(self, entity, param_name, value);}pub fn prepareShapeAssetReload(    self: *Self,    asset: ShapeAsset,    options: asset_reload.PrepareOptions,) !asset_reload.PreparedShapeAsset {    return shape_api.prepareReload(self, asset, options);}pub fn commitShapeAssetReload(    self: *Self,    prepared: asset_reload.PreparedShapeAsset,) !u64 {    return shape_api.commitReload(self, prepared);}pub fn setRenderOptions(self: *Self, request: types.RenderPlanRequest) void {    render_config.setOptions(self, request);}pub fn setRenderStyle(self: *Self, request: types.RenderStyleRequest) void {    render_config.setStyle(self, request);}pub fn installRenderPalette(self: *Self, colors: []BackendExecutor.PaletteColor) void {    render_config.installPalette(self, colors);}pub fn commandSink(self: *Self) CommandSink {    return CommandSink.bind(self.allocator, self.activeWorld());}pub fn enterPlay(self: *Self) !void {    try world_session.enterPlay(self);}pub fn exitPlay(self: *Self) void {    world_session.exitPlay(self);}pub fn playWorld(self: *Self) ?*WorldStore {    return world_session.playWorld(self);}pub fn applyPlayBack(    self: *Self,    batch: *WorldCommands.Batch,    spawned_ids: ?[]WorldStore.EntityId,) !u32 {    return try world_session.applyBack(self, batch, spawned_ids);}pub fn captureWorld(self: *Self, allocator: std.mem.Allocator) !WorldSave.Package {    return world_session.captureWorld(self, allocator);}pub fn restoreWorld(self: *Self, package: *const WorldSave.Package) !void {    try world_session.restoreWorld(self, package);}pub fn activeWorld(self: *Self) *WorldStore {    return world_session.active(self);}pub fn activeWorldConst(self: *const Self) *const WorldStore {    return world_session.activeConst(self);}fn initDirtyTracking(self: *Self) void {    world_dirty.initTracking(self);}pub fn isCompileDirty(self: *const Self) bool {    return world_dirty.isCompileDirty(self);}pub fn worldStep(self: *Self, commands: types.CommandBatch, input: types.FrameInput) types.StepResult {    return step.world(self, commands, input);}pub fn frameStep(self: *Self, input: types.FrameStepInput) types.FrameStepResult {    return step.frame(self, input);}pub fn publishSceneEdit(    self: *Self,    nodes: []const SceneArtifact.NativeNodeDesc,    program_nodes: []const ScenePublish.ProgramNode,    root_index: u32,) !void {    try self.scene.publishEdit(&self.compiler, nodes, program_nodes, root_index);    self.invalidateSceneDerivations();}pub fn sceneEditRevision(self: *Self) u64 {    return if (self.scene.editPublished()) |published| published.revision else 0;}pub fn publishScene(self: *Self, publication: ScenePublication) !usize {    const result = try self.scene.apply(&self.compiler, publication);    self.invalidateSceneDerivations();    return result;}pub fn invalidateSceneDerivations(self: *Self) void {    self.invalidateSceneConsumers();    self.scene.releaseOwnedActivePublication(&self.compiler);    _ = self.artifact_arena.reset(.free_all);}pub fn invalidateWorldBoundaryDerivations(self: *Self) void {    self.invalidateSceneConsumers();    self.compiler.resetWorldState(        self.scene_compile.activeAllocator(),        self.collision_compile.activeAllocator(),    );    self.scene.invalidateWorldBoundary(&self.compiler);    self.scene_compile.clear();    self.collision_compile.clear();    _ = self.artifact_arena.reset(.free_all);}fn invalidateSceneConsumers(self: *Self) void {    self.queries.invalidateBinding();    self.backend.invalidateBindings();    self.renderer.invalidateScene();    self.clearRenderOutput();    self.compiled_artifact = null;}pub fn clearRenderOutput(self: *Self) void {    self.pixel_buffer = null;    self.graphics_buffer = null;    self.pixel_width = 0;    self.pixel_height = 0;}pub fn publishInputCommand(self: *Self, command: InputCommand) !void {    try self.input.apply(command);}pub fn readClientInput(self: *Self, session_id: u64) ?ClientInputSnapshot {    return self.input.read(session_id);}pub fn bindUiRootToInputSession(self: *Self, root_id: u64, session_id: u64) !void {    const prepared = try self.ui_input_bindings.prepareBind(self.allocator, root_id);    try self.input.admitUiCaptureSession(session_id);    const previous = self.ui_input_bindings.commitBind(prepared, session_id);    if (previous) |previous_session_id| {        if (previous_session_id != session_id) self.input.clearUiCaptured(previous_session_id);    }    self.ui_input_bindings.syncCapture(&self.ui, &self.input);}pub fn unbindUiRootFromInputSession(self: *Self, root_id: u64) !bool {    const session_id = self.ui_input_bindings.unbind(root_id) orelse return false;    self.input.clearUiCaptured(session_id);    self.ui_input_bindings.syncCapture(&self.ui, &self.input);    return true;}pub fn advanceUiInput(self: *Self, frame_index: u64) !void {    try self.ui.advanceInput(frame_index);    self.ui_input_bindings.syncCapture(&self.ui, &self.input);}pub fn publishPhysicsStep(self: *Self, context: PhysicsStepContext) !void {    const start_ns = @import("sdfii_timing").nowNs(.frame);    const admission = try self.preparePhysicsStep(context);    const plan = try self.physics.planFixedSteps(        admission.scratch,        admission.active_world,        admission.collision,        context.dt_s,    );    const outputs = self.physics.collectPublicSummary(        admission.active_world,        admission.collision,        plan.fixed_step_count,    );    self.physics_snapshot = .{        .synced_revision = outputs.status.synced_revision,        .fixed_step_count = plan.fixed_step_count,        .step_ns = @import("sdfii_timing").sinceNs(.frame, start_ns),        .body_pose_count = outputs.body_pose_count,        .contact_count = outputs.contact_count,    };}pub fn preflightPhysicsStep(self: *Self, context: PhysicsStepContext) !void {    _ = try self.preparePhysicsStep(context);}const PhysicsStepAdmission = struct {    active_world: *WorldStore,    collision: ?*const Compiler.PublishedRevision,    scratch: PhysicsRuntime.StepScratch,};fn preparePhysicsStep(self: *Self, context: PhysicsStepContext) !PhysicsStepAdmission {    const collision = if (context.collision_published) |published|        if (published.revision == context.collision_revision) published else null    else        null;    const active_world = self.activeWorld();    const scratch = try self.physics_scratch.frame(        PhysicsWorld.physicsBodyCount(active_world, collision),        PhysicsWorld.physicsPlaneCount(collision),    );    return .{        .active_world = active_world,        .collision = collision,        .scratch = scratch,    };}pub fn readPhysicsRuntime(self: *Self) PhysicsRuntimeSnapshot {    return self.physics_snapshot;}pub fn readPhysicsScratch(self: *const Self) PhysicsScratchStatus {    return self.physics_scratch.status();}pub fn readBehaviorRuntime(self: *Self) BehaviorRuntimeSnapshot {    return self.behavior_snapshot;}pub fn readRenderRuntime(self: *Self) RenderRuntimeSnapshot {    return self.renderer.snapshot(&self.backend);}pub fn readRenderFrame(self: *Self) RenderFrameView {    return self.renderer.frameView();}pub const PointerRay = struct {    origin: [3]f32,    direction: [3]f32,};pub fn readPointerRay(self: *Self, pixel_x: f32, pixel_y: f32) ?PointerRay {    const view = self.renderer.frameView();    if (!view.valid) return null;    if (!view.camera.valid) return null;    if (view.width == 0 or view.height == 0) return null;    if (!std.math.isFinite(pixel_x) or !std.math.isFinite(pixel_y)) return null;    const camera = Raymarch.SdfiiCameraDesc.from(view.camera.camera);    const ray = switch (view.camera.projection) {        .scene_camera => Raymarch.pixelRayPerspective(            camera,            view.width,            view.height,            pixel_x,            pixel_y,        ),        .orthographic => Raymarch.pixelRayOrthographic(            camera,            view.camera.orthographic_height,            view.width,            view.height,            pixel_x,            pixel_y,        ),    };    return .{        .origin = .{ ray.origin.x, ray.origin.y, ray.origin.z },        .direction = .{ ray.direction.x, ray.direction.y, ray.direction.z },    };}pub fn readSceneRuntime(self: *Self) SceneRuntimeSnapshot {    return self.scene.snapshot();}pub fn readSceneAuthoringGap(self: *const Self) ?SceneAuthoringGap {    return self.scene.authoring_gap;}pub fn readSceneMetadata(self: *const Self) Compiler.SceneMetadata {    return self.scene.metadata();}pub fn readSceneEditPublished(self: *const Self) ?*const Compiler.PublishedRevision {    return self.scene.editPublished();}pub fn readSceneCamera(self: *const Self) Compiler.CameraDesc {    return self.scene.camera;}pub fn readSceneDefaultMaterial(self: *const Self) Compiler.MaterialDesc {    return self.scene.default_material;}pub fn readSceneBackground(self: *const Self) @import("linear").Vec3 {    return self.scene.background;}pub fn readSceneSettings(self: *const Self) Compiler.SettingsDesc {    return self.scene.settings;}pub fn readSceneLightCount(self: *const Self) usize {    return self.scene.lights.items.len;}pub fn currentPublishedScene(self: *const Self) CurrentPublishedScene {    const published = self.scene.activePublished(&self.compiler) orelse return .{};    return .{        .value = published.*,        .has_value = true,    };}pub fn currentQueryRevision(self: *const Self) !u64 {    const published = self.scene.activePublished(&self.compiler) orelse return error.NoRevisionBound;    if (!self.queries.isBoundTo(published.revision)) return error.NoRevisionBound;    return published.revision;}pub fn bindCurrentScene(self: *Self) !u64 {    const published = self.scene.activePublished(&self.compiler) orelse return error.NoRevisionBound;    try self.queries.bindPublishedRevision(published.*);    return published.revision;}pub fn publishUiCommand(self: *Self, command: UiCommand) !void {    try self.ui.apply(command);}pub fn publishUiSurface(    self: *Self,    root_id: u64,    revision: u64,    surface: UiSurface,) UiStorageExhaustion!void {    try self.ui.publishNativeSurface(.{        .root_id = root_id,        .revision = revision,        .surface = surface,    });}pub fn readUiStorageStatus(self: *const Self) UiStorageStatus {    return self.ui.storageStatus();}pub fn readUiSurfaceState(self: *const Self, root_id: u64) ?*const UiSurfaceState {    return self.ui.surfaceState(root_id);}pub fn readUiPublishedFrame(self: *Self) *const UiPublishedFrame {    return self.ui.frameView();}pub fn readUiActivationEvents(self: *Self) []const UiActivationEvent {    return self.ui.activationEvents();}pub fn readUiTextEditEvents(self: *Self) []const UiTextEditEvent {    return self.ui.textEditEvents();}pub fn readUiTextPointEvents(self: *Self) []const UiTextPointEvent {    return self.ui.textPointEvents();}pub fn publishAudioCommand(self: *Self, command: AudioCommand) !void {    try self.audio.apply(command);}pub fn readAudioRevision(self: *Self) u64 {    return self.audio.revision;}pub fn readAudioRuntime(self: *Self) AudioRuntimeSnapshot {    return self.audio.snapshot();}pub fn readAudioPlaybackStatus(self: *Self, playback_ref: u64) ?AudioPlaybackSnapshot {    return self.audio.playback(playback_ref);}pub fn readAudioAsset(self: *Self, asset_ref: u64) ?AudioAsset {    return self.audio.asset(asset_ref);}pub fn readAudioEmitterAcoustics(self: *Self, emitter_ref: u64) ?AudioEmitterAcousticsSnapshot {    return self.audio.emitter(emitter_ref);}pub fn readAudioListenerPose(self: *Self) ?AudioListenerPose {    return self.audio.listenerPose();}pub fn readAudioTransport(self: *Self) ?AudioTransport {    return self.audio.transport();}pub fn readAudioOutput(self: *Self) ?AudioOutput {    return self.audio.output();}fn backendAvailability(self: *const Self) types.BackendAvailability {    return self.backend.liveAvailability();}pub const AcousticExecutorBinding = struct {    executor: BackendExecutor.Executor,    backend_kind: types.BackendKind,    scene_version: u64,};pub fn bindAcousticExecutor(self: *Self) !AcousticExecutorBinding {    const artifact = self.compiled_artifact orelse return error.NoCompiledArtifact;    if (artifact.summary.compiled_revision == 0 or        artifact.summary.node_count == 0 or        !types.boolFromFlag(artifact.summary.supports_field_queries))    {        return error.NoCompiledArtifact;    }    const summary = types.CompiledArtifactSummary.from(artifact.summary);    const availability = self.backendAvailability();    const selection = self.backend.selectBackend(.{        .summary = summary,        .availability = availability,        .preference = @backingInt(self.render_preference),        .requested_backend = @backingInt(self.requested_backend),        .existing_backend = @backingInt(self.backend.selected),    });    const selected_backend = types.backendKindFromRaw(selection.selected_backend);    if (selected_backend == .none) return error.NoSupportedBackend;    const executor = self.backend.wosQueryExecutor(summary, availability) orelse return error.NoSupportedBackend;    const query_backend = executor.capabilities().kind;    if (query_backend == .none) return error.NoSupportedBackend;    const upload_plan = self.backend.upload.plan(query_backend, summary, availability);    try executor.bind(&artifact, upload_plan);    self.backend.upload.commit(query_backend, summary);    return .{        .executor = executor,        .backend_kind = query_backend,        .scene_version = if (artifact.summary.scene_version != 0)            artifact.summary.scene_version        else            artifact.summary.compiled_revision,    };}pub fn captureLastFrame(self: *Self, scratch: std.mem.Allocator) !frame_mod.capture.FrameCapture {    return frame_system.captureLastFrame(self, scratch);}pub fn frameHistoryCount(self: *const Self) usize {    return frame_system.historyCount(self);}pub fn frameHistoryLatest(self: *const Self) ?frame_mod.history.FrameRecord {    return frame_system.historyLatest(self);}pub fn frameHistoryAt(self: *const Self, offset_from_oldest: usize) ?frame_mod.history.FrameRecord {    return frame_system.historyAt(self, offset_from_oldest);}pub fn clearFrameHistory(self: *Self) void {    frame_system.clearHistory(self);}fn encodeMaterialBlob(desc: Compiler.MaterialDesc) [48]u8 {    var blob = @as([48]u8, @splat(0));    blob[0] = 1;    @memcpy(blob[4..48], std.mem.asBytes(&desc));    return blob;}pub fn upsertEntityMaterial(    self: *Self,    entity: WorldStore.EntityId,    desc: Compiler.MaterialDesc,) !void {    var batch = try WorldCommands.Batch.init(self.allocator, 1);    defer batch.deinit();    const blob = encodeMaterialBlob(desc);    try batch.pushUpsertComponent(        entity,        @backingInt(Schema.ComponentSchema.material),        &blob,    );    _ = try self.world.submit(&batch, null);}fn encodeLightsBlob(lights: []const Compiler.LightDesc) [232]u8 {    var blob = @as([232]u8, @splat(0));    const count: u32 = @intCast(@min(lights.len, 8));    @as(*align(1) u32, @ptrCast(&blob[0])).* = count;    for (lights[0..count], 0..) |light, i| {        const offset = 8 + i * @sizeOf(Compiler.LightDesc);        @memcpy(blob[offset .. offset + @sizeOf(Compiler.LightDesc)], std.mem.asBytes(&light));    }    return blob;}fn seedShapeEntity(engine: *Self) !WorldStore.EntityId {    var batch = try WorldCommands.Batch.init(engine.allocator, 4);    defer batch.deinit();    try batch.pushSpawn(null, null, .{        .pos_x = 0.0,        .pos_y = 0.0,        .pos_z = 0.0,        .rot_axis_x = 0.0,        .rot_axis_y = 1.0,        .rot_axis_z = 0.0,        .rot_angle = 0.0,        .scale = 1.0,    });    var ids: [1]WorldStore.EntityId = undefined;    _ = try engine.world.submit(&batch, &ids);    try batch.pushUpsertComponent(        ids[0],        @backingInt(Schema.ComponentSchema.shape),        "{\"asset_id\":\"sphere\",\"params\":{\"radius\":1.0}}",    );    _ = try engine.world.submit(&batch, null);    return ids[0];}const CommittedFrameProducts = struct {    published_revision: u64,    collision_revision: u64,    compiler_revision: u64,    compiler_collision_revision: u64,    artifact_summary: SceneArtifact.CompiledArtifactSummary,    artifact_nodes_ptr: usize,    artifact_nodes_len: usize,    artifact_materials_ptr: usize,    artifact_material_count: usize,    active_nodes_ptr: usize,    query_revision: u64,    query_nodes_ptr: usize,    render_projection_revision: u64,    frame_published_revision: u64,    frame_pixels_ptr: usize,    frame_pixel_count: usize,    frame_width: u32,    frame_height: u32,    context_frame_index: u64,    history_count: usize,};fn captureCommittedFrameProducts(engine: *Self) !CommittedFrameProducts {    const scene = engine.readSceneRuntime();    const compiler_published = engine.compiler.published() orelse return error.TestUnexpectedResult;    const collision_published = engine.compiler.collisionPublished() orelse return error.TestUnexpectedResult;    const artifact = engine.compiled_artifact orelse return error.TestUnexpectedResult;    const active_scene = (engine.scene.activePublished(&engine.compiler) orelse return error.TestUnexpectedResult).scene orelse return error.TestUnexpectedResult;    const query_nodes = engine.queries.nodes orelse return error.TestUnexpectedResult;    const render = engine.readRenderRuntime();    const frame = engine.readRenderFrame();    if (!frame.valid or frame.pixels.len == 0) return error.TestUnexpectedResult;    return .{        .published_revision = scene.published_revision,        .collision_revision = scene.collision_revision,        .compiler_revision = compiler_published.revision,        .compiler_collision_revision = collision_published.revision,        .artifact_summary = artifact.summary,        .artifact_nodes_ptr = @intFromPtr(artifact.sdfProgram().?.nodes.ptr),        .artifact_nodes_len = artifact.sdfProgram().?.nodes.len,        .artifact_materials_ptr = if (artifact.metadata.materials.len == 0) 0 else @intFromPtr(artifact.metadata.materials.ptr),        .artifact_material_count = artifact.metadata.materials.len,        .active_nodes_ptr = @intFromPtr(active_scene.nodes.ptr),        .query_revision = try engine.currentQueryRevision(),        .query_nodes_ptr = @intFromPtr(query_nodes.ptr),        .render_projection_revision = render.render_projection_revision,        .frame_published_revision = render.frame_published_revision,        .frame_pixels_ptr = @intFromPtr(frame.pixels.ptr),        .frame_pixel_count = frame.pixels.len,        .frame_width = frame.width,        .frame_height = frame.height,        .context_frame_index = engine.last_frame_context.frame_index,        .history_count = engine.frame_history.count,    };}fn expectCommittedFrameProductsUnchanged(engine: *Self, expected: CommittedFrameProducts) !void {    const actual = try captureCommittedFrameProducts(engine);    try std.testing.expectEqualDeep(expected, actual);    try std.testing.expect(engine.queries.isBoundTo(expected.query_revision));}fn expectedLiveRenderBackend(engine: *const Self) []const u8 {    const report = engine.backend.capabilityReport();    return if (report.accy.available) "accy" else "zig_cpu";}test "frameStep recompiles on world scene resources and ignores demoted performance resources" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 16, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    _ = try seedShapeEntity(&engine);    const initial = engine.frameStep(.{        .frame_index = 0,        .dt_s = 1.0 / 60.0,        .input_event_count = 0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u8, 1), initial.recompiled);    var batch = try WorldCommands.Batch.init(std.testing.allocator, 8);    defer batch.deinit();    const camera = Compiler.CameraDesc{        .position = .{ .x = 1.0, .y = 2.0, .z = 6.0 },        .target = .{ .x = 0.0, .y = 0.5, .z = 0.0 },        .up = .{ .x = 0.0, .y = 1.0, .z = 0.0 },        .fov = 35.0,    };    const background = @import("linear").Vec3{ .x = 0.2, .y = 0.3, .z = 0.4 };    const default_material = Compiler.MaterialDesc{        .ambient = 0.4,        .diffuse = 0.5,        .specular = 0.6,        .shininess = 24.0,        .color = .{ .x = 0.7, .y = 0.1, .z = 0.2 },        .rim_color = .{ .x = 0.0, .y = 0.2, .z = 0.4 },        .rim_exponent = 5.0,    };    const lights = [_]Compiler.LightDesc{        .{            .direction = .{ .x = 0.0, .y = -1.0, .z = -0.5 },            .color = .{ .x = 0.8, .y = 0.9, .z = 1.0 },            .intensity = 2.5,        },    };    const lights_blob = encodeLightsBlob(&lights);    const default_material_blob = encodeMaterialBlob(default_material);    try batch.pushUpsertResource(@backingInt(Schema.ResourceSchema.camera), std.mem.asBytes(&camera));    try batch.pushUpsertResource(@backingInt(Schema.ResourceSchema.background), std.mem.asBytes(&background));    try batch.pushUpsertResource(@backingInt(Schema.ResourceSchema.default_material), &default_material_blob);    try batch.pushUpsertResource(@backingInt(Schema.ResourceSchema.lights), &lights_blob);    try batch.pushUpsertResource(        @backingInt(Schema.ResourceSchema.scene_options),        "{\"ao_steps\":4,\"shadow_steps\":24,\"fog_density\":0.05}",    );    _ = try engine.world.submit(&batch, null);    const updated = engine.frameStep(.{        .frame_index = 1,        .dt_s = 1.0 / 60.0,        .input_event_count = 0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u8, 1), updated.recompiled);    try std.testing.expect(updated.published_revision > initial.published_revision);    const published = engine.compiler.published().?.scene.?;    try std.testing.expectEqual(camera.fov, published.camera.fov);    try std.testing.expectApproxEqAbs(@as(f32, 1.0), published.camera.position.x, 1e-6);    try std.testing.expectApproxEqAbs(@as(f32, 0.2), published.background.x, 1e-6);    try std.testing.expectApproxEqAbs(@as(f32, 0.4), published.default_material.ambient, 1e-6);    try std.testing.expectEqual(@as(usize, 1), published.lights.len);    try std.testing.expectApproxEqAbs(@as(f32, 2.5), published.lights[0].intensity, 1e-6);    try std.testing.expectEqual(@as(u32, 4), published.settings.ao_steps);    try std.testing.expectEqual(@as(u32, 24), published.settings.shadow_steps);    try std.testing.expectApproxEqAbs(@as(f32, 0.05), published.settings.fog_density, 1e-6);    try batch.pushUpsertResource(        @backingInt(Schema.ResourceSchema.performance_preset),        "\"high\"",    );    _ = try engine.world.submit(&batch, null);    try std.testing.expect(!engine.isCompileDirty());    const performance_only = engine.frameStep(.{        .frame_index = 2,        .dt_s = 1.0 / 60.0,        .input_event_count = 0,        .render_width = 0,        .render_height = 0,    });    _ = performance_only;    const performance_scene = engine.compiler.published().?.scene.?;    try std.testing.expectEqual(camera.fov, performance_scene.camera.fov);    try std.testing.expectEqual(@as(u32, 4), performance_scene.settings.ao_steps);    try std.testing.expectApproxEqAbs(@as(f32, 0.05), performance_scene.settings.fog_density, 1e-6);}test "metadata-only scene change preserves execution subversions and query cleanliness" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const entity = try seedShapeEntity(&engine);    const first = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u32, 0), first.diagnostic_flags);    const first_summary = (engine.compiled_artifact orelse return error.TestUnexpectedResult).summary;    const first_collision_index = engine.collision_compile.active_index;    const first_collision = engine.compiler.collisionPublished() orelse return error.TestUnexpectedResult;    const first_collision_nodes = (first_collision.scene orelse return error.TestUnexpectedResult).nodes.ptr;    const camera = Compiler.CameraDesc{        .position = .{ .x = 1.0, .y = 2.0, .z = 6.0 },        .target = .{ .x = 0.0, .y = 0.5, .z = 0.0 },        .up = .{ .x = 0.0, .y = 1.0, .z = 0.0 },        .fov = 35.0,    };    var batch = try WorldCommands.Batch.init(std.testing.allocator, 1);    defer batch.deinit();    try batch.pushUpsertResource(        @backingInt(Schema.ResourceSchema.camera),        std.mem.asBytes(&camera),    );    _ = try engine.world.submit(&batch, null);    const changed = engine.frameStep(.{        .frame_index = 1,        .dt_s = 0.0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u32, 0), changed.diagnostic_flags);    try std.testing.expectEqual(@as(u8, 1), changed.recompiled);    const changed_artifact = engine.compiled_artifact orelse return error.TestUnexpectedResult;    const changed_summary = changed_artifact.summary;    try std.testing.expectEqual(first_summary.compiled_revision + 1, changed_summary.compiled_revision);    try std.testing.expectEqual(first_summary.scene_version + 1, changed_summary.scene_version);    try std.testing.expectEqual(first_summary.execution_ir_version, changed_summary.execution_ir_version);    try std.testing.expectEqual(first_summary.native_payload_version, changed_summary.native_payload_version);    try std.testing.expectEqual(@as(u32, 0), changed_summary.dirty_region_count);    try std.testing.expectEqual(@as(usize, 0), changed_artifact.contract.dirty_region_count);    try std.testing.expectEqual(        @as(usize, 0),        engine.compiler.published().?.query_state.dirtyRegionCountForRevision(changed.published_revision),    );    try std.testing.expectEqual(first_collision_index, engine.collision_compile.active_index);    try std.testing.expectEqual(first_collision.revision, engine.compiler.collisionPublished().?.revision);    const unchanged = engine.frameStep(.{        .frame_index = 2,        .dt_s = 0.0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u32, 0), unchanged.diagnostic_flags);    try std.testing.expectEqual(@as(u8, 0), unchanged.recompiled);    try std.testing.expectEqual(changed.published_revision, unchanged.published_revision);    try std.testing.expectEqualDeep(changed_summary, engine.compiled_artifact.?.summary);    const before_direct = engine.compiled_artifact.?.summary;    _ = try engine.publishScene(.{ .background = .{ .x = 0.2, .y = 0.3, .z = 0.4 } });    try std.testing.expect(engine.compiler.published() == null);    try std.testing.expect(engine.compiled_artifact == null);    const direct = engine.frameStep(.{        .frame_index = 3,        .dt_s = 0.0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u32, 0), direct.diagnostic_flags);    try std.testing.expectEqual(@as(u8, 1), direct.recompiled);    const direct_artifact = engine.compiled_artifact orelse return error.TestUnexpectedResult;    const direct_summary = direct_artifact.summary;    try std.testing.expectEqual(before_direct.compiled_revision + 1, direct_summary.compiled_revision);    try std.testing.expectEqual(before_direct.scene_version + 1, direct_summary.scene_version);    try std.testing.expectEqual(before_direct.execution_ir_version, direct_summary.execution_ir_version);    try std.testing.expectEqual(before_direct.native_payload_version, direct_summary.native_payload_version);    try std.testing.expectEqual(@as(u32, 0), direct_summary.dirty_region_count);    try std.testing.expectEqual(@as(usize, 0), direct_artifact.contract.dirty_region_count);    try std.testing.expectEqual(        @as(usize, 0),        engine.compiler.published().?.query_state.dirtyRegionCountForRevision(direct.published_revision),    );    try std.testing.expectEqual(first_collision_index, engine.collision_compile.active_index);    const direct_collision = engine.compiler.collisionPublished() orelse return error.TestUnexpectedResult;    try std.testing.expectEqual(first_collision.revision, direct_collision.revision);    try std.testing.expectEqual(        @intFromPtr(first_collision_nodes),        @intFromPtr((direct_collision.scene orelse return error.TestUnexpectedResult).nodes.ptr),    );    var transform = engine.world.transforms.getDesc(entity.index) orelse return error.TestUnexpectedResult;    transform.pos_x = 2.0;    try engine.world.transforms.insert(entity.index, transform);    const geometry = engine.frameStep(.{        .frame_index = 4,        .dt_s = 0.0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u32, 0), geometry.diagnostic_flags);    const geometry_summary = engine.compiled_artifact.?.summary;    try std.testing.expect(geometry_summary.compiled_revision > direct_summary.compiled_revision);    try std.testing.expect(geometry_summary.scene_version > direct_summary.scene_version);    try std.testing.expect(geometry_summary.execution_ir_version > direct_summary.execution_ir_version);    try std.testing.expect(geometry_summary.native_payload_version > direct_summary.native_payload_version);    try batch.pushUpsertResource(        @backingInt(Schema.ResourceSchema.scene_options),        "{\"max_steps\":96}",    );    _ = try engine.world.submit(&batch, null);    const settings = engine.frameStep(.{        .frame_index = 5,        .dt_s = 0.0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u32, 0), settings.diagnostic_flags);    const settings_artifact = engine.compiled_artifact orelse return error.TestUnexpectedResult;    const settings_summary = settings_artifact.summary;    try std.testing.expect(settings_summary.compiled_revision > geometry_summary.compiled_revision);    try std.testing.expect(settings_summary.scene_version > geometry_summary.scene_version);    try std.testing.expect(settings_summary.execution_ir_version > geometry_summary.execution_ir_version);    try std.testing.expect(settings_summary.native_payload_version > geometry_summary.native_payload_version);    try std.testing.expectEqual(@as(u32, 0), settings_summary.dirty_region_count);    try std.testing.expectEqual(@as(usize, 0), settings_artifact.contract.dirty_region_count);}test "compiled fallback lights survive runtime light storage replacement" {    var moving = std.testing.FailingAllocator.init(std.testing.allocator, .{ .resize_fail_index = 0 });    var engine = Self.init(moving.allocator(), .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    _ = try seedShapeEntity(&engine);    _ = try engine.publishScene(.{ .add_light = .{        .direction = .{ .y = -1.0 },        .color = .{ .x = 1.0, .y = 0.5, .z = 0.25 },        .intensity = 1.0,    } });    try engine.scene.lights.shrinkAndFreePrecise(engine.allocator, engine.scene.lights.items.len);    const first = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u32, 0), first.diagnostic_flags);    const first_scene = (engine.compiler.published() orelse return error.TestUnexpectedResult).scene orelse        return error.TestUnexpectedResult;    try std.testing.expectEqual(@as(usize, 1), first_scene.lights.len);    try std.testing.expect(@intFromPtr(engine.scene.lights.items.ptr) != @intFromPtr(first_scene.lights.ptr));    const runtime_lights_ptr = engine.scene.lights.items.ptr;    _ = try engine.publishScene(.{ .add_light = .{        .direction = .{ .x = 1.0 },        .color = .{ .x = 0.25, .y = 0.5, .z = 1.0 },        .intensity = 2.0,    } });    try std.testing.expect(@intFromPtr(runtime_lights_ptr) != @intFromPtr(engine.scene.lights.items.ptr));    const second = engine.frameStep(.{        .frame_index = 1,        .dt_s = 0.0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u32, 0), second.diagnostic_flags);    try std.testing.expectEqual(@as(u8, 1), second.recompiled);    try std.testing.expect(second.published_revision > first.published_revision);    const second_scene = (engine.compiler.published() orelse return error.TestUnexpectedResult).scene orelse        return error.TestUnexpectedResult;    try std.testing.expectEqual(@as(usize, 2), second_scene.lights.len);    try std.testing.expectEqual(@as(f32, 1.0), second_scene.lights[0].intensity);    try std.testing.expectEqual(@as(f32, 2.0), second_scene.lights[1].intensity);}test "shape asset reload prepare failure preserves resident registry and commit republishes frame" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 16, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const initial_asset = ShapeAsset.init("hot.ship", 1).withAnalyticProgram(.{        .root = 0,        .node_count = 2,        .payload_hash = 0x1111,    });    const initial_prepared = try engine.prepareShapeAssetReload(initial_asset, .{});    _ = try engine.commitShapeAssetReload(initial_prepared);    const first = engine.frameStep(.{        .frame_index = 1,        .dt_s = 1.0 / 60.0,        .input_event_count = 0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expectEqual(@as(u64, 1), first.published_revision);    try std.testing.expectEqual(@as(?u32, 1), engine.assets.versionOf("hot.ship"));    const first_collision = engine.compiler.collisionPublished() orelse return error.TestUnexpectedResult;    const first_collision_index = engine.collision_compile.active_index;    const bad_asset = ShapeAsset.init("hot.ship", 2);    try std.testing.expectError(        error.InvalidReloadProgram,        engine.prepareShapeAssetReload(bad_asset, .{}),    );    const resident_after_failure = engine.assets.get("hot.ship").?;    try std.testing.expectEqual(@as(u32, 1), resident_after_failure.version);    try std.testing.expectEqual(@as(u32, 0x1111), resident_after_failure.analytic_program.payload_hash);    try std.testing.expectEqual(first.published_revision, engine.compiler.published().?.revision);    try std.testing.expectEqual(first_collision.revision, engine.compiler.collisionPublished().?.revision);    const updated_asset = ShapeAsset.init("hot.ship", 2).withAnalyticProgram(.{        .root = 0,        .node_count = 3,        .payload_hash = 0x2222,    });    const prepared = try engine.prepareShapeAssetReload(updated_asset, .{});    try std.testing.expect(prepared.artifact_revision != initial_prepared.artifact_revision);    _ = try engine.commitShapeAssetReload(prepared);    const resident_after_commit = engine.assets.get("hot.ship").?;    try std.testing.expectEqual(@as(u32, 2), resident_after_commit.version);    try std.testing.expectEqual(@as(u32, 0x2222), resident_after_commit.analytic_program.payload_hash);    try std.testing.expect(engine.compiler.collisionPublished() == null);    const second = engine.frameStep(.{        .frame_index = 2,        .dt_s = 1.0 / 60.0,        .input_event_count = 0,        .render_width = 0,        .render_height = 0,    });    try std.testing.expect(second.published_revision > first.published_revision);    try std.testing.expectEqual(@as(usize, 1), engine.compiler.published().?.view.asset_count);    try std.testing.expect(engine.compiler.collisionPublished().?.revision > first_collision.revision);    try std.testing.expectEqual(first_collision_index ^ 1, engine.collision_compile.active_index);}test "readPointerRay is null before any rendered frame and hits the rendered scene after" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    try std.testing.expectEqual(@as(?PointerRay, null), engine.readPointerRay(0.0, 0.0));    const sdf_types = @import("sdfii_sdf").types;    const nodes = [_]SceneArtifact.NativeNodeDesc{        .{            .kind_id = @backingInt(sdf_types.NodeKind.sphere),            .f0 = 1.0,        },    };    try engine.publishSceneEdit(&nodes, &.{}, 0);    _ = try engine.publishScene(.{ .camera = .{        .position = .{ .x = 0.0, .y = 0.0, .z = 6.0 },        .target = .{ .x = 0.0, .y = 0.0, .z = 0.0 },        .up = .{ .x = 0.0, .y = 1.0, .z = 0.0 },        .fov = 45.0,    } });    const width: u32 = 33;    const height: u32 = 33;    const result = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .input_event_count = 0,        .render_width = width,        .render_height = height,    });    try std.testing.expectEqual(@as(u8, 1), result.render_valid);    const center: f32 = 16.0;    const ray = engine.readPointerRay(center, center) orelse return error.TestUnexpectedResult;    try std.testing.expectApproxEqAbs(@as(f32, 0.0), ray.direction[0], 0.01);    try std.testing.expectApproxEqAbs(@as(f32, 0.0), ray.direction[1], 0.01);    try std.testing.expectApproxEqAbs(@as(f32, -1.0), ray.direction[2], 0.01);    const hit = try engine.queries.queryRaycast(@import("linear").Vec3.fromArray(ray.origin), @import("linear").Vec3.fromArray(ray.direction));    try std.testing.expect(hit.hit);    try std.testing.expectApproxEqAbs(@as(f32, 1.0), hit.point.z, 0.05);    const view = engine.readRenderFrame();    const center_pixel = view.pixels[@as(usize, center) * width + @as(usize, center)];    try std.testing.expect(center_pixel.flags != 0);    const expected_depth = hit.t;    try std.testing.expectApproxEqAbs(expected_depth, center_pixel.depth, 0.1);}test "frameStep keeps rendering an edit scene when the compiled world is empty" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const sdf_types = @import("sdfii_sdf").types;    const nodes = [_]SceneArtifact.NativeNodeDesc{        .{            .kind_id = @backingInt(sdf_types.NodeKind.sphere),            .f0 = 1.0,        },    };    try engine.publishSceneEdit(&nodes, &.{}, 0);    const result = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .input_event_count = 0,        .render_width = 32,        .render_height = 16,    });    try std.testing.expectEqual(@as(u8, 1), result.render_valid);    try std.testing.expect(engine.pixel_buffer != null);    const rendered = engine.readRenderFrame();    try std.testing.expect(rendered.valid);    try std.testing.expectEqual(@as(u32, 32), rendered.width);    try std.testing.expectEqual(@as(u32, 16), rendered.height);    const copied_pixels = engine.pixel_buffer.?;    const renderer_pixels = rendered.pixels[0..copied_pixels.len];    try std.testing.expectEqualSlices(types.FramePixel, renderer_pixels, copied_pixels);    var hit_count: usize = 0;    for (copied_pixels) |pixel| {        if (pixel.flags != 0) hit_count += 1;    }    try std.testing.expect(hit_count > 0);    const second_result = engine.frameStep(.{        .frame_index = 1,        .dt_s = 1.0 / 60.0,        .input_event_count = 0,        .render_width = 32,        .render_height = 16,    });    try std.testing.expectEqual(@as(u8, 1), second_result.render_valid);    try engine.last_frame_context.stages.assertCompleted(.readback);    try std.testing.expectEqual(frame_mod.StageAccess.none, engine.last_frame_context.stages.get(.readback).contract.world_access);    const render_history = engine.frameHistoryLatest().?;    try std.testing.expectEqual(second_result.frame_index, render_history.frame_index);    try std.testing.expect(render_history.render_graph.pass_count > 0);    try std.testing.expect(render_history.transient_bytes > 0);    try std.testing.expectEqualStrings(expectedLiveRenderBackend(&engine), render_history.backend.selected_backend);    var second_hit_count: usize = 0;    for (engine.pixel_buffer.?) |pixel| {        if (pixel.flags != 0) second_hit_count += 1;    }    try std.testing.expect(second_hit_count > 0);}test "authored scene replacement invalidates query binding until the next frame" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const sdf_types = @import("sdfii_sdf").types;    const first_nodes = [_]SceneArtifact.NativeNodeDesc{.{        .kind_id = @backingInt(sdf_types.NodeKind.sphere),        .f0 = 1.0,    }};    try engine.publishSceneEdit(&first_nodes, &.{}, 0);    const first = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,    });    try std.testing.expect(engine.queries.isBoundTo(first.published_revision));    _ = try engine.queries.queryDistanceAtRevision(first.published_revision, @import("linear").Vec3.init(0.0, 0.0, 0.0));    const backend_binding = try engine.bindAcousticExecutor();    var backend_points = [_]@import("linear").Vec3{.{}};    var backend_distances = [_]f32{0};    try backend_binding.executor.sampleDistances(.{        .points = &backend_points,        .distances_out = &backend_distances,    });    const replacement_nodes = [_]SceneArtifact.NativeNodeDesc{.{        .kind_id = @backingInt(sdf_types.NodeKind.sphere),        .f0 = 0.25,    }};    try engine.publishSceneEdit(&replacement_nodes, &.{}, 0);    try std.testing.expectError(        error.NoRevisionBound,        engine.queries.queryDistanceAtRevision(first.published_revision, @import("linear").Vec3.init(0.0, 0.0, 0.0)),    );    try std.testing.expectError(error.NoRevisionBound, engine.currentQueryRevision());    try std.testing.expectError(        error.ArtifactNotBound,        backend_binding.executor.sampleDistances(.{            .points = &backend_points,            .distances_out = &backend_distances,        }),    );    const next = engine.frameStep(.{        .frame_index = 1,        .dt_s = 0.0,    });    try std.testing.expect(next.published_revision != first.published_revision);    try std.testing.expect(engine.queries.isBoundTo(next.published_revision));    _ = try engine.queries.queryDistanceAtRevision(next.published_revision, @import("linear").Vec3.init(0.0, 0.0, 0.0));}test "authored scene mutation retires borrowed backend bindings before storage changes" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const sdf_types = @import("sdfii_sdf").types;    const nodes = [_]SceneArtifact.NativeNodeDesc{.{        .kind_id = @backingInt(sdf_types.NodeKind.sphere),        .f0 = 1.0,    }};    try engine.publishSceneEdit(&nodes, &.{}, 0);    _ = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expect(engine.pixel_buffer != null);    const owned_artifact = engine.compiled_artifact.?;    const source_scene = engine.readSceneEditPublished().?.scene.?;    try std.testing.expect(owned_artifact.sdfProgram().?.nodes.ptr != source_scene.nodes.ptr);    const binding = try engine.bindAcousticExecutor();    var points = [_]@import("linear").Vec3{.{}};    var distances = [_]f32{0};    try binding.executor.sampleDistances(.{ .points = &points, .distances_out = &distances });    for (0..64) |index| {        _ = try engine.publishScene(.{ .add_material = .{ .diffuse = @floatFromInt(index) } });    }    try std.testing.expectError(        error.ArtifactNotBound,        binding.executor.sampleDistances(.{ .points = &points, .distances_out = &distances }),    );    try std.testing.expectError(error.NoCompiledArtifact, engine.bindAcousticExecutor());    try std.testing.expect(!engine.readRenderRuntime().frame_valid);    try std.testing.expect(engine.pixel_buffer == null);    try std.testing.expect(engine.graphics_buffer == null);    try std.testing.expectEqual(@as(u32, 0), engine.pixel_width);    try std.testing.expectEqual(@as(u32, 0), engine.pixel_height);    _ = engine.frameStep(.{ .frame_index = 1, .dt_s = 0.0 });    const rebound = try engine.bindAcousticExecutor();    try rebound.executor.sampleDistances(.{ .points = &points, .distances_out = &distances });    try std.testing.expect(std.math.isFinite(distances[0]));}test "unchanged scene frames retain one owned active publication" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    _ = try seedShapeEntity(&engine);    const first = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    const first_active = engine.scene.activePublished(&engine.compiler).?.scene.?;    const first_owned = engine.compiled_artifact.?.sdfProgram().?;    try std.testing.expectEqual(@intFromPtr(first_owned.nodes.ptr), @intFromPtr(first_active.nodes.ptr));    try std.testing.expectEqual(@intFromPtr(first_owned.nodes.ptr), @intFromPtr(engine.queries.nodes.?.ptr));    const second = engine.frameStep(.{        .frame_index = 1,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    const second_active = engine.scene.activePublished(&engine.compiler).?.scene.?;    const second_owned = engine.compiled_artifact.?.sdfProgram().?;    try std.testing.expectEqual(first.published_revision, second.published_revision);    try std.testing.expectEqual(@intFromPtr(first_owned.nodes.ptr), @intFromPtr(second_owned.nodes.ptr));    try std.testing.expectEqual(@intFromPtr(second_owned.nodes.ptr), @intFromPtr(second_active.nodes.ptr));    try std.testing.expectEqual(@intFromPtr(second_owned.nodes.ptr), @intFromPtr(engine.queries.nodes.?.ptr));}test "unchanged warmed frames perform exact preflight without retained allocation" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    _ = try seedShapeEntity(&engine);    for (0..2) |frame_index| {        const result = engine.frameStep(.{            .frame_index = frame_index,            .dt_s = 0.0,            .render_width = 8,            .render_height = 8,        });        try std.testing.expectEqual(@as(u32, 0), result.diagnostic_flags);    }    const revision = engine.readSceneRuntime().published_revision;    const artifact_nodes = engine.compiled_artifact.?.sdfProgram().?.nodes.ptr;    const scene_capacity = engine.scene_compile.retainedCapacity();    const collision_capacity = engine.collision_compile.retainedCapacity();    const scene_staging_index = engine.scene_compile.active_index ^ 1;    engine.scene_compile.arenas[scene_staging_index].deinit();    engine.scene_compile.arenas[scene_staging_index] = std.heap.ArenaAllocator.init(failing.allocator());    const collision_staging_index = engine.collision_compile.active_index ^ 1;    engine.collision_compile.arenas[collision_staging_index].deinit();    engine.collision_compile.arenas[collision_staging_index] = std.heap.ArenaAllocator.init(failing.allocator());    failing.fail_index = 0;    failing.resize_fail_index = 0;    const unchanged = engine.frameStep(.{        .frame_index = 2,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expect(!failing.has_induced_failure);    try std.testing.expectEqual(@as(u32, 0), unchanged.diagnostic_flags);    try std.testing.expectEqual(revision, unchanged.published_revision);    try std.testing.expectEqual(@intFromPtr(artifact_nodes), @intFromPtr(engine.compiled_artifact.?.sdfProgram().?.nodes.ptr));    try std.testing.expect(engine.scene_compile.retainedCapacity() <= scene_capacity);    try std.testing.expect(engine.collision_compile.retainedCapacity() <= collision_capacity);}test "fixed-cardinality scene churn retains two compile banks" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const entity = try seedShapeEntity(&engine);    for (0..2) |frame_index| {        var transform = engine.world.transforms.getDesc(entity.index) orelse return error.TestUnexpectedResult;        transform.pos_x = @floatFromInt(frame_index);        try engine.world.transforms.insert(entity.index, transform);        const result = engine.frameStep(.{            .frame_index = frame_index,            .dt_s = 0.0,            .render_width = 8,            .render_height = 8,        });        try std.testing.expectEqual(@as(u32, 0), result.diagnostic_flags);    }    const scene_capacity = engine.scene_compile.retainedCapacity();    const collision_capacity = engine.collision_compile.retainedCapacity();    try std.testing.expect(scene_capacity != 0);    try std.testing.expect(collision_capacity != 0);    var previous_revision = engine.readSceneRuntime().published_revision;    for (0..64) |offset| {        var transform = engine.world.transforms.getDesc(entity.index) orelse return error.TestUnexpectedResult;        transform.pos_x = @floatFromInt(offset + 2);        try engine.world.transforms.insert(entity.index, transform);        const result = engine.frameStep(.{            .frame_index = offset + 2,            .dt_s = 0.0,            .render_width = 8,            .render_height = 8,        });        try std.testing.expectEqual(@as(u32, 0), result.diagnostic_flags);        try std.testing.expectEqual(@as(u8, 1), result.recompiled);        try std.testing.expect(result.published_revision > previous_revision);        try std.testing.expectEqual(scene_capacity, engine.scene_compile.retainedCapacity());        try std.testing.expectEqual(collision_capacity, engine.collision_compile.retainedCapacity());        previous_revision = result.published_revision;    }}test "dynamic-only scene churn leaves collision compile bank unchanged" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    _ = try seedShapeEntity(&engine);    const dynamic_entity = try seedShapeEntity(&engine);    var batch = try WorldCommands.Batch.init(std.testing.allocator, 1);    defer batch.deinit();    const dynamic_body = PhysicsWorld.PhysicsComponentDesc{ .motion_type = 0 };    try batch.pushUpsertComponent(        dynamic_entity,        @backingInt(Schema.ComponentSchema.physics),        std.mem.asBytes(&dynamic_body),    );    _ = try engine.world.submit(&batch, null);    const first = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), first.diagnostic_flags);    var scene_index = engine.scene_compile.active_index;    const collision_index = engine.collision_compile.active_index;    const collision_capacity = engine.collision_compile.retainedCapacity();    const collision = engine.compiler.collisionPublished() orelse return error.TestUnexpectedResult;    const collision_scene = collision.scene orelse return error.TestUnexpectedResult;    const collision_nodes = collision_scene.nodes.ptr;    var previous_scene_revision = first.published_revision;    for (0..64) |offset| {        var transform = engine.world.transforms.getDesc(dynamic_entity.index) orelse return error.TestUnexpectedResult;        transform.pos_x = @floatFromInt(offset + 3);        try engine.world.transforms.insert(dynamic_entity.index, transform);        const next = engine.frameStep(.{            .frame_index = offset + 1,            .dt_s = 0.0,            .render_width = 8,            .render_height = 8,        });        try std.testing.expectEqual(@as(u32, 0), next.diagnostic_flags);        try std.testing.expectEqual(@as(u8, 1), next.recompiled);        try std.testing.expect(next.published_revision > previous_scene_revision);        try std.testing.expectEqual(scene_index ^ 1, engine.scene_compile.active_index);        scene_index = engine.scene_compile.active_index;        previous_scene_revision = next.published_revision;        try std.testing.expectEqual(collision_index, engine.collision_compile.active_index);        try std.testing.expectEqual(collision_capacity, engine.collision_compile.retainedCapacity());        const unchanged_collision = engine.compiler.collisionPublished() orelse return error.TestUnexpectedResult;        try std.testing.expectEqual(collision.revision, unchanged_collision.revision);        try std.testing.expectEqual(            @intFromPtr(collision_nodes),            @intFromPtr((unchanged_collision.scene orelse return error.TestUnexpectedResult).nodes.ptr),        );    }}test "empty and unknown intersect edits leave collision publication unchanged" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    _ = try seedShapeEntity(&engine);    const first = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), first.diagnostic_flags);    const first_collision_index = engine.collision_compile.active_index;    const first_collision = engine.compiler.collisionPublished() orelse return error.TestUnexpectedResult;    const first_collision_scene = first_collision.scene orelse return error.TestUnexpectedResult;    var batch = try WorldCommands.Batch.init(std.testing.allocator, 2);    defer batch.deinit();    try batch.pushUpsertEdit(.{        .edit_id = "empty-intersect",        .asset_id = "empty",        .op = .intersect,    });    try batch.pushUpsertEdit(.{        .edit_id = "unknown-intersect",        .asset_id = "missing",        .op = .intersect,    });    _ = try engine.world.submit(&batch, null);    const second = engine.frameStep(.{        .frame_index = 1,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), second.diagnostic_flags);    try std.testing.expectEqual(first_collision_index, engine.collision_compile.active_index);    const second_collision = engine.compiler.collisionPublished() orelse return error.TestUnexpectedResult;    try std.testing.expectEqual(first_collision.revision, second_collision.revision);    try std.testing.expectEqual(        @intFromPtr(first_collision_scene.nodes.ptr),        @intFromPtr((second_collision.scene orelse return error.TestUnexpectedResult).nodes.ptr),    );}test "failed scene publication retains owned consumers and permits retry" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const sdf_types = @import("sdfii_sdf").types;    const first_nodes = [_]SceneArtifact.NativeNodeDesc{.{        .kind_id = @backingInt(sdf_types.NodeKind.sphere),        .f0 = 1.0,    }};    try engine.publishSceneEdit(&first_nodes, &.{}, 0);    const first = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    const committed_nodes = engine.compiled_artifact.?.sdfProgram().?.nodes.ptr;    const binding = try engine.bindAcousticExecutor();    var points = [_]@import("linear").Vec3{.{}};    var distances = [_]f32{0};    try binding.executor.sampleDistances(.{ .points = &points, .distances_out = &distances });    const replacement_nodes = [_]SceneArtifact.NativeNodeDesc{.{        .kind_id = @backingInt(sdf_types.NodeKind.sphere),        .f0 = 0.25,    }};    var edit_failure = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    engine.scene.allocator = edit_failure.allocator();    try std.testing.expectError(error.OutOfMemory, engine.publishSceneEdit(&replacement_nodes, &.{}, 0));    engine.scene.allocator = std.testing.allocator;    try std.testing.expectEqual(first.published_revision, engine.readSceneRuntime().published_revision);    try std.testing.expectEqual(@intFromPtr(committed_nodes), @intFromPtr(engine.compiled_artifact.?.sdfProgram().?.nodes.ptr));    try std.testing.expectEqual(@intFromPtr(committed_nodes), @intFromPtr(engine.scene.activePublished(&engine.compiler).?.scene.?.nodes.ptr));    try std.testing.expectEqual(first.published_revision, try engine.currentQueryRevision());    try binding.executor.sampleDistances(.{ .points = &points, .distances_out = &distances });    try std.testing.expect(engine.readRenderRuntime().frame_valid);    var metadata_failure = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    engine.scene.allocator = metadata_failure.allocator();    try std.testing.expectError(        error.OutOfMemory,        engine.publishScene(.{ .add_material = .{ .diffuse = 0.5 } }),    );    engine.scene.allocator = std.testing.allocator;    try std.testing.expectEqual(first.published_revision, engine.readSceneRuntime().published_revision);    try std.testing.expectEqual(@intFromPtr(committed_nodes), @intFromPtr(engine.compiled_artifact.?.sdfProgram().?.nodes.ptr));    try std.testing.expectEqual(first.published_revision, try engine.currentQueryRevision());    try binding.executor.sampleDistances(.{ .points = &points, .distances_out = &distances });    try engine.publishSceneEdit(&replacement_nodes, &.{}, 0);    try std.testing.expect(engine.compiled_artifact == null);    try std.testing.expectError(error.NoRevisionBound, engine.currentQueryRevision());    try std.testing.expectError(        error.ArtifactNotBound,        binding.executor.sampleDistances(.{ .points = &points, .distances_out = &distances }),    );    const retried = engine.frameStep(.{ .frame_index = 1, .dt_s = 0.0 });    try std.testing.expect(retried.published_revision > first.published_revision);    try std.testing.expectEqual(retried.published_revision, try engine.currentQueryRevision());}test "compile scene artifact failure preserves the committed revision and history" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const entity = try seedShapeEntity(&engine);    const completed = engine.frameStep(.{        .frame_index = 20,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    const committed_revision = completed.published_revision;    const committed_compiler_revision = engine.compiler.published().?.revision;    const committed_nodes = engine.compiled_artifact.?.sdfProgram().?.nodes.ptr;    const committed_context_frame = engine.last_frame_context.frame_index;    const committed_history_count = engine.frame_history.count;    var transform = engine.world.transforms.getDesc(entity.index).?;    transform.pos_x = 2.0;    try engine.world.transforms.insert(entity.index, transform);    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    engine.artifact_allocator = failing.allocator();    const failed = engine.frameStep(.{        .frame_index = 21,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    engine.artifact_allocator = std.testing.allocator;    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(step.diagnostic_task_skipped, failed.diagnostic_flags & step.diagnostic_task_skipped);    try std.testing.expectEqual(frame_mod.task_graph.TaskName.compile_scene, engine.last_task_run.first_failure.?.task);    try std.testing.expectEqual(error.OutOfMemory, engine.last_task_run.first_failure.?.err);    try std.testing.expectEqual(committed_revision, failed.published_revision);    try std.testing.expectEqual(committed_revision, engine.readSceneRuntime().published_revision);    try std.testing.expectEqual(committed_compiler_revision, engine.compiler.published().?.revision);    try std.testing.expectEqual(committed_revision, try engine.currentQueryRevision());    try std.testing.expectEqual(@intFromPtr(committed_nodes), @intFromPtr(engine.compiled_artifact.?.sdfProgram().?.nodes.ptr));    try std.testing.expectEqual(@intFromPtr(committed_nodes), @intFromPtr(engine.scene.activePublished(&engine.compiler).?.scene.?.nodes.ptr));    try std.testing.expectEqual(@intFromPtr(committed_nodes), @intFromPtr(engine.queries.nodes.?.ptr));    try std.testing.expectEqual(committed_context_frame, engine.last_frame_context.frame_index);    try std.testing.expectEqual(committed_history_count, engine.frame_history.count);    const recovered = engine.frameStep(.{        .frame_index = 22,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), recovered.diagnostic_flags);    try std.testing.expect(recovered.published_revision > committed_revision);    try expectActiveSceneAgreement(&engine, recovered.published_revision);    try std.testing.expectEqual(committed_history_count + 1, engine.frame_history.count);}test "repeated collision gather failures retain one scratch high water and retry" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    var engine = Self.init(failing.allocator(), .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const entity = try seedShapeEntity(&engine);    _ = try engine.publishScene(.{ .add_material = .{        .ambient = 0.15,        .diffuse = 0.65,        .specular = 0.2,        .shininess = 8.0,    } });    const completed = engine.frameStep(.{        .frame_index = 70,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), completed.diagnostic_flags);    const committed = try captureCommittedFrameProducts(&engine);    try std.testing.expectEqual(@as(usize, 1), committed.artifact_material_count);    var transform = engine.world.transforms.getDesc(entity.index) orelse return error.TestUnexpectedResult;    transform.pos_x = 1.5;    try engine.world.transforms.insert(entity.index, transform);    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    var failed: types.FrameStepResult = undefined;    var scratch_high_water_capacity: usize = 0;    for (0..16) |attempt| {        failed = engine.frameStep(.{            .frame_index = 71 + attempt,            .dt_s = 0.0,            .render_width = 8,            .render_height = 8,        });        try std.testing.expect(failing.has_induced_failure);        try std.testing.expectEqual(frame_mod.task_graph.TaskName.compile_collision, engine.last_task_run.first_failure.?.task);        const scratch_capacity = engine.scene.scratch.queryCapacity();        try std.testing.expect(scratch_capacity != 0);        if (attempt == 0) {            scratch_high_water_capacity = scratch_capacity;        } else {            try std.testing.expectEqual(scratch_high_water_capacity, scratch_capacity);        }    }    const failure = engine.last_task_run.first_failure.?;    try std.testing.expectEqual(frame_mod.task_graph.TaskName.compile_collision, failure.task);    try std.testing.expectEqual(step.TaskFailureStage.execution, failure.stage);    try std.testing.expectEqual(error.OutOfMemory, failure.err);    try std.testing.expectEqual(frame_mod.task_graph.TaskState.failed, engine.last_task_run.outcomes.state(.compile_collision));    inline for (.{        frame_mod.task_graph.TaskName.physics,        frame_mod.task_graph.TaskName.animation,        frame_mod.task_graph.TaskName.compile_scene,        frame_mod.task_graph.TaskName.behavior,        frame_mod.task_graph.TaskName.ui_render,        frame_mod.task_graph.TaskName.render,    }) |task| try std.testing.expectEqual(frame_mod.task_graph.TaskState.skipped, engine.last_task_run.outcomes.state(task));    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(step.diagnostic_task_skipped, failed.diagnostic_flags & step.diagnostic_task_skipped);    try std.testing.expectEqual(@as(u8, 0), failed.recompiled);    try std.testing.expectEqual(@as(u8, 0), failed.render_valid);    try std.testing.expectEqual(committed.published_revision, failed.published_revision);    try expectCommittedFrameProductsUnchanged(&engine, committed);    failing.fail_index = std.math.maxInt(usize);    failing.resize_fail_index = std.math.maxInt(usize);    const recovered = engine.frameStep(.{        .frame_index = 87,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), recovered.diagnostic_flags);    try std.testing.expectEqual(@as(u8, 1), recovered.recompiled);    try std.testing.expectEqual(@as(u8, 1), recovered.render_valid);    const advanced = try captureCommittedFrameProducts(&engine);    try std.testing.expectEqual(committed.published_revision + 1, advanced.published_revision);    try std.testing.expectEqual(committed.collision_revision + 1, advanced.collision_revision);    try std.testing.expectEqual(committed.compiler_revision + 1, advanced.compiler_revision);    try std.testing.expectEqual(committed.compiler_collision_revision + 1, advanced.compiler_collision_revision);    try std.testing.expectEqual(advanced.published_revision, advanced.query_revision);    try std.testing.expectEqual(advanced.published_revision, advanced.render_projection_revision);    try std.testing.expectEqual(advanced.published_revision, advanced.frame_published_revision);    try std.testing.expectEqual(committed.history_count + 1, advanced.history_count);}test "repeated scene gather failures retain one scratch high water and retry" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    var engine = Self.init(failing.allocator(), .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const entity = try seedShapeEntity(&engine);    _ = try engine.publishScene(.{ .add_material = .{        .ambient = 0.1,        .diffuse = 0.7,        .specular = 0.2,        .shininess = 12.0,    } });    var batch = try WorldCommands.Batch.init(std.testing.allocator, 2);    defer batch.deinit();    const body = PhysicsWorld.PhysicsComponentDesc{ .motion_type = 0 };    try batch.pushUpsertComponent(        entity,        @backingInt(Schema.ComponentSchema.physics),        std.mem.asBytes(&body),    );    try batch.pushUpsertEdit(.{        .edit_id = "visual-edit",        .asset_id = "sphere",        .params = "{\"radius\":1.0}",        .dynamic = true,        .collidable = false,    });    _ = try engine.world.submit(&batch, null);    const completed = engine.frameStep(.{        .frame_index = 80,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), completed.diagnostic_flags);    const committed = try captureCommittedFrameProducts(&engine);    try std.testing.expectEqual(@as(usize, 1), committed.artifact_material_count);    try batch.pushUpsertEdit(.{        .edit_id = "visual-edit",        .asset_id = "sphere",        .params = "{\"radius\":0.5}",        .dynamic = true,        .collidable = false,    });    _ = try engine.world.submit(&batch, null);    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    var failed: types.FrameStepResult = undefined;    var scratch_high_water_capacity: usize = 0;    for (0..16) |attempt| {        failed = engine.frameStep(.{            .frame_index = 81 + attempt,            .dt_s = 0.0,            .render_width = 8,            .render_height = 8,        });        try std.testing.expect(failing.has_induced_failure);        try std.testing.expectEqual(frame_mod.task_graph.TaskName.compile_scene, engine.last_task_run.first_failure.?.task);        const scratch_capacity = engine.scene.scratch.queryCapacity();        try std.testing.expect(scratch_capacity != 0);        if (attempt == 0) {            scratch_high_water_capacity = scratch_capacity;        } else {            try std.testing.expectEqual(scratch_high_water_capacity, scratch_capacity);        }    }    const failure = engine.last_task_run.first_failure.?;    try std.testing.expectEqual(frame_mod.task_graph.TaskName.compile_scene, failure.task);    try std.testing.expectEqual(step.TaskFailureStage.execution, failure.stage);    try std.testing.expectEqual(error.OutOfMemory, failure.err);    try std.testing.expectEqual(frame_mod.task_graph.TaskState.failed, engine.last_task_run.outcomes.state(.compile_scene));    inline for (.{        frame_mod.task_graph.TaskName.behavior,        frame_mod.task_graph.TaskName.ui_render,        frame_mod.task_graph.TaskName.render,    }) |task| try std.testing.expectEqual(frame_mod.task_graph.TaskState.skipped, engine.last_task_run.outcomes.state(task));    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(step.diagnostic_task_skipped, failed.diagnostic_flags & step.diagnostic_task_skipped);    try std.testing.expectEqual(@as(u8, 0), failed.recompiled);    try std.testing.expectEqual(@as(u8, 0), failed.render_valid);    try std.testing.expectEqual(committed.published_revision, failed.published_revision);    try expectCommittedFrameProductsUnchanged(&engine, committed);    failing.fail_index = std.math.maxInt(usize);    failing.resize_fail_index = std.math.maxInt(usize);    const recovered = engine.frameStep(.{        .frame_index = 97,        .dt_s = 0.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), recovered.diagnostic_flags);    try std.testing.expectEqual(@as(u8, 1), recovered.recompiled);    try std.testing.expectEqual(@as(u8, 1), recovered.render_valid);    const advanced = try captureCommittedFrameProducts(&engine);    try std.testing.expectEqual(committed.published_revision + 1, advanced.published_revision);    try std.testing.expectEqual(committed.collision_revision, advanced.collision_revision);    try std.testing.expectEqual(committed.compiler_revision + 1, advanced.compiler_revision);    try std.testing.expectEqual(committed.compiler_collision_revision, advanced.compiler_collision_revision);    try std.testing.expectEqual(advanced.published_revision, advanced.query_revision);    try std.testing.expectEqual(advanced.published_revision, advanced.render_projection_revision);    try std.testing.expectEqual(advanced.published_revision, advanced.frame_published_revision);    try std.testing.expectEqual(committed.history_count + 1, advanced.history_count);}test "world and authored scene transitions share one monotonic active generation" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 16, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const world_entity = try seedShapeEntity(&engine);    const world_first = engine.frameStep(.{        .frame_index = 0,        .dt_s = 0.0,        .render_width = 16,        .render_height = 8,    });    const sdf_types = @import("sdfii_sdf").types;    const nodes = [_]SceneArtifact.NativeNodeDesc{.{        .kind_id = @backingInt(sdf_types.NodeKind.sphere),        .f0 = 0.5,    }};    const committed_nodes = engine.compiled_artifact.?.sdfProgram().?.nodes.ptr;    const world_nodes = engine.compiler.published().?.scene.?.nodes.ptr;    try std.testing.expect(committed_nodes != world_nodes);    try engine.publishSceneEdit(&nodes, &.{}, 0);    const safe_world = engine.currentPublishedScene();    try std.testing.expect(safe_world.has_value);    try std.testing.expectEqual(@intFromPtr(world_nodes), @intFromPtr(safe_world.value.scene.?.nodes.ptr));    try std.testing.expect(@intFromPtr(committed_nodes) != @intFromPtr(safe_world.value.scene.?.nodes.ptr));    try std.testing.expectError(error.NoRevisionBound, engine.currentQueryRevision());    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    engine.artifact_allocator = failing.allocator();    const failed = engine.frameStep(.{        .frame_index = 1,        .dt_s = 0.0,        .render_width = 16,        .render_height = 8,    });    engine.artifact_allocator = std.testing.allocator;    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(frame_mod.task_graph.TaskName.compile_scene, engine.last_task_run.first_failure.?.task);    try std.testing.expectEqual(error.OutOfMemory, engine.last_task_run.first_failure.?.err);    const failed_safe_world = engine.currentPublishedScene();    try std.testing.expect(failed_safe_world.has_value);    try std.testing.expectEqual(@intFromPtr(world_nodes), @intFromPtr(failed_safe_world.value.scene.?.nodes.ptr));    try std.testing.expectError(error.NoRevisionBound, engine.currentQueryRevision());    const world_second = engine.frameStep(.{        .frame_index = 2,        .dt_s = 0.0,        .render_width = 16,        .render_height = 8,    });    try std.testing.expectEqual(world_first.published_revision, world_second.published_revision);    var batch = try WorldCommands.Batch.init(std.testing.allocator, 1);    defer batch.deinit();    try batch.pushDespawn(world_entity);    _ = try engine.world.submit(&batch, null);    const edit = engine.frameStep(.{        .frame_index = 3,        .dt_s = 0.0,        .render_width = 16,        .render_height = 8,    });    try std.testing.expect(edit.published_revision > world_second.published_revision);    try expectActiveSceneAgreement(&engine, edit.published_revision);    _ = try seedShapeEntity(&engine);    const world_third = engine.frameStep(.{        .frame_index = 4,        .dt_s = 0.0,        .render_width = 16,        .render_height = 8,    });    try std.testing.expect(world_third.published_revision > edit.published_revision);    try expectActiveSceneAgreement(&engine, world_third.published_revision);}fn expectActiveSceneAgreement(engine: *Self, revision: u64) !void {    const snapshot = engine.readSceneRuntime();    const render = engine.readRenderRuntime();    try std.testing.expectEqual(revision, snapshot.published_revision);    try std.testing.expectEqual(revision, snapshot.render_projection_revision);    try std.testing.expectEqual(revision, try engine.currentQueryRevision());    try std.testing.expectEqual(revision, render.render_projection_revision);    try std.testing.expectEqual(revision, render.frame_published_revision);    try std.testing.expect(engine.queries.isBoundTo(revision));    try std.testing.expect(render.frame_valid);}test "frameStep publishes deterministic typed task products" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    _ = try seedShapeEntity(&engine);    const result = engine.frameStep(.{        .frame_index = 11,        .dt_s = 1.0 / 60.0,        .input_event_count = 0,        .render_width = 0,        .render_height = 0,    });    const scene_runtime = engine.readSceneRuntime();    const ui_frame = engine.readUiPublishedFrame();    try std.testing.expect(scene_runtime.collision_revision != 0);    try std.testing.expect(scene_runtime.published_revision != 0);    try std.testing.expectEqual(result.published_revision, scene_runtime.published_revision);    try std.testing.expect(engine.queries.isBoundTo(result.published_revision));    try std.testing.expectEqual(result.frame_index, ui_frame.revision);    try std.testing.expectEqual(        frame_mod.task_graph.defaultGraph().tasks.len + @as(usize, result.fixed_step_count),        engine.phase_count,    );    try std.testing.expectEqual(@as(u32, 0), result.diagnostic_flags & step.diagnostic_task_failed);    try engine.last_frame_context.stages.assertCompleted(.simulation);    try engine.last_frame_context.stages.assertCompleted(.scene_compile);    try engine.last_frame_context.stages.assertCompleted(.render_extract);    try engine.last_frame_context.stages.assertCompleted(.render_submit);    const capture = try engine.captureLastFrame(std.testing.allocator);    try std.testing.expectEqual(result.frame_index, capture.frame_index);    try std.testing.expectEqual(result.published_revision, capture.revisions.published_revision);    try std.testing.expectEqual(scene_runtime.collision_revision, capture.revisions.collision_revision);    try std.testing.expect(capture.stage_count >= frame_mod.stage_count);    try std.testing.expectEqual(engine.last_frame_context.phase_timings.get(.total), capture.timings[@backingInt(frame_mod.Phase.total)].elapsed_ns);    try std.testing.expectEqual(frame_mod.allocator.tag_count, capture.allocation_count);    try std.testing.expectEqualStrings("frame", capture.allocations[@backingInt(frame_mod.allocator.Tag.frame)].tag);    try std.testing.expect(capture.allocations[@backingInt(frame_mod.allocator.Tag.frame)].peak_bytes > 0);    try std.testing.expectEqualStrings("query", capture.allocations[@backingInt(frame_mod.allocator.Tag.query)].tag);    try std.testing.expect(capture.allocations[@backingInt(frame_mod.allocator.Tag.query)].current_bytes > 0);    try std.testing.expectEqualStrings("demo_validation", capture.allocations[@backingInt(frame_mod.allocator.Tag.demo_validation)].tag);    const latest = engine.frameHistoryLatest().?;    try std.testing.expectEqual(result.frame_index, latest.frame_index);    try std.testing.expectEqual(result.published_revision, latest.published_revision);    try std.testing.expect(latest.task_count >= frame_mod.phase_count);    try std.testing.expectEqual(frame_mod.allocator.tag_count, latest.allocation_count);    try std.testing.expectEqualStrings("scene_compile", latest.allocations[@backingInt(frame_mod.allocator.Tag.scene_compile)].tag);    try std.testing.expect(latest.render_graph.pass_count > 0);    try std.testing.expect(latest.render_graph.resource_count > 0);    try std.testing.expectEqualStrings(expectedLiveRenderBackend(&engine), latest.backend.selected_backend);    try std.testing.expect(latest.backend.upload_mode.len != 0);}test "SDFII Engine physics scratch exposes its derived caller limits" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./system/physics/scratch/root.zig").Store, "sdfii_physics_scratch_public"),            null,            null,            null,            null,            null,            null,        );    }    var engine = Self.init(std.testing.allocator, .{        .entity_capacity = 3,        .physics_scratch = .{ .program_nodes = 2 },    });    defer engine.deinit();    const status = engine.readPhysicsScratch();    try std.testing.expectEqual(@as(usize, 3), status.capacity.bodies);    try std.testing.expectEqual(@as(usize, 2), status.capacity.program_nodes);    try std.testing.expectEqual(@as(usize, 18), status.capacity.default_loss_values);    try std.testing.expect(status.capacity.storage_bytes > 0);}test "SDFII Engine physics scratch preserves the last published frame on overload" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./system/physics/scratch/root.zig").Store, "sdfii_physics_scratch_engine_full"),            null,            null,            null,            null,            null,            null,        );    }    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 1, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const entity = try seedShapeEntity(&engine);    var batch = try WorldCommands.Batch.init(std.testing.allocator, 2);    defer batch.deinit();    const body = PhysicsWorld.PhysicsComponentDesc{        .collider_type = 1,        .collider_radius = 0.5,    };    try batch.pushUpsertComponent(        entity,        @backingInt(Schema.ComponentSchema.physics),        std.mem.asBytes(&body),    );    _ = try engine.world.submit(&batch, null);    const completed = engine.frameStep(.{        .frame_index = 20,        .dt_s = 1.0 / 60.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), completed.diagnostic_flags);    const published_revision = completed.published_revision;    const rendered_revision = engine.readRenderRuntime().frame_published_revision;    const context_frame_index = engine.last_frame_context.frame_index;    const history_count = engine.frame_history.count;    const ui_revision = engine.readUiPublishedFrame().revision;    const physics_snapshot = engine.readPhysicsRuntime();    const body_pointer = engine.physics_scratch.bodies.ptr;    const overflow_entity = try seedShapeEntity(&engine);    try batch.pushUpsertComponent(        overflow_entity,        @backingInt(Schema.ComponentSchema.physics),        std.mem.asBytes(&body),    );    _ = try engine.world.submit(&batch, null);    const failed = engine.frameStep(.{        .frame_index = 21,        .dt_s = 1.0 / 60.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(step.diagnostic_task_skipped, failed.diagnostic_flags & step.diagnostic_task_skipped);    try std.testing.expectEqual(@as(u8, 0), failed.recompiled);    try std.testing.expectEqual(@as(u8, 0), failed.render_valid);    try std.testing.expectEqual(@as(u32, 0), failed.behavior_execution_count);    const failure = engine.last_task_run.first_failure.?;    try std.testing.expectEqual(frame_mod.task_graph.TaskName.physics, failure.task);    try std.testing.expectEqual(step.TaskFailureStage.execution, failure.stage);    try std.testing.expectEqual(error.PhysicsBodyCapacityExceeded, failure.err);    try std.testing.expectEqual(frame_mod.task_graph.TaskState.failed, engine.last_task_run.outcomes.state(.physics));    inline for (.{        frame_mod.task_graph.TaskName.animation,        frame_mod.task_graph.TaskName.compile_scene,        frame_mod.task_graph.TaskName.behavior,        frame_mod.task_graph.TaskName.ui_render,        frame_mod.task_graph.TaskName.render,    }) |task| {        try std.testing.expectEqual(frame_mod.task_graph.TaskState.skipped, engine.last_task_run.outcomes.state(task));    }    try std.testing.expectEqual(published_revision, failed.published_revision);    const failed_scene = engine.readSceneRuntime();    try std.testing.expectEqual(published_revision, failed_scene.published_revision);    try std.testing.expect(!failed_scene.recompiled);    try std.testing.expectEqual(rendered_revision, engine.readRenderRuntime().frame_published_revision);    try std.testing.expectEqual(ui_revision, engine.readUiPublishedFrame().revision);    try std.testing.expectEqual(context_frame_index, engine.last_frame_context.frame_index);    try std.testing.expectEqual(history_count, engine.frame_history.count);    try std.testing.expectEqual(physics_snapshot, engine.readPhysicsRuntime());    try std.testing.expect(engine.physics_scratch.bodies.ptr == body_pointer);}test "control allocation failure preserves world and desired pose atomically" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const controller_schema: u64 = @backingInt(Schema.ComponentSchema.controller);    var batch = try WorldCommands.Batch.init(std.testing.allocator, 4);    defer batch.deinit();    try batch.pushSpawn("Actor", "failing-input-actor", .{        .pos_x = 0.0,        .pos_y = -0.35,        .pos_z = 0.0,        .scale = 1.0,    });    var spawned: [1]WorldStore.EntityId = undefined;    _ = try engine.world.submit(&batch, spawned[0..]);    const controller = ControllerComponent.ComponentDesc{        .session_id = 1,        .walk_speed = 3.2,        .strafe_speed = 2.4,        .ground_y = -0.35,    };    try batch.pushUpsertComponent(spawned[0], controller_schema, std.mem.asBytes(&controller));    _ = try engine.world.submit(&batch, null);    try publishRawDeviceEventForTest(&engine, InputRuntime.event_key_down, InputRuntime.key_d, 1.0);    const before = engine.world.transformDesc(spawned[0]) orelse return error.TestUnexpectedResult;    try std.testing.expect(engine.physics.desiredTransform(spawned[0]) == null);    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    const allocator = engine.allocator;    engine.allocator = failing.allocator();    const failed = engine.frameStep(.{        .frame_index = 30,        .dt_s = 1.0 / 60.0,        .input_event_count = 1,    });    engine.allocator = allocator;    const failure = engine.last_task_run.first_failure.?;    try std.testing.expectEqual(frame_mod.task_graph.TaskName.control, failure.task);    try std.testing.expectEqual(step.TaskFailureStage.execution, failure.stage);    try std.testing.expectEqual(error.OutOfMemory, failure.err);    try std.testing.expectEqual(frame_mod.task_graph.TaskState.failed, engine.last_task_run.outcomes.state(.control));    inline for (.{        frame_mod.task_graph.TaskName.compile_collision,        frame_mod.task_graph.TaskName.physics,        frame_mod.task_graph.TaskName.animation,        frame_mod.task_graph.TaskName.compile_scene,        frame_mod.task_graph.TaskName.behavior,        frame_mod.task_graph.TaskName.ui_render,        frame_mod.task_graph.TaskName.render,    }) |task| try std.testing.expectEqual(frame_mod.task_graph.TaskState.skipped, engine.last_task_run.outcomes.state(task));    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(step.diagnostic_task_skipped, failed.diagnostic_flags & step.diagnostic_task_skipped);    try std.testing.expectEqual(before, engine.world.transformDesc(spawned[0]).?);    try std.testing.expect(engine.physics.desiredTransform(spawned[0]) == null);}test "animation shape parameter failure preserves binding and world publication" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const entity = try seedShapeEntity(&engine);    try engine.bindShapeAsset(entity, "sphere");    try engine.bindShapeParam(entity, "radius", 0.0);    var clip = try curve.ParameterClip.init(std.testing.allocator, "radius", 1.0, 1);    defer clip.deinit(std.testing.allocator);    _ = try clip.addCurve(std.testing.allocator, &.{ 0.0, 1.0 }, &.{ 1.0, 2.0 }, 1);    var mixer = try curve.ParameterMixer.init(std.testing.allocator, 2);    defer mixer.deinit(std.testing.allocator);    var fsm = try curve.ParameterMachine.init(std.testing.allocator, &mixer, 2, 1);    defer fsm.deinit(std.testing.allocator);    const state = try fsm.addState(&clip, "radius", .{ .loop = false });    try fsm.setInitialState(state);    const controller_id = try engine.animation.attachFsm(std.testing.allocator, &fsm);    try engine.animation.bindShapeParam(        std.testing.allocator,        &engine.world,        controller_id,        entity,        "radius",        0,        1.0,        0.0,    );    const completed = engine.frameStep(.{ .frame_index = 35, .dt_s = 0.0 });    try std.testing.expectEqual(@as(u32, 0), completed.diagnostic_flags);    var binding = try shape_binding.readAssetBinding(std.testing.allocator, &engine.world, entity);    defer binding.deinit(std.testing.allocator);    try std.testing.expectEqual(@as(f32, 1.0), binding.params.get("radius").?);    const shape_schema_id: u64 = @backingInt(Schema.ComponentSchema.shape);    const before_component = engine.world.components.get(entity.index, shape_schema_id) orelse return error.TestUnexpectedResult;    const before_payload = try std.testing.allocator.dupe(u8, before_component.payload.slice());    defer std.testing.allocator.free(before_payload);    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    const allocator = engine.allocator;    engine.allocator = failing.allocator();    const failed = engine.frameStep(.{ .frame_index = 36, .dt_s = 0.5 });    engine.allocator = allocator;    const failure = engine.last_task_run.first_failure.?;    try std.testing.expectEqual(frame_mod.task_graph.TaskName.animation, failure.task);    try std.testing.expectEqual(error.OutOfMemory, failure.err);    try std.testing.expectEqual(frame_mod.task_graph.TaskState.failed, engine.last_task_run.outcomes.state(.animation));    inline for (.{        frame_mod.task_graph.TaskName.compile_scene,        frame_mod.task_graph.TaskName.behavior,        frame_mod.task_graph.TaskName.ui_render,        frame_mod.task_graph.TaskName.render,    }) |task| try std.testing.expectEqual(frame_mod.task_graph.TaskState.skipped, engine.last_task_run.outcomes.state(task));    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(step.diagnostic_task_skipped, failed.diagnostic_flags & step.diagnostic_task_skipped);    var updated_binding = try shape_binding.readAssetBinding(std.testing.allocator, &engine.world, entity);    defer updated_binding.deinit(std.testing.allocator);    try std.testing.expectEqual(@as(f32, 1.0), updated_binding.params.get("radius").?);    const after_component = engine.world.components.get(entity.index, shape_schema_id) orelse return error.TestUnexpectedResult;    try std.testing.expectEqualSlices(u8, before_payload, after_component.payload.slice());}test "shape binding API edits the active play world without mutating authoring" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const entity = try seedShapeEntity(&engine);    try engine.enterPlay();    try engine.bindShapeParam(entity, "radius", 2.0);    var runtime_binding = try shape_binding.readAssetBinding(std.testing.allocator, engine.activeWorldConst(), entity);    defer runtime_binding.deinit(std.testing.allocator);    try std.testing.expectEqual(@as(f32, 2.0), runtime_binding.params.get("radius").?);    var authoring_while_playing = try shape_binding.readAssetBinding(std.testing.allocator, &engine.world, entity);    defer authoring_while_playing.deinit(std.testing.allocator);    try std.testing.expectEqual(@as(f32, 1.0), authoring_while_playing.params.get("radius").?);    engine.exitPlay();    var authoring_after_exit = try shape_binding.readAssetBinding(std.testing.allocator, &engine.world, entity);    defer authoring_after_exit.deinit(std.testing.allocator);    try std.testing.expectEqual(@as(f32, 1.0), authoring_after_exit.params.get("radius").?);}test "UI input allocation failure preserves interaction and published frame" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const root_id = 61;    try publishInputCaptureSurfaceForTest(&engine, root_id, false);    const completed = engine.frameStep(.{ .frame_index = 40, .dt_s = 1.0 / 60.0 });    try std.testing.expectEqual(@as(u32, 0), completed.diagnostic_flags);    const published = engine.readUiPublishedFrame().*;    const history_count = engine.frame_history.count;    try engine.publishUiCommand(.{ .pointer_event = .{        .root_id = root_id,        .kind = .down,        .x = 10,        .y = 10,    } });    engine.ui.input.pointers_staging.deinit();    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    engine.ui.input.pointers_staging = @TypeOf(engine.ui.input.pointers_staging).init(failing.allocator());    const failed = engine.frameStep(.{ .frame_index = 41, .dt_s = 1.0 / 60.0 });    const failure = engine.last_task_run.first_failure.?;    try std.testing.expectEqual(frame_mod.task_graph.TaskName.ui_input, failure.task);    try std.testing.expectEqual(error.OutOfMemory, failure.err);    try std.testing.expectEqual(frame_mod.task_graph.TaskState.failed, engine.last_task_run.outcomes.state(.ui_input));    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(step.diagnostic_task_skipped, failed.diagnostic_flags & step.diagnostic_task_skipped);    const after = engine.readUiPublishedFrame();    try std.testing.expectEqual(published.revision, after.revision);    try std.testing.expectEqual(published.root_count, after.root_count);    try std.testing.expectEqual(published.widget_count, after.widget_count);    try std.testing.expectEqual(published.roots.ptr, after.roots.ptr);    try std.testing.expectEqual(published.widgets.ptr, after.widgets.ptr);    try std.testing.expect(!engine.ui.capturesInput(root_id));    try std.testing.expectEqual(history_count, engine.frame_history.count);}test "UI render allocation failure preserves the last published UI frame" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const root_id = 71;    try publishInputCaptureSurfaceForTest(&engine, root_id, true);    const completed = engine.frameStep(.{ .frame_index = 50, .dt_s = 1.0 / 60.0 });    try std.testing.expectEqual(@as(u32, 0), completed.diagnostic_flags);    const published = engine.readUiPublishedFrame().*;    const history_count = engine.frame_history.count;    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    const allocator = engine.ui.renderer.session.allocator;    engine.ui.renderer.session.allocator = failing.allocator();    const failed = engine.frameStep(.{ .frame_index = 51, .dt_s = 1.0 / 60.0 });    engine.ui.renderer.session.allocator = allocator;    const failure = engine.last_task_run.first_failure.?;    try std.testing.expectEqual(frame_mod.task_graph.TaskName.ui_render, failure.task);    try std.testing.expectEqual(error.OutOfMemory, failure.err);    try std.testing.expectEqual(frame_mod.task_graph.TaskState.failed, engine.last_task_run.outcomes.state(.ui_render));    try std.testing.expectEqual(frame_mod.task_graph.TaskState.skipped, engine.last_task_run.outcomes.state(.render));    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(step.diagnostic_task_skipped, failed.diagnostic_flags & step.diagnostic_task_skipped);    const after = engine.readUiPublishedFrame();    try std.testing.expectEqual(published.revision, after.revision);    try std.testing.expectEqual(published.root_count, after.root_count);    try std.testing.expectEqual(published.widget_count, after.widget_count);    try std.testing.expectEqual(published.roots.ptr, after.roots.ptr);    try std.testing.expectEqual(published.widgets.ptr, after.widgets.ptr);    try std.testing.expectEqual(history_count, engine.frame_history.count);}test "render allocation failure preserves the last complete render product" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    _ = try seedShapeEntity(&engine);    const completed = engine.frameStep(.{        .frame_index = 60,        .dt_s = 1.0 / 60.0,        .render_width = 8,        .render_height = 8,    });    try std.testing.expectEqual(@as(u32, 0), completed.diagnostic_flags);    const rendered = engine.readRenderFrame();    try std.testing.expect(rendered.valid);    const history_count = engine.frame_history.count;    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0 });    const allocator = engine.renderer.allocator;    engine.renderer.allocator = failing.allocator();    const failed = engine.frameStep(.{        .frame_index = 61,        .dt_s = 1.0 / 60.0,        .render_width = 16,        .render_height = 16,    });    engine.renderer.allocator = allocator;    const failure = engine.last_task_run.first_failure.?;    try std.testing.expectEqual(frame_mod.task_graph.TaskName.render, failure.task);    try std.testing.expectEqual(error.OutOfMemory, failure.err);    try std.testing.expectEqual(frame_mod.task_graph.TaskState.failed, engine.last_task_run.outcomes.state(.render));    try std.testing.expectEqual(step.diagnostic_task_failed, failed.diagnostic_flags & step.diagnostic_task_failed);    try std.testing.expectEqual(@as(u32, 0), failed.diagnostic_flags & step.diagnostic_task_skipped);    const after = engine.readRenderFrame();    try std.testing.expect(after.valid);    try std.testing.expectEqual(rendered.width, after.width);    try std.testing.expectEqual(rendered.height, after.height);    try std.testing.expectEqual(rendered.published_revision, after.published_revision);    try std.testing.expectEqual(rendered.pixels.ptr, after.pixels.ptr);    try std.testing.expectEqual(history_count, engine.frame_history.count);}test "frameStep applies ClientInput during control phase" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const controller_schema: u64 = @backingInt(Schema.ComponentSchema.controller);    var batch = try WorldCommands.Batch.init(std.testing.allocator, 4);    defer batch.deinit();    try batch.pushSpawn("Actor", "input-actor", .{        .pos_x = 0.0,        .pos_y = -0.35,        .pos_z = 0.0,        .scale = 1.0,    });    var spawned: [1]WorldStore.EntityId = undefined;    _ = try engine.world.submit(&batch, spawned[0..]);    const controller = ControllerComponent.ComponentDesc{        .session_id = 1,        .walk_speed = 3.2,        .strafe_speed = 2.4,        .ground_y = -0.35,    };    try batch.pushUpsertComponent(spawned[0], controller_schema, std.mem.asBytes(&controller));    _ = try engine.world.submit(&batch, null);    try publishRawDeviceEventForTest(&engine, InputRuntime.event_key_down, InputRuntime.key_d, 1.0);    _ = engine.frameStep(.{        .frame_index = 0,        .dt_s = 1.0 / 60.0,        .input_event_count = 1,        .render_width = 0,        .render_height = 0,    });    const moved = engine.world.transformDesc(spawned[0]) orelse return error.TestUnexpectedResult;    try std.testing.expect(moved.pos_x > 0.0);}test "focused UI suppresses held movement for its bound input session" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const ui_root_id = 41;    const input_session_id = 7;    try engine.bindUiRootToInputSession(ui_root_id, input_session_id);    try publishInputCaptureSurfaceForTest(&engine, ui_root_id, true);    stepInputCaptureFrameForTest(&engine, 1, 0);    try engine.publishInputCommand(.{ .raw_device_event = .{        .session_id = input_session_id,        .event_type = InputRuntime.event_key_down,        .code = InputRuntime.key_w,        .value = 1,    } });    stepInputCaptureFrameForTest(&engine, 2, 1);    try std.testing.expectEqual(@as(f32, 1), engine.readClientInput(input_session_id).?.motion_y);    try engine.publishUiCommand(.{ .key_event = .{        .root_id = ui_root_id,        .key_code = Ui.key_tab,        .modifiers = 0,    } });    stepInputCaptureFrameForTest(&engine, 3, 1);    try expectSuppressedInputForTest(engine.readClientInput(input_session_id).?);    try engine.publishUiCommand(.{ .key_event = .{        .root_id = ui_root_id,        .key_code = Ui.key_escape,        .modifiers = 0,    } });    stepInputCaptureFrameForTest(&engine, 4, 1);    try std.testing.expectEqual(@as(f32, 1), engine.readClientInput(input_session_id).?.motion_y);}test "pointer-captured UI suppresses held movement for its bound input session" {    var engine = Self.init(std.testing.allocator, .{ .entity_capacity = 8, .physics_scratch = .{ .program_nodes = 0 } });    defer engine.deinit();    const ui_root_id = 51;    const input_session_id = 9;    try engine.bindUiRootToInputSession(ui_root_id, input_session_id);    try publishInputCaptureSurfaceForTest(&engine, ui_root_id, false);    stepInputCaptureFrameForTest(&engine, 1, 0);    try engine.publishInputCommand(.{ .raw_device_event = .{        .session_id = input_session_id,        .event_type = InputRuntime.event_key_down,        .code = InputRuntime.key_w,        .value = 1,    } });    stepInputCaptureFrameForTest(&engine, 2, 1);    try std.testing.expectEqual(@as(f32, 1), engine.readClientInput(input_session_id).?.motion_y);    try engine.publishUiCommand(.{ .pointer_event = .{        .root_id = ui_root_id,        .kind = .down,        .x = 10,        .y = 10,    } });    stepInputCaptureFrameForTest(&engine, 3, 1);    try expectSuppressedInputForTest(engine.readClientInput(input_session_id).?);    try engine.publishUiCommand(.{ .pointer_event = .{        .root_id = ui_root_id,        .kind = .up,        .x = 10,        .y = 10,    } });    stepInputCaptureFrameForTest(&engine, 4, 1);    try std.testing.expectEqual(@as(f32, 1), engine.readClientInput(input_session_id).?.motion_y);}fn publishInputCaptureSurfaceForTest(engine: *Self, root_id: u64, with_focusable_child: bool) !void {    const model = @import("gui").model;    const children = [_]model.UiNode{.{        .widget_id = 2,        .kind = .button,        .size = .{ .width = 40, .height = 20 },        .focusable = true,    }};    const tree = UiSurfaceTree{        .available_size = .{ .width = 100, .height = 40 },        .root = .{            .widget_id = 1,            .size = .{ .width = 100, .height = 40 },            .children = if (with_focusable_child) &children else &.{},        },    };    try engine.publishUiSurface(root_id, 1, .{ .tree = &tree });}fn stepInputCaptureFrameForTest(engine: *Self, frame_index: u64, input_event_count: usize) void {    _ = engine.worldStep(.{ .command_count = 0 }, .{        .frame_index = frame_index,        .dt_s = 1.0 / 60.0,        .input_event_count = input_event_count,    });}fn expectSuppressedInputForTest(snapshot: ClientInputSnapshot) !void {    try std.testing.expectEqual(@as(f32, 0), snapshot.motion_x);    try std.testing.expectEqual(@as(f32, 0), snapshot.motion_y);    try std.testing.expectEqual(@as(f32, 0), snapshot.look_x);    try std.testing.expectEqual(@as(f32, 0), snapshot.look_y);    try std.testing.expectEqual(@as(u32, 0), snapshot.verb_bits);}fn publishRawDeviceEventForTest(    engine: *Self,    event_type: u8,    code: u32,    value: f32,) !void {    try engine.publishInputCommand(.{ .raw_device_event = .{        .session_id = 1,        .event_type = event_type,        .code = code,        .value = value,    } });}

Source: fun/sdfii/src/root.zig:14

zig
pub const Engine = engine.Engine;

Source: fun/sdfii/src/engine/system/ui/command.zig:6

zig
pub const UiPublishedFrame = model.UiFrame;

Source: fun/sdfii/src/engine/system/ui/command.zig:5

zig
pub const UiSurface = gui.surface.Surface;

Source: fun/sdfii/src/engine/system/ui/command.zig:4

zig
pub const UiSurfaceTree = model.UiSurfaceTree;

Complete caller list for Engine.deinit

16 direct callers.

Audit

Definitions129
Public names129
Members85
Version26.7.0
Revisiondaab053ee433