[Public WebGL] Re: WEBGL_get_buffer_sub_data_async

Maksims Mihejevs [email protected]
Fri Jan 6 09:33:41 PST 2017

That is very good point too.
Most common case of similar pattern is mouse, keyboard, touch input - it is
in callback, and you end up collecting own state information about input,
so to access it in main loop of your app in requestAnimationFrame.

Developers coming from real-time applications and other platforms get
confused a lot by this all the time. That is based on many users on
PlayCanvas from hobbyists to commercial clients do mention it time to times.

On 6 January 2017 at 16:36, Florian Bösch <[email protected]> wrote:

> The problem isn't just the promise allocation, it's also the closure
> allocation. And while you can avoid that in some cases, you can't avoid it
> in all cases. And beyond that, the further problem of registering callbacks
> to do stuff would be that it lifts rendering logic out of the
> requestAnimationFrame loop and occurs... whenever. Which isn't a proper way
> to render. So in practice you'd end up attaching a callback just to collect
> the result and put it in a variable you'll check for not being null at the
> start of the next requestAnimationFrame invocation. Of course when you do
> that, the entire exercise of providing a callback is moot. Since that'd be
> the most common usage pattern that everybody would recommend based on sound
> reasoning about the predictability of rendering in a requestAnimationFrame
> loop, that makes promises/callbacks entirely moot and the wrong thing to do.
> On Fri, Jan 6, 2017 at 1:52 PM, Maksims Mihejevs <[email protected]>
> wrote:
>> Why not to use classic callbacks with (err, response) arguments?
>> On 6 January 2017 at 00:01, Kenneth Russell <[email protected]> wrote:
>>> On Thu, Jan 5, 2017 at 2:55 AM, Maksims Mihejevs <[email protected]>
>>> wrote:
>>>> Thank you for answer, this examples make sense.
>>>> The only concern as mentioned before are: Promises. There is no a
>>>> single use of promises in WebGL, and there is a reason why they should not
>>>> be used in real-time applications if they can be avoided (which is the
>>>> case).
>>>> If possible Fence (Sync Objects) were involved in design process? Could
>>>> something like this be achieved by using more generic functionality in GL
>>>> such as Sync Objects?
>>> Promises were chosen for a particular reason. Even if a primitive like
>>> mapBufferRange were exposed in WebGL, a typed array would still need to be
>>> allocated as the return result. There's no provision in the ECMAScript
>>> specification for "re-pointing" a typed array at a new backing store,
>>> although Chrome's V8 team proposed this a while back. Mapping a buffer's
>>> range at the OpenGL ES level returns a void*, and that would need to be
>>> exposed to ECMAScript. Passing in an already-allocated typed array wouldn't
>>> work in the current form of the APIs.
>>> Given that an allocation would be needed anyway, returning a Promise is
>>> much more web-friendly. It avoids the need for the application to deal with
>>> sync objects, and potentially inconsistent states of the returned typed
>>> array. getBufferSubDataAsync lets the application specify where it wants
>>> the returned data to be copied.
>>> -Ken
>>>> Kind Regards,
>>>> Max
>>>> On 4 January 2017 at 18:55, Kai Ninomiya <[email protected]> wrote:
>>>>> Max,
>>>>> In my demo [1] there are 3 different possible readback paths:
>>>>> * readPixels to CPU [2]
>>>>> * readPixels to PBO + getBufferSubData [3]
>>>>> * readPixels to PBO + getBufferSubDataAsync [4]
>>>>> As you said, getBufferSubData(/Async) can be used for reading back any
>>>>> buffer data (such as transform feedback or GPGPU shader results). PBO is
>>>>> necessary (AFAIK) for async readback from framebuffer data (note: an async
>>>>> readPixels wouldn't be as useful as it would block any operation which
>>>>> writes to the framebuffer).
>>>>> -Kai
>>>>> [1] https://github.com/kainino0x/getBufferSubDataAsync-Demo/
>>>>> [2] https://github.com/kainino0x/getBufferSubDataAsync-Demo/
>>>>> blob/master/index.html#L245
>>>>> [3] https://github.com/kainino0x/getBufferSubDataAsync-Demo/
>>>>> blob/master/index.html#L261
>>>>> [4] https://github.com/kainino0x/getBufferSubDataAsync-Demo/
>>>>> blob/master/index.html#L280
>>>>> On Wed, Jan 4, 2017 at 5:09 AM Maksims Mihejevs <[email protected]>
>>>>> wrote:
>>>>>> From PlayCanvas side, we express a need for async glReadPixels path
>>>>>> too. We and our users have been using it in many ways, some of the ways:
>>>>>> 1. GPU picking: ID encoded in unique colour, reading pixel under
>>>>>> mouse.
>>>>>> 2. GPU screen to world: reading pixel from depth texture, and using
>>>>>> frustum with math reconstructing world position.
>>>>>> 3. Render Target to another Canvas. In Editor we have thumbnail
>>>>>> previews for materials, models, cubemaps and other assets. We render them
>>>>>> into render target in main context and then reading pixels to create
>>>>>> ImageData so it can be put to another canvas using putImageData.
>>>>>> 4. Some custom algorithms to generate large amounts of computation
>>>>>> heavy data saved into texture, then read on CPU - this depends per case.
>>>>>> Sometimes async approach is viable there, sometimes it is not.
>>>>>> In many cases glReadPixels is called per each frame, like for
>>>>>> picking, and easily can drop frame rate due to blocking nature.
>>>>>> I've noticed that PBOs are mentioned in WebGL 2.0 spec, but not much
>>>>>> info apart of just that mention: https://www.khronos.o
>>>>>> rg/registry/webgl/specs/latest/2.0/#4.2
>>>>>> PBOs would allow to get render target data into buffers without
>>>>>> stalling GPU pipeline, and then read them.
>>>>>> How does getBufferSubDataAsync relates to PBOs?
>>>>>> Cheers,
>>>>>> Max
>>>>>> On 4 January 2017 at 05:27, Kenneth Russell <[email protected]> wrote:
>>>>>> Apologies for not discussing this extension on public_webgl before
>>>>>> introducing it as a draft in the WebGL extension registry.
>>>>>> The cost of synchronous glReadPixels has been a longstanding problem
>>>>>> in WebGL. The Chrome browser specifically has a particularly deep graphics
>>>>>> pipeline, and draining it with a synchronous call each frame imposes a
>>>>>> too-great performance penalty. This has forced applications to rewrite
>>>>>> certain algorithms when porting to WebGL.
>>>>>> getBufferSubDataAsync is a direct parallel to getBufferSubData, and
>>>>>> solves these performance pitfalls in Chrome. We've gathered data from two
>>>>>> test cases so far, a GPU-based picking algorithm and a GPGPU global
>>>>>> illumination algorithm, and the results look good. We will present this
>>>>>> data on public_webgl soon, when making a case for moving the extension
>>>>>> forward.
>>>>>> -Ken
>>>>>> On Mon, Jan 2, 2017 at 2:27 PM, Maksims Mihejevs <[email protected]>
>>>>>> wrote:
>>>>>> Worth mentioning that promises are extremely bad for GC and real-time
>>>>>> applications, they do not provide a developer enough control to structure
>>>>>> logic so to avoids any allocations.
>>>>>> Promises - are not good for real-time at all, and lead to issues with
>>>>>> GC. Any API in WebGL that is meant to be used in real-time applications
>>>>>> should not be based on API's that are not real-time friendly.
>>>>>> On 2 January 2017 at 20:49, Florian Bösch <[email protected]> wrote:
>>>>>> Upon thinking about this extension, I don't think it should exist at
>>>>>> all. Ideally the mapBuffer semantic would be exposed. But even if it isn't,
>>>>>> it shall not be that an extension is required to express functionality
>>>>>> already found in the core functionality of the underlying ES specification.
>>>>>> Furthermore, getBufferSubDataAsync does not adequately express the
>>>>>> reality of map/flush/unmap, and hides the fact that unmap/flush are still
>>>>>> synchronizing calls happening. However getBufferSubDataAsync obstructs
>>>>>> appropriate code dealing with proper insertion of synchronization points.
>>>>>> In addition, it would lead to allocating promises once or many times
>>>>>> per frame, and since tracking would be required in some instances, would
>>>>>> also lead to allocating a closure once or many times a call. An issue that
>>>>>> map buffer range does not exhibit.
>>>>>> Due to the lack of discussion of this feature, I believe a great
>>>>>> disservice is done to WebGL 2 by the introduction of these ideas/APIs and I
>>>>>> strongly suggest to withdraw this from draft immediately and go back to the
>>>>>> drawing board.
>>>>>> On Mon, Jan 2, 2017 at 5:48 PM, Florian Bösch <[email protected]>
>>>>>> wrote:
>>>>>> This extension https://www.khronos.org/registry/webgl/extensions/
>>>>>> WEBGL_get_buffer_sub_data_async/ has been introduced and elevated to
>>>>>> draft without any public discussion.
>>>>>> In a nutshell it proposes a new WebGL2 function called
>>>>>> getBufferSubDataAsync which returns a promise that will be called
>>>>>> eventually with the buffer data.
>>>>>> I think there are several problems:
>>>>>>    1. The extension process states that "*Extensions move through
>>>>>>    four states during their development: proposed, draft, community approved,
>>>>>>    and Khronos ratified**"*. This extension never moved through the
>>>>>>    proposal stage.
>>>>>>    2. The extension introduces promises to the WebGL API. This
>>>>>>    requires a more fundamental discussion.
>>>>>>    3. A discussion if this extension is required if WebWorkers can
>>>>>>    access the same context as the main thread has not happened.
>>>>>> This extension should be in proposal status, and the necessary
>>>>>> discussions should happen first.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://khronos.org/pipermail/public_webgl_khronos.org/attachments/20170106/5fe210f2/attachment.html>

More information about the public_webgl mailing list