WebGL 2: Multiple Render Targets

2,653 views
Skip to first unread message

Evgeny Demidov

unread,
Jan 28, 2016, 7:18:47 AM1/28/16
to webgl-d...@googlegroups.com
to make simulations on GPU, I have to ping-pong 2 textures with data. In
WebGL 1 I used 2 FBO but

"Avoid extraneous glBindFramebuffer calls. Use multiple attachments to a
FBO rather than managing multiple FBOs." OpenGL Insights

therefore, I make FBO with 2 texures
FBO = gl.createFramebuffer()
gl.bindFramebuffer(gl.FRAMEBUFFER, FBO)
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D, texture, 0)
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1,
gl.TEXTURE_2D, texture1, 0)
if( gl.checkFramebufferStatus(gl.FRAMEBUFFER) !=
gl.FRAMEBUFFER_COMPLETE) alert("FBOs are not complete")
and trying something like this
gl.bindFramebuffer(gl.FRAMEBUFFER, FBO)
gl.uniform1i(sampLoc, 0) // input texture
gl.drawBuffers([gl.COLOR_ATTACHMENT1]) // output texture
// gl.bindFramebuffer(gl.FRAMEBUFFER, FBO1) // used in WebGL 1
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)

See http://www.ibiblio.org/e-notes/webgl/gpu/flat_wave2mu.htm
I get in Canary
INVALID_OPERATION: drawBuffers: COLOR_ATTACHMENTi_EXT or NONE

what is wrong?

Evgeny

Evgeny Demidov

unread,
Jan 28, 2016, 8:21:59 AM1/28/16
to webgl-d...@googlegroups.com
may be it is not implemented in Canary yet. There is WEBGL_draw_buffers
extension and for
gl.uniform1i(sampLoc, 0)
gl.drawBuffers([gl.COLOR_ATTACHMENT1_WEBGL]) // was COLOR_ATTACHMENT1
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)

Really it is a mix of WebGL 1 and 2 and I get another
ERROR :GL_INVALID_OPERATION : glDrawArrays: Source and destination
textures of the draw are the same.

May be I'll MRT in WebGL 1 ?

Evgeny

Catalin

unread,
Jan 28, 2016, 9:16:32 AM1/28/16
to webgl-d...@googlegroups.com
try http://www.doesmybrowsersupportwebgl.com/ to check your webgl extension .
I think are many tools on web to see if your browser support

about glDrawArrays you put same variable and that don't allow

is not a mix into webgl , it's just update of extension for example if you want to understand that think this question:
why development team make drawArrays ?
why need FBO and where we can used ?  not just take one good screenshot .

tell me if I wrong .

--
You received this message because you are subscribed to the Google Groups "WebGL Dev List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webgl-dev-lis...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Won

unread,
Jan 28, 2016, 11:49:46 AM1/28/16
to webgl-d...@googlegroups.com
I don't think you should have both color attachments at the same time if you intend on pingponging. Instead, alternate which is the render target and which is the texture. In other words, you can't avoid the state changes (FrameBufferTexture, Uniform1i) but you can avoid the bind call to BindFramebuffer.

-Won

Shannon Woods

unread,
Jan 28, 2016, 7:12:47 PM1/28/16
to webgl-d...@googlegroups.com
In OpenGL ES, the attachment list specified to glDrawBuffers must be sequential for user-defined framebuffers: "If the GL is bound to a framebuffer object, the ith buffer listed in bufs must be COLOR_ATTACHMENTi or NONE. Specifying a buffer out of order, BACK, or COLOR_ATTACHMENTm where m is greater than or equal to the value of MAX_- COLOR_ATTACHMENTS, will generate the error INVALID_OPERATION." I believe this constraint also holds for WebGL, and that's what causes the INVALID_OP in your first message.

The second error sounds like you're causing a feedback loop-- attempting to sample from a texture in a draw call when that texture is bound as a draw buffer. This is an error in WebGL.

Jeff Dash

