From UBO to BindableBuffersEXT

Started by Estraven, May 22, 2010, 09:11:27

Previous topic - Next topic

Estraven

Hello,
I've developped a multiplateform 3D software , automatically switching from OGL 2.1 on Mac, to OGL 3.x on windows/Linux.

I recently discovered the OGL 3.1 Uniform buffer objects, that i successfully implemented.
However, before using them in my main software, i need to find an equivalent in OGL 2.1.
Mac OS 10.6.3 expose a GL_EXT_BindableUniform extension, so i tryied in this direction.
but i do not work yet... and I'm really stuck !

Here is what i've done.

Creating buffers - OGL 3.x (Note that the packBlockData() generates a correct byteBuffer)

UBO_ID = glGenBuffers();

		glBindBuffer(GL_UNIFORM_BUFFER, UBO_ID);
		glBufferData(GL_UNIFORM_BUFFER, packBlockData(), GL_DYNAMIC_DRAW);

		glBindBufferBase(GL_UNIFORM_BUFFER, 0, UBO_ID);


Creating buffers - OGL 2.1

UBO_ID = glGenBuffers();

		//Create UBO.
		glBindBuffer(EXTBindableUniform.GL_UNIFORM_BUFFER_EXT, UBO_ID);
		glBufferData(EXTBindableUniform.GL_UNIFORM_BUFFER_EXT, packBlockData(), GL_STATIC_READ);

		// is there any equilavent the the glBindBufferBase for OGL 2.1 ??


binding to shader and Updating data  - OGL 3.x

int uniformBlockLocation = glGetUniformBlockIndex(prog_id, blockName);

		if  (uniformBlockLocation>=0)
			glUniformBlockBinding(prog_id, uniformBlockLocation, UBO_ID);
		else{
			EGL_Log.Log("No uniform buffer object found with name "+blockName+" on shader with ID : "+prog_id +" "+uniformBlockLocation);	
			return;
		}

		glBindBuffer(GL_UNIFORM_BUFFER, UBO_ID);
		
		ByteBuffer data = packBlockData();		
		glBufferData(GL_UNIFORM_BUFFER, data, GL_DYNAMIC_DRAW);
		
		glBindBufferBase(GL_UNIFORM_BUFFER, 0, UBO_ID);



binding to shader and Updating data  - OGL 2.1

int uniformBlockLocation = glGetUniformLocation(prog_id, blockName);

		if (uniformBlockLocation>=0)
			EXTBindableUniform.glUniformBufferEXT(prog_id, uniformBlockLocation, UBO_ID);
		else{
			EGL_Log.Log("No uniform buffer object found with name "+blockName+" on shader with ID : "+prog_id +" "+uniformBlockLocation);
			return;
		}

		glBindBuffer(EXTBindableUniform.GL_UNIFORM_BUFFER_EXT, UBO_ID);
		
		ByteBuffer data = packBlockData();
		glBufferData(EXTBindableUniform.GL_UNIFORM_BUFFER_EXT, data, GL_STATIC_READ);

		// is there any equilavent the the glBindBufferBase for OGL 2.1 ??


I already tried to replace the GL_STATIC_READ by GL_DYNAMIC_DRAW... it does not change anything !

Now the shader part: Of course using GL3.2 i use GLSL 1.5

#version 150 
precision highp float;

uniform blockName_APItarget
{
  vec2 MyVar1;
  float MyVar2;
} blockName_shader;

(...)

blockName_shader.MyVar1.x

(...)


Using GL2.1 i use GLSL 1.2 + EXT

#version 120
#extension GL_EXT_bindable_uniform : enable


bindable uniform struct 
{
  vec2 MyVar1;
  float MyVar2;
} blockName_APItarget;

(...)

blockName_APItarget.MyVar1.x

(...)


As you probably realize, the goal here is to use a unique API name, and thus, loading different shader but then using a unique API-side code (except for the specific code above).

So the issue is, the GL3.2 code works, the GL2.1 code don't.

more precisely, the GL2.1 glGetUniformLocation returns a positive value, (thus it does find the block declaration within the shader)
The shader compiles, but it's seems that the uniform block values are all Zero.
My guess is that the buffer is not binded correctly, but I haven't found much examples on this on the web...

Any idea ??

Thanks
Estraven

spasi

Try to use glGetUniformOffsetEXT, it may be a data alignment issue.

Estraven

Indeed:

System.out.println( block_API_Name );
		System.out.println(  "   LOCATION : " + uniformBlockLocation);
		System.out.println(  "   OFFSET : " + EXTBindableUniform.glGetUniformOffsetEXT(prog_id, uniformBlockLocation));
		System.out.println(  "   SIZE : " + EXTBindableUniform.glGetUniformBufferSizeEXT(prog_id, uniformBlockLocation));


returns:
blockName_APItarget
   LOCATION : 3
   OFFSET : -1
   SIZE : 16


What did i miss ?

Estraven

spasi

I haven't used this extension and can't be sure, but I think you're supposed to also query the locations of the 2 uniforms inside the struct. Then you should be able to query the byte offsets for each one and fill the buffer object accordingly. As you can see the struct takes 16 bytes to hold 3 floats values (12 bytes), so there's definitely some data padding in there.

Estraven

I checked error report, glGetUniformOffsetEXT generates a GL_INVALID_VALUE error.

I've found that  :

Quote

   intptr GetUniformOffsetEXT(uint program, int location);

   returns the offset (in bytes) of the uniform in <program> whose location
   as returned by GetUniformLocation is <location>.  The error INVALID_VALUE
   is generated if the object named by <program> does not exist.


However, the program does exist, and is correllty binded at this time.

QuoteI think you're supposed to also query the locations of the 2 uniforms inside the struct. Then you should be able to query the byte offsets for each one and fill the buffer object accordingly. As you can see the struct takes 16 bytes to hold 3 floats values (12 bytes), so there's definitely some data padding in there.

Yes, I suspected something like that, I'll search for a way to do that.

Thanks, I'll keep you posted.