Skip to content

perf(producer): cache transfer-converted hdr image buffers per render job#384

Open
vanceingalls wants to merge 1 commit intomainfrom
vance/hdr-image-transfer-cache
Open

perf(producer): cache transfer-converted hdr image buffers per render job#384
vanceingalls wants to merge 1 commit intomainfrom
vance/hdr-image-transfer-cache

Conversation

@vanceingalls
Copy link
Copy Markdown
Collaborator

@vanceingalls vanceingalls commented Apr 21, 2026

Summary

Add HdrImageTransferCache — a per-render-job bounded LRU keyed by (imageId, targetTransfer) — so static HDR image layers whose source transfer differs from the render's effective transfer (PQ↔HLG) are converted once per job instead of once per composited frame.

Why

Chunk 8B of plans/hdr-followups.md. blitHdrImageLayer was running Buffer.from + convertTransfer on every composited frame, even though the converted buffer is identical for the entire job. For a multi-second comp at 30 fps this is hundreds of redundant transfer conversions on the hot path.

What changed

  • New packages/producer/src/services/hdrImageTransferCache.ts — bounded LRU keyed by (imageId, targetTransfer) that owns the converted HDR rgb48 buffer for static HDR image layers:
    • Same-transfer requests return the source buffer untouched (zero copy).
    • Cross-transfer requests pay one Buffer.from + convertTransfer on first miss, reuse the cached copy on every subsequent frame.
  • Wired into renderOrchestrator.ts via HdrCompositeContext.hdrImageTransferCache, instantiated once per render job, and consumed by blitHdrImageLayer on both the main composite path and the transition path.

Test plan

  • packages/producer/src/services/hdrImageTransferCache.test.ts — 12 tests:
    • hit/miss semantics
    • distinct keys per image and per target transfer
    • LRU eviction + promotion
    • maxEntries=0 passthrough
    • source-buffer immutability for cached entries
    • invalid options
  • Re-ran the Chunk 8A HDR benchmark — for the hdr-regression fixture (which has cross-transfer image layers) the cache hits 100% after the first frame; for HDR fixtures without cross-transfer images the same-transfer passthrough is a no-op.

Stack

Chunk 8B of plans/hdr-followups.md. Sits on top of Chunk 8C (logger gating) and Chunk 8A (benchmark harness) so the win is measurable.

This was referenced Apr 21, 2026
Copy link
Copy Markdown
Collaborator Author

vanceingalls commented Apr 21, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from a3d4984 to b3241ce Compare April 23, 2026 00:45
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from b8d319d to d222b31 Compare April 23, 2026 01:58
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from b3241ce to 8b636ec Compare April 23, 2026 01:58
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from d222b31 to e72f484 Compare April 23, 2026 02:59
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 8b636ec to 6bc1dd6 Compare April 23, 2026 03:00
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from e72f484 to 5338173 Compare April 23, 2026 03:22
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 6bc1dd6 to b03a62f Compare April 23, 2026 03:23
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from 5338173 to b99006d Compare April 23, 2026 03:44
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from b03a62f to 31915d0 Compare April 23, 2026 03:45
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from b99006d to 644607f Compare April 23, 2026 04:52
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 31915d0 to 90bd43b Compare April 23, 2026 04:53
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from 644607f to 0d7dd4c Compare April 23, 2026 05:12
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 90bd43b to 4555013 Compare April 23, 2026 05:13
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from 0d7dd4c to 50cc3df Compare April 23, 2026 05:47
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 4555013 to 1f61054 Compare April 23, 2026 05:48
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from 50cc3df to bd2cbff Compare April 23, 2026 06:07
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 1f61054 to 0b54ff2 Compare April 23, 2026 06:07
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from bd2cbff to 732d2d4 Compare April 23, 2026 07:00
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch 2 times, most recently from 0afa982 to 282395d Compare April 23, 2026 15:33
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from 732d2d4 to 217c325 Compare April 23, 2026 15:33
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 282395d to ec4315a Compare April 23, 2026 16:35
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch 2 times, most recently from eef88c9 to 1ab61c6 Compare April 23, 2026 17:41
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from ec4315a to 55a76b1 Compare April 23, 2026 17:41
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from 1ab61c6 to 824aca2 Compare April 23, 2026 18:14
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 55a76b1 to 31e1374 Compare April 23, 2026 18:14
@vanceingalls vanceingalls force-pushed the vance/logger-level-gating branch from 824aca2 to cb757f1 Compare April 23, 2026 18:44
@vanceingalls vanceingalls force-pushed the vance/hdr-image-transfer-cache branch from 31e1374 to 226d019 Compare April 23, 2026 18:45
… job

Static HDR image layers whose source transfer differs from the render's effective
transfer (PQ↔HLG) were re-running `Buffer.from` + `convertTransfer` on every
composited frame, even though the converted buffer is identical for the entire
job. Added `HdrImageTransferCache` — a per-render-job bounded LRU keyed by
`(imageId, targetTransfer)` that converts once and reuses on every subsequent
frame, while leaving same-transfer requests as a zero-copy passthrough.

Wired into `renderOrchestrator.ts` via `HdrCompositeContext.hdrImageTransferCache`,
instantiated once per job and consumed by `blitHdrImageLayer` on both the main
composite path and the transition path. Covered by `hdrImageTransferCache.test.ts`
(hit/miss, distinct keys per image and per target transfer, LRU eviction +
promotion, `maxEntries=0` passthrough, source-buffer immutability for cached
entries, invalid options).

Made-with: Cursor
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.

3 participants