Closed Bug 1763507 Opened 2 years ago Closed 2 years ago

Firefox clears canvas when RASTERIZER_DISCARD is enabled (webgl2)

Categories

(Core :: Graphics: CanvasWebGL, defect)

Firefox 98
defect

Tracking

()

RESOLVED INVALID

People

(Reporter: me, Unassigned)

References

()

Details

Steps to reproduce:

Doing a WebGL2 call with RASTERIZER_DISCARD enabled clears the canvas in Firefox (reproduced in versions 96 and 98). This behaviour does not occur in Chrome 98 or Edge 98. And as section 3.1 of the OpenGL ES spec (https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf) writes, "When enabled, RASTERIZER_DISCARD also causes the Clear and ClearBuffer* commands to be ignored".

I'm using a Linux distribution (Pop!_OS 21.10), and my unmasked renderer is "ANGLE (Intel, Mesa Intel(R) UHD Graphics 620 (WHL GT2), OpenGL 4.6 (Core Profile) Mesa 21.2.2)".

<details>

<summary>Code to reproduce</summary>

let canvas = document.createElement('canvas')
let gl = canvas.getContext('webgl2')
document.body.appendChild(canvas)
gl.clearColor(1, 0, 0, 1)
gl.clear(gl.COLOR_BUFFER_BIT)

// removing this delay stops the issue occuring
await new Promise((resolve) => setTimeout(resolve, 200))

let vs = '#version 300 es\nflat out int result; void main() { result = gl_VertexID; }'
let fs = '#version 300 es\nvoid main() {}'

let vsc = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vsc, vs)
gl.compileShader(vsc)

let fsc = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fsc, fs)
gl.compileShader(fsc)

let program = gl.createProgram()
gl.attachShader(program, vsc)
gl.attachShader(program, fsc)
gl.transformFeedbackVaryings(program, ['result'], gl.SEPARATE_ATTRIBS)
gl.linkProgram(program)

let n = 8
let buf = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buf)
gl.bufferData(gl.ARRAY_BUFFER, n * 4, gl.STATIC_DRAW)
gl.bindBuffer(gl.ARRAY_BUFFER, null)

let tf = gl.createTransformFeedback()
gl.useProgram(program)

gl.enable(gl.RASTERIZER_DISCARD)
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf)
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf)
gl.beginTransformFeedback(gl.POINTS)
gl.drawArrays(gl.POINTS, 0, n)
gl.endTransformFeedback()
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null)
gl.disable(gl.RASTERIZER_DISCARD)

let result = new Int32Array(n)
gl.bindBuffer(gl.ARRAY_BUFFER, buf)
gl.getBufferSubData(gl.ARRAY_BUFFER, 0, result)
gl.bindBuffer(gl.ARRAY_BUFFER, null)
console.log(result) // [0, 1, 2, 3, 4, 5, 6, 7]

</details

Actual results:

When running the provided code, a red square briefly appears on the screen, and then disappears.

Expected results:

The red square should remain visible after gl.drawArrays is called.

The Bugbug bot thinks this bug should belong to the 'Core::Canvas: WebGL' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.

Component: Untriaged → Canvas: WebGL
Product: Firefox → Core

The severity field is not set for this bug.
:jgilbert, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(jgilbert)

I wrapped up the testcase provided into a jsfiddle: https://jsfiddle.net/5t0219xg/

Flags: needinfo?(jgilbert)

I confirm the behavior as-described in Firefox.
Chrome appears to have the same behavior as Firefox for me now.
WebGL's spec'd behavior for "should preserveDrawingBuffer:false cause a clear" is very basic, and does not take into account RASTERIZER_DISCARD.

I can see how this might be suboptimal, because the workaround would be to create a framebuffer that you never actually use: https://jsfiddle.net/5t0219xg/2/

In this case, you can use a 1x1 renderbuffer, but for something related to the scene, you might actually need a WxH renderbuffer that never gets otherwise written to.

If this usecase is important to you, and you think we should consider changing the spec here, please file an issue: https://github.com/KhronosGroup/WebGL/issues

("RESOLVED INVALID" is our "NOTABUG")

Status: UNCONFIRMED → RESOLVED
Closed: 2 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.