Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions jme3-core/src/main/java/com/jme3/material/Material.java
Original file line number Diff line number Diff line change
Expand Up @@ -881,14 +881,10 @@ private void updateShaderMaterialParameter(Renderer renderer, VarType type, Shad
ShaderBufferBlock.BufferType btype;
if (type == VarType.ShaderStorageBufferObject) {
btype = ShaderBufferBlock.BufferType.ShaderStorageBufferObject;
bufferBlock.setBufferObject(btype, bufferObject);
renderer.setShaderStorageBufferObject(unit.bufferUnit, bufferObject); // TODO: probably not needed
} else {
btype = ShaderBufferBlock.BufferType.UniformBufferObject;
bufferBlock.setBufferObject(btype, bufferObject);
renderer.setUniformBufferObject(unit.bufferUnit, bufferObject); // TODO: probably not needed
}
unit.bufferUnit++;
bufferBlock.setBufferObject(btype, bufferObject);
} else {
Uniform uniform = shader.getUniform(param.getPrefixedName());
if (!override && uniform.isSetByCurrentMaterial())
Expand Down
16 changes: 16 additions & 0 deletions jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,20 @@ public interface GL3 extends GL2 {
* uniformBlockIndex within program.
*/
public void glUniformBlockBinding(int program, int uniformBlockIndex, int uniformBlockBinding);

/**
* <p><a target="_blank" href="http://docs.gl/gl4/glGetActiveUniformBlock">Reference Page</a></p>
*
* Queries information about an active uniform block.
*
* @param program the name of a program containing the uniform block.
* @param uniformBlockIndex the index of the uniform block within program.
* @param pname the name of the parameter to query. One of:
* {@link #GL_UNIFORM_BLOCK_BINDING}
* {@link #GL_UNIFORM_BLOCK_DATA_SIZE}
* {@link #GL_UNIFORM_BLOCK_NAME_LENGTH}
* {@link #GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS}
* @return the value of the queried parameter.
*/
public int glGetActiveUniformBlocki(int program, int uniformBlockIndex, int pname);
}
24 changes: 23 additions & 1 deletion jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
*/
package com.jme3.renderer.opengl;

import java.nio.IntBuffer;

/**
* GL functions only available on vanilla desktop OpenGL 4.0.
*
Expand Down Expand Up @@ -77,6 +79,11 @@ public interface GL4 extends GL3 {
public static final int GL_SHADER_STORAGE_BUFFER = 0x90D2;
public static final int GL_SHADER_STORAGE_BLOCK = 0x92E6;

/**
* Accepted by the {@code props} parameter of GetProgramResourceiv.
*/
public static final int GL_BUFFER_BINDING = 0x9302;

/**
* Accepted by the &lt;pname&gt; parameter of GetIntegerv, GetBooleanv,
* GetInteger64v, GetFloatv, and GetDoublev:
Expand Down Expand Up @@ -124,7 +131,22 @@ public interface GL4 extends GL3 {
* @param storageBlockBinding The index storage block binding to associate with the specified storage block.
*/
public void glShaderStorageBlockBinding(int program, int storageBlockIndex, int storageBlockBinding);


/**
* <p><a target="_blank" href="http://docs.gl/gl4/glGetProgramResource">Reference Page</a></p>
*
* Retrieves values for multiple properties of a single active resource within a program object.
*
* @param program the name of a program object whose resources to query.
* @param programInterface a token identifying the interface within program containing the resource named name.
* @param index the active resource index.
* @param props an array of properties to query.
* @param length an array that will receive the number of values written to params.
* @param params an array that will receive the property values.
*/
public void glGetProgramResourceiv(int program, int programInterface, int index, IntBuffer props, IntBuffer length, IntBuffer params);


/**
* Binds a single level of a texture to an image unit for the purpose of reading
* and writing it from shaders.
Expand Down
80 changes: 56 additions & 24 deletions jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -1456,7 +1456,6 @@ protected void updateShaderBufferBlock(final Shader shader, final ShaderBufferBl

final BufferObject bufferObject = bufferBlock.getBufferObject();
final BufferType bufferType = bufferBlock.getType();


if (bufferObject.isUpdateNeeded()) {
if (bufferType == BufferType.ShaderStorageBufferObject) {
Expand All @@ -1473,35 +1472,52 @@ protected void updateShaderBufferBlock(final Shader shader, final ShaderBufferBl

final int shaderId = shader.getId();

int bindingPoint = bufferObject.getBinding();
// Resolve the block index (location) from the compiled shader
int blockIndex = bufferBlock.getLocation();
if (blockIndex < 0) {
if (bufferType == BufferType.ShaderStorageBufferObject) {
blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName());
} else {
blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName());
}
bufferBlock.setLocation(blockIndex);
}

// Block not found in the shader — skip silently
if (blockIndex < 0 || blockIndex == NativeObject.INVALID_ID) {
bufferBlock.clearUpdateNeeded();
return;
}

// Resolve the binding point for this block. First try to read the
// binding declared in the shader (layout(binding=N)). If the query
// returns 0 the shader may not have an explicit binding, so fall
// back to blockIndex to avoid multiple blocks colliding on point 0.
int bindingPoint = bufferBlock.getBinding();
if (bindingPoint < 0) {
if (bufferType == BufferType.ShaderStorageBufferObject) {
bindingPoint = queryShaderStorageBlockBinding(shaderId, blockIndex);
} else {
bindingPoint = gl3.glGetActiveUniformBlocki(shaderId, blockIndex, GL3.GL_UNIFORM_BLOCK_BINDING);
}
if (bindingPoint == 0) {
bindingPoint = blockIndex;
}
Comment on lines +1503 to +1505
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This logic incorrectly handles layout(binding=0). When a uniform block has an explicit layout(binding=0), the GL query will return 0. This code then overwrites bindingPoint with blockIndex, which might be different from 0, thus ignoring the explicit binding from the shader. This is a bug for shaders that use layout(binding=0). The ambiguity of the return value 0 from the GL functions makes this tricky, but the current implementation doesn't fully respect layout(binding=N) as intended.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think there is a correct solution, if binding trough the material system is allowed, and the direct binding version too. then unfortuantely due to opengl returning 0 for "not defined" creates always a a point where collision can happen.

if (bufferType == BufferType.ShaderStorageBufferObject) {
gl4.glShaderStorageBlockBinding(shaderId, blockIndex, bindingPoint);
} else {
gl3.glUniformBlockBinding(shaderId, blockIndex, bindingPoint);
}
bufferBlock.setBinding(bindingPoint);
}

switch (bufferType) {
case UniformBufferObject: {
setUniformBufferObject(bindingPoint, bufferObject); // rebind buffer if needed
if (bufferBlock.isUpdateNeeded()) {
int blockIndex = bufferBlock.getLocation();
if (blockIndex < 0) {
blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName());
bufferBlock.setLocation(blockIndex);
}
if (bufferBlock.getLocation() != NativeObject.INVALID_ID) {
gl3.glUniformBlockBinding(shaderId, bufferBlock.getLocation(), bindingPoint);
}
}
setUniformBufferObject(bindingPoint, bufferObject);
break;
}
case ShaderStorageBufferObject: {
setShaderStorageBufferObject(bindingPoint, bufferObject); // rebind buffer if needed
if (bufferBlock.isUpdateNeeded() ) {
int blockIndex = bufferBlock.getLocation();
if (blockIndex < 0) {
blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName());
bufferBlock.setLocation(blockIndex);
}
if (bufferBlock.getLocation() != NativeObject.INVALID_ID) {
gl4.glShaderStorageBlockBinding(shaderId, bufferBlock.getLocation(), bindingPoint);
}
}
setShaderStorageBufferObject(bindingPoint, bufferObject);
break;
}
default: {
Expand All @@ -1512,6 +1528,22 @@ protected void updateShaderBufferBlock(final Shader shader, final ShaderBufferBl
bufferBlock.clearUpdateNeeded();
}

/**
* Queries the binding point of a shader storage block using
* glGetProgramResourceiv with GL_BUFFER_BINDING.
*
* @param program the shader program id.
* @param blockIndex the block index within the program.
* @return the binding point assigned to the block.
*/
private int queryShaderStorageBlockBinding(int program, int blockIndex) {
IntBuffer props = BufferUtils.createIntBuffer(1);
props.put(GL4.GL_BUFFER_BINDING).flip();
IntBuffer params = BufferUtils.createIntBuffer(1);
gl4.glGetProgramResourceiv(program, GL4.GL_SHADER_STORAGE_BLOCK, blockIndex, props, null, params);
return params.get(0);
Comment on lines +1542 to +1544
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This method allocates a new IntBuffer for params on every call. To improve performance and reduce garbage, you can reuse the class member intBuf1 which is already available for this purpose.

Suggested change
IntBuffer params = BufferUtils.createIntBuffer(1);
gl4.glGetProgramResourceiv(program, GL4.GL_SHADER_STORAGE_BLOCK, blockIndex, props, null, params);
return params.get(0);
intBuf1.clear();
gl4.glGetProgramResourceiv(program, GL4.GL_SHADER_STORAGE_BLOCK, blockIndex, props, null, intBuf1);
return intBuf1.get(0);

}

protected void updateShaderUniforms(Shader shader) {
ListMap<String, Uniform> uniforms = shader.getUniformMap();
for (int i = 0; i < uniforms.size(); i++) {
Expand Down
24 changes: 24 additions & 0 deletions jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public static enum BufferType {
protected WeakReference<BufferObject> bufferObjectRef;
protected BufferType type;

/**
* The binding point assigned to this block, or -1 if not yet assigned.
*/
protected int binding = -1;

/**
* Set the new buffer object.
*
Expand Down Expand Up @@ -90,11 +95,30 @@ public void clearUpdateNeeded(){
updateNeeded = false;
}

/**
* Get the binding point assigned to this block.
*
* @return the binding point, or -1 if not yet assigned.
*/
public int getBinding() {
return binding;
}

/**
* Set the binding point for this block.
*
* @param binding the binding point.
*/
public void setBinding(int binding) {
this.binding = binding;
}

/**
* Reset this storage block.
*/
public void reset() {
location = -1;
binding = -1;
updateNeeded = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public void initializeEmpty(int length) {
BufferUtils.destroyDirectBuffer(data);
}
this.data = BufferUtils.createByteBuffer(length);
setUpdateNeeded();
}


Expand Down
10 changes: 10 additions & 0 deletions jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
Original file line number Diff line number Diff line change
Expand Up @@ -660,4 +660,14 @@ public void glBindBufferBase(final int target, final int index, final int buffer
public void glUniformBlockBinding(final int program, final int uniformBlockIndex, final int uniformBlockBinding) {
GL31.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
}

@Override
public int glGetActiveUniformBlocki(final int program, final int uniformBlockIndex, final int pname) {
return GL31.glGetActiveUniformBlocki(program, uniformBlockIndex, pname);
}

@Override
public void glGetProgramResourceiv(final int program, final int programInterface, final int index, IntBuffer props, IntBuffer length, IntBuffer params) {
GL43.glGetProgramResource(program, programInterface, index, props, length, params);
}
}
12 changes: 11 additions & 1 deletion jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
Original file line number Diff line number Diff line change
Expand Up @@ -698,5 +698,15 @@ public void glBindBufferBase(final int target, final int index, final int buffer
public void glUniformBlockBinding(final int program, final int uniformBlockIndex, final int uniformBlockBinding) {
GL31.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
}


@Override
public int glGetActiveUniformBlocki(final int program, final int uniformBlockIndex, final int pname) {
return GL31.glGetActiveUniformBlocki(program, uniformBlockIndex, pname);
}

@Override
public void glGetProgramResourceiv(final int program, final int programInterface, final int index, IntBuffer props, IntBuffer length, IntBuffer params) {
GL43.glGetProgramResourceiv(program, programInterface, index, props, length, params);
}

}
Loading