Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-monorepo",
"version": "0.10.20",
"version": "0.10.21",
"private": true,
"engines": {
"node": ">=24"
Expand Down
2 changes: 1 addition & 1 deletion packages/data-ai/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "adobe-data-ai",
"version": "0.10.20",
"version": "0.10.21",
"description": "Architecture skills for @adobe/data — data-oriented modelling, archetype iteration, hot-path performance, and related conventions.",
"author": {
"name": "Adobe"
Expand Down
2 changes: 1 addition & 1 deletion packages/data-ai/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-ai",
"version": "0.10.20",
"version": "0.10.21",
"description": "Cross-agent architecture skills for @adobe/data — installable as a Claude Code plugin or copied into any Agent-Skills-compatible agent (Cursor, Codex).",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-gpu/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-gpu",
"version": "0.10.20",
"version": "0.10.21",
"description": "Adobe data WebGPU plugins and types for graphics and compute",
"type": "module",
"private": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,37 @@ import {

interface InstCache { buffer: GPUBuffer; indexBuffer: GPUBuffer; bindGroup: GPUBindGroup; capacity: number }

interface StaticPrimDraw {
readonly primId: Entity;
readonly n: number;
readonly indexCount: number;
readonly indexFormat: GPUIndexFormat;
readonly vertexBuffer: GPUBuffer;
readonly indexBuffer: GPUBuffer;
readonly bindGroup: GPUBindGroup;
}

/**
* pbrFactorRender — instanced primitive PBR from material factors only (no map
* sampling). Extends `pbrIblRender` for IBL + skybox + optional glTF draws.
* Pairs with `materialPaletteGpu` (`_paletteIndex` on factor materials).
*
* Pairs with `materialPaletteGpu` (`_paletteIndex`). Idle when no factor materials or drawables exist.
*
* Set resource `_pbrFactorStaticInstances = true` for fully static scenes
* (e.g. terrain heightfield): after drawable count stabilizes, skip per-frame
* TRS gather + instance buffer uploads and only re-issue drawIndexed.
*/
export const pbrFactorRender = Database.Plugin.create({
extends: Database.Plugin.combine(pbrIblRender, materialPaletteGpu, displayTransform),
resources: {
/**
* When true, instance matrices are uploaded once the drawable set is
* stable; later frames only rebind and draw. Clear or leave false for
* scenes that move/add bodies every frame.
*/
_pbrFactorStaticInstances: { default: false as boolean, nonPersistent: true },
},
systems: {
pbrFactorPrimitiveRenderSystem: {
schedule: { during: ["render"], after: ["beginRenderPass", "pbrIblRenderSystem"], before: ["endRenderPass"] },
Expand All @@ -54,10 +76,15 @@ export const pbrFactorRender = Database.Plugin.create({
let mats = new Float32Array(64 * 16);
const batches = new Map<Entity, MeshBatch>();

let staticDraws: StaticPrimDraw[] | null = null;
let staticDrawCount = -1;
let staticStableFrames = 0;

return () => {
const {
device, renderPassEncoder, canvasFormat, depthFormat, _sceneUniformsBuffer,
_factorPaletteBindGroup, _iblIrradiance, _iblPrefiltered, _iblBrdfLut,
_pbrFactorStaticInstances,
} = db.store.resources;
if (!device || !renderPassEncoder || !_sceneUniformsBuffer || !_factorPaletteBindGroup) return;
if (!_iblIrradiance || !_iblPrefiltered || !_iblBrdfLut) return;
Expand Down Expand Up @@ -104,6 +131,21 @@ export const pbrFactorRender = Database.Plugin.create({
cachedIrradiance = _iblIrradiance;
}

// Static path: re-draw without re-gather / re-upload.
if (_pbrFactorStaticInstances && staticDraws != null && staticDraws.length > 0) {
renderPassEncoder.setPipeline(pipeline);
renderPassEncoder.setBindGroup(0, sceneBindGroup);
renderPassEncoder.setBindGroup(1, _factorPaletteBindGroup);
renderPassEncoder.setBindGroup(2, iblBindGroup);
for (const d of staticDraws) {
renderPassEncoder.setBindGroup(3, d.bindGroup);
renderPassEncoder.setVertexBuffer(0, d.vertexBuffer);
renderPassEncoder.setIndexBuffer(d.indexBuffer, d.indexFormat);
renderPassEncoder.drawIndexed(d.indexCount, d.n);
}
return;
}

let mc = 0;
for (const arch of db.store.queryArchetypes(["_paletteIndex"])) mc += arch.rowCount;
if (mc !== matCount) {
Expand Down Expand Up @@ -150,6 +192,8 @@ export const pbrFactorRender = Database.Plugin.create({
renderPassEncoder.setBindGroup(1, _factorPaletteBindGroup);
renderPassEncoder.setBindGroup(2, iblBindGroup);

const nextStatic: StaticPrimDraw[] = [];

for (const arch of db.store.queryArchetypes(PRIMITIVE)) {
const vbs = arch.columns._vertexBuffer, ibs = arch.columns._indexBuffer;
const counts = arch.columns._indexCount, formats = arch.columns._indexFormat;
Expand Down Expand Up @@ -187,7 +231,37 @@ export const pbrFactorRender = Database.Plugin.create({
renderPassEncoder.setVertexBuffer(0, vbs.get(i)!);
renderPassEncoder.setIndexBuffer(ibs.get(i)!, formats.get(i));
renderPassEncoder.drawIndexed(counts.get(i), n);

if (_pbrFactorStaticInstances) {
nextStatic.push({
primId,
n,
indexCount: counts.get(i),
indexFormat: formats.get(i),
vertexBuffer: vbs.get(i)!,
indexBuffer: ibs.get(i)!,
bindGroup: entry.bindGroup,
});
}
}
}

// Freeze only after the drawable set stops growing for one frame
// (mesh resolve / material assign finish during the first seconds).
if (_pbrFactorStaticInstances) {
if (drawCount === staticDrawCount && drawCount > 0) {
staticStableFrames++;
} else {
staticStableFrames = 0;
staticDrawCount = drawCount;
}
if (staticStableFrames >= 1 && nextStatic.length > 0) {
staticDraws = nextStatic;
}
} else {
staticDraws = null;
staticStableFrames = 0;
staticDrawCount = -1;
}
};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,22 @@ import { boundsFromShapeMesh } from "../../scene/model/shape/bounds-from-shape-m
import type { ColliderMesh } from "../../../physics/body/collider-mesh.js";
import { interpolation } from "../interpolation-plugin.js";

/** Authored column sets for primitive collider rows (RigidBody, ConvexBody,
* StaticCollider, MeshCollider). Query by these sets — not the named handle —
* so solver-tagged variants are found after migration. Rows with
* `voxelShapeName` are skipped at runtime (mechs voxel bodies). */
/**
* Authored column sets for primitive collider rows still missing a render mesh.
* - exclude `mesh` → once assigned, rows drop out of the scan (O(pending) not O(all)).
* - exclude `voxelShapeName` → mechs voxel bodies use voxelShapeVisualBridge only
* (never visit ~all static voxel colliders every frame).
*/
const PRIMITIVE_COLLIDER_QUERIES: readonly {
include: readonly string[];
exclude?: readonly string[];
exclude: readonly string[];
}[] = [
{ include: RIGID_BODY_COMPONENTS, exclude: ["convexPoints"] },
{ include: [...RIGID_BODY_COMPONENTS, "convexPoints"] },
{ include: STATIC_COLLIDER_COMPONENTS, exclude: ["colliderMesh"] },
{ include: [...STATIC_COLLIDER_COMPONENTS, "colliderMesh"] },
{ include: RIGID_BODY_COMPONENTS, exclude: ["convexPoints", "voxelShapeName", "mesh"] },
{ include: [...RIGID_BODY_COMPONENTS, "convexPoints"], exclude: ["voxelShapeName", "mesh"] },
{ include: STATIC_COLLIDER_COMPONENTS, exclude: ["colliderMesh", "voxelShapeName", "mesh"] },
{ include: [...STATIC_COLLIDER_COMPONENTS, "colliderMesh"], exclude: ["voxelShapeName", "mesh"] },
];

const hasVoxelShapeName = (store: { read(id: Entity): Record<string, unknown> | null }, id: Entity): boolean =>
store.read(id)?.voxelShapeName != null;

/**
* physicsRenderBridge — assigns default primitive render meshes for standard
* physics bodies whose visual is the collider primitive (RigidBody,
Expand Down Expand Up @@ -97,15 +96,13 @@ export const physicsRenderBridge = Database.Plugin.create({
for (const { include, exclude } of PRIMITIVE_COLLIDER_QUERIES) {
for (const arch of db.store.queryArchetypes(
include as typeof RIGID_BODY_COMPONENTS,
exclude ? { exclude: exclude as ["convexPoints"] | ["colliderMesh"] } : undefined,
{ exclude: exclude as ["mesh"] },
)) {
const ids = arch.columns.id;
const css = arch.columns.colliderShape;
const hes = arch.columns.halfExtents;
for (let i = arch.rowCount - 1; i >= 0; i--) {
const id = ids.get(i);
if (hasVoxelShapeName(db.store, id)) continue;
if (db.store.get(id, "mesh") != null) continue;
const shape = css.get(i);
const he = hes.get(i);
let meshId: Entity;
Expand Down
2 changes: 1 addition & 1 deletion packages/data-lit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-lit",
"version": "0.10.20",
"version": "0.10.21",
"description": "Adobe data Lit bindings - hooks, elements, decorators",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-persistence/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-persistence",
"version": "0.10.20",
"version": "0.10.21",
"description": "Worker-based incremental persistence layer for @adobe/data ECS over OPFS (browser) and node:fs (server).",
"type": "module",
"sideEffects": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-react",
"version": "0.10.20",
"version": "0.10.21",
"description": "Adobe data React bindings — hooks and context for ECS database",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-rpc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-rpc",
"version": "0.10.20",
"version": "0.10.21",
"description": "Schema-driven, bidirectional projection of @adobe/data async data services across a boundary (iframe / MessagePort / Worker). Only Data crosses the wire.",
"type": "module",
"sideEffects": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-solid/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-solid",
"version": "0.10.20",
"version": "0.10.21",
"description": "Adobe data SolidJS bindings — context and provider for ECS database",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-sync/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-sync",
"version": "0.10.20",
"version": "0.10.21",
"description": "Multi-user real-time synchronisation for @adobe/data ECS — server, client, and in-process loopback.",
"type": "module",
"sideEffects": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-testing/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-testing",
"version": "0.10.20",
"version": "0.10.21",
"description": "Conformance-testing utilities (Match + Conformance runners) for @adobe/data ECS features",
"type": "module",
"sideEffects": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data",
"version": "0.10.20",
"version": "0.10.21",
"description": "Adobe data oriented programming library",
"type": "module",
"sideEffects": false,
Expand Down
Loading