Hello,
I'm trying to figure out how do uniform blocks work and I can't understand the results I get.
In my fragment shader code I have this uniform block :
layout (std140, binding = 0) uniform BlobSettings {
// Base alignment // Aligned Offset (MUST BE multiple of base alignment, in std140)
vec4 innerColor; // 16 // 0 - 16
vec4 outerColor; // 16 // 16 - 32
float radiusInner; // 4 // 32 - 36
float radiusOuter; // 4 // 36 - 40
};
So when I ask in my application the size of this block I'm expecting to see 40 but actually I get 48 ... Where does it come from ? Here is my code to get the uniform block size :
public int getUniformBlockSize(int shaderProgramID, String uniformBlockName) {
int uniformBlockIndex = uniformBlockIndices.get(uniformBlockName).getBlockIndex();
int uboSize = GL31.glGetActiveUniformBlocki(shaderProgramID, uniformBlockIndex, GL31.GL_UNIFORM_BLOCK_DATA_SIZE);
return uboSize;
}
Furthermore in a lot of code (C++ or C) they're using malloc after retrieving the uniform block size to allocate the memory of their buffer, but we can't in Java... I paste my entire code here dealing with uniform buffer and if some benevolent spirits could have a look and give me some feedback (if I'm doing wrong or if I could do better) I would really appreciate :
public class ShaderUniformBlockComponent {
private Hashtable<String, UniformBufferObjectInfos>uniformBlockIndices;
public ShaderUniformBlockComponent() {
uniformBlockIndices = new Hashtable<String, UniformBufferObjectInfos>();
}
public void prepareUniformBuffer(String uniformBlockName, int sizeToAllocate) {
// Prepare a uniform buffer, allocating memory
int uboID = GL15.glGenBuffers();
GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, uboID);
GL44.glBufferStorage(GL31.GL_UNIFORM_BUFFER, sizeToAllocate, GL44.GL_DYNAMIC_STORAGE_BIT);
GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, 0);
UniformBufferObjectInfos uniformBufferObjectInfo = new UniformBufferObjectInfos();
uniformBufferObjectInfo.setUboID(uboID);
uniformBufferObjectInfo.setAllocatedSize(sizeToAllocate);
uniformBlockIndices.put(uniformBlockName, uniformBufferObjectInfo);
}
public void bindUniformBlockIndex(int shaderProgramID, String uniformBlockName, int bindingPoint) {
/*
* Retrieving the uniform block index, and binding it to a specific binding point (0 here)
* NOTE USED SINCE 4.2 IF IT'S SPECIFIED THE BINDING POINT IN SHADER with "layout(binding = n)"
*/
int uniformBlockIndex = GL31.glGetUniformBlockIndex(shaderProgramID, uniformBlockName);
GL31.glUniformBlockBinding(shaderProgramID, uniformBlockIndex, bindingPoint);
uniformBlockIndices.get(uniformBlockName).setBindingPoint(bindingPoint);
uniformBlockIndices.get(uniformBlockName).setBlockIndex(uniformBlockIndex);
}
public void updateUniformBlock(String uniformBlockName, float[] values, int offset) {
int uboID = uniformBlockIndices.get(uniformBlockName).getUboID();
int bindingPoint = uniformBlockIndices.get(uniformBlockName).getBindingPoint();
int allocatedSize = uniformBlockIndices.get(uniformBlockName).getAllocatedSize();
/*
* Finaly bind the uniform buffer object to the same binding point to acctualy link
* the uniform buffer to the uniform block (pointing each to the same binding point)
*/
GL30.glBindBufferBase(GL31.GL_UNIFORM_BUFFER, bindingPoint, uboID);
/*
* Fill the buffer object to update the uniform block
*/
FloatBuffer floatBuffer = BufferUtils.createFloatBuffer(allocatedSize - offset);
floatBuffer.put(values);
floatBuffer.flip();
GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, uboID);
GL15.glBufferSubData(GL31.GL_UNIFORM_BUFFER, offset, floatBuffer);
GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, 0);
}
// Not used ==> std140
public int getUniformBlockSize(int shaderProgramID, String uniformBlockName) {
int uniformBlockIndex = uniformBlockIndices.get(uniformBlockName).getBlockIndex();
int uboSize = GL31.glGetActiveUniformBlocki(shaderProgramID, uniformBlockIndex, GL31.GL_UNIFORM_BLOCK_DATA_SIZE);
return uboSize;
}
private class UniformBufferObjectInfos {
private static final int NONE = -1;
private int uboID;
private int blockIndex;
private int allocatedSize;
private int bindingPoint;
private UniformBufferObjectInfos() {
this.uboID = NONE;
this.allocatedSize = NONE;
this.bindingPoint = NONE;
this.blockIndex = NONE;
}
public int getUboID() {
return uboID;
}
public void setUboID(int uboID) {
this.uboID = uboID;
}
public int getBlockIndex() {
return blockIndex;
}
public void setBlockIndex(int blockIndex) {
this.blockIndex = blockIndex;
}
public int getAllocatedSize() {
return allocatedSize;
}
public void setAllocatedSize(int allocatedSize) {
this.allocatedSize = allocatedSize;
}
public int getBindingPoint() {
return bindingPoint;
}
public void setBindingPoint(int bindingPoint) {
this.bindingPoint = bindingPoint;
}
}
}
and in my application :
shader = new ShaderProgram("src/shaders/vertexShader.glsl", "src/shaders/fragmentShader.glsl");
float[] uniformValues = {
1, 0, 0, 1,
0, 0, 0, 1,
0.25f,
0.45f
};
shader.prepareUniformBuffer("BlobSettings", 40);
shader.bindUniformBlockIndex("BlobSettings", 0);
shader.updateUniformBlock("BlobSettings", uniformValues, 0);
Thanks for your help !
and sorry for my bad english
And if someone could redirect me (or explain here) to tutorials explaining how does memory in openGL work (like when to use glMap ? vs vpBufferData ? vs glBufferStorage etc... ). I'm 1000% a beginner so it would be great if it could be explain so that I won't be drowned in highly technical terms
.