handles: one interleaved vertices/indices arena

Geometry becomes a span in a single 80-byte interleaved `vertices` array
plus a span in a single `indices` array, allocated through the core's
span allocator instead of one arena array per mesh attribute. Draws are
always indexed with baseVertex; face-material overrides emit one draw per
run of same-material faces rather than one per face. Vertex data is
validated as a whole before any span is touched, same-geometry mutations
are serialised, and render signal 4 is held across a span change until
the graph reflecting it is published. Sibling arrays grow to the primary
array's capacity in one batch; reserve() takes vertex/index totals.

Amp-Thread-ID: https://ampcode.com/threads/T-01a0b2dd-db32-712d-99ce-12ce4a86d979
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-09-18 07:00:36 +00:00
co-authored by heaust
parent 92638e6c9f
commit f324ff6bb2
5 changed files with 699 additions and 591 deletions
+14 -5
View File
@@ -87,7 +87,12 @@ declare module "@yawn/handles" {
stride: number,
format: "f32" | "u32" | "i32",
): Promise<SharedRows>;
reserve(additional: { nodes?: number; materials?: number }): Promise<void>;
reserve(additional: {
nodes?: number;
materials?: number;
vertices?: number;
indices?: number;
}): Promise<void>;
batchWrites<T>(operation: () => T): T;
batchGraphUpdates<T>(operation: () => T | Promise<T>): Promise<T>;
compileRenderGraph(serialized: string): Promise<string>;
@@ -149,18 +154,22 @@ declare module "@yawn/handles" {
export interface MeshOptions extends NodeOptions {
geometryId?: number;
material?: PBRMaterial;
vertexData?: Partial<Record<VertexKind, ArrayLike<number>>>;
vertexData?: VertexStreams;
visible?: boolean;
}
export type VertexStreams = Partial<Record<VertexKind, ArrayLike<number>>>;
export class Mesh extends Node {
constructor(scene: Scene, options?: MeshOptions);
geometryId: number;
vertexCount: number;
indexCount: number;
readonly vertexCount: number;
readonly indexCount: number;
isVisible: boolean;
material: PBRMaterial;
clone(options?: Omit<MeshOptions, "geometryId" | "vertexData">): Mesh;
setVertexData(kind: VertexKind, data: ArrayLike<number>): Promise<this>;
setVertexData(
kind: VertexKind | VertexStreams,
data?: ArrayLike<number>,
): Promise<this>;
setMaterialForFaces(
material: PBRMaterial,
faces: number | number[],