From 54e39870227bea6e066afd8e364fe4195a22df0b Mon Sep 17 00:00:00 2001 From: javasabr Date: Sun, 11 Feb 2018 14:56:07 +0300 Subject: [PATCH] updated API of BO. --- .../main/java/com/jme3/material/Material.java | 24 ++-- .../main/java/com/jme3/renderer/Renderer.java | 2 - .../com/jme3/renderer/opengl/GLRenderer.java | 65 ++++++---- .../java/com/jme3/shader/BufferObject.java | 121 ++++++++++++++---- .../shader/ShaderStorageBufferObject.java | 21 --- .../com/jme3/shader/UniformBufferObject.java | 17 --- .../java/com/jme3/system/NullRenderer.java | 7 +- 7 files changed, 153 insertions(+), 104 deletions(-) delete mode 100644 jme3-core/src/main/java/com/jme3/shader/ShaderStorageBufferObject.java delete mode 100644 jme3-core/src/main/java/com/jme3/shader/UniformBufferObject.java diff --git a/jme3-core/src/main/java/com/jme3/material/Material.java b/jme3-core/src/main/java/com/jme3/material/Material.java index c6279240a..115f31626 100644 --- a/jme3-core/src/main/java/com/jme3/material/Material.java +++ b/jme3-core/src/main/java/com/jme3/material/Material.java @@ -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 value the buffer object. */ - public void setBufferObject(final String name, final BufferObject value) { - if (value instanceof UniformBufferObject) { - setParam(name, VarType.UniformBufferObject, value); - } else if (value instanceof ShaderStorageBufferObject) { - setParam(name, VarType.ShaderStorageBufferObject, value); - } else { - throw new IllegalArgumentException("Not expected value " + value); - } + public void setUniformBufferObject(final String name, final BufferObject value) { + value.setBufferType(BufferObject.BufferType.UniformBufferObject); + setParam(name, VarType.UniformBufferObject, 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); } /** diff --git a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java index 88dcb8456..201729da8 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java @@ -38,8 +38,6 @@ import com.jme3.scene.VertexBuffer; import com.jme3.shader.BufferObject; import com.jme3.shader.Shader; import com.jme3.shader.Shader.ShaderSource; -import com.jme3.shader.ShaderStorageBufferObject; -import com.jme3.shader.UniformBufferObject; import com.jme3.system.AppSettings; import com.jme3.texture.FrameBuffer; import com.jme3.texture.Image; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 266cea2ea..345ec9e95 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -1229,15 +1229,24 @@ public final class GLRenderer implements Renderer { bindProgram(shader); final int shaderId = shader.getId(); + final BufferObject.BufferType bufferType = bufferObject.getBufferType(); - if (bufferObject instanceof 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()); - } else if (bufferObject instanceof UniformBufferObject) { - final int blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName()); - gl3.glBindBufferBase(GL3.GL_UNIFORM_BUFFER, bufferObject.getBinding(), bufferObject.getId()); - gl3.glUniformBlockBinding(GL3.GL_UNIFORM_BUFFER, blockIndex, bufferObject.getBinding()); + switch (bufferType) { + case UniformBufferObject: { + final int blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName()); + gl3.glBindBufferBase(GL3.GL_UNIFORM_BUFFER, bufferObject.getBinding(), bufferObject.getId()); + 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(); @@ -2577,16 +2586,10 @@ public final class GLRenderer implements Renderer { int maxSize = Integer.MAX_VALUE; - if (bo instanceof UniformBufferObject) { - if (!caps.contains(Caps.UniformBufferObject)) { - throw new IllegalArgumentException("The current video hardware doesn't support UBO."); - } - } 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 BufferObject.BufferType bufferType = bo.getBufferType(); + + if (!caps.contains(bufferType.getRequiredCaps())) { + throw new IllegalArgumentException("The current video hardware doesn't support " + bufferType); } final ByteBuffer data = bo.computeData(maxSize); @@ -2609,14 +2612,22 @@ public final class GLRenderer implements Renderer { data.rewind(); - if (bo instanceof UniformBufferObject) { - gl3.glBindBuffer(GL3.GL_UNIFORM_BUFFER, bufferId); - gl3.glBufferData(GL4.GL_UNIFORM_BUFFER, data, GL3.GL_DYNAMIC_DRAW); - gl3.glBindBuffer(GL4.GL_UNIFORM_BUFFER, 0); - } else { - gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, bufferId); - gl4.glBufferData(GL4.GL_SHADER_STORAGE_BUFFER, data, GL4.GL_DYNAMIC_COPY); - gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, 0); + switch (bufferType) { + case UniformBufferObject: { + gl3.glBindBuffer(GL3.GL_UNIFORM_BUFFER, bufferId); + gl3.glBufferData(GL4.GL_UNIFORM_BUFFER, data, GL3.GL_DYNAMIC_DRAW); + gl3.glBindBuffer(GL4.GL_UNIFORM_BUFFER, 0); + break; + } + case ShaderStorageBufferObject: { + gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, bufferId); + gl4.glBufferData(GL4.GL_SHADER_STORAGE_BUFFER, data, GL4.GL_DYNAMIC_COPY); + gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, 0); + break; + } + default: { + throw new IllegalArgumentException("Doesn't support binding of " + bufferType); + } } bo.clearUpdateNeeded(); @@ -2644,7 +2655,7 @@ public final class GLRenderer implements Renderer { } intBuf1.clear(); - intBuf1.put(0, bufferId); + intBuf1.put(bufferId); intBuf1.flip(); gl.glDeleteBuffers(intBuf1); diff --git a/jme3-core/src/main/java/com/jme3/shader/BufferObject.java b/jme3-core/src/main/java/com/jme3/shader/BufferObject.java index 88a14e16e..ebd5963ac 100644 --- a/jme3-core/src/main/java/com/jme3/shader/BufferObject.java +++ b/jme3-core/src/main/java/com/jme3/shader/BufferObject.java @@ -1,6 +1,7 @@ package com.jme3.shader; import com.jme3.math.*; +import com.jme3.renderer.Caps; import com.jme3.renderer.Renderer; import com.jme3.util.BufferUtils; import com.jme3.util.NativeObject; @@ -23,11 +24,37 @@ public class BufferObject extends NativeObject { 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. */ private final Map fields; + /** + * The field's array. + */ + private final BufferObjectField[] fieldArray; + /** * The buffer's data layout. */ @@ -38,19 +65,38 @@ public class BufferObject extends NativeObject { */ private final int binding; + /** + * The buffer's type. + */ + private BufferType bufferType; + /** * The previous data buffer. */ 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.bufferType = bufferType; this.binding = binding; this.layout = layout; this.fields = new LinkedHashMap<>(fields.length); for (final BufferObjectField field : fields) { 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) { @@ -58,6 +104,30 @@ public class BufferObject extends NativeObject { this.binding = -2; this.fields = 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,31 +189,34 @@ public class BufferObject extends NativeObject { int estimateSize = 0; - for (final Map.Entry entry : fields.entrySet()) { - final BufferObjectField field = entry.getValue(); + for (final BufferObjectField field : fieldArray) { estimateSize += estimateSize(field); } if(maxSize < estimateSize) { throw new IllegalStateException("The estimated size(" + estimateSize + ") of this BO is bigger than " + - "maximum available size " + maxSize); + "maximum available size " + maxSize); } if (previousData != null) { if (previousData.capacity() < estimateSize) { BufferUtils.destroyDirectBuffer(previousData); 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 entry : fields.entrySet()) { - writeField(entry.getValue(), data); + for (final BufferObjectField field : fieldArray) { + writeField(field, data); } data.flip(); + this.previousData = data; + return data; } @@ -510,25 +583,25 @@ public class BufferObject extends NativeObject { final Vector4f vec4 = (Vector4f) value; data.putFloat(vec4.getX()) - .putFloat(vec4.getY()) - .putFloat(vec4.getZ()) - .putFloat(vec4.getW()); + .putFloat(vec4.getY()) + .putFloat(vec4.getZ()) + .putFloat(vec4.getW()); } else if(value instanceof Quaternion) { final Quaternion vec4 = (Quaternion) value; data.putFloat(vec4.getX()) - .putFloat(vec4.getY()) - .putFloat(vec4.getZ()) - .putFloat(vec4.getW()); + .putFloat(vec4.getY()) + .putFloat(vec4.getZ()) + .putFloat(vec4.getW()); } else if(value instanceof ColorRGBA) { final ColorRGBA vec4 = (ColorRGBA) value; data.putFloat(vec4.getRed()) - .putFloat(vec4.getGreen()) - .putFloat(vec4.getBlue()) - .putFloat(vec4.getAlpha()); + .putFloat(vec4.getGreen()) + .putFloat(vec4.getBlue()) + .putFloat(vec4.getAlpha()); } } @@ -541,8 +614,8 @@ public class BufferObject extends NativeObject { protected void write(final ByteBuffer data, final Vector3f value) { data.putFloat(value.getX()) - .putFloat(value.getY()) - .putFloat(value.getZ()); + .putFloat(value.getY()) + .putFloat(value.getZ()); if (layout == Layout.std140) { data.putInt(0); @@ -560,8 +633,8 @@ public class BufferObject extends NativeObject { protected void write(final ByteBuffer data, final float x, final float y, final float z) { data.putFloat(x) - .putFloat(y) - .putFloat(z); + .putFloat(y) + .putFloat(z); if (layout == Layout.std140) { data.putInt(0); @@ -579,9 +652,9 @@ public class BufferObject extends NativeObject { */ protected void write(final ByteBuffer data, final float x, final float y, final float z, final float w) { data.putFloat(x) - .putFloat(y) - .putFloat(z) - .putFloat(w); + .putFloat(y) + .putFloat(z) + .putFloat(w); } /** @@ -592,7 +665,7 @@ public class BufferObject extends NativeObject { */ protected void write(final ByteBuffer data, final Vector2f value) { data.putFloat(value.getX()) - .putFloat(value.getY()); + .putFloat(value.getY()); } /** diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderStorageBufferObject.java b/jme3-core/src/main/java/com/jme3/shader/ShaderStorageBufferObject.java deleted file mode 100644 index ebe8a59e4..000000000 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderStorageBufferObject.java +++ /dev/null @@ -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); - } -} diff --git a/jme3-core/src/main/java/com/jme3/shader/UniformBufferObject.java b/jme3-core/src/main/java/com/jme3/shader/UniformBufferObject.java deleted file mode 100644 index 5ae54650c..000000000 --- a/jme3-core/src/main/java/com/jme3/shader/UniformBufferObject.java +++ /dev/null @@ -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); - } -} diff --git a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java index 63c3735eb..3c289ecc3 100644 --- a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java +++ b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java @@ -31,9 +31,6 @@ */ package com.jme3.system; -import java.nio.ByteBuffer; -import java.util.EnumSet; - import com.jme3.light.LightList; import com.jme3.material.RenderState; import com.jme3.math.ColorRGBA; @@ -47,11 +44,13 @@ import com.jme3.scene.VertexBuffer; import com.jme3.shader.BufferObject; import com.jme3.shader.Shader; import com.jme3.shader.Shader.ShaderSource; -import com.jme3.shader.ShaderStorageBufferObject; import com.jme3.texture.FrameBuffer; import com.jme3.texture.Image; import com.jme3.texture.Texture; + +import java.nio.ByteBuffer; import java.util.EnumMap; +import java.util.EnumSet; public class NullRenderer implements Renderer {