-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
opengl support for memory64 #18744
opengl support for memory64 #18744
Conversation
7db7b6c
to
85d3e5a
Compare
4111e3f
to
a0f65ae
Compare
6084252
to
6d06901
Compare
68d6c7b
to
bc1a4fd
Compare
src/library_html5.js
Outdated
@@ -651,7 +657,7 @@ var LibraryHTML5 = { | |||
{{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaY, 'wheelDeltaY', 'double') }}}; | |||
{{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaZ, '0 /* Not available */', 'double') }}}; | |||
{{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaMode, '0 /* DOM_DELTA_PIXEL */', 'i32') }}}; | |||
var shouldCancel = {{{ makeDynCall('iiii', 'callbackfunc') }}}( eventTypeId, JSEvents.wheelEvent, userData); | |||
var shouldCancel = {{{ makeDynCall('iipp', 'callbackfunc') }}}( eventTypeId, JSEvents.wheelEvent, userData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes look good. I wonder is we could figure out a test that uses these in test_browser.py
and add also_with_wasm64
the that test? Then we could that this change in isolation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like the existing tests in test-windows test-mac and test-other are failing due to some of these changes. And right, i can take a quick look and see if this can be added to a separate commit/pull request.
src/library_strings.js
Outdated
@@ -157,6 +157,9 @@ mergeInto(LibraryManager.library, { | |||
#if CAN_ADDRESS_2GB | |||
outIdx >>>= 0; | |||
#endif | |||
#if MEMORY64 | |||
outIdx = Number(outIdx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not bee needed outIdx
should already be a number by the time it gets here. Can you find the backtrace that leads here without outIdx
being converted to an number already?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is now also working without the explicit conversion. Will remove it.
} else { | ||
const mod = size == 1 ? '' : ('>>' + Math.log2(size)); | ||
return `HEAP${which}.subarray((${start})${mod}, (${end})${mod})`; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last line of each branch here looks the same, right? Can we simplify here to avoid duplication? e.g.:
if (MEMORY64) {
mod = ..
} else {
mod = ..
}
return `HEAP${which}.subarray((${start})${mod}, (${end})${mod})`;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, will make this change.
bc1a4fd
to
4c3a66e
Compare
I checked this commit over tag 3.1.38 hoping it fixes WebGL problems in wasm32 with 4GB memory (as it incorporates changes from #15433). Vertex/index buffers and uncompressed textures work with pointers over 2GB, but compressed textures (DXT1/BC1) work only in WebGL 1 but don't work in WebGL 2, the following run-time error is shown:
|
The primary issue with these _glXTexImageX methods in WebGL 2 is that they directly access an ArrayBuffer. It looks like most browsers nowadays have limitations wrt the size of these buffers when passed into the corresponding webgl 2 functions. Thus my changes in this commit create a copy of the data that is being sent to WebGL 2. This is similar to how the WebGL 1 code path is working. Though please note, that most of the changes proposed here are only active when compiling to wasm64. |
Anyway, I found the same problem with _glCompressedTexSubImage2D. Both problems are solved by changing the |
68cf024
to
3ebab42
Compare
src/library_webgl2.js
Outdated
@@ -630,23 +646,23 @@ var LibraryWebGL2 = { | |||
assert((value & 3) == 0, 'Pointer to integer data passed to glClearBufferiv must be aligned to four bytes!'); | |||
#endif | |||
|
|||
GLctx.clearBufferiv(buffer, drawbuffer, HEAP32, value>>2); | |||
GLctx.clearBufferiv(buffer, drawbuffer, HEAP32, {{{ ptrToIdx('value', 2) }}}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about using the existing getHeapOffset('value', 'u32')
here instead of this new macro?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In particular I don't love the 2
in the second argument to ptrToIdx. It seems very non-obvious compared to getHeapOffset('value', 'u32')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, since there is now a more standardized way to make this conversion i will use it (these index conversion macros are part of an old commit from @juj that i pulled in to get some of this to work which i did not want to change too much).
src/parseTools.js
Outdated
} | ||
|
||
// Browsers might not support passing BigInts to different API entry points that take in addresses, so convert those to Number()s before calling into the browser APIs. | ||
function idxToMemory53(heapIndex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would hope this is not needed since all pointers should be converted to int53 numbers when they arrive from native code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, i will give removing this a try
80329b9
to
4801d2c
Compare
src/library_webgl.js
Outdated
@@ -376,7 +376,11 @@ var LibraryGL = { | |||
var source = ''; | |||
for (var i = 0; i < count; ++i) { | |||
var len = length ? {{{ makeGetValue('length', 'i*4', 'i32') }}} : -1; | |||
#if MEMORY64 | |||
source += UTF8ToString({{{ makeGetValue('string', 'i*8', '*') }}}, len < 0 ? undefined : len); | |||
#else | |||
source += UTF8ToString({{{ makeGetValue('string', 'i*4', 'i32') }}}, len < 0 ? undefined : len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you just use i*{POINTERSIZE}
and *
here, which should work in both cases I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, will make that change.
@@ -1424,7 +1428,7 @@ var LibraryGL = { | |||
}, | |||
|
|||
glCompressedTexImage2D: (target, level, internalFormat, width, height, border, imageSize, data) => { | |||
#if MAX_WEBGL_VERSION >= 2 | |||
#if MAX_WEBGL_VERSION >= 2 && !MEMORY64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not checked the newest versions of chrome/firefox, but up until recently calling webgl functions that directly accessed an array view via an offset did not work, when the array view was larger than 4GB (this is why i am using the fallback versions of these functions for which data has to be copied into a separate array). I will check, if this still holds true. If newer browser versions got rid of that limitation i can remove a lot of these checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I am not mistaken, in wasm32 when the array view is larger than 2GB, there is the same problem.
src/library_webgl.js
Outdated
|
||
#if MEMORY64 | ||
{{{ makeSetValue('pointer', '0', 'GLctx.getVertexAttribOffset(index, pname)', 'i64') }}}; | ||
#else | ||
{{{ makeSetValue('pointer', '0', 'GLctx.getVertexAttribOffset(index, pname)', 'i32') }}}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you just use '*
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, that should work.
@@ -2320,17 +2338,17 @@ var LibraryGL = { | |||
glUniform1iv: (location, count, value) => { | |||
#if GL_ASSERTIONS | |||
GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform1iv', 'location'); | |||
assert((value & 3) == 0, 'Pointer to integer data passed to glUniform1iv must be aligned to four bytes!'); | |||
assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to integer data passed to glUniform1iv must be aligned to four bytes!'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{POINTER_SIZE} bytes
?
@@ -920,6 +925,36 @@ function to64(x) { | |||
return `BigInt(${x})`; | |||
} | |||
|
|||
// Generates an expression that tests whether a pointer (either a BigInt or a signed int32 JS Number) is aligned to the given byte multiple. | |||
function isPtrAligned(ptr, alignment) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to second argument here? Shouldn't pointer always be aligned to pointer size? i.e. should alignment here not always be POINTER_SIZE?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is used in all the places where we previously did something like this
assert((value & 3) == 0, 'Pointer to integer data passed to glUniform2iv must be aligned to four bytes!');
So for example, if we want to pass int32 values to webGL (e.g. via glUniform2iv) then this data has to be aligned to 4 bytes because it is being passed via the HEAP32 array buffer view. To be honest, when i first saw this code i was a bit weary, since on the C/C++ side such guarantees are never required and i am pretty sure, that i could write some simple code which would break this assumption. But as far as i can tell, up until now, our production code has never caused any issues here.
As for whether the second parameter is required. I think currently we are always either using 4 byte alignment or 1 byte alignment (i.e. unaligned). So there is definitely space for improvement. Will take a closer look at this.
I tested it above 3.1.47 on wasm32 with 4GB: WebGL2 still doesn't work. |
4801d2c
to
f15150e
Compare
f15150e
to
266116b
Compare
Right, so i am trying to keep the changes in this commit limited to the wasm64 compile target. The whole 2GB (and sometimes 4GB) limit on array views that are passed off to webgl2 functions seems to be something that probably has to be addressed by browser developers? In the long run i would also like to get rid of the workarounds used in my commit to actually use the faster webgl2 functions that do not involve copying all the data that is being passed in. |
By the way, there are some failures with WebGL1, too. Cannot you take into consideration the case of wasm32 >2GB as well? I suppose it requires similar fixes. I can help to test many different uses of WebGL 1/2 with my graphical engine. Thanks in advance. |
I believe that all of these fixes have now landed as part of the sequence of changes that made all our tests pass in wasm64 and 2gb+ mode and 4gb+ mode. e.g. #21573, #21445, #21306, #21264, #21220. My apologies for not landing this change and instead incrementally implementing it. Hopefully the end result is that all your code should now work. If you think there are any remaining wasm64 or 2gb+ issue please let me know. |
No worries, i am glad that i was able to point out issues that we ran into with this PR and i am excited to test this again. |
Next week, I am going to check 4GB WebGL2 with the newly released 3.1.57 (which should include all these fixes, am I right?) and I let you know if there are problems. |
Thanks! I guess we can close this issue, and please open any new ones if you fine them. I'm pretty sure we have good test coverage at this point. |
@sbc100, this is a second try at getting the opengl layer of emscripten to work when the MEMORY64 flag is used.
Since i worked on this as an employee of Siemens i was advised to add some copyright comments into file headers that were modified.
@juj i have incorporated some of the changes from #15433 into this pull request and i will wait for you finishing that up before considering merging.