updated API of BO.
This commit is contained in:
parent
2297441c13
commit
54e3987022
@ -669,19 +669,25 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a buffer object to the material shader.
|
* Pass an uniform buffer object to the material shader.
|
||||||
*
|
*
|
||||||
* @param name the name of the buffer object defined in the material definition (j3md).
|
* @param name the name of the buffer object defined in the material definition (j3md).
|
||||||
* @param value the buffer object.
|
* @param value the buffer object.
|
||||||
*/
|
*/
|
||||||
public void setBufferObject(final String name, final BufferObject value) {
|
public void setUniformBufferObject(final String name, final BufferObject value) {
|
||||||
if (value instanceof UniformBufferObject) {
|
value.setBufferType(BufferObject.BufferType.UniformBufferObject);
|
||||||
setParam(name, VarType.UniformBufferObject, value);
|
setParam(name, VarType.UniformBufferObject, value);
|
||||||
} else if (value instanceof ShaderStorageBufferObject) {
|
|
||||||
setParam(name, VarType.ShaderStorageBufferObject, value);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Not expected value " + value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass a shader storage buffer object to the material shader.
|
||||||
|
*
|
||||||
|
* @param name the name of the buffer object defined in the material definition (j3md).
|
||||||
|
* @param value the buffer object.
|
||||||
|
*/
|
||||||
|
public void setShaderStorageBufferObject(final String name, final BufferObject value) {
|
||||||
|
value.setBufferType(BufferObject.BufferType.ShaderStorageBufferObject);
|
||||||
|
setParam(name, VarType.ShaderStorageBufferObject, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,8 +38,6 @@ import com.jme3.scene.VertexBuffer;
|
|||||||
import com.jme3.shader.BufferObject;
|
import com.jme3.shader.BufferObject;
|
||||||
import com.jme3.shader.Shader;
|
import com.jme3.shader.Shader;
|
||||||
import com.jme3.shader.Shader.ShaderSource;
|
import com.jme3.shader.Shader.ShaderSource;
|
||||||
import com.jme3.shader.ShaderStorageBufferObject;
|
|
||||||
import com.jme3.shader.UniformBufferObject;
|
|
||||||
import com.jme3.system.AppSettings;
|
import com.jme3.system.AppSettings;
|
||||||
import com.jme3.texture.FrameBuffer;
|
import com.jme3.texture.FrameBuffer;
|
||||||
import com.jme3.texture.Image;
|
import com.jme3.texture.Image;
|
||||||
|
@ -1229,15 +1229,24 @@ public final class GLRenderer implements Renderer {
|
|||||||
bindProgram(shader);
|
bindProgram(shader);
|
||||||
|
|
||||||
final int shaderId = shader.getId();
|
final int shaderId = shader.getId();
|
||||||
|
final BufferObject.BufferType bufferType = bufferObject.getBufferType();
|
||||||
|
|
||||||
if (bufferObject instanceof ShaderStorageBufferObject) {
|
switch (bufferType) {
|
||||||
final int blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName());
|
case UniformBufferObject: {
|
||||||
gl4.glShaderStorageBlockBinding(shaderId, blockIndex, bufferObject.getBinding());
|
|
||||||
gl4.glBindBufferBase(GL4.GL_SHADER_STORAGE_BUFFER, bufferObject.getBinding(), bufferObject.getId());
|
|
||||||
} else if (bufferObject instanceof UniformBufferObject) {
|
|
||||||
final int blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName());
|
final int blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName());
|
||||||
gl3.glBindBufferBase(GL3.GL_UNIFORM_BUFFER, bufferObject.getBinding(), bufferObject.getId());
|
gl3.glBindBufferBase(GL3.GL_UNIFORM_BUFFER, bufferObject.getBinding(), bufferObject.getId());
|
||||||
gl3.glUniformBlockBinding(GL3.GL_UNIFORM_BUFFER, blockIndex, bufferObject.getBinding());
|
gl3.glUniformBlockBinding(GL3.GL_UNIFORM_BUFFER, blockIndex, bufferObject.getBinding());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ShaderStorageBufferObject: {
|
||||||
|
final int blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName());
|
||||||
|
gl4.glShaderStorageBlockBinding(shaderId, blockIndex, bufferObject.getBinding());
|
||||||
|
gl4.glBindBufferBase(GL4.GL_SHADER_STORAGE_BUFFER, bufferObject.getBinding(), bufferObject.getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new IllegalArgumentException("Doesn't support binding of " + bufferType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferBlock.clearUpdateNeeded();
|
bufferBlock.clearUpdateNeeded();
|
||||||
@ -2577,16 +2586,10 @@ public final class GLRenderer implements Renderer {
|
|||||||
|
|
||||||
int maxSize = Integer.MAX_VALUE;
|
int maxSize = Integer.MAX_VALUE;
|
||||||
|
|
||||||
if (bo instanceof UniformBufferObject) {
|
final BufferObject.BufferType bufferType = bo.getBufferType();
|
||||||
if (!caps.contains(Caps.UniformBufferObject)) {
|
|
||||||
throw new IllegalArgumentException("The current video hardware doesn't support UBO.");
|
if (!caps.contains(bufferType.getRequiredCaps())) {
|
||||||
}
|
throw new IllegalArgumentException("The current video hardware doesn't support " + bufferType);
|
||||||
} else if (bo instanceof ShaderStorageBufferObject) {
|
|
||||||
if (!caps.contains(Caps.ShaderStorageBufferObject)) {
|
|
||||||
throw new IllegalArgumentException("The current video hardware doesn't support SSBO.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Not expected type of the BO " + bo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final ByteBuffer data = bo.computeData(maxSize);
|
final ByteBuffer data = bo.computeData(maxSize);
|
||||||
@ -2609,14 +2612,22 @@ public final class GLRenderer implements Renderer {
|
|||||||
|
|
||||||
data.rewind();
|
data.rewind();
|
||||||
|
|
||||||
if (bo instanceof UniformBufferObject) {
|
switch (bufferType) {
|
||||||
|
case UniformBufferObject: {
|
||||||
gl3.glBindBuffer(GL3.GL_UNIFORM_BUFFER, bufferId);
|
gl3.glBindBuffer(GL3.GL_UNIFORM_BUFFER, bufferId);
|
||||||
gl3.glBufferData(GL4.GL_UNIFORM_BUFFER, data, GL3.GL_DYNAMIC_DRAW);
|
gl3.glBufferData(GL4.GL_UNIFORM_BUFFER, data, GL3.GL_DYNAMIC_DRAW);
|
||||||
gl3.glBindBuffer(GL4.GL_UNIFORM_BUFFER, 0);
|
gl3.glBindBuffer(GL4.GL_UNIFORM_BUFFER, 0);
|
||||||
} else {
|
break;
|
||||||
|
}
|
||||||
|
case ShaderStorageBufferObject: {
|
||||||
gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, bufferId);
|
gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, bufferId);
|
||||||
gl4.glBufferData(GL4.GL_SHADER_STORAGE_BUFFER, data, GL4.GL_DYNAMIC_COPY);
|
gl4.glBufferData(GL4.GL_SHADER_STORAGE_BUFFER, data, GL4.GL_DYNAMIC_COPY);
|
||||||
gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, 0);
|
gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new IllegalArgumentException("Doesn't support binding of " + bufferType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bo.clearUpdateNeeded();
|
bo.clearUpdateNeeded();
|
||||||
@ -2644,7 +2655,7 @@ public final class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
intBuf1.clear();
|
intBuf1.clear();
|
||||||
intBuf1.put(0, bufferId);
|
intBuf1.put(bufferId);
|
||||||
intBuf1.flip();
|
intBuf1.flip();
|
||||||
|
|
||||||
gl.glDeleteBuffers(intBuf1);
|
gl.glDeleteBuffers(intBuf1);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.jme3.shader;
|
package com.jme3.shader;
|
||||||
|
|
||||||
import com.jme3.math.*;
|
import com.jme3.math.*;
|
||||||
|
import com.jme3.renderer.Caps;
|
||||||
import com.jme3.renderer.Renderer;
|
import com.jme3.renderer.Renderer;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
import com.jme3.util.NativeObject;
|
import com.jme3.util.NativeObject;
|
||||||
@ -23,11 +24,37 @@ public class BufferObject extends NativeObject {
|
|||||||
std430,
|
std430,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum BufferType {
|
||||||
|
ShaderStorageBufferObject(Caps.ShaderStorageBufferObject),
|
||||||
|
UniformBufferObject(Caps.UniformBufferObject),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Caps requiredCaps;
|
||||||
|
|
||||||
|
BufferType(final Caps requiredCaps) {
|
||||||
|
this.requiredCaps = requiredCaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required caps.
|
||||||
|
*
|
||||||
|
* @return the required caps.
|
||||||
|
*/
|
||||||
|
public Caps getRequiredCaps() {
|
||||||
|
return requiredCaps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The fields of this BO.
|
* The fields of this BO.
|
||||||
*/
|
*/
|
||||||
private final Map<String, BufferObjectField> fields;
|
private final Map<String, BufferObjectField> fields;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The field's array.
|
||||||
|
*/
|
||||||
|
private final BufferObjectField[] fieldArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The buffer's data layout.
|
* The buffer's data layout.
|
||||||
*/
|
*/
|
||||||
@ -38,19 +65,38 @@ public class BufferObject extends NativeObject {
|
|||||||
*/
|
*/
|
||||||
private final int binding;
|
private final int binding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer's type.
|
||||||
|
*/
|
||||||
|
private BufferType bufferType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The previous data buffer.
|
* The previous data buffer.
|
||||||
*/
|
*/
|
||||||
private ByteBuffer previousData;
|
private ByteBuffer previousData;
|
||||||
|
|
||||||
public BufferObject(final int binding, final Layout layout, final BufferObjectField... fields) {
|
public BufferObject(final int binding, final Layout layout, final BufferType bufferType, final BufferObjectField... fields) {
|
||||||
this.handleRef = new Object();
|
this.handleRef = new Object();
|
||||||
|
this.bufferType = bufferType;
|
||||||
this.binding = binding;
|
this.binding = binding;
|
||||||
this.layout = layout;
|
this.layout = layout;
|
||||||
this.fields = new LinkedHashMap<>(fields.length);
|
this.fields = new LinkedHashMap<>(fields.length);
|
||||||
for (final BufferObjectField field : fields) {
|
for (final BufferObjectField field : fields) {
|
||||||
this.fields.put(field.getName(), field);
|
this.fields.put(field.getName(), field);
|
||||||
}
|
}
|
||||||
|
this.fieldArray = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferObject(final int binding, final Layout layout, final BufferObjectField... fields) {
|
||||||
|
this(binding, layout, BufferType.UniformBufferObject, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferObject(final int binding, final BufferObjectField... fields) {
|
||||||
|
this(binding, Layout.std140, BufferType.UniformBufferObject, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferObject(final BufferObjectField... fields) {
|
||||||
|
this(1, Layout.std140, BufferType.UniformBufferObject, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferObject(final int id) {
|
public BufferObject(final int id) {
|
||||||
@ -58,6 +104,30 @@ public class BufferObject extends NativeObject {
|
|||||||
this.binding = -2;
|
this.binding = -2;
|
||||||
this.fields = null;
|
this.fields = null;
|
||||||
this.layout = null;
|
this.layout = null;
|
||||||
|
this.fieldArray = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the buffer's type.
|
||||||
|
*
|
||||||
|
* @return the buffer's type.
|
||||||
|
*/
|
||||||
|
public BufferType getBufferType() {
|
||||||
|
return bufferType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the buffer's type.
|
||||||
|
*
|
||||||
|
* @param bufferType the buffer's type.
|
||||||
|
*/
|
||||||
|
public void setBufferType(final BufferType bufferType) {
|
||||||
|
|
||||||
|
if (getId() != -1) {
|
||||||
|
throw new IllegalStateException("Can't change buffer's type when this buffer is already initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bufferType = bufferType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,8 +189,7 @@ public class BufferObject extends NativeObject {
|
|||||||
|
|
||||||
int estimateSize = 0;
|
int estimateSize = 0;
|
||||||
|
|
||||||
for (final Map.Entry<String, BufferObjectField> entry : fields.entrySet()) {
|
for (final BufferObjectField field : fieldArray) {
|
||||||
final BufferObjectField field = entry.getValue();
|
|
||||||
estimateSize += estimateSize(field);
|
estimateSize += estimateSize(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,17 +202,21 @@ public class BufferObject extends NativeObject {
|
|||||||
if (previousData.capacity() < estimateSize) {
|
if (previousData.capacity() < estimateSize) {
|
||||||
BufferUtils.destroyDirectBuffer(previousData);
|
BufferUtils.destroyDirectBuffer(previousData);
|
||||||
previousData = null;
|
previousData = null;
|
||||||
|
} else {
|
||||||
|
previousData.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final ByteBuffer data = previousData == null ? BufferUtils.createByteBuffer((int) (estimateSize * 1.1F)) : previousData;
|
final ByteBuffer data = previousData == null ? BufferUtils.createByteBuffer(estimateSize) : previousData;
|
||||||
|
|
||||||
for (final Map.Entry<String, BufferObjectField> entry : fields.entrySet()) {
|
for (final BufferObjectField field : fieldArray) {
|
||||||
writeField(entry.getValue(), data);
|
writeField(field, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.flip();
|
data.flip();
|
||||||
|
|
||||||
|
this.previousData = data;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package com.jme3.shader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The implementation of SSBO.
|
|
||||||
*
|
|
||||||
* @author JavaSaBr
|
|
||||||
*/
|
|
||||||
public class ShaderStorageBufferObject extends BufferObject {
|
|
||||||
|
|
||||||
public ShaderStorageBufferObject(final int binding, final Layout layout, final BufferObjectField... fields) {
|
|
||||||
super(binding, layout, fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShaderStorageBufferObject(final int binding, final BufferObjectField... fields) {
|
|
||||||
super(binding, Layout.std430, fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShaderStorageBufferObject(final int id) {
|
|
||||||
super(id);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package com.jme3.shader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The implementation of UBO.
|
|
||||||
*
|
|
||||||
* @author JavaSaBr
|
|
||||||
*/
|
|
||||||
public class UniformBufferObject extends BufferObject {
|
|
||||||
|
|
||||||
public UniformBufferObject(final int binding, final BufferObjectField... fields) {
|
|
||||||
super(binding, Layout.std140, fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniformBufferObject(final int id) {
|
|
||||||
super(id);
|
|
||||||
}
|
|
||||||
}
|
|
@ -31,9 +31,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.system;
|
package com.jme3.system;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
|
|
||||||
import com.jme3.light.LightList;
|
import com.jme3.light.LightList;
|
||||||
import com.jme3.material.RenderState;
|
import com.jme3.material.RenderState;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
@ -47,11 +44,13 @@ import com.jme3.scene.VertexBuffer;
|
|||||||
import com.jme3.shader.BufferObject;
|
import com.jme3.shader.BufferObject;
|
||||||
import com.jme3.shader.Shader;
|
import com.jme3.shader.Shader;
|
||||||
import com.jme3.shader.Shader.ShaderSource;
|
import com.jme3.shader.Shader.ShaderSource;
|
||||||
import com.jme3.shader.ShaderStorageBufferObject;
|
|
||||||
import com.jme3.texture.FrameBuffer;
|
import com.jme3.texture.FrameBuffer;
|
||||||
import com.jme3.texture.Image;
|
import com.jme3.texture.Image;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
public class NullRenderer implements Renderer {
|
public class NullRenderer implements Renderer {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user