Bug 1220

Summary: glTexSubImage3D interprets the z index as third dimension although a 2d array texture has been provided
Product: [JogAmp] Jogl Reporter: Giuseppe Barbieri <elect86>
Component: coreAssignee: Sven Gothel <sgothel>
Status: RESOLVED INVALID    
Severity: blocker CC: sgothel
Priority: P1    
Version: 2.3.2   
Hardware: pc_x86_64   
OS: windows   
Type: DEFECT SCM Refs:
Workaround: ---

Description Giuseppe Barbieri 2015-09-18 14:25:28 CEST
glTexSubImage3D interprets the z index as third dimension although a 2d array texture has been provided

ByteBuffer data = GLBuffers.newDirectByteBuffer(256*256);

gl4.glTexSubImage3D(GL4.GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 256, 256, 2, GL_RED_INTEGER, GL_UNSIGNED_BYTE, data);

Caused by: java.lang.IndexOutOfBoundsException: Required 131072 remaining bytes in buffer, only had 65536
	at com.jogamp.common.nio.Buffers.rangeCheckBytes(Buffers.java:1056)
	at jogamp.opengl.gl4.GL4bcImpl.glTexSubImage3D(GL4bcImpl.java:7979)
Comment 1 Giuseppe Barbieri 2015-09-18 14:26:38 CEST
Crap, we can't edit comments..

anyway, here it's the api doc https://www.opengl.org/sdk/docs/man3/xhtml/glTexSubImage3D.xml

void glTexSubImage3D(GLenum target,  GLint level,  GLint xoffset,  GLint yoffset,  GLint zoffset,  GLsizei width,  GLsizei height,  GLsizei depth,  GLenum format,  GLenum type,  const GLvoid * data);

"For three-dimensional textures, the z index refers to the third
            dimension. For two-dimensional array textures, the z index refers to
            the slice index.
"
Comment 2 Sven Gothel 2015-09-28 04:13:27 CEST
Implementation example:
  public void glTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, int format, int type, Buffer pixels)  {
    checkUnpackPBOUnbound(true);
    Buffers.rangeCheckBytes(pixels, 
                imageSizeInBytes(format, type, width, height, depth, false));
    ...

+++

Spec:

"glTexSubImage3D redefines a contiguous subregion of an existing three-
dimensional or two-dimensioanl array texture image.
The texels referenced by data replace the portion of the
existing texture array with 
  x indices xoffset and xoffset+width-1, inclusive,
  y indices yoffset and yoffset+height-1, inclusive
  z indices zoffset and zoffset+depth-1, inclusive"

Further, as Giuseppe mentioned:

"For three-dimensional textures, the z index refers to the third
dimension. For two-dimensional array textures, the z index refers to
the slice index."
            
+++

Hence implementation completely ignores the [xyz] offset
while calculating the required minimum-size of the given buffer!

Impact: Application always needs to supply a fully-texture-sized buffer,
where only the updated region needs to be supplied in the buffer.

+++

Wonder how this bug could have survived undetected that long ..
Comment 3 Sven Gothel 2015-09-28 04:27:51 CEST
Further more, we need to range-check and PBO check 'glTextureSubImage[123]D',
see Bug 1233.
Comment 4 Sven Gothel 2015-09-28 04:53:34 CEST
Invalidating my comment 2, guess I was reading the spec to quickly
w/o thinking (too later probably).

  x indices xoffset and xoffset+width-1, inclusive,
  y indices yoffset and yoffset+height-1, inclusive
  z indices zoffset and zoffset+depth-1, inclusive"

this means that we simply have to calculate the imageSize
on the width x height x depth, as we do it already!

reverting the bug description to original.
Comment 5 Sven Gothel 2015-09-28 04:59:07 CEST
(In reply to Giuseppe Barbieri from comment #0)
> glTexSubImage3D interprets the z index as third dimension although a 2d
> array texture has been provided
> 
> ByteBuffer data = GLBuffers.newDirectByteBuffer(256*256);
> 
> gl4.glTexSubImage3D(GL4.GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 256, 256, 2,
> GL_RED_INTEGER, GL_UNSIGNED_BYTE, data);
> 
> Caused by: java.lang.IndexOutOfBoundsException: Required 131072 remaining
> bytes in buffer, only had 65536
> 	at com.jogamp.common.nio.Buffers.rangeCheckBytes(Buffers.java:1056)
> 	at jogamp.opengl.gl4.GL4bcImpl.glTexSubImage3D(GL4bcImpl.java:7979)


You seem to use the API wrong,
i.e. you probably want to update slice index 2
using your TEXTURE_2D sub-image.
The depth should be 1 in this case, of course!
Comment 6 Sven Gothel 2015-09-28 05:00:34 CEST
(In reply to Sven Gothel from comment #5)
> 
> You seem to use the API wrong,
> i.e. you probably want to update slice index 2
> using your TEXTURE_2D sub-image.
> The depth should be 1 in this case, of course!

like this:

gl4.glTexSubImage3D(GL4.GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 256, 256, 1,
GL_RED_INTEGER, GL_UNSIGNED_BYTE, data);

as mentioned above, no offset is even being used while calculating the
image size for the buffer range check.
Comment 7 Giuseppe Barbieri 2015-10-03 17:28:38 CEST
I don't get it, if I want to update layer 2 of a 256x256 red/unsigned byte texture I need to supply a 256*256*1=65536 bytes buffer, not a 131072-bytes one.
Comment 8 Sven Gothel 2015-10-03 18:26:58 CEST
(In reply to Giuseppe Barbieri from comment #7)
> I don't get it, if I want to update layer 2 of a 256x256 red/unsigned byte
> texture I need to supply a 256*256*1=65536 bytes buffer, not a 131072-bytes
> one.

131072 / 2 = 256*256

You put in factor 2, by depth argument, which must be 1 instead,
since you only want to update 1 layer. 

Read the comment above.
Comment 9 Giuseppe Barbieri 2015-10-03 19:14:29 CEST
Ah, now I got what you meant, I'll try next week

thanks
Comment 10 Giuseppe Barbieri 2016-01-23 13:24:57 CET
Yep, you were right, Sven, sorry for the trouble

Thanks