[RFE] LWJGL 3.0

Started by spasi, November 08, 2012, 13:23:54

Previous topic - Next topic

Kai


spasi

Build #27 has the renamed callbacks. Exceptions: CLNativeKernel, XErrorHandler, WindowProc

kappa

Just updated to latest nightly, API is now a lot cleaner and nicer to work with.

Got some time to work on the LWJGL2 compatibility layer, it now runs Minecraft pretty well.

There were some wanting to use Slick-Util with LWGL3 so wrapped a compatibility layer version of it. It can be downloaded from here.

Next up tested jMonkeyEngine3 on compatibility layer, however it uses a few extensions which are currently missing from LWJGL3, namely:

- org.lwjgl.opengl.EXTPackedDepthStencil.*;
- org.lwjgl.opengl.EXTPackedFloat.*;
- org.lwjgl.opengl.EXTTextureArray.*;
- org.lwjgl.opengl.EXTTextureCompressionLATC.*;
- org.lwjgl.opengl.EXTTextureSRGB.*;
- org.lwjgl.opengl.EXTTextureSharedExponent.*;


Once implemented it should be able to run jME3. There is also usage of pbuffers in jME3, which if I recall won't be implemented in LWJGL3, so will add a dummy PBuffer class which just returns them as unsupported.

Also the Slick library uses one GL11 variable and two extensions which are not in LWJGL3, namely:

- GL11.GL_ALL_CLIENT_ATTRIB_BITS;
- import org.lwjgl.opengl.EXTSecondaryColor;
- import org.lwjgl.opengl.EXTTextureMirrorClamp;

spasi

Thanks, will add missing stuff asap.

Quote from: kappa on December 07, 2014, 18:51:04There is also usage of pbuffers in jME3, which if I recall won't be implemented in LWJGL3, so will add a dummy PBuffer class which just returns them as unsupported.

There's no cross-platform abstraction for pbuffers, but you can use the OS-specific APIs. There's currently support for WGL_ARB_pbuffer and GLX 1.3/GLX_SGIX_pbuffer. NSOpenGLPixelBuffer will be added when bindings generation for ObjC is implemented.

kappa

One other thing, seem to be getting a debug error message when running minecraft:

Quote[LWJGL] Failed to locate address for GL function glVertexArrayVertexAttribDivisorEXT

Have been trying to track down its source and noticed its being thrown from within LWJLG3 (was running with '-Dorg.lwjgl.util.Debug=true').

Any idea's why its being thrown or how to fix it?

spasi

This function is introduced by ARB_instanced_arrays, but only when EXT_direct_state_access is also available. This interaction was added to the spec many years after its initial release, so drivers are not required to expose it:

QuoteIf implementations respond to a wglGetProcAddress, etc. query for "glVertexArrayVertexAttribDivisorEXT" with a NULL pointer, the DSA functionality is not available.

The correct way to detect it is:

ContextCapabilities caps = GL.getCapabilities();
if ( caps.GL_ARB_instanced_arrays && ARBInstancedArrays.getInstance().VertexArrayVertexAttribDivisorEXT != NULL ) {
	glVertexArrayVertexAttribDivisorEXT(vaobj, index, divisor);
}

spasi

The LWJGL 3 wiki now has a tutorial section and the first tutorial is up: Ray tracing with OpenGL Compute Shaders (Part I), authored by Kai.

spasi

Quote from: kappa on December 07, 2014, 18:51:04
- org.lwjgl.opengl.EXTPackedDepthStencil.*;
- org.lwjgl.opengl.EXTPackedFloat.*;
- org.lwjgl.opengl.EXTTextureArray.*;
- org.lwjgl.opengl.EXTTextureCompressionLATC.*;
- org.lwjgl.opengl.EXTTextureSRGB.*;
- org.lwjgl.opengl.EXTTextureSharedExponent.*;


- import org.lwjgl.opengl.EXTSecondaryColor;
- import org.lwjgl.opengl.EXTTextureMirrorClamp;

These extensions have been added. GL11.GL_ALL_CLIENT_ATTRIB_BITS was actually a typo in LWJGL 2, the correct is GL_CLIENT_ALL_ATTRIB_BITS.

spasi

Quote from: kappa on November 26, 2014, 00:28:18Lastly the following 2 methods are different
GL20.glVertexAttribPointer(int index, int size, boolean unsigned, boolean normalized, int stride, java.nio.ByteBuffer buffer);
GL20.glVertexAttribPointer(int index, int size, boolean unsigned, boolean normalized, int stride, java.nio.ShortBuffer buffer);

They no longer have the 'unsigned' boolean variable but require an int 'type' variable. This is definitely a change for the better in LWJGL3.

I had another look at this and realized that LWJGL 3 already supports the virtual unsigned argument, it just wasn't applied to this particular function. I've pushed a commit that fixes functions that were missing it, so that all vertex pointer functions are consistent.

Now the question is, should we remove it? First, lets see what is generated now:

