Open Bug 1908624 Opened 4 months ago Updated 3 months ago

niels747.github.io - Issues with WebGL and texture drawcall types, making certain features unusable

Categories

(Core :: Graphics: CanvasWebGL, defect, P3)

Desktop
Linux
defect

Tracking

()

People

(Reporter: ctanase, Assigned: jgilbert)

References

()

Details

(Whiteboard: [webcompat-source:web-bugs])

Environment:
Operating system: Linux
Firefox version: Firefox 128.0/130

Steps to reproduce:

  1. Go to https://niels747.github.io/2D-Weather-Sandbox
  2. Click on "Create New Simulation".
  3. Wait for the simulation to load.
  4. Click anywhere on the screen.
  5. Press "A" on the keyboard.

Expected Behavior:
The flight simulator remains on the screen.

Actual Behavior:
The flight simulator disappears after a few seconds.

Notes:

  • Reproduces regardless of the status of ETP
  • Reproduces in Firefox Nightly, and Firefox Release
  • Does not reproduce in Chrome
  • Doesn't seem to reproduce on Windows 10

Created from https://github.com/webcompat/web-bugs/issues/139286

Moving this over to the graphics team, maybe they have a quick idea.

Component: Site Reports → Graphics: CanvasWebGL
Product: Web Compatibility → Core

Thanks for filing. We'll try to reproduce and determine what's going on.

Blocks: gfx-triage

I was able to reproduce this (and suggested the filing of this webcompat bug in the first place), so we can count this one as confirmed.

Also weather stations are another repro.

1a. Select weather station from the side pane. User Interaction (collapsible) -> Tools (dropdown) -> weather station
OR
1b. Click anywhere on the sky or ground to focus the sim and press N to activate the tool.
2. Click anywhere on the sky or on/underground.

Expected behavior: Text overlay should appear at the point where you clicked displaying local atmospheric conditions.

Actual behavior: Nothing appears

This feature makes use of a texture array of some sort, of which multiple are used for different purposes for each in-sim pixel/texel, in this case to determine what is the sky, ground, or water. The arrays are never populated/initialized to 0, always interpreted as ground, hence the flight sim plane immediately exploding thinking it crashed into the ground.

The weather station changes content or behavior depending on whether it's in the sky or on the ground, measuring rain/snow amounts based on the state of each pixel representing the ground for instance.

The downstream GitHub issue contains key information including relevant JS code snippets and what worked around a particular case of it related to water temperature: https://github.com/niels747/2D-Weather-Sandbox/issues/99

Severity: -- → S3
Priority: -- → P2

From github: https://github.com/niels747/2D-Weather-Sandbox/issues/99#issuecomment-1817703743

Found this little nugget.

WebGL warning: readPixels: Format and type RGBA_INTEGER/<enum 0x1400> incompatible with this RGBA8I attachment. This framebuffer requires either RGBA_INTEGER/INT or getParameter(IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE) RGBA_INTEGER/INT.

For some reason this fixes it. It probably blows up memory usage.

gl.readBuffer(gl.COLOR_ATTACHMENT2);
var wallTextureValues = new Int32Array(4 * sim_res_y);
gl.readPixels(simXpos, 0, 1, sim_res_y, gl.RGBA_INTEGER, gl.INT, wallTextureValues); // read a vertical column of cells

Using Int32Array and gl.INT where ever wallTextureValues is populated fixes both this issue, and the unreported issue of weather stations not working on Firefox. No side effects on Chrome.

Why? I don't know.

So this is an attempt to call ReadPixels(RGBA_INTEGER,BYTE) from a RGBAI8 source. The only spec-guaranteed way to read from an "int-ish" format is RGBA_INTEGER/INT, but a driver may offer some other pair, that authors may query via getParameter(IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE).
So that's why switching to gl.RGBA_INTEGER, gl.INT works: It is the only combo that is guaranteed to work on all computers!

Authors may choose to check the alternative, which might happen to be supported by a driver:

const alternative = {
  format: gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT),
  type: gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE),
};
if (alternative.format == gl.RGBA_INTEGER &&
   alternative.type == gl.BYTE) {
  // the existing readPixels(RGBA_INTEGER,BYTE) code
} else {
  // readPixels(gl.RGBA_INTEGER, gl.INT) code
}

I made a PR to fix the app: https://github.com/niels747/2D-Weather-Sandbox/pull/134

We could clarify the error message better though, I suppose.

It's worth checking if the driver is offering this to us, but we are just choosing to ignore it because maybe we don't recognize 0x1400=GL_BYTE in this case. (or maybe we can rely on this on desktop GL?)

Absent driver support, it would be hard to polyfill correctly, because if this were a ReadPixels command with a PBO destination, that's all "GPU-side", so it would be hard to emulate support for e.g. BYTE when only INT is supported.

Severity: S3 → S4
Priority: P2 → P3
No longer blocks: gfx-triage

This version should be fixed, if someone can check! https://kdashg.github.io/niels747-2D-Weather-Sandbox/

Assignee: nobody → jgilbert
See Also: → 1916561
You need to log in before you can comment on or make changes to this bug.