unread,
Jan 28, 2016, 7:31:58 PM1/28/16
to webgl-d...@googlegroups.com
I agree with Shannon. Two FBs is the way to do this.

You should also be getting a GL error for `gl.drawBuffers([gl.COLOR_ATTACHMENT1])` anyway. This is an error in Firefox:

> > g.drawBuffers([g.COLOR_ATTACHMENT1])
> undefined
> Error: WebGL: drawBuffers: `buffers[i]` must be NONE or COLOR_ATTACHMENTi.

Evgeny Demidov

unread,
Jan 29, 2016, 12:01:11 AM1/29/16
to webgl-d...@googlegroups.com
"Avoid extraneous glBindFramebuffer calls. Use multiple attachments to a FBO rather than managing multiple FBOs." OpenGL Insights :)

to Won: thank you. I could try but then I needn't MRT, just change "framebufferTexture2D" and textures will be tested for compatibility again. Don't know what is better to change FBOs or framebufferTexture2Ds.

"Specifying a buffer out of order... will generate the error INVALID_OPERATION" - it is a pity.
Can I use 2 MRT and if operator in fragment shader? E.g.

layout(location = 0) out vec4 fragData0;
layout(location = 1) out vec4 fragData1;
uniform int out;
...
if(out == 0)  fragData0 = out0;
else              fragData1 = out1;

I think it is forbidden too :)

In any case "INVALID_OPERATION: drawBuffers: COLOR_ATTACHMENTi_EXT or NONE" is confusing.

Evgeny

Won

unread,
Jan 29, 2016, 8:12:32 AM1/29/16
to webgl-d...@googlegroups.com
On Fri, Jan 29, 2016 at 12:00 AM, Evgeny Demidov <dem...@ipm.sci-nnov.ru> wrote:
"Avoid extraneous glBindFramebuffer calls. Use multiple attachments to a FBO rather than managing multiple FBOs." OpenGL Insights :)

to Won: thank you. I could try but then I needn't MRT, just change "framebufferTexture2D" and textures will be tested for compatibility again. Don't know what is better to change FBOs or framebufferTexture2Ds.

I don't know which is better either, but it is an alternative that I think we both can agree is likely to at least work, so maybe worth a try? It is possible that WebGL will cache the validation for the texture attachment, or that attachment state is cheaper than framebuffer state.
 

"Specifying a buffer out of order... will generate the error INVALID_OPERATION" - it is a pity.
Can I use 2 MRT and if operator in fragment shader? E.g.

layout(location = 0) out vec4 fragData0;
layout(location = 1) out vec4 fragData1;
uniform int out;
...
if(out == 0)  fragData0 = out0;
else              fragData1 = out1;

I think it is forbidden too :)

In any case "INVALID_OPERATION: drawBuffers: COLOR_ATTACHMENTi_EXT or NONE" is confusing.

Like I said, I think the issue is that WebGL doesn't let you have a texture bound to a sampler and a frame buffer at the same time.

-Won
 

Muhammad Mobeen Movania

unread,
Jan 29, 2016, 8:55:15 AM1/29/16
to webgl-d...@googlegroups.com
From what I remember when I was doing this sort of thing, the color attachments that we pass have to be in sequence. So suppose if you are writing to two draw buffers, if you only want to write to attachment0 you would make a call like so
ext.drawBuffersWEBGL([ext.COLOR_ATTACHMENT0_WEBGL]);

if you want to write to attacment1, you would have to pass gl.None as first element even if you are only writing to attachment1
ext.drawBuffersWEBGL([gl.NONE, ext.COLOR_ATTACHMENT1_WEBGL]);

if you are writing to both attachments, you would call it like so
ext.drawBuffersWEBGL([ext.COLOR_ATTACHMENT0_WEBGL, ext.COLOR_ATTACHMENT1_WEBGL]);

On the other hand, if you call the drawBuffers function as shown below, it would generate an invalid operation error.
ext.drawBuffersWEBGL([ext.COLOR_ATTACHMENT1_WEBGL]);

Evgeny Demidov

unread,
Feb 1, 2016, 12:14:24 AM2/1/16
to webgl-d...@googlegroups.com
thank you Muhammad,
that explains why there is gl.NONE in specifications
unfortunately for the test
http://www.ibiblio.org/e-notes/webgl/gpu/flat_wave2mrt.htm
   texture = gl.createTexture()
   gl.activeTexture(gl.TEXTURE0)
   gl.bindTexture(gl.TEXTURE_2D, texture)
   gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RG32F, n,n)
...

   FBO = gl.createFramebuffer()
   gl.bindFramebuffer(gl.FRAMEBUFFER, FBO)
   gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)
   gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, texture1, 0)
...
    gl.bindFramebuffer(gl.FRAMEBUFFER, FBO)
    gl.uniform1i(sampLoc, 0)
    gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1_WEBGL])
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)

I get in Canary

ERROR :GL_INVALID_OPERATION : glDrawArrays: Source and destination textures of the draw are the same.

is it useful to make "r/w to the same source" test more accurate (the overhead of tracking samplers and buffers needs to be taken into consideration)?

I forgot, in Firefox Dev 46.0a2 (2016-01-31) old WebGL 1 based application "Lorenz particle system"
http://www.ibiblio.org/e-notes/webgl/gpu/chaos/lorenz_gpu.html
can't get "OES_texture_float" extension. The script works fine in Canary

Evgeny

Kenneth Russell

unread,
Feb 9, 2016, 6:33:03 PM2/9/16
to webgl-d...@googlegroups.com
On Sun, Jan 31, 2016 at 9:13 PM, Evgeny Demidov <dem...@ipm.sci-nnov.ru> wrote:
thank you Muhammad,
that explains why there is gl.NONE in specifications
unfortunately for the test
http://www.ibiblio.org/e-notes/webgl/gpu/flat_wave2mrt.htm
   texture = gl.createTexture()
   gl.activeTexture(gl.TEXTURE0)
   gl.bindTexture(gl.TEXTURE_2D, texture)
   gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RG32F, n,n)
...
   FBO = gl.createFramebuffer()
   gl.bindFramebuffer(gl.FRAMEBUFFER, FBO)
   gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)
   gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, texture1, 0)
...
    gl.bindFramebuffer(gl.FRAMEBUFFER, FBO)
    gl.uniform1i(sampLoc, 0)
    gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1_WEBGL])
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)

I get in Canary
ERROR :GL_INVALID_OPERATION : glDrawArrays: Source and destination textures of the draw are the same.

is it useful to make "r/w to the same source" test more accurate (the overhead of tracking samplers and buffers needs to be taken into consideration)?

It's infeasible to make the detection of feedback loops fuly precise -- since whether there is a loop may depend on the shader's dynamic execution. The validation that the WebGL implementations perform is conservative, but should not allow illegal states to be passed down to the OpenGL or OpenGL ES driver, where they would be rejected.

I think you should allocate two framebuffers and use bindFramebuffer to ping-pong. As far as I have heard, re-validating the framebuffer's state is expensive -- I think more expensive than binding an already-validated framebuffer.

-Ken

 

Jeff Dash

unread,
Feb 10, 2016, 12:04:51 AM2/10/16
to webgl-d...@googlegroups.com
Firefox (at least) caches FB completeness, so changing FB bindings is preferable to changing the FB. I would not worry too much about optimizing more than that.

Evgeny Demidov

unread,
Feb 10, 2016, 12:45:28 AM2/10/16
to webgl-d...@googlegroups.com
thank you. Sorry I was misguided by :)
"Avoid extraneous glBindFramebuffer calls. Use multiple attachments to a
FBO rather than managing multiple FBOs." OpenGL Insights

to calculate on GPU average quantity in Monte-Carlo simulations (e.g. on
a square grid of floating point numbers)
reduction algorithm may be used (shader sums 4 numbers and render result
in new a texture, e.g. 512x512 -> 256x256 ...)
not sure if 8-10 changing FB bindings will be efficient.

Evgeny
Reply all
Reply to author
Forward
0 new messages