Repository navigation
GLEmulation: use highp in generated fixed-function fragment shaders - #28062
TheTomBritton wants to merge 1 commit into
Conversation
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
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
| SDL_Surface *screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL); | |
| SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, SDL_OPENGL); |
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 wheremediumpis genuinely fp16 texture coordinates through a texture matrix overflow it. This emits the same guarded header GLEmulation already adds to user shaders: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