// Unsafe version, matches the native function
void nglVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long pointer)
// Direct mapping of the unsafe version to Java, ARRAY_BUFFER_BINDING == 0
void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer)
// Direct mapping of the unsafe version to Java, ARRAY_BUFFER_BINDING != 0
void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long pointerOffset)

// Below are the "convenient" methods that we may want to change.

// type = GL_BYTE or GL_UNSIGNED_BYTE
void glVertexAttribPointer(int index, int size, boolean unsigned, boolean normalized, int stride, ByteBuffer pointer)
// type = GL_SHORT or GL_UNSIGNED_SHORT
void glVertexAttribPointer(int index, int size, boolean unsigned, boolean normalized, int stride, ShortBuffer pointer)
// type = GL_INT
void glVertexAttribPointer(int index, int size, boolean normalized, int stride, IntBuffer pointer)
// type = GL_FLOAT
void glVertexAttribPointer(int index, int size, boolean normalized, int stride, FloatBuffer pointer)
// type = GL_DOUBLE
void glVertexAttribPointer(int index, int size, boolean normalized, int stride, DoubleBuffer pointer)

There are a few issues here:

a) The unsigned argument. It does not exist in the native function and the signature is different for different buffer types.
b) Why is a GL_UNSIGNED_INT version missing?
c) What if we want to use GL30.GL_HALF_FLOAT with a ShortBuffer or GL12#UNSIGNED_INT_2_10_10_10_REV with an IntBuffer?

So, it might make sense to expose the type argument in the convenient methods too, i.e.:

void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ShortBuffer pointer)
void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, IntBuffer pointer)
void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, FloatBuffer pointer)
void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, DoubleBuffer pointer)

The pros are that we have full flexibility and one less method (the ByteBuffer version already exists). The cons are:

a) The type argument for the FloatBuffer and DoubleBuffer versions is useless. I don't think it'll ever be anything other than GL_FLOAT and GL_DOUBLE respectively.
b) We break LWJGL 2 compatibility for these functions.

A hybrid solution would be: Replace unsigned with type for integer buffers and hide type for floating point buffers.

Cornix

I would just expose it. The user is probably going to wrap the method up anyways. And everybody is used to give an OpenGL method like a million arguments already.

shivshank

Quote from: spasiA hybrid solution would be: Replace unsigned with type for integer buffers and hide type for floating point buffers.
Is this more difficult to do? It seems somewhat optimal. Though is this something that might change in future OpenGL versions? Will there be a float 2.0 or 128bit float, etc, or some type our brains can't yet comprehend?

kappa

Quote from: spasi on December 08, 2014, 19:05:13
These extensions have been added. GL11.GL_ALL_CLIENT_ATTRIB_BITS was actually a typo in LWJGL 2, the correct is GL_CLIENT_ALL_ATTRIB_BITS.
super cool stuff, will give it a spin tonight.

In relation to the glVertexAttribPointer variations, just an idea, if we are exposing the type variable for the convenience methods, then do we still need a convenience method for each data type? We could just have one convenience method (thus matching the native style and reducing the API size)
i.e.
glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, java.nio.Buffer pointer)


btw LWJGL's on opengl.org :)

spasi

Quote from: kappa on December 09, 2014, 13:45:05In relation to the glVertexAttribPointer variations, just an idea, if we are exposing the type variable for the convenience methods, then do we still need a convenience method for each data type? We could just have one convenience method (thus matching the native style and reducing the API size)
i.e.
glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, java.nio.Buffer pointer)

Yes, we still need the different buffer types. The reason is that the pointer passed to native code depends on the buffer's current .position() and the byte offset needs to be scaled according to the buffer's element type (x1 for ByteBuffer, x2 for ShortBuffer, x4 for Int/Float, etc). It could be implemented with a switch statement on the buffer's .class, but it feels "dirty" and I don't know if it can be optimized by the JVM.

kappa

Quote from: spasi on December 09, 2014, 17:07:10
It could be implemented with a switch statement on the buffer's .class, but it feels "dirty" and I don't know if it can be optimized by the JVM.
Also instanceof could be used, e.g.
switch (type) {
	case GL11.GL_UNSIGNED_BYTE: case GL11.GL_BYTE:
		if (buffer instanceof ByteBuffer) {
			// x1
		}
		break;
	case GL11.GL_UNSIGNED_SHORT: case GL11.GL_SHORT:
		if (buffer instanceof ShortBuffer) {
			//x2
		}
		break;
	case GL11.GL_UNSIGNED_INT: case GL11.GL_INT:
		if (buffer instanceof IntBuffer) {
			//x4
		}
		break;
	case GL11.GL_FLOAT:
		if (buffer instanceof FloatBuffer) {
			//x4
		}
		break;
	case GL11.GL_DOUBLE:
		if (buffer instanceof DoubleBuffer) {
			//x8
		}
		break;
}

spasi

Sorry, I meant an if/else chain, with instanceof. The switch isn't necessary and also hard to maintain (new GL types are introduced all the time).