1

In my app I generate mipmaps for the 6x4096x4096 cube map texture. Next I need to undertake some other changes on that texture that are time dependent. All the drawing is done inside of the requestAnimationFrame's loop.

Depending on the browser, device, etc., sometimes it takes three, sometimes four or even five consecutive frames of the loop to finally generate those mipmaps, and I need to know in which frame exactly mipmaps are already done.

So the question is: how to check in which frame of the requestAnimationFrame's loop mipmaps generated for the "TEXTURE_CUBE_MAP" by the WebGL's command "generateMipmap" are ready? Is there some flag for checking status of the "generateMipmap" completion?

2 Answers2

1

There is no way to find out when generateMipmap will finish or how long it will take. I'd be surprised it takes that long but if the point is that you want to avoid jank one solution would be to make your own mips. This way you can upload them one lod per face per frame or even in smaller increments.

One other possible solution but probably only works on Chrome is to just guess and wait a few frames with code like

gl.generateMipmap(...);
gl.flush();  // make sure the previous command will be executed

// now do something to wait 4 frames like
var framesToWait = 4;
function render() {
  if (framesToWait) {
    --framesToWait;
  } else {
     ... call drawArrays ...
  }
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

This might work because chrome is multi-process. I'm not sure what the point would be though.

In WebGL2 you could use a FenceSync object to find out when something finished.

gman
  • 100,619
  • 31
  • 269
  • 393
0

generateMipmap is a "synchronous" call. Whereas browsers can try to optimise it by returning from it immediately, before generating mip-levels is actually done, the first usage of a texture for which generateMipmap was called will make sure, that mip-levels're ready to use. To put it in code:

const texture = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, /* ... */);
gl.generateMipmap(gl.TEXTURE_2D);
gl.uniform1i(someSamplerUniform, 0);
gl.drawArrays(/* ... */); // Here WebGL implementation will make sure that
                          // mip-levels for tetxure are ready. If they aren't,
                          // this call will cause blocking.

If you change content of 0 mip-level of the texture, you need to call generateMipmap again.

Here's a bit more info about this behaviour.

Kirill Dmitrenko
  • 3,474
  • 23
  • 31
  • Thank you for your answer. My problem is not with the order of WebGL commands, but with the requestAnimationFrame's loop behaviour. Let's say that I invoke "generateMipmap" at the frame number 0. Then I would like to know how many frames would be needed to complete generation of the mipmaps, because in the last of those frames I would like to invoke the function like "drawArrays". I don't need to know the exact number of frames by advance, just need to check using some kind of "if" statement when the job (generate mipmaps) is done. – Lech Stawikowski Feb 03 '17 at 16:28
  • There's not API for that. More over, as I've said, `generateMipmap` may lock till it's done. Also, user's hardware plays significant role here, so there's also no way to reliably obtain number of frames generating mip-levels would take. If you don't need to regenerate mipmaps frequently, I suggest just using the texture in the same frame (or maybe next one). If you need to update texture frequently, there's sense in looking for ways to avoid using mipmaping. – Kirill Dmitrenko Feb 03 '17 at 16:41
  • The reason for what I need (which may seem strange at first glance) is that I'm using some time parameter t which I pass to the "drawArrays"-like call. I need to know when "generateMipmap" is done (in which frame), so I could pass "drawArrays(t)" the right value of t (I measure duration of each frame of the requestAnimationFrame's loop). – Lech Stawikowski Feb 03 '17 at 16:44
  • As I've said, unfortunately, there's no explicit API to check if `generateMipmap` result. However, it'd be correct to consider `generateMipmap` done right after it returned. BTW, bear in mind, that measuring time `requestAnimationFrame` callback took is somewhat useless for measuring performance (if that's what you're after with pre parameter), since draw calls (and some other WebGL calls) are asynchronous. – Kirill Dmitrenko Feb 03 '17 at 17:02
  • I've checked for return value of "gl.generateMipmap(gl.TEXTURE_CUBE_MAP)" function, and it is always "undefined", and returns in the same frame it is invoked, but still needs few more frames to generate mipmaps (usually from 3 to 5 - I can tell it by looking at how long each frame lasts; unfortunately it is strongly device dependent so I cannot use this value in my desired "if" statement). – Lech Stawikowski Feb 03 '17 at 17:44