Skip to content

feat(acceptance): the #1259 integrated AAA acceptance scene, measured and attributed - #1597

Merged
drsnuggles8 merged 48 commits into
masterfrom
feature/integrated-aaa-acceptance-scene-1259
Oct 11, 2026
Merged

drsnuggles8 merged 48 commits into
masterfrom
feature/integrated-aaa-acceptance-scene-1259

Conversation

@drsnuggles8

Copy link
Copy Markdown
Owner

Refs #1259. Closes #1581. Refs #1578, #1580.

What this is

The #1259 acceptance gate: one generated scene holding every subject of the #1225 programme at once, captured on every backend and path under one protocol, with the result published. The gate (16.7 ms p95 with virtual shadow maps, 1920x1080, RTX 4090) is not met on any cell. Every miss is attributed to its pass or CPU scope and has an open issue. Nothing was disabled or thinned to get closer. Full write-up: docs/analysis/integrated-acceptance-1259.md.

The scene. Scenes/Benchmark/Acceptance.olo is generated by scripts/perf/generate-acceptance-scene.py, never hand-edited. It contains:

  • the meadow-to-woodland flora with interaction;
  • 41 foxes walking the traversal in bound short and long coats;
  • the bound short- and long-coat horses under a moving shadowed lantern;
  • the rigged InfiniteScanHead with skin, its measured thickness map and bound hair, in a studio beside the terrain.

19 manifests cover the gate cells, CSM controls, upscale cells, motion footage and lighting taps.

Engine work the scene needed:

  • animals follow the terrain (AnimalPathComponent::m_FollowTerrain, save-game format 45);
  • a capture walks the animal paths, and manifests pin VSM and capture frame sequences;
  • bound fox coats and bindings, with the animal scheduler posing a budgeted coat's body;
  • a byte-based coat-volume budget past the eighth volume;
  • a groom view cull that skips coats no view or shadow sweep can see;
  • bound-coat LOD measured where the body puts it;
  • the head's thickness map through the imported-material codec;
  • re-cooked horse bindings.

Decided sibling items merged in:

Measurement tooling:

  • scripts/perf/acceptance-benchmark.py, the interleaved fresh-process Release protocol for the GL test host;
  • scripts/perf/acceptance-live.py, the live editor cells with CPU-scope, groom, RT and per-pass-CPU attribution.

The editor-host capture cannot load this scene within its main-thread wait (#1591), so the Vulkan cells are live measurements.

Results (RTX 4090, driver 617.14, i7-14700KF, Release, native 1080p, VSM on)

backend × path p95 frame ms across the five cameras binding cost
GL Forward / Forward+ / Deferred (3 counted runs each) 66–443 CPU: groom deformation; GPU: ShadowPass 35–59 ms, GroomPass 88–120 ms at the head
Vulkan Forward / Forward+ / Deferred (live, 3 passes) 49–688 CPU-bound: CPU p50 within 2–4 ms of frame p50 on every row
Vulkan hybrid RT (live) 83–546 the RT TLAS is withheld at every camera (#1578 still binds), so lights take the counted raster fallback

Where the frame goes:

  • Groom::Deform costs 59–128 ms of main-thread CPU whenever the herd is in view, with 16–43 coats on the card tier.
  • GroomPass's CPU side costs 34–76 ms.
  • ShadowPass is unattributed beyond its foliage brackets. A CSM control shows the lamp atlas route costs 0.1–0.9 s.
  • The Vulkan tails are 0.65–2.1 s CPU hitches.

Evidence is in docs/testing/evidence/integrated-acceptance-1259/:

  • GL motion footage (WebP) and AOV sheets (Beauty, Albedo, Normals, Velocity) for every camera;
  • the lighting-tap sheet;
  • Vulkan stills of the head;
  • the GL protocol summary;
  • the raw live Vulkan JSON.

Verification

cell how result
GL Forward, Forward+, Deferred acceptance-benchmark.py, 3 interleaved fresh-process runs, 300 frames per camera; AcceptanceSceneTest.* (every subject bound and grounded, cameras clear the terrain, every gate camera sees its subject on every raster path; Acceptance_GL_* PNGs inspected) gate FAIL, measured; tests 3 pass, 1 skip (env-gated exporter)
Vulkan Forward, Forward+, Deferred, hybrid acceptance-live.py on a Release --rhi=vulkan editor, 3 passes; attribution pass; post-fix Deferred check gate FAIL, measured
Vulkan validation Khronos layer forced on the Release editor (core, sync, object lifetime, thread safety), every cell × camera plus the scene load. Control: the same launch with info logs CURRENT-VALIDATION-ENABLED no error, no warning
Shaders GroomStrand.glsl through glslc (vulkan1.2, opengl4.5); GL logs clean
Lighting taps LightingTapEvidenceTest.* with a lit tuft added 4 pass; the previous shader fails every cell
Touched suites coat shadow, fox coats, groom animals, skin head, benchmark capture, manifests, foliage cull/VSM, save-game, schedulers, terrain following, vegetation policy 357 pass; one failure attributed to master (#1595)
Import and asset suites *Import*:*Model*:*MeshCache*:*Asset*:*Vegetation*:*Fox*:*Dog* 787 pass; DogShowcaseEvidenceTest fails on master's rig sidecar (#1596)

Found and fixed

  • 373c6d6 fix(acceptance): every shadowed light requests the ray-traced tier. The hybrid cell traced nothing: no light opted in. Found by olo_rt_scene_stats. AcceptanceSceneTest names all four lights on the old scene.
  • 7e46d04 fix(groom): a coat splits its light across the lighting taps. Coats carried their full colour into all five terms. Found by the acceptance AOVs. LightingTapEvidenceTest's new tuft fails every cell on the old shader. A shader-swap A/B shows 40 groom evidence PNGs pixel-identical tap-off.
  • 3e6cba2 fix(rt): build vegetation and groom proxies only for an armed consumer. Raster-shadowed Deferred frames built RT proxies whenever a light requested the tier: 24–39 ms of CPU. Found by CPU scopes. Pinned by VegetationPolicy.HybridProducersRunOnlyForAnArmedConsumer; live Deferred frame p50 72 → 30 ms at head-backlit.
  • b4235bc fix(groom): a coat volume past the count is admitted only within the byte budget (self-review). Pinned by GroomCoatShadowSelection.ALargeNewcomerReclaimsUntilItFitsOrIsRefused.
  • 6f6bc5f fix(scene): a ground-following animal stands where it is, on terrains read once a tick (self-review). Pinned by AnimalPathFollowsTerrain.AParentedAnimalStandsOnTheGroundUnderItsWorldPosition.
  • 472d498 fix(benchmark): a capture steps only an edit-mode scene's animal paths, and reads VSync on the main thread (self-review). Pinned by AnimalPathFollowsTerrain.ACaptureStepLeavesARunningSceneToItsOwnTick.
  • 2de11df fix(editor): the Animal Path inspector's tooltips sit on their own checkboxes (self-review).
  • 97b214c fix(foliage): a grown shadow cull slot is redrawn, and stale demand is dropped (self-review). Both are multi-frame readback races with no CPU seam; the foliage cull and VSM cache evidence suites stay green.
  • 001948d fix(assets): a one-mesh model's material table is attached at load, not by its getter (self-review).
  • 591e219 fix(assets): import glTF files whose external buffers have escaped names. Found merging master: AnimatedModelCacheSurface.AnExternalBufferEditInvalidatesBothCaches failed on every GPU machine. It passes now.
  • Merge with master: AssetRegistry.oar taken as a three-way union of the binary registry (+5 here, +36 there). Save-game format 45 covers both payload changes.

Filed, not fixed

Review guide

Where I'd look hardest

  1. OloEditor/assets/shaders/GroomStrand.glsl, the tap split in main(). Direct versus environment is taken as the result minus a snapshot taken after the light loop. A future edit that adds light after that snapshot would land in the indirect taps.
  2. OloEngine/src/OloEngine/Scene/Scene.cpp, UpdateAnimalPaths and the new Reads(kWorldTransforms) on "AnimalPaths". The read is declared so the derived order holds, and the parented round trip writes the full local translation, not only Y.
  3. OloEngine/src/OloEngine/Renderer/PercentDecodingAssimpIO.h, now in every static and animated import. It decodes only when the literal path does not exist.

What I verified, and how

  • The fixes are pinned as listed, each with a check that fails on the old code (the light assertion, the tap tuft, the admission cases, the URI test).
  • The gate numbers come from the protocol runs and live passes in the doc, with the raw data committed.
  • The two remaining master failures are bisected to master commits with each sibling worktree's own binary.

Least confident about

🤖 Generated with Claude Code

drsnuggles8 and others added 30 commits October 10, 2026 10:28
HeadRigged.gltf's only material, HeadSkin, had a base colour texture and
nothing else, so the animated head of #1259 could never have a thin ear.

- tools/skin-thickness bakes from a .gltf too (--mesh HeadRigged.gltf, metres,
  v flipped to the FBX convention). The rig keeps every UV of the scan (both
  meshes rasterise the same 961 403 texels; per-vertex UVs match Head.fbx to
  3e-8), but the bust is 1.34x the size DigitalHuman.olo gives Head.fbx, so it
  gets its own measurement: Textures/HeadRigged_Thickness.png.
- prepare_head_rig.py writes it as a KHR_materials_volume thicknessTexture with
  thicknessFactor 0.02 (thickness / 20 mm), refuses to name a missing map,
  sets baseColorFactor 1 (the exporter wrote its 0.8 socket default, darkening
  the scan's albedo by a fifth) and roughness 0.42 (the static Cranium's).
  Re-run in Blender 5.2: HeadRigged.bin is byte-identical, so the cooked groom
  binding stays valid.

The asset is a CC BY 3.0 derivative; the README records the new file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ImportedMaterialCodec persisted KHR_materials_volume's thicknessFactor but not
its thickness TEXTURE. Both carriers lost it: a static glTF's warm .omesh load
and every asset-pack MeshSource came back with the factor alone, so a skin
material measured thin at the ear rendered uniformly thick from the second
load on (the cache-stored silent-drop class), and the pack cook never asked
for the texture's colour space.

- Codec v4: a Thickness TextureRef per record, in the shared slot list, so
  Describe/Realize/CanPersistEveryTexture all see it; linear intent in the
  pack cook's colour-space pass; the cook warns about it like any other slot.
- OMeshFormat v15 and AssetPackFile v8 move with the codec, so an older cache
  is re-imported and an older pack rejected instead of decode-failing.
- ImportedMaterialPackTest's pack and .omesh round trips and the wire-format
  test now carry a thickness map.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Past the detailed distance a casting layer's card plants are grouped by
square area cells (a whole number of 16 m registry cells) instead of
256-plant slices per registry cell. The cell is the smallest one whose
count over the layer's view disc, pi * (R / S + sqrt 2)^2, stays within
UpdatesPerFrame / 8: 32 m for Grass (R 150), 48 m for TallGrass (R 170).
A cell denser than VerticesPerFrame / 16 plants splits into equal parts.
Mesh groups, their card fallback and detailed cards keep their size; the
0.25 m error bound and the 1,024-build budget are unchanged.

IntegratedRenderer, Vulkan, Release editor: casting builds demanded drop
from 1,024 (capped) to 103 at the meadow edge and 243 inside, and groups
left out from 414 / 935 to 15 / 31. The TLAS is still withheld there:
the per-frame VERTEX budget now binds (1.02-1.04 M of 1,048,576), because
at the editor's 0.1 s step every card proxy refreshes every frame and the
meadow holds ~400k casting plants. Not sufficient on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every foliage cull view slot held a compacted stream sized to the whole
layer, twice over for a layer with an authored mesh, in each of the five
slots: 320 MB of the traversal scene's 371 MB foliage GPU floor.

A slot is now sized when it is first created from the spatial groups its
view's frustum and draw distance admit (FoliageGPUCuller::EstimateSurvivors,
an upper bound on the GPU's survivors), with half again of headroom
(StreamCapacityFor). The mesh region is sized from the groups within
MeshRegionReach of the eye and sits right after the list instead of a
second whole-layer copy. A view that outgrows its slot overflows the
existing bounded, counted way (FoliageCullOutput / FoliageCullDropped) and
now also records what it wanted in a demand pair at the end of the State
header, which the CPU never seeds. FoliageCullDemandReadback copies the
pairs out through a fenced ring after the frame's culls (ShadowRenderPass
end, or the next main cull) and polls it without waiting; a slot whose
demand exceeds its capacity grows at its next cull and says so in the log.

Memory (#1342 rows, FoliageCostBaselineTest at load):
  traversal  pinned 370.8 -> 146.8 MB, cull streams 319.7 -> 95.7 MB
  Meadow     pinned 299.5 ->  94.0 MB, cull streams 273.5 -> 67.9 MB
  Woodland   pinned 121.6 ->  53.9 MB, cull streams  91.9 -> 24.2 MB
FloraTraversalEvidenceTest PNGs are bit-identical to the before binary's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A MaterialOverridesComponent could never apply to a one-mesh rigged model,
for two reasons, so the rigged scan head (#1259) could not be made skin:

- The mesh an entity draws had no imported material table: only the combined
  source of a multi-mesh model carried one. A patch found nothing to patch,
  and an entity without a MaterialComponent drew the engine default.
  AnimatedModel::GetEntityMeshSource now attaches the model's material to its
  one mesh as entry 0.
- Loading re-wires the model before the generated blocks add the
  MaterialOverridesComponent, so ModelImporter gave the entity an entity-wide
  copy of its imported material, which overrides every submesh: the Scene then
  reported every patch inactive. The deserializer drops a MaterialComponent
  the import ADDED when the entity patches its materials (an authored one
  stays), and ModelImporter does not add one to an entity that already has
  patches.

An entity with no patches still gets its imported material as a
MaterialComponent, as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SkinRiggedHeadEvidenceTest (L8, GL) renders the rigged scan head of #1259's
acceptance scene: HeadRigged.gltf playing LookAround, carrying GroomAnimals'
cooked hair coat, loaded through SceneSerializer from kAcceptanceHumanEntity
-- the exact .olo block the acceptance scene should use, its handles pinned
to the committed scenes'.

- The import carries HeadSkin's measured map; the patch makes it Skin with
  ReferenceHead.oloskin and no MaterialComponent shadows it.
- Backlit A/B on every path: the right ear changes when the map is removed
  (uniform 20 mm), the forehead and closed lids do not move at all; the
  deferred transmission AOV is lit at the ear only with the map.
- Close-up framings (front, three-quarter, profile, backlit) with the coat
  under TAA on every path, and seven frames through LookAround.
- The rest pose against the static Cranium placed by the rig's own
  normalisation: silhouette IoU 0.98 / 0.97, ear transmission comparable.
- The game build stages the thickness map beside the glTF.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scan's README sized the bust at roughly 1.4 units. Loaded, its bounds
are 0.842 units tall (0.43 m / the 0.51058 scale SkinRiggedHeadEvidenceTest
measures), which is also what prepare_head_rig.py normalises from.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The apps get /DEBUG in Release through olo_set_link_options, but the test
executable is not configured through olo_configure_app, so its Release link
wrote no PDB. The GL capture host is the timing host for Release benchmarks
(#1259), and a crash in it (an access violation in a groom asset lookup) gave
an LLDB stack of bare addresses. The objects already carry /Z7 debug info;
this only asks the linker to write it out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`TotalFramesRendered` in an editor-host result.json was the warm-up frame
count. That was everything the host rendered when #974 wrote it; measured
frames came later and were never added, so a 180-frame-per-camera run
reported 192 frames instead of 732. The test-binary host has always counted
every stepped frame; the editor host now reports the stepped-frame counter it
already keeps for the pinned clock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A benchmark capture is an edit-mode tick (Scene::OnUpdateEditor) on a pinned
clock, and edit mode never runs the gameplay scheduler's "AnimalPaths"
system. So in every capture the herd played its walk clip on the spot: the
#1338 integrated-renderer runs measured and pictured a population that never
moved, although the scene authors 40 animals on closed-form paths.

ApplyEntityMotion, which both capture hosts call once per rendered frame, now
advances the paths by the manifest's fixed step first (through a new public
Scene::AdvanceAnimalPaths), and the editor host calls it on every step rather
than only when the manifest has EntityMotion entries. The path stays closed
form in elapsed time, so both hosts place the herd identically at a frame.

Pinned by AnimalPathFollowsTerrain.ACaptureStepWalksTheHerdOneFixedStepPerFrame
(added with the ground-following change that follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AnimalPathComponent traces a closed-form figure at a fixed height, so a herd
crossing the acceptance scene's meadow-to-woodland relief floated over the
dips and sank into the rises. The new FollowTerrain flag sets the animal's
height each tick to the terrain surface under it, sampled from the loaded
height field in the terrain entity's own space (the nav-mesh bake's mapping),
so a moved or Y-turned terrain answers correctly.

The sampler is a free function, SampleTerrainGroundHeight (Scene/TerrainGround),
shared with the acceptance scene's camera-clearance contract. Off every
terrain, or where no height field exists yet (a headless host never builds
one), the animal keeps its height and the engine warns once rather than
dropping it to zero silently.

Touch-points: the flag takes the struct's former padding byte (still 44
bytes, no padding, BitwiseEqualLayout holds); generated scene YAML/binary and
field registries; save-game serializer with kSaveGameFormatVersion 44; the
inspector's "Follow terrain" checkbox. Lua and C# do not expose this
component.

Tests: AnimalPathFollowsTerrainTest (Functional): the walker stands on a
sloped, translated terrain at every step of its figure; without the flag, or
off the terrain, the height stays; and a capture step walks the herd one fixed
step per frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cord presentation

Three capture gaps the #1259 acceptance gate needs closed:

* RendererSettings.VirtualShadowMaps pins ShadowMap::Settings.VSM.Enabled,
  which no scene serializes. The gate is measured with VSM on, so without it a
  manifest could not say which shadow technique it timed. Decoded strictly: a
  typo is refused, not read as "off". result.json records it as requested and
  as selected.
* A camera's Sequence {Every, Count, Attachments} is motion footage: after the
  warm-up the camera keeps moving for Count steps of Every frames and reads the
  named attachments back after each step, written to <camera>/sequence/ as
  <Name>_<step> with the step's frame, clock and pose in result.json. A
  sequence reads back mid-run, so the parser refuses it beside a Measurement
  block. Both hosts implement it; the end-of-camera capture follows the
  sequence and its recorded pose accounts for it (CameraFrameCount).
* provenance.presentation / provenance.vsync: "offscreen" for the test host;
  "window" with the window's VSync for the editor host, whose frame time is a
  completed-frame interval that includes present and snaps to the refresh
  under VSync.

The sequence types are plain members with TIsTriviallyRelocatable traits, so
the capture records stay TArray-relocatable.

Tests: ReferenceFixtureManifest.ParsesVirtualShadowMapsAndRefusesNonBooleans,
ParsesACameraSequenceAndRefusesUnusableOnes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/perf/acceptance-benchmark.py runs the #1259 measurement protocol over
a plan of cells (a manifest on the GL test host or the Vulkan editor host):

* Release only, with a declared compiler; a cell whose counted runs come from
  different binaries is refused, and a binary, shader or asset change aborts
  the campaign.
* Interleaved fresh-process runs, the start cell rotated each round, at least
  three counted runs per cell.
* Other GPU load checked before every run and sampled every 30 s during it
  (foliage-cost-baseline's probe); a contended run is kept but not counted,
  with the competing process named, and retried.
* Provenance per binary: binary/shader/asset hashes, commit, dirty diff and
  untracked files (controlled-benchmark's provenance(), which now accepts
  precomputed tree hashes).
* Per camera: actual internal/display sizes, resolved upscaler, VSM selected,
  and p50/p95/p99/max plus deadline misses for frame, CPU, fence, present,
  recording and total GPU time, and per-pass GPU distributions from
  measurement-passes.jsonl (valid, distinct frame ids, sub-passes separate).
  `requirePasses` refuses a run in which a named pass never produced a valid
  sample, the evidence that a technique actually ran.
* Ranges across runs, never resampled frames; PASS only if every counted run's
  p95 is within the gate (default 16.667 ms). Exit 0/1/2.

Tests: test_acceptance_benchmark.py (29 cases, no GPU), with six mutations
each caught (dedupe, sub-pass separation, verdict, contention, process
ancestry, rotation).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the editor loads

Opening Scenes/GroomAnimals.olo refused both horse coats ("the target mesh is
not the surface this binding was built against"), on master too: the coats
stood at their bind pose while the horses walked.

Root cause: stale cooked data, not an import or cache bug. The bindings were
cooked (d14c66b) against the HorseSkin primitive alone, 4316 vertices and
22170 indices. A day later 404acda (#1533) made an animated entity draw every
mesh of its model, so the surface a horse coat binds to is body + eyes, 8284
vertices and 27930 indices, and nobody re-exported. A cold import and a warm
.omesh load of Horse.gltf give the identical surface (same index and rest
hashes), so the cache is not involved; the Human binding still matches.

- Re-cooked through the existing exporter
  (GroomAnimalsAcceptanceEvidenceTest.ExportsTheLiveScene). The grooms and the
  Human binding came out byte-identical, so only the two horse bindings change;
  the scene and registry it also rewrites were left as committed (same handles,
  and the scene's entity UUIDs are referenced elsewhere).
- GroomAnimalsCookedBindingTest loads each committed coat against a cold and a
  warm import of its body and asks CheckCompatibility for the Scene's verdict.
  It fails on master (both horses, TargetTopologyMismatch) and passes here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d contracts (#1259)

Scenes/Benchmark/Acceptance.olo is generated by
scripts/perf/generate-acceptance-scene.py from committed scenes: the
meadow-to-woodland flora traversal, the moving fox population laid along it,
the bound short- and long-coat horses walking in the meadow, and the rigged
human head with its hair in a studio beside the terrain, plus a moving
shadowed light. Every walking animal follows the ground, every coat is
parented to the body its binding targets, and the 16 subjects nearest the
cameras push the grass (the interaction field's slot count).

The flora content is adjusted for legibility (gentler relief, no snow, meadow
grass heights, more pines); no layer is removed and no density lowered. The
docs/analysis note says so.

Manifests (acceptance-*.yaml): the gate cells per path with VSM on and a
16.667 ms deadline, hybrid RT on Vulkan, CSM controls, an upscaler cell,
motion-footage sequences, and Deferred lighting-tap AOV runs. Five cameras:
head close-up, head into the sun, coat close-up, a dolly through the herd
toward the wood, and a rapid turn. Cameras are placed from a committed ground
grid exported from the real height field.

AcceptanceSceneEvidenceTest (integration, GL): every coat bound and parented
to its body, every walker on the terrain and on the ground after walking, the
interaction field not oversubscribed; every manifest camera clears the terrain
along its whole path; every gate camera sees a non-flat frame on every raster
path. It caught two generator bugs while being written (a FollowTerrain key
written under GroomLodComponent, which the loader silently ignores, and a herd
path running off the terrain).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e branch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A groom's apparent size (GroomLod, the ray-tracing proxy tier, the animal
scheduler) was measured from the groom asset's rest bounds through the groom
entity's transform. For a BOUND coat those bounds sit where the coat was when
the binding was cooked; the deformation maps the body into the groom's space
with this frame's inverse(groomWorld) * bodyWorld, so the two agree only at the
cook placement. In the acceptance scene the rigged head stands at
[-34, 1.24, 196], turned -2.2143 rad, with HumanCoat parented to it; the rest
bounds then read the hair as 3.7 m from where it is drawn.

Scene::BoundGroomPlacementOffset averages the binding's bind-time root origins
(groom space) and the same roots on the body's surface (barycentrics on the
bound triangles), cached on the binding handle and surface generation, and
shifts the rest bounds by where this frame's mapping puts that centroid.

The binding itself was already surface-relative: at the acceptance placement
it binds, deforms every root and holds none at rest.
SkinRiggedHeadCloseUp.TheCoatBindsAndFollowsAtTheAcceptanceScenePlacement loads
that configuration and compares it with the cook placement from a camera placed
identically relative to the head: coverage per 16 px cell differed by 0.110
before this change (the coat thinned in the close-up) and 0.012 after; both
placements draw all 44235 strands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion (#1580)

Foliage went to the VSM as a deforming footprint every frame, so every page
under it in all sixteen clip levels was cleared and every level re-culled
and redrew every layer.

Policy (FoliageShadowInvalidation.h, FoliageRenderer::CollectVsmInvalidations):
a layer's footprint is invalidated each frame only in levels whose texel is
finer than its declared wind bound (FoliageWindMaximumDisplacement); around
each live interaction influence (its cylinder box, plus last frame's) in
levels finer than wind + FoliageInteractionMaximumDisplacement; when the main
eye moves, in the levels a receiver within twice the view distance selects
plus the fallback level; coarser levels keep their pages and are refreshed
one level every 4 frames in rotation. Silhouette changes without motion go
through ShadowFamilyCache with FoliageRenderer::GetShadowRevision. The
invalidation queue carries a clip-level mask in the min's w lane (0 = every
level, what every other caster still submits).

The clip-level cull now also rejects every spatial group over no dirty page
(FoliageGroupCullVsm.comp, the vsmFootprintHasDirtyPage test VSM_CullCasters
uses), so a level that keeps its pages draws no foliage.

Also: the #1581 demand capture moves to the frame epilogue (after
GPUReadbackStats::EndFrame, registered as out-of-band epilogue work), the
VSM lanes sit after the demand pair in the cull State header, and
FoliageCostBaselineTest records the memory floor after its cells and takes
OLO_FOLIAGE_COST_VSM_POLICY=everyframe for a same-binary A/B.

Measured: FoliageVsmCacheVisualEvidenceTest shows the shipped cache equal
to a full redraw at the same clock (0 px of shadow-factor difference, three
angles) with a never-invalidate control at 75-149 k px. On the committed
scenes the policy itself saves nothing: with 0.1-0.84 m wind bounds only
levels 10-15 may cache and no resident page is there (1533 pages redrawn per
frame against 1522 with per-frame invalidation), and the GL headless VSM
cells are unchanged. Live on Vulkan the VSM frame at the traversal Step4
framing went from 39.0 to 15.1 ms (shadow pass 35.5 -> 11.5 ms), which is
the dirty-page group cull; see docs/agent-rules/foliage-vsm-page-caching.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1580) into the #1259 acceptance branch

Matched interleaved GL A/B (same shaders per binary, 2 rounds, RTX 4090, Release):
Meadow Deferred VSM 63.0 -> 55.9 ms, Woodland Deferred VSM 97.9 -> 89.1 ms,
Traversal Step4 Forward CSM 15.1 -> 14.6 ms; no overflowed frame in any arm.
Foliage GPU floor: traversal 370.8 -> 146.8 MB, Meadow 299.5 -> 94.0 MB,
Woodland 121.6 -> 53.9 MB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A bound coat is its own entity, parented to the body it rides, so a herd
authored that way carries its AnimalBudgetComponent on the coat while the
skeleton sits one binding away. The gather priced no bones for it and
ShouldPoseAnimalThisFrame never found a schedule for the body: the
deformation axis silently did nothing for the whole herd.

The gather now takes the bone count from the binding's target (when the
target has no budget of its own), and the body is posed by its coat's
schedule through m_AnimalBodySchedules (finer step wins for two coats).
BoundCoatPopulationFixture holds it, with a bindings-off control arm in
which every body poses every frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…budget (#1259)

The coat-volume budget was eight resident volumes of any size, first come.
In AnimalPopulation.olo forty fox coats reached the slots before the hero,
and a coat refused its volume loses its dual scattering with it: the hero
and most of the herd rendered dark brown and grey where they are orange
(GL and Vulkan, editor and headless capture alike).

Past the eighth volume a newcomer is now admitted while the resident set
stays within 256 MiB (estimate: the whole ring at RGBA32F plus the body
texture). A herd's distant coats are 16^3-32^3 volumes of a few hundred KiB.
FoxCoatEvidenceTest.AHerdKeepsEveryCoatVolume (16 bound foxes, all drawn
coats shadowed, BudgetExhausted 0) lands with the fox coats.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ce (#1259)

FoxCoatEvidenceTest grows a summer (short) and a winter (long) red-fox coat
on the Khronos Fox's own bind-pose surface, cooks them and a card level with
the real cookers, and binds them with the real binder. The coat is authored
in metres (the Fox's centimetres times 0.0125) and its entity carries a local
scale of 80 under the fox, so SurfaceToGroom is the same at every fox scale.

- FoxShortCoat: 265,724 strands, 5.4 points each, 8,947 cards
- FoxLongCoat: 232,394 strands, 6.6 points each, 8,890 cards
- FoxCoatColor.png: the Fox texture remapped to a fox's colours, islands
  dilated, region edges softened, low-frequency value noise

Cases: the roots sit on the independently skinned skin through the Walk
(p99 0.000 mm, max 0.010 mm; bind-pose control p99 200-340 mm); skin showing
at four hero framings per coat 2.0-4.5% (bound 5%, head 6%); cards keep
coverage 0.91-0.99 and energy 0.81-1.04 past the hand-over; the bindings
accept a cold and a warm load of the Fox; the colour map reads back the same
through the editor import; a 16-fox herd keeps every coat volume.

Regenerate: OLO_FOX_COATS_EXPORT=1 OloEngine-Tests
--gtest_filter=FoxCoatEvidenceTest.ExportsTheFoxCoats (cwd OloEditor/),
which also registers the files in AssetRegistry.oar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every AnimalPopulation fox is now a Fox body (model, clip, path) and a coat
entity parented to it and bound to it: FoxLongCoat on the hero, the featured
foxes and every other herd animal, FoxShortCoat on the rest. Keys are copied
from Dog.olo / GroomAnimals.olo. The generator reads the coats' handles from
AssetRegistry.oar by path, so a re-export needs only a re-run.

Authoring choices, each measured in the live editor:
- MaxRenderStrands is each coat's exact strand count. A round 1,000,000 and
  its ladder halvings built the same full coat under three cache keys.
- VariationSeed 0 on every fox. The seed is in the build digest, so a seed per
  animal gave each fox its own ~350 MiB rest stream (~15 GiB requested).
- Herd coats do not cast into the scene shadow maps (hero and featured do):
  each casting coat holds caster entries per shadow step.
- The hero faces the camera three-quarter on (yaw 0.6).
- The AnimalBudgetComponent sits on the coat; the scheduler poses its body.

IntegratedRenderer.olo and its manifests are regenerated from it; the stale
"unbound blob" notes are gone, and animal-population.diagnostic.yaml lists the
fox coats, bindings and colour map with their hashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ance branch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o frame (#1259)

The pair capture looked from x = 0, between the two foxes, so the long fox
showed the flank that faces away from the sun. In this sky-less fixture that
flank is near-black for either coat, and the PNG read as a broken long coat.
Measured with mirrored framings: the long coat is 0.059 mean linear luma from
the shaded side and 0.101 from the lit side; the short coat 0.039 shaded and
0.132 lit. No engine state was involved: the pair was as dark when captured
first, before any other view, toggle or history reset.

The pair is now framed from the sun's side, and each coat's mean luma there
must stay within 0.65-1.5x of its own lit side view (0.92 short, 0.85 long),
so a coat that skins the body but renders dark -- the old framing at 0.54, a
coat refused its density volume at ~0.1 -- fails rather than passing on
skin coverage alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scene::PublishGroomStrandRequests deformed, simulated and submitted every coat
every frame. In the #1259 acceptance scene the 41-fox herd behind the camera
cost ~80 ms of CPU (binding, guide simulation, upload) and ~65 ms of GPU root
frames for coats that drew nothing.

A coat is now published only when its rest bounds, posed and padded (a
quarter of the extent plus 0.25 m, for a walking body and a swaying coat),
reach the culling camera's frustum, or, for a coat that casts scene shadows,
when its shadow can: its box swept along a shadowing sun for the light's
shadow distance, or inside a shadowing point/spot light whose range reaches
the view. The frustum is the one this frame's BeginScene derived, so each
camera that renders the scene culls against its own view. A coat that comes
back resumes through the deformer's DeformationSkipped history reset and the
simulation's re-seed, and stays "live" while culled, so its guide-influence
table, streaming key and LOD hysteresis are not evicted and rebuilt.

Measured (GL, Release, acceptance-deferred, 300 frames per camera, one run):
the into-the-sun head camera 274 -> 20.5 ms p50, the rapid turn 276 -> 80 ms.
Cameras that keep the herd inside the frustum, even at 230 m, are unchanged;
that is the per-coat deformation cost, not the cull.

Tests: GroomViewCullTest (cullinglod): in view submitted, behind not,
behind-but-casting-into-view submitted, behind-and-casting-away not; with
frustum culling off every coat is submitted (the control).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regenerated from AnimalPopulation now that every fox wears a bound coat. The
coat (and its AnimalBudgetComponent) is a child of the fox, so the generator
relocates the root animated bodies and lets the coats follow. 44 bound coats
(41 foxes, 2 horses, the head's hair), 43 ground-following walkers, 16 grass
pushers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…into the #1259 acceptance branch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The coat view cull posed the groom's rest bounds through the coat entity's
transform. For a bound coat those bounds sit where the binding was cooked, so a
coat moved with its body (the acceptance scene's horses, or the head's hair
3.7 m from its cook placement) was tested metres from where it is drawn. The
cull now reuses the placed rest bounds the LOD size already computes through
Scene::BoundGroomPlacementOffset, so the two cannot disagree about where a
coat is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
drsnuggles8 and others added 17 commits October 11, 2026 09:45
…kness

The acceptance scene's rigged head patches its imported HeadSkin to the
reference skin (ReferenceHead.oloskin, 20 mm thickness factor) through a
MaterialOverridesComponent; the measured thickness map rides in
HeadRigged.gltf. No MaterialComponent, which would switch the patch off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The acceptance scene's resident set exceeds the test harness's 6 GB guard, so
its GL captures need --olo-rss-ceiling-mb=0; the plan's testHostArgs carries
that (and any other test-host flag) to every GL run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ches a run writes

A GL capture writes git-ignored, generated files under the asset root (the
mesh cache, the scene's .scenebin sidecar), so hashing every file on disk made
the campaign's asset fingerprint change after its first run and abort it as a
mid-campaign build change. The asset hash now covers tracked files plus
untracked ones git does not ignore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hybrid manifest turns the renderer's ray-traced shadows on, but the
tier traces only the lights that request it (RayTracedShadows on the
light, #1056), and none of the source scenes' lights do. The hybrid cell
traced nothing: olo_rt_scene_stats on the live Vulkan editor showed no
traced light, and the cell measured the same as Deferred.

The generator now sets RayTracedShadows on the sun, the head's key and
side lights and the moving lantern; a raster cell ignores it.
AcceptanceSceneTest.EverySubjectIsBoundGroundedAndOnTheTerrain checks it
for every shadowed light, and fails on the previous scene naming all four.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The editor host's benchmark capture reopens the scene, and a second load
of the acceptance scene's 44 bound coats in one editor process stalls
the main thread past the MCP wait, so no Vulkan cell completed through
acceptance-benchmark.py. acceptance-live.py opens the scene once and, per
render path (and hybrid ray-traced shadows) with VSM on, poses each
manifest camera and keeps the last N completed frames' frame, CPU, GPU,
fence and present split and a pass-timing snapshot. An attribution pass
on the same editor adds averaged CPU scopes, groom budget stats, per-pass
CPU, the raw series and, for hybrid, the RT scene stats.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A coat is composited after the deferred lighting pass by GroomStrand.glsl,
which never read the lighting tap (#1526), so every tap showed the coat's
full lit colour: the five taps counted every coat five times, and the
#1259 acceptance AOVs showed the head's hair and the horses' manes at full
brightness in each one.

The shader now records the split the other lit shaders record: the R lobe
(cuticle reflection) is the specular term and what entered the fibre (TT,
TRT, the residual, the coat's multiple scattering) the diffuse one; the
lights are direct and the environment indirect, taken as the result minus
the lights' share. The composite is linear, so the four sum to the lit
colour. An unlit coat and the tangent diagnostic are the remainder, and
the primary sun's scene visibility feeds the shadow tap. A tap-off frame
is the same expression as before.

LightingTapEvidenceTest's scene gains a lit tuft between the spheres. With
the previous shader the partition fails on every cell (0.3-4.4% of lit
pixels out, worst relative error 4: the coat counted five times); with
this one, 0 pixels out on all eight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Renderer3D::WantsRayTracingVegetation (and WantsRayTracingGrooms, which
shares it) ran the producers on a Deferred frame whenever a light asked
for ray-traced shadows, but RayTracedShadowPass only runs when the shadow
technique is RayTraced. A scene whose lights request the tier therefore
built vegetation and groom proxies on every raster-shadowed Deferred
frame for no consumer.

The predicate is now RayTracing::HybridProducersWanted: a light's request
counts only while the tier is armed (shadows on, technique RayTraced),
the condition RenderPipeline enables the pass on; reflections are as
before. VegetationPolicy.HybridProducersRunOnlyForAnArmedConsumer pins it.

Live Vulkan editor, #1259 acceptance scene, Deferred with raster shadows
(its lights request the tier for the hybrid cell): Vegetation::Queue
24-39 ms -> 0, frame p50 72 -> 30 ms (head-backlit), 137 -> 96
(coats-closeup), 190 -> 136 (population-dolly), 161 -> 99 (rapid-turn).
The hybrid cell still builds them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd raw data

The gate (16.667 ms p95 with VSM, 1920x1080, RTX 4090) is missed on every
cell: GL Forward, Forward+ and Deferred under the controlled protocol
(three counted runs each), and Vulkan Forward, Forward+, Deferred and
hybrid live in the editor. The frame is CPU-bound on both backends, and
each miss is attributed to its scope or pass with an open issue: bound-coat
deformation and the strand pass's CPU side (#1588), GroomPass on GL
(#1589), ShadowPass outside its brackets with a CSM control (#1590), the
load-time memory transient that defeats the editor-host capture (#1591),
CPU hitches on the live editor (#1594), the vegetation build budget that
withholds the hybrid TLAS (#1578), lamps without groom shadows under VSM
(#1592) and the head's hair (#1593).

Evidence: the fifteen per-path stills, GL motion footage and AOV sheets,
the lighting-tap sheet, Vulkan stills of the head, the GL protocol summary,
the raw live Vulkan runs, and a validation walk under the Khronos layer
(no error or warning, with an info-level control).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two conflicts. AssetRegistry.oar is a three-way union of the binary
registry (338 base entries, +5 here: the fox coats and their bindings,
+36 on master: the dog breeds), every handle kept, no path on two
handles. kSaveGameFormatVersion: both sides changed the payload under 44
(AnimalPathComponent::m_FollowTerrain here, GroomComponent's authored
segment budget on master), so the combined layout is 45.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…byte budget

Past the eighth resident coat volume a newcomer is admitted while the set
stays within kMaxResidentCoatVolumeBytes (5972968). When it did not fit,
the pass reclaimed ONE least-recently-used volume and granted the slot
whatever its size, so a close-up coat could take a 300 KiB herd volume's
slot and push the resident set hundreds of megabytes past the budget.

GroomCoatShadow::AdmitCoatVolume now reclaims until the newcomer fits by
count or bytes and refuses it (BudgetExhausted) when nothing more can be
reclaimed. ReclaimLeastRecentlyUsedCoatVolume returns the bytes it freed,
and the resident bytes are summed once per newcomer, only once the count
is reached, instead of walking the cache on every check.
GroomCoatShadowSelection.ALargeNewcomerReclaimsUntilItFitsOrIsRefused pins
all three cases; FoxCoatEvidenceTest.AHerdKeepsEveryCoatVolume stays green.

Found by the #1259 self-review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… read once a tick

UpdateAnimalPaths sampled the terrain at the animal's LOCAL translation
and wrote the world height into local Y, so an animal under an offset or
turned group floated or sank by the group's transform. It now takes the
path point through the parent's world matrix, sets it on the ground there
and brings it back into the parent's space.

The terrain sampler (TerrainGroundSampler) gathers the terrains and their
inverse world matrices once per UpdateAnimalPaths call instead of inverting
one per animal per terrain; SampleTerrainGroundHeight is a one-shot wrapper
over it. The "AnimalPaths" system declares the read it makes,
Reads(kWorldTransforms), beside its ReadsWrites(kLocalTransforms).

AnimalPathFollowsTerrain.AParentedAnimalStandsOnTheGroundUnderItsWorldPosition
pins the parented case.

Found by the #1259 self-review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApplyEntityMotion advanced the scene's animal paths on every captured
frame (c9cc753), but a running scene's gameplay schedule already runs
"AnimalPaths", so a capture taken in Play walked the herd at twice the
speed and off the test host's trajectory. It now steps them only while
the scene is not running. On the editor host, a step with no active scene
is again a failure only for a manifest that names an EntityMotion target.

The editor host also read the window's VSync on the MCP tool thread after
the restore epilogue; it is now read on the main thread while the capture's
settings are applied, and that is the value result.json records.

AnimalPathFollowsTerrain.ACaptureStepLeavesARunningSceneToItsOwnTick pins
the first.

Found by the #1259 self-review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eckboxes

"Follow terrain" was inserted between "Orient to path" and its tooltip,
so hovering it showed the yaw explanation and "Orient to path" showed
nothing. Each checkbox now carries its own.

Found by the #1259 self-review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s dropped

Two gaps in the view-sized cull slots (#1581) as the VSM caches pages
(#1580):

- A shadow slot is shared by every shadow view and learns of an overflow
  only through the fenced demand readback, so the frames before it grows
  (up to the ring's depth) draw short -- and the VSM's coarse levels keep
  such pages. When a shadow slot grows, the next CollectVsmInvalidations
  now redraws every clip level once.
- A demand capture in flight indexes the layers as they were. Applied after
  a regeneration rebuilt the layer list, it grew whichever slot then sat at
  its index, and slots only grow. FoliageCullDemandReadback::DiscardInFlight
  retires those captures without returning them; a slot that still
  overflows writes its demand again.

The FoliageGPUCuller.h note that "the frame that overflowed is the only
one" to draw short is corrected. FoliageGPUCullEvidenceTest and
FoliageVsmCacheVisualEvidenceTest stay green; neither race has a CPU seam
to pin it with.

Found by the #1259 self-review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ot by its getter

AnimatedModel::GetEntityMeshSource() is const, yet for a one-mesh model
(fb98963) it rewrote the shared m_Meshes[0] in place on every call:
every submesh's material index set to 0 and an imported-material table
attached, a side effect any other holder of that MeshSource saw depending
on call order. AttachOneMeshMaterialTable does it once, at the end of
LoadModel's cache and import paths, and the getter only returns the mesh.
m_Materials holds one entry per mesh, so entry 0 remains the right
material. SkinRiggedHead* and the GroomAnimals binding tests stay green.

Found by the #1259 self-review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
glTF names its buffers and images by URI, so "editable buffer.bin" is
written "editable%20buffer.bin". Assimp 6.0.4 opens the URI as a literal
path and fails ("GLTF: could not open referenced file"), so a valid glTF
whose external files have a space -- or any escaped byte -- in their names
did not import. AnimatedModelCacheSurface.AnExternalBufferEditInvalidatesBothCaches,
added with the external-buffer cache invalidation on master (482f8cf),
builds exactly that file and failed on every machine with a GPU (it skips
on CI, which has none).

Both importer setups (ConfigureAnimatedImporter, ConfigureStaticImporter)
now install PercentDecodingAssimpIO: the literal path first, so a file whose
name really contains '%' still opens, then the percent-decoded one, the same
decoding MeshCache fingerprints the buffers with. DefaultIOSystem is final,
so it is wrapped. The test now passes, and 787 model, import, mesh-cache and asset tests
pass with it. DogShowcaseEvidenceTest fails before any import, on the
committed Dog.rig.json having no "assembly" block (filed).

Found by the #1259 merge with master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 145 files, which is 45 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration
  • Configuration used: Repository YAML (base), Repository UI (inherited)
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 150800d1-4bed-4ae5-b114-a9d66226e368

📥 Commits

Reviewing files that changed from the base of the PR and between 402f1ce and 5396dff.


⛔ Files ignored due to path filters (130)
  • OloEditor/SandboxProject/AssetRegistry.oar is excluded by !**/*.oar
  • OloEditor/SandboxProject/Assets/Grooms/Animals/FoxCoatColor.png is excluded by !**/*.png
  • OloEditor/SandboxProject/Assets/Grooms/Animals/FoxLongCoat.ologroom is excluded by !**/*.ologroom
  • OloEditor/SandboxProject/Assets/Grooms/Animals/FoxLongCoat.ologroombinding is excluded by !**/*.ologroombinding
  • OloEditor/SandboxProject/Assets/Grooms/Animals/FoxShortCoat.ologroom is excluded by !**/*.ologroom
  • OloEditor/SandboxProject/Assets/Grooms/Animals/FoxShortCoat.ologroombinding is excluded by !**/*.ologroombinding
  • OloEditor/SandboxProject/Assets/Grooms/Animals/LongCoatHorse.ologroombinding is excluded by !**/*.ologroombinding
  • OloEditor/SandboxProject/Assets/Grooms/Animals/ShortCoatHorse.ologroombinding is excluded by !**/*.ologroombinding
  • OloEditor/assets/models/InfiniteScanHead/HeadRigged.gltf is excluded by !**/*.gltf
  • OloEditor/assets/models/InfiniteScanHead/Textures/HeadRigged_Thickness.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Deferred_coats-closeup.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Deferred_head-backlit.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Deferred_head-closeup.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Deferred_population-dolly.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Deferred_rapid-turn.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_ForwardPlus_coats-closeup.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_ForwardPlus_head-backlit.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_ForwardPlus_head-closeup.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_ForwardPlus_population-dolly.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_ForwardPlus_rapid-turn.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Forward_coats-closeup.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Forward_head-backlit.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Forward_head-closeup.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Forward_population-dolly.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/Acceptance_GL_Forward_rapid-turn.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Ground_Policy.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Ground_PolicyFresh.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Ground_ShadowFactor_NeverDiffx8.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Ground_ShadowFactor_PolicyDiffx8.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Overview_Policy.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Overview_PolicyFresh.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Overview_ShadowFactor_NeverDiffx8.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Overview_ShadowFactor_PolicyDiffx8.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Reverse_Policy.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Reverse_PolicyFresh.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Reverse_ShadowFactor_NeverDiffx8.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoliageVsmCache_GL_Deferred_Reverse_ShadowFactor_PolicyDiffx8.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatLod_GL_Forward_LongCoat_Far.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatLod_GL_Forward_LongCoat_Handover.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatLod_GL_Forward_LongCoat_Mid.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatLod_GL_Forward_LongCoat_Near.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatLod_GL_Forward_ShortCoat_Far.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatLod_GL_Forward_ShortCoat_Handover.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatLod_GL_Forward_ShortCoat_Mid.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatLod_GL_Forward_ShortCoat_Near.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatSkin_GL_Forward_LongCoat_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatSkin_GL_Forward_LongCoat_Head.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatSkin_GL_Forward_LongCoat_Side.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatSkin_GL_Forward_LongCoat_ThreeQuarter.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatSkin_GL_Forward_ShortCoat_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatSkin_GL_Forward_ShortCoat_Head.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatSkin_GL_Forward_ShortCoat_Side.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatSkin_GL_Forward_ShortCoat_ThreeQuarter.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoatWalk_GL_Forward_Stride.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_LongCoat_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_LongCoat_Head.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_LongCoat_Side.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_LongCoat_ThreeQuarter.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_Pair.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_ShortCoat_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_ShortCoat_Head.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_ShortCoat_Side.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/FoxCoat_GL_Forward_ShortCoat_ThreeQuarter.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/LightingTap_GL_DeferredMSAA4_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/LightingTap_GL_Deferred_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/LightingTap_GL_Deferred_High.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/LightingTap_GL_ForwardPlus_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/LightingTap_GL_ForwardPlus_High.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/LightingTap_GL_Forward_FSR1Quality_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/LightingTap_GL_Forward_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/LightingTap_GL_Forward_High.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadCraniumTransmission_GL_Deferred_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadCranium_GL_Deferred_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadCranium_GL_Deferred_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadPlacement_GL_Forward_Acceptance.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadPlacement_GL_Forward_Cooked.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadRestTransmission_GL_Deferred_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadRest_GL_Deferred_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadRest_GL_Deferred_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadSkinNoMap_GL_Deferred_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadSkinNoMap_GL_ForwardPlus_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadSkinNoMap_GL_Forward_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadSkin_GL_Deferred_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadSkin_GL_ForwardPlus_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadSkin_GL_Forward_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadTransmissionNoMap_GL_Deferred_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHeadTransmission_GL_Deferred_BacklitEar.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Deferred_Backlit.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Deferred_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Deferred_Profile.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Deferred_ThreeQuarter.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_ForwardPlus_Backlit.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_ForwardPlus_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_ForwardPlus_Profile.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_ForwardPlus_ThreeQuarter.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_Backlit.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_Front.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_LookAround_150.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_LookAround_230.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_LookAround_340.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_LookAround_445.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_LookAround_45.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_LookAround_5.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_LookAround_515.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_Profile.png is excluded by !**/*.png
  • OloEditor/assets/tests/visual/SkinRiggedHead_GL_Forward_ThreeQuarter.png is excluded by !**/*.png
  • OloEditor/src/MCP/Generated/McpFieldRegistry.Generated.inl is excluded by !**/*.generated.*, !**/generated/**
  • OloEngine/src/OloEngine/Scene/Generated/SceneBinaryReadComponents.Generated.inl is excluded by !**/*.generated.*, !**/generated/**
  • OloEngine/src/OloEngine/Scene/Generated/SceneBinaryWriteComponents.Generated.inl is excluded by !**/*.generated.*, !**/generated/**
  • OloEngine/src/OloEngine/Scene/Generated/SceneDeserializeComponents.Generated.inl is excluded by !**/*.generated.*, !**/generated/**
  • OloEngine/src/OloEngine/Scene/Generated/SceneSerializeComponents.Generated.inl is excluded by !**/*.generated.*, !**/generated/**
  • OloEngine/src/OloEngine/Scripting/VisualScript/Generated/ComponentFieldRegistry.Generated.inl is excluded by !**/*.generated.*, !**/generated/**
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_coats-closeup_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_head-backlit_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_head-closeup_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_lighting_taps.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_population-dolly_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_rapid-turn_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_ForwardPlus_coats-closeup_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_ForwardPlus_head-backlit_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_ForwardPlus_head-closeup_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_ForwardPlus_population-dolly_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_ForwardPlus_rapid-turn_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Forward_coats-closeup_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Forward_head-backlit_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Forward_head-closeup_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Forward_population-dolly_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/GL_Forward_rapid-turn_aov.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/VK_Hybrid_head-backlit.jpg is excluded by !**/*.jpg
  • docs/testing/evidence/integrated-acceptance-1259/VK_Hybrid_head-closeup.jpg is excluded by !**/*.jpg

📒 Files selected for processing (145)
  • OloEditor/SandboxProject/Assets/Scenes/Benchmark/Acceptance.olo
  • OloEditor/SandboxProject/Assets/Scenes/Benchmark/AnimalPopulation.olo
  • OloEditor/SandboxProject/Assets/Scenes/Benchmark/IntegratedRenderer.olo
  • OloEditor/assets/benchmark/manifests/acceptance-deferred-csm.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-deferred-motion.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-deferred-tap-direct-diffuse.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-deferred-tap-direct-specular.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-deferred-tap-indirect-diffuse.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-deferred-tap-indirect-specular.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-deferred-tap-remainder.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-deferred-upscale-quality.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-deferred.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-forward-csm.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-forward-motion.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-forward-plus-csm.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-forward-plus-motion.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-forward-plus-upscale-quality.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-forward-plus.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-forward-upscale-quality.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-forward.yaml
  • OloEditor/assets/benchmark/manifests/acceptance-hybrid.yaml
  • OloEditor/assets/benchmark/manifests/animal-population.diagnostic.yaml
  • OloEditor/assets/benchmark/manifests/integrated-deferred-msaa4.yaml
  • OloEditor/assets/benchmark/manifests/integrated-deferred-upscale-quality-fsr2.yaml
  • OloEditor/assets/benchmark/manifests/integrated-deferred-upscale-quality.yaml
  • OloEditor/assets/benchmark/manifests/integrated-deferred.yaml
  • OloEditor/assets/benchmark/manifests/integrated-forward-plus-renderscale-67.yaml
  • OloEditor/assets/benchmark/manifests/integrated-forward-plus-upscale-quality-fsr2.yaml
  • OloEditor/assets/benchmark/manifests/integrated-forward-plus-upscale-quality.yaml
  • OloEditor/assets/benchmark/manifests/integrated-forward-plus.yaml
  • OloEditor/assets/benchmark/manifests/integrated-forward-renderscale-67.yaml
  • OloEditor/assets/benchmark/manifests/integrated-forward-upscale-quality-fsr2.yaml
  • OloEditor/assets/benchmark/manifests/integrated-forward-upscale-quality.yaml
  • OloEditor/assets/benchmark/manifests/integrated-forward.yaml
  • OloEditor/assets/benchmark/manifests/integrated-hybrid-upscale-quality.yaml
  • OloEditor/assets/benchmark/manifests/integrated-hybrid.yaml
  • OloEditor/assets/models/InfiniteScanHead/README.md
  • OloEditor/assets/models/InfiniteScanHead/prepare_head_rig.py
  • OloEditor/assets/shaders/GroomStrand.glsl
  • OloEditor/assets/shaders/compute/FoliageGroupCull.comp
  • OloEditor/assets/shaders/compute/FoliageGroupCullVsm.comp
  • OloEditor/assets/shaders/compute/FoliageInstanceCull.comp
  • OloEditor/assets/shaders/compute/VSM_InvalidatePages.comp
  • OloEditor/assets/shaders/include/FoliageCullCommon.glsl
  • OloEditor/assets/shaders/include/FoliageGroupCullKernel.glsl
  • OloEditor/src/MCP/McpToolsBenchmark.cpp
  • OloEditor/src/Panels/SceneHierarchyPanel.cpp
  • OloEngine/src/CMakeLists.txt
  • OloEngine/src/OloEngine/Asset/AssetPackBuilder.cpp
  • OloEngine/src/OloEngine/Asset/AssetSerializer.cpp
  • OloEngine/src/OloEngine/Groom/CoatVolumeAdmission.h
  • OloEngine/src/OloEngine/Renderer/AnimatedModel.cpp
  • OloEngine/src/OloEngine/Renderer/AnimatedModel.h
  • OloEngine/src/OloEngine/Renderer/Benchmark/BenchmarkCapture.cpp
  • OloEngine/src/OloEngine/Renderer/Benchmark/BenchmarkCapture.h
  • OloEngine/src/OloEngine/Renderer/Benchmark/BenchmarkManifest.cpp
  • OloEngine/src/OloEngine/Renderer/Benchmark/BenchmarkManifest.h
  • OloEngine/src/OloEngine/Renderer/Model.cpp
  • OloEngine/src/OloEngine/Renderer/Passes/GroomRenderPass.cpp
  • OloEngine/src/OloEngine/Renderer/Passes/GroomRenderPass.h
  • OloEngine/src/OloEngine/Renderer/Passes/ShadowRenderPass.cpp
  • OloEngine/src/OloEngine/Renderer/Passes/ShadowRenderPass.h
  • OloEngine/src/OloEngine/Renderer/PercentDecodingAssimpIO.h
  • OloEngine/src/OloEngine/Renderer/RayTracing/VegetationPolicy.h
  • OloEngine/src/OloEngine/Renderer/RayTracing/VegetationSurfaceCache.cpp
  • OloEngine/src/OloEngine/Renderer/RenderGraphOutOfBand.cpp
  • OloEngine/src/OloEngine/Renderer/Renderer3DFrameExecution.cpp
  • OloEngine/src/OloEngine/Renderer/Renderer3DGPUScene.cpp
  • OloEngine/src/OloEngine/Renderer/Shadow/FoliageShadowInvalidation.h
  • OloEngine/src/OloEngine/Renderer/Shadow/ShadowInvalidationQueue.h
  • OloEngine/src/OloEngine/Renderer/Shadow/VirtualShadowMap.cpp
  • OloEngine/src/OloEngine/Renderer/Shadow/VirtualShadowMap.h
  • OloEngine/src/OloEngine/SaveGame/SaveGameComponentSerializer.cpp
  • OloEngine/src/OloEngine/SaveGame/SaveGameTypes.h
  • OloEngine/src/OloEngine/Scene/Components.h
  • OloEngine/src/OloEngine/Scene/ModelImporter.cpp
  • OloEngine/src/OloEngine/Scene/Scene.cpp
  • OloEngine/src/OloEngine/Scene/Scene.h
  • OloEngine/src/OloEngine/Scene/SceneSerializer.cpp
  • OloEngine/src/OloEngine/Scene/TerrainGround.cpp
  • OloEngine/src/OloEngine/Scene/TerrainGround.h
  • OloEngine/src/OloEngine/Serialization/AssetPackFile.h
  • OloEngine/src/OloEngine/Serialization/ImportedMaterialCodec.cpp
  • OloEngine/src/OloEngine/Serialization/ImportedMaterialCodec.h
  • OloEngine/src/OloEngine/Serialization/MeshBinaryFormat.h
  • OloEngine/src/OloEngine/Terrain/Foliage/FoliageGPUCuller.cpp
  • OloEngine/src/OloEngine/Terrain/Foliage/FoliageGPUCuller.h
  • OloEngine/src/OloEngine/Terrain/Foliage/FoliageRenderer.cpp
  • OloEngine/src/OloEngine/Terrain/Foliage/FoliageRenderer.h
  • OloEngine/tests/AssetPackTest.cpp
  • OloEngine/tests/CMakeLists.txt
  • OloEngine/tests/Functional/Rendering/AnimalPathFollowsTerrainTest.cpp
  • OloEngine/tests/Functional/Rendering/AnimalPopulationViaSceneTickTest.cpp
  • OloEngine/tests/Groom/GroomCoatShadowSelectionTest.cpp
  • OloEngine/tests/ModelImporterTest.cpp
  • OloEngine/tests/Rendering/AnimatedModelDedupTest.cpp
  • OloEngine/tests/Rendering/FoliageCullStreamSizingContractTest.cpp
  • OloEngine/tests/Rendering/FoliageShadowInvalidationContractTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/AcceptanceSceneEvidenceTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/BenchmarkCaptureTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/FoliageCostBaselineTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/FoliageGPUCullEvidenceTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/FoliageVsmCacheVisualEvidenceTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/FoxCoatEvidenceTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/GroomAnimalsCookedBindingTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/GroomViewCullTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/ImportedMaterialPackTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/LightingTapEvidenceTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/ReferenceFixtureManifestTest.cpp
  • OloEngine/tests/Rendering/PropertyTests/SkinRiggedHeadEvidenceTest.cpp
  • OloEngine/tests/Rendering/RayTracing/VegetationPolicyTest.cpp
  • OloEngine/tests/scripts/generate_animal_population_scene.py
  • docs/README.md
  • docs/agent-rules/README.md
  • docs/agent-rules/foliage-vsm-page-caching.md
  • docs/agent-rules/multi-animal-scheduling-budgets.md
  • docs/agent-rules/virtual-shadow-map-page-cache.md
  • docs/analysis/integrated-acceptance-1259.md
  • docs/guides/gltf-material-extensions.md
  • docs/guides/groom-animals.md
  • docs/guides/integrated-renderer-benchmark.md
  • docs/guides/skin-digital-human.md
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_coats-closeup.webp
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_head-backlit.webp
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_head-closeup.webp
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_population-dolly.webp
  • docs/testing/evidence/integrated-acceptance-1259/GL_Deferred_rapid-turn.webp
  • docs/testing/evidence/integrated-acceptance-1259/gl-summary.md
  • docs/testing/evidence/integrated-acceptance-1259/vulkan-live/README.md
  • docs/testing/evidence/integrated-acceptance-1259/vulkan-live/live-vk-attrib.json
  • docs/testing/evidence/integrated-acceptance-1259/vulkan-live/live-vk-gatefix.json
  • docs/testing/evidence/integrated-acceptance-1259/vulkan-live/live-vk-hybrid.json
  • docs/testing/evidence/integrated-acceptance-1259/vulkan-live/live-vk-vvl.json
  • docs/testing/evidence/integrated-acceptance-1259/vulkan-live/live-vk.json
  • docs/testing/evidence/integrated-acceptance-1259/vulkan-live/reopen.json
  • scripts/perf/acceptance-benchmark.py
  • scripts/perf/acceptance-ground.json
  • scripts/perf/acceptance-live.py
  • scripts/perf/capture_process.py
  • scripts/perf/controlled-benchmark.py
  • scripts/perf/generate-acceptance-scene.py
  • scripts/perf/generate-integrated-benchmark.py
  • scripts/perf/test_acceptance_benchmark.py
  • tools/skin-thickness/README.md
  • tools/skin-thickness/bake_thickness.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

AssetContentValidity.EverySupportedAssetOnDiskIsInTheRegistry failed in CI:
Scenes/Benchmark/Acceptance.olo is on disk but not in AssetRegistry.oar.
The registry this branch carried was the three-way union from the master
merge, and the scene's entry had only ever been added by a local editor
run, never committed. Rebased with AssetContentValidity.DISABLED_RebaseAssetRegistry:
one entry added, none removed or changed (380 total); all 28
AssetContentValidity cases pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@drsnuggles8
drsnuggles8 merged commit ada4198 into master Oct 11, 2026
30 of 31 checks passed
@drsnuggles8
drsnuggles8 deleted the feature/integrated-aaa-acceptance-scene-1259 branch October 11, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Foliage cull streams hold every plant twice per view slot: 320 MB of a 371 MB GPU floor

1 participant