Run below code, get error msg:
Caused by: java.lang.IndexOutOfBoundsException: Required 522143 remaining bytes in buffer, only had 521256 at com.jogamp.common.nio.Buffers.rangeCheckBytes(Buffers.java:1056) at jogamp.opengl.gl4.GL4bcImpl.glDrawPixels(GL4bcImpl.java:5648) ------My Code--------- short[] pixels16 = ... // generate short array data, length is 521256. (521256 = 587*888 = 888*587). int w = 587; int h = 888; BufferedImage bi = ImageDisplayUtils.createImage(w, h, pixels16); DataBufferByte buf = (DataBufferByte)bi.getData().getDataBuffer(); byte[] bytes = buf.getData(); ByteBuffer imgBuffer = ByteBuffer.wrap(bytes); gl.glRasterPos2f(0, 0); gl.glDrawPixels(w, h, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, imgBuffer); !! BUT , if set w = 888, h = 587, everything is ok, no exception was thrown. Any help? Thanks in advance. |
Administrator
|
Hi
Look at the source code: https://github.com/sgothel/gluegen/blob/master/src/java/com/jogamp/common/nio/Buffers.java#L1050 Check the size of the byte array inside DataBufferByte returned by getData(). By the way, your code seems to be inefficient, I just hope that you don't create an indirect NIO buffer at each call. You should rather find a way to reuse the data buffer as is and pass it to JOGL or create a single direct NIO buffer into which you could copy the content of the data buffer.
Julien Gouesse | Personal blog | Website
|
>Check the size of the byte array inside DataBufferByte returned by getData().
Add one line below 'getData()', the output is correct. So the size inside DataBufferByte returned by getData() is correct. byte[] bytes = buf.getData(); // length : w*h System.out.println(bytes.length); // output : 521256 ( = 587*888) >I just hope that you don't create an indirect NIO buffer at each call. You means using 'Buffers.newDirectByteBuffer(bytes)' instead of 'ByteBuffer.wrap(bytes)' ? |
Administrator
|
There is probably a problem of alignment:
http://forum.jogamp.org/glTexImage2D-error-td4033393.html I mean that you should create a direct NIO buffer with Buffers.newDirectByteBuffer() only once and reuse it. As you don't show a complete example, I don't really know what you do. If you create a new buffer at each call of GLEventListener.display(), you'll run out of memory.
Julien Gouesse | Personal blog | Website
|
>There is probably a problem of alignment:
>http://forum.jogamp.org/glTexImage2D-error-td4033393.html Do you have any plan to fix it ? |
This post was updated on .
It works like this, you need a buffer (h-1) * (w + (alignemnt - w % alignment)) + w bytes big given: int w = 587; int h = 888; alignment = 4 byte your buffer will be 887 * (587 + (4 - 587 % 4)) + 587 = = 887 * (587 + 1) + 587 = 522143 bytes This is because data gets loaded line by line based on the alignment, except the last line which seems it doesnt matter int h = 587; int w = 888; works out of the box because w fits perfectly the 4 bytes alignment (888 % 4 = 0) https://www.opengl.org/wiki/Common_Mistakes#Texture_upload_and_pixel_reads |
Administrator
|
Big kudos to elect :D We should make a small article about that for the wiki.
Julien Gouesse | Personal blog | Website
|
Mercì, I added a small section about common OpenGL and GLSL mistakes |
In reply to this post by elect
if set:
h = 587 w = 888 alignment = 4 using below formula, the output is '523600' v = (h-1) * (w + (alignemnt - w % alignment)) + w System.out.println(v); BUT, if I use function G:Buffers.sizeof()', I got '521256', which is equal to 888*587. int v = GLBuffers.sizeof(gl, new int[1], 1, 888, 587, 1, false); Above two results are different, is the formula '(h-1) * (w + (alignemnt - w % alignment)) + w' correct ? |
Administrator
|
It's probably a rounding error, isn't it?
((h-1) * (w + (alignment - (w % alignment)))) + w Moreover, it's up to you to pass the right size for the newly created buffer. ((888 - 1) * (587 + (4 - 587 % 4))) + 587 = 522143 It seems to work for me. Are you sure that you pass the right "type" and the right "depth" to GLBuffers.sizeof()?
Julien Gouesse | Personal blog | Website
|
Yep, Gouessej is right, the modulo has the precedence
|
What is the condition determines the 'alignment' value ?
|
Administrator
|
GLBuffers.sizeof() computes the bytes per pixel from the format and the type or use the value in input. Look at the implementation of this method.
Julien Gouesse | Personal blog | Website
|
In reply to this post by george2008
https://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml
Associated Gets glGet with argument GL_PACK_ALIGNMENT or GL_UNPACK_ALIGNMENT |
Administrator
|
In reply to this post by gouessej
On 08/07/2015 04:25 PM, gouessej [via jogamp] wrote:
> GLBuffers.sizeof() computes the bytes per pixel from the format and the type > or use the value in input. Look at the implementation of this method. Yup .. this is our canonical buffer size definition/method. ~Sven signature.asc (828 bytes) Download Attachment |
Forgot to say, unpack is when you transfer data from cpu -> gpu, pack the other way round
|
Little update, I came across this issue recently for a glTexImage3D
The same logic applies, but it is interesting to know how it works in 3 dimensions. Supposing we have x, y and z where in general - x is the layer (for texture arrays) - y is the face (for cubemap textures) - z is the level (for mipmaps) Data will be loaded starting from the xy plane, row by row. So if we have a 4-bytes alignment, x must be aligned to this value and it must be so up to the end. This for all the xy planes on z, except the very last row on the last z. Examples: (3, 2, 2) requires 4 bytes for row, this means 4 bytes for the first three rows: - ([0-3], 0, 0) - ([0-3], 1, 0) - ([0-3], 0, 1) except the last one, ([0-3], 1, 1), that needs only 3 The count is 3*4+3 = 15 Bytes.. So what counts about alignment is always and only the size of the first dimension, except the last row Let's say this is the complex way of dealing with it. The easy fix is to switch the unpack alignment to 1 byte and forget about it :D |
Free forum by Nabble | Edit this page |