feat(tilemap): Uint16Array layerData + drawTileRaw renderer bypass (#1401 foundation)#1445
Open
obiot wants to merge 1 commit into
Open
feat(tilemap): Uint16Array layerData + drawTileRaw renderer bypass (#1401 foundation)#1445obiot wants to merge 1 commit into
obiot wants to merge 1 commit into
Conversation
…1401) Foundation for the upcoming GPU tilemap shader path. Refactors TMX tile layer storage and rendering so that: - TMXLayer.layerData is now a flat Uint16Array (GID + flip mask per cell). Stable Tile identity is preserved via a lazy cachedTile view-cache that allocates on the first user-facing cellAt/getTile call — games that never query tiles by coord keep it null for the layer's lifetime. - Map parsing decodes TMX layer data straight into bytes — zero Tile allocations during parse (saves ~500k constructor calls on a dense 1000x1000 map). - The orientation renderers (Orthogonal / Oblique / Isometric / Hexagonal) read layerData directly and dispatch via new drawTileRaw methods on each renderer and on TMXTileset. The per-frame render loop never constructs a Tile, never touches cachedTile. - TMXLayer.dataVersion counter bumps on setTile/clearTile — groundwork for GPU upload invalidation in the shader path. - New buildFlipTransform(matrix, flipMask, w, h) helper shared between Tile.setTileTransform and the new raw render path. - Public API (getTile, setTile, cellAt, clearTile, getTileId, getTileById, getRenderable) is unchanged. Memory: per-layer drops ~25x for games that don't query tiles by coord (~40 KB vs ~1 MB on a 100x100 dense layer). Per-frame FPS: modest gain on Canvas (~2-5% in tile-heavy scenes); the big WebGL win lands when the shader path comes online on top of this foundation. Tests: tmxlayer-data.spec.js (68 adversarial encoding tests including all 8 flip combinations + real-fixture snapshot) + tmxlayer-drawraw.spec.js (16 parity tests between legacy drawTile and new drawTileRaw). 3021/3021 suite green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First commit toward #1401 — GPU-accelerated tilemap rendering. Refactors the TMX tile-layer data layout and renderer hot path so the upcoming WebGL2 shader path has a contiguous, GPU-uploadable backing store to draw from. No GPU shader code yet — that lands on top of this foundation in a follow-up PR.
What changed
TMXLayer.layerDatais now a flatUint16Array(GID + 3-bit flip mask per cell, row-major). Stable user-facingTileidentity is preserved via a lazycachedTileview-cache that allocates on firstcellAt/getTilecall — games that never query tiles by coord keep itnullfor the layer's lifetime.Tileallocations during load.layerDatadirectly and dispatch via newdrawTileRawmethods on each renderer and onTMXTileset. The per-frame render loop never constructs aTile.TMXLayer.dataVersioncounter bumps onsetTile/clearTile— groundwork for GPU upload invalidation in the shader path.buildFlipTransform(matrix, flipMask, w, h)helper shared betweenTile.setTileTransformand the new raw render path.Public API
Unchanged —
getTile,setTile,cellAt,clearTile,getTileId,getTileById,getRenderableall work as before.Wins
Tileconstructor calls saved on a dense 1000×1000 map.Tileallocations during render. Modest FPS gain on Canvas (~2–5% in tile-heavy scenes); WebGL gains come with the shader path.Tests
tmxlayer-data.spec.js(68 adversarial encoding tests) — all 8 flip combinations, GID range edge cases, identity stability via lazy cache, bounds validation,dataVersionmonotonicity, parser-path no-allocation guard, cross-cell isolation, real-fixture round-trip.tmxlayer-drawraw.spec.js(16 parity tests) — pixel-level byte-for-byte parity between legacydrawTileand newdrawTileRawfor every flip combination; spy-verified zeroTileconstruction during render;buildFlipTransformmatchesTile.setTileTransform.Next
Phase 2 of #1401:
WebGLRenderer.drawTileLayershader path on top of this foundation — single quad per tileset, fragment-shader tile lookup viaRG16UIindex texture upload.Test plan
pnpm -F melonjs build)🤖 Generated with Claude Code