-
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
glPixelStorei does not support PACK_ALIGNMENT #23151
Comments
Can you share an example of a call to Could you perhaps give this bug with something more descriptive? Something like |
Here is an example index.html <body>
<script>
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([
1, 2, 3, 4,
5, 6, 7, 8,
]));
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.pixelStorei(gl.PACK_ALIGNMENT, 8);
const buffer = new ArrayBuffer(3 * 4);
gl.readPixels(0, 0, 1, 2, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(buffer));
console.log(new Uint8Array(buffer));
</script>
<canvas id="canvas"></canvas>
<script src="./a.out.js"></script>
</body> main.cpp #include <emscripten/html5.h>
#include <iostream>
#include <GLES3/gl3.h>
int main() {
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);
auto handle = emscripten_webgl_create_context("canvas", &attrs);
emscripten_webgl_make_context_current(handle);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
std::array<std::uint8_t, 8> data = {
1, 2, 3, 4,
5, 6, 7, 8,
};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 8);
std::array<std::uint8_t, 3 * 4> buffer{};
glReadPixels(0, 0, 1, 2, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
for (auto x : buffer) {
std::cout << static_cast<int>(x) << ", ";
}
std::cout << std::endl;
return 0;
} Put index.html main.cpp in the same directory. Run
Use a http server to host these files, for example Open the url of the index.html in any browser, and open the console, you will get an error about buffer length. I ran this example in Emscripten 3.1.74. The js version works fine, but the c++ version doesn't. Chrome:
FireFox:
|
If WebGL2 and 4G memory is enable. glPixelStorei does not support GL_PACK_ROW_LENGTH either. Here is the code. <body>
<script>
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([
1, 2, 3, 4,
5, 6, 7, 8,
]));
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.pixelStorei(gl.PACK_ROW_LENGTH, 2);
const buffer = new ArrayBuffer(3 * 4);
gl.readPixels(0, 0, 1, 2, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(buffer));
console.log(new Uint8Array(buffer));
</script>
<canvas id="canvas"></canvas>
<script src="./a.out.js"></script>
</body> main.cpp #include <emscripten/html5.h>
#include <iostream>
#include <GLES3/gl3.h>
int main() {
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);
attrs.majorVersion = 2;
auto handle = emscripten_webgl_create_context("canvas", &attrs);
emscripten_webgl_make_context_current(handle);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
std::array<uint8_t, 16> data = {
1, 2, 3, 4,
5, 6, 7, 8,
};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glPixelStorei(GL_PACK_ROW_LENGTH, 2);
std::array<std::uint8_t, 3 * 4> buffer{};
glReadPixels(0, 0, 1, 2, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
for (auto x : buffer) {
std::cout << static_cast<int>(x) << ", ";
}
std::cout << std::endl;
return 0;
} The operation process is the same as above, except for the C++ compilation parameters. |
Thanks for the repro cases. As far as you are aware have these features always been missing from emscripten or is this a regression? Any ideas for fixes? Would you like to send a PR? |
This issue originates from #21968
Calling
glPixelStorei
affects the memory layout of pixel data inglTexImage2D
,glTexSubImage2D
, andglReadPixels
, thereby affecting the valid length of the pixel data. The OpenGL documentation provides a more detailed explanation:https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
Emscripten restricts the length of pixel data through
emscriptenWebGLGetTexPixelData
, but this restriction may be shorter than expected after callingglPixelStorei
. This results in browser errors.Chrome and Safari:
FireFox:
The problem with
emscriptenWebGLGetTexPixelData
is that it does not distinguish between pack and unpack, nor does it handle all possible parameters inglPixelStorei
.My simple patch is:
This removes the length restriction on the pixel data, since the C API only passes a pointer without data length.
The issue with this patch is that it makes it easier for the pixel data length to exceed 2GB, which in FireFox leads to a new problem:
The text was updated successfully, but these errors were encountered: