DiligentCore icon indicating copy to clipboard operation
DiligentCore copied to clipboard

Emscipten/WebGL support and the lack of glMapBufferRange/glUnmapBuffer

Open eugeneko opened this issue 1 year ago • 8 comments

Pretty much the subject.

WebGL 2.0 specs explicitly lack glMapBufferRange and glUnmapBuffer: https://registry.khronos.org/webgl/specs/latest/2.0/#5.14

Maybe there can be a workaround on Diligent level? These are only these two functions missing, and they are 100% workaroundable via non-mapping API.

eugeneko avatar Apr 22 '23 08:04 eugeneko

I don't understand what the question/suggestion really is. Diligent supports buffer mapping/unmapping through IDeviceContxt::MapBuffer/IDeviceContxt::UnmapBuffer in Emscripten.

TheMostDiligent avatar Apr 22 '23 16:04 TheMostDiligent

Diligent supports buffer mapping/unmapping through IDeviceContxt::MapBuffer/IDeviceContxt::UnmapBuffer in Emscripten

Diligent uses functions glMapBufferRange and glUnmapBuffer in BufferGLImpl::MapRange/Unmap which is called from IDeviceContext::MapBuffer/UnmapBuffer. These functions (glMapBufferRange and glUnmapBuffer) don't exist in WebGL.

Therefore, Diligent can only work if I enable GLES3.0 emulation in Emscripten, instead of using "true" WebGL2. If I try to use Emscripten in WebGL2 mode, I get "unresolved symbol" errors for glMapBufferRange and glUnmapBuffer

eugeneko avatar Apr 22 '23 16:04 eugeneko

tl;dr: I wonder if it's possible to use Diligent with "WebGL-friendly subset of OpenGL ES 3.0" instead of "OpenGL ES 3.0 emulation", going by this article: https://emscripten.org/docs/porting/multimedia_and_graphics/OpenGL-support.html

If it's hard to do, then it's probably not worth it. But if it's only these two functions...

eugeneko avatar Apr 22 '23 16:04 eugeneko

These functions (glMapBufferRange and glUnmapBuffer) don't exist in WebGL.

Sorry, I missed this comment. I think it should be possible to implement buffer mapping through glBufferData. I am wondering though, how many browsers don't support GLES3.0 emulation.

TheMostDiligent avatar Apr 22 '23 18:04 TheMostDiligent

I am wondering though, how many browsers don't support GLES3.0 emulation.

AFAIK emulation is done by Emscripten, not by browsers. My only real concern here is that there is no option to "emulate buffer mapping and nothing else". Emscripten has two modes: high-performance "pure" WebGL2, and emulated GLES3 with possible performance penalties. And I don't know the scope of this "emulation" and how much it does affect performance in practice. Is it "don't pay for what you don't use" or does it incur additional penalties?..

eugeneko avatar Apr 23 '23 06:04 eugeneko

Is it "don't pay for what you don't use" or does it incur additional penalties?..

I don't know. Since GLES3 is largely similar to WebGL2, I don't see any reason why that would be substantially slower. I also don't see the point in re-implementing something that has already been done unless that implementation has been shown to be a real problem.

TheMostDiligent avatar Apr 23 '23 17:04 TheMostDiligent

I found curious issue which may be related to this topic. I am getting this warning in RenderDoc when using OpenGL backend on my PC:

Buffer performance warning: Buffer object CameraCB#4116606499 (bound to GL_UNIFORM_BUFFER (0), and GL_UNIFORM_BUFFER_EXT, usage hint is GL_DYNAMIC_DRAW) is being copied/moved from VIDEO memory to SYSTEM HEAP memory

I am doing IDeviceContext::MapBuffer(MAP_WRITE, MAP_FLAG_DISCARD) for USAGE_DYNAMIC buffer on my side, so it is as "optimal" as it can be.

On the other hand, Apple suggest to use glMapBufferRange on their devices:

https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html

In iOS, GL_DYNAMIC_DRAW and GL_STREAM_DRAW are equivalent. You can use the glBufferSubData function to update buffer contents, but doing so incurs a performance penalty because it flushes the command buffer and waits for all commands to complete. Double or triple buffering can reduce this performance cost somewhat. (...) For better performance, use the glMapBufferRange function in OpenGL ES 3.0 or the corresponding function provided by the EXT_map_buffer_range extension in OpenGL ES 2.0 or 1.1.

eugeneko avatar May 16 '23 08:05 eugeneko

OpenGL backend should really only be used on Web. On other platforms any other backend will perform much better. On Apple, OpenGL has been deprecated for over a decade now. Metal (or Vulkan + MoltenVK) should be used on Apple platforms instead.

TheMostDiligent avatar May 17 '23 05:05 TheMostDiligent

Buffer mapping in WebGL was reworked in 55c46aa1b97ea3e0067c3dc65b024c18925f56a4

TheMostDiligent avatar Feb 23 '24 02:02 TheMostDiligent