Fix WebGL texture.read() for R8/RG8/RGB8 formats and add UNPACK_ALIGNMENT state caching #8406
Merged
Conversation
…MENT state caching
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes WebGL texture readback for non-RGBA 8-bit formats and reduces GL state churn by caching UNPACK_ALIGNMENT.
Changes:
- Add RGBA/
UNSIGNED_BYTEforced readback path forR8/RG8/RGB8on WebGL and channel extraction into the expected output format. - Fix
getPixelFormatArrayType(PIXELFORMAT_RG8)to returnUint8Array. - Add cached
setUnpackAlignment()and update WebGL texture upload paths to consistently set alignment for typed-array uploads; add a hidden example to validate read/write roundtrips.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/platform/graphics/webgl/webgl-upload-stream.js | Uses device-cached UNPACK_ALIGNMENT setter during PBO uploads to avoid redundant state calls. |
| src/platform/graphics/webgl/webgl-texture.js | Ensures alignment is set to 1 for typed-array upload paths to prevent row-alignment-related upload errors. |
| src/platform/graphics/webgl/webgl-graphics-device.js | Adds setUnpackAlignment() and implements RGBA-forced readback + channel extraction for R8/RG8/RGB8. |
| src/platform/graphics/constants.js | Corrects getPixelFormatArrayType behavior for PIXELFORMAT_RG8. |
| examples/thumbnails/test_texture-read_small.webp | Adds thumbnail for the new example. |
| examples/thumbnails/test_texture-read_large.webp | Adds thumbnail for the new example. |
| examples/src/examples/test/texture-read.example.mjs | Adds hidden example to validate texture.read() roundtrip for 8-bit formats across WebGL/WebGPU. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
willeastcott
approved these changes
Jan 23, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 7 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
slimbuck
approved these changes
Jan 23, 2026
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
texture.read()for non-RGBA 8-bit formats on WebGL: WebGL2'sreadPixelsonly guarantees support forRGBA/UNSIGNED_BYTEfrom renderable framebuffers. Formats likeR8,RG8, andRGB8now correctly read back by using RGBA readback internally and extracting the appropriate channels.getPixelFormatArrayTypeforPIXELFORMAT_RG8: Corrected the return type fromUint16ArraytoUint8Array.setUnpackAlignment()with state caching: Added a cached setter forUNPACK_ALIGNMENTto avoid redundant GL calls and prevent state pollution between texture uploads (e.g., when streaming uploads changed alignment).texture-read.example.mjsthat verifies texture read/write roundtrip for 8-bit formats.Technical Details
WebGL
texture.read()FixgetPixelFormatChannelsForRgbaReadback()helper inwebgl-graphics-device.jsreadPixelsAsync()with optionalforceRgbaparameterreadTextureAsync()detects formats requiring RGBA readback, reads into an RGBA buffer, then extracts the correct channels into the user's expected formatUNPACK_ALIGNMENT Caching
this.unpackAlignmentstate variable initialized to 1setUnpackAlignment(alignment)method that only callsgl.pixelStoreiwhen the value changeswebgl-texture.js,webgl-upload-stream.js) to use the cached setterTest Example
examples/src/examples/test/texture-read.example.mjs(hidden)R8,RG8,RGB8, andRGBA8formatsTest Plan
texture-readtest example on WebGL - all formats passtexture-readtest example on WebGPU - all formats pass