Skip to content

GLEmulation: use highp in generated fixed-function fragment shaders - #28062

Open
TheTomBritton wants to merge 1 commit into
emscripten-core:mainfrom
TheTomBritton:glemu-fs-highp
Open

TheTomBritton wants to merge 1 commit into
emscripten-core:mainfrom
TheTomBritton:glemu-fs-highp

Conversation

@TheTomBritton

Copy link
Copy Markdown

Fixes #27948.

The generated fixed-function fragment shaders declared precision mediump float;. GL 1.x fixed function is specified in at least fp32-class precision (GL 1.5 §2.1.1), and on GPUs where mediump is genuinely fp16 texture coordinates through a texture matrix overflow it. This emits the same guarded header GLEmulation already adds to user shaders:

#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif

so WebGL1 implementations without fragment highp keep working. Adds test_gl_ffp_texcoord_precision, which draws with texture coordinates from 1000 to 1001 (where fp16 can only step by 0.5) and checks them texel by texel. As expected it does not fire on desktop (it passes with and without the change on Chrome/ANGLE Metal and SwiftShader); the case for the change is the spec and GPUs where mediump really is fp16. The other LEGACY_GL_EMULATION browser tests pass locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AFhyBALrPm8CSkyHzQizDH

The fixed-function fragment shaders that GLImmediate generates declared a
plain `precision mediump float;`. GL 1.x fixed function needs more than
mediump guarantees: GL 1.5 section 2.1.1 asks for texture coordinates up
to 2^10 in magnitude and results accurate to about one part in 10^5,
while mediump only promises a relative precision of 2^-10 and a range of
2^14, and it is real half precision on some GPUs.

Emit the same guarded header that GLEmulation already prepends to user
shaders without a precision statement: highp where
GL_FRAGMENT_PRECISION_HIGH says it exists, mediump otherwise.

Adds a browser test that draws a texture with coordinates running from
1000 to 1001 (brought back to 0..1 by the texture matrix) and checks that
each quarter of the screen shows its own texel. Under half precision the
coordinate 1000.375 rounds to 1000.5 and picks the wrong texel. On GPUs
where mediump is already full precision the test passes with or without
this change.

Fixes emscripten-core#27948

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UR3bCLyLBQiGtevGJx2ARt

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the fixed-function fragment shaders generated by LEGACY_GL_EMULATION to use highp precision when supported by the GPU, preventing precision loss in texture coordinates on platforms where mediump is only half-precision. It also adds a regression test and registers it in the browser test suite. The reviewer suggests updating the test to request a 32-bit color depth instead of 16-bit in SDL_SetVideoMode to ensure standard 8-bit precision per channel and avoid potential failures during color assertions.


SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

SDL_Surface *screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Requesting a 16-bit color depth (16) in SDL_SetVideoMode can lead to precision loss in the color channels (e.g., RGB565 or RGBA4444) depending on how the platform/emulation layer handles it. Since the test asserts precise color values (e.g., px[c] > 200 and px[c] < 50), it is safer and more robust to request a 32-bit depth (32) to ensure 8-bit precision per channel (RGBA8888), which aligns with standard WebGL backbuffer precision.

Suggested change
SDL_Surface *screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL);
SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, SDL_OPENGL);

@sbc100
sbc100 requested a review from juj October 23, 2026 19:41

This branch has not been deployed

No deployments
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.

LEGACY_GL_EMULATION: generated fixed-function fragment shaders use mediump — fp16 overflow where mediump is half precision

1 participant