ソースを参照

added limits, caps, working with buffer objects in renderer.

JavaSaBr 7 年 前
コミット
b342b1ede1

+ 27 - 0
jme3-core/src/main/java/com/jme3/material/Material.java

@@ -409,6 +409,17 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
         return paramValues.get(name);
     }
 
+    /**
+     * Returns the current parameter's value.
+     *
+     * @param name the parameter name to look up.
+     * @return current value or null if the parameter wasn't set.
+     */
+    public <T> T getParamValue(final String name) {
+        final MatParam param = paramValues.get(name);
+        return param == null ? null : (T) param.getValue();
+    }
+
     /**
      * Returns the texture parameter set on this material with the given name,
      * returns <code>null</code> if the parameter is not set.
@@ -657,6 +668,22 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
         setParam(name, VarType.Vector4, value);
     }
 
+    /**
+     * Pass a 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);
+        }
+    }
+
     /**
      * Pass a Vector2f to the material shader.
      *

+ 4 - 0
jme3-core/src/main/java/com/jme3/renderer/Caps.java

@@ -395,6 +395,10 @@ public enum Caps {
      * GPU can provide and accept binary shaders.
      */
     BinaryShader,
+    /**
+     * Supporting working with UniformBufferObject.
+     */
+    UniformBufferObject,
     /**
      * Supporting working with ShaderStorageBufferObjects.
      */

+ 16 - 0
jme3-core/src/main/java/com/jme3/renderer/Limits.java

@@ -62,4 +62,20 @@ public enum Limits {
     ColorTextureSamples,
     DepthTextureSamples,
     TextureAnisotropy,
+
+    // UBO
+    UniformBufferObjectMaxVertexBlocks,
+    UniformBufferObjectMaxFragmentBlocks,
+    UniformBufferObjectMaxGeometryBlocks,
+    UniformBufferObjectMaxBlockSize,
+
+    // SSBO
+    ShaderStorageBufferObjectMaxBlockSize,
+    ShaderStorageBufferObjectMaxVertexBlocks,
+    ShaderStorageBufferObjectMaxFragmentBlocks,
+    ShaderStorageBufferObjectMaxGeometryBlocks,
+    ShaderStorageBufferObjectMaxTessControlBlocks,
+    ShaderStorageBufferObjectMaxTessEvaluationBlocks,
+    ShaderStorageBufferObjectMaxComputeBlocks,
+    ShaderStorageBufferObjectMaxCombineBlocks,
 }

+ 8 - 7
jme3-core/src/main/java/com/jme3/renderer/Renderer.java

@@ -39,6 +39,7 @@ 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;
@@ -277,17 +278,17 @@ public interface Renderer {
     public void updateBufferData(ShaderStorageBufferObject ssbo);
 
     /**
-     * Deletes a vertex buffer from the GPU.
-     * @param vb The vertex buffer to delete
+     * Uploads data of the buffer object on the GPU.
+     *
+     * @param bo the buffer object to upload.
      */
-    public void deleteBuffer(VertexBuffer vb);
+    public void updateBufferData(BufferObject bo);
 
     /**
-     * Deletes a shader storage buffer object from the GPU.
-     *
-     * @param ssbo the shader storage buffer object to delete.
+     * Deletes a vertex buffer from the GPU.
+     * @param vb The vertex buffer to delete
      */
-    public void deleteBuffer(ShaderStorageBufferObject ssbo);
+    public void deleteBuffer(VertexBuffer vb);
 
     /**
      * Deletes the buffer object from the GPU.

+ 15 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java

@@ -102,6 +102,21 @@ public interface GL3 extends GL2 {
     public static final int GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER = 0x8A45;
     public static final int GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8A46;
 
+    /**
+     *  Accepted by the &lt;pname&gt; parameter of GetBooleanv, GetIntegerv,
+     *  GetFloatv, and GetDoublev:
+     */
+    public static final int GL_MAX_VERTEX_UNIFORM_BLOCKS = 0x8A2B;
+    public static final int GL_MAX_GEOMETRY_UNIFORM_BLOCKS = 0x8A2C;
+    public static final int GL_MAX_FRAGMENT_UNIFORM_BLOCKS = 0x8A2D;
+    public static final int GL_MAX_COMBINED_UNIFORM_BLOCKS = 0x8A2E;
+    public static final int GL_MAX_UNIFORM_BUFFER_BINDINGS = 0x8A2F;
+    public static final int GL_MAX_UNIFORM_BLOCK_SIZE = 0x8A30;
+    public static final int GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = 0x8A31;
+    public static final int GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS = 0x8A32;
+    public static final int GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = 0x8A33;
+    public static final int GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 0x8A34;
+
     /**
      * Accepted by the {@code target} parameters of BindBuffer, BufferData, BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, GetBufferPointerv,
      * BindBufferRange, BindBufferOffset and BindBufferBase.

+ 14 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java

@@ -52,7 +52,21 @@ 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 &lt;pname&gt; parameter of GetIntegerv, GetBooleanv,
+     *  GetInteger64v, GetFloatv, and GetDoublev:
+     */
+    public static final int GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS = 0x90D6;
+    public static final int GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS = 0x90D7;
+    public static final int GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS = 0x90D8;
+    public static final int GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS = 0x90D9;
+    public static final int GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS = 0x90DA;
+    public static final int GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS = 0x90DB;
+    public static final int GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS = 0x90DC;
     public static final int GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS = 0x90DD;
+    public static final int GL_MAX_SHADER_STORAGE_BLOCK_SIZE = 0x90DE;
+    public static final int GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT = 0x90DF;
 
     /**
      * <p><a target="_blank" href="http://docs.gl/gl4/glPatchParameteri">Reference Page</a></p>

+ 47 - 21
jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java

@@ -480,6 +480,22 @@ public final class GLRenderer implements Renderer {
 
         if (hasExtension("GL_ARB_shader_storage_buffer_object")) {
             caps.add(Caps.ShaderStorageBufferObject);
+            limits.put(Limits.ShaderStorageBufferObjectMaxBlockSize, getInteger(GL4.GL_MAX_SHADER_STORAGE_BLOCK_SIZE));
+            limits.put(Limits.ShaderStorageBufferObjectMaxComputeBlocks, getInteger(GL4.GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS));
+            limits.put(Limits.ShaderStorageBufferObjectMaxGeometryBlocks, getInteger(GL4.GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS));
+            limits.put(Limits.ShaderStorageBufferObjectMaxFragmentBlocks, getInteger(GL4.GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS));
+            limits.put(Limits.ShaderStorageBufferObjectMaxVertexBlocks, getInteger(GL4.GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS));
+            limits.put(Limits.ShaderStorageBufferObjectMaxTessControlBlocks, getInteger(GL4.GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS));
+            limits.put(Limits.ShaderStorageBufferObjectMaxTessEvaluationBlocks, getInteger(GL4.GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS));
+            limits.put(Limits.ShaderStorageBufferObjectMaxCombineBlocks, getInteger(GL4.GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS));
+        }
+
+        if (hasExtension("GL_ARB_uniform_buffer_object")) {
+            caps.add(Caps.UniformBufferObject);
+            limits.put(Limits.UniformBufferObjectMaxBlockSize, getInteger(GL3.GL_MAX_UNIFORM_BLOCK_SIZE));
+            limits.put(Limits.UniformBufferObjectMaxGeometryBlocks, getInteger(GL3.GL_MAX_GEOMETRY_UNIFORM_BLOCKS));
+            limits.put(Limits.UniformBufferObjectMaxFragmentBlocks, getInteger(GL3.GL_MAX_FRAGMENT_UNIFORM_BLOCKS));
+            limits.put(Limits.UniformBufferObjectMaxVertexBlocks, getInteger(GL3.GL_MAX_VERTEX_UNIFORM_BLOCKS));
         }
 
         // Print context information
@@ -2550,18 +2566,28 @@ public final class GLRenderer implements Renderer {
     }
 
     @Override
-    public void updateBufferData(final ShaderStorageBufferObject ssbo) {
+    public void updateBufferData(final BufferObject bo) {
+
+        int maxSize = Integer.MAX_VALUE;
 
-        if (!caps.contains(Caps.ShaderStorageBufferObject)) {
-            throw new IllegalArgumentException("The current video hardware doesn't support SSBO.");
+        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 ByteBuffer data = ssbo.getData();
+        final ByteBuffer data = bo.computeData(maxSize);
         if (data == null) {
-            throw new IllegalArgumentException("Can't upload SSBO without data.");
+            throw new IllegalArgumentException("Can't upload BO without data.");
         }
 
-        int bufferId = ssbo.getId();
+        int bufferId = bo.getId();
         if (bufferId == -1) {
 
             // create buffer
@@ -2569,19 +2595,24 @@ public final class GLRenderer implements Renderer {
             gl.glGenBuffers(intBuf1);
             bufferId = intBuf1.get(0);
 
-            ssbo.setId(bufferId);
+            bo.setId(bufferId);
 
-            objManager.registerObject(ssbo);
+            objManager.registerObject(bo);
         }
 
-        gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, bufferId);
-
         data.rewind();
 
-        gl4.glBufferData(GL4.GL_SHADER_STORAGE_BUFFER, data, GL4.GL_DYNAMIC_COPY);
-        gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, 0);
+        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);
+        }
 
-        ssbo.clearUpdateNeeded();
+        bo.clearUpdateNeeded();
     }
 
     public void deleteBuffer(VertexBuffer vb) {
@@ -2598,9 +2629,9 @@ public final class GLRenderer implements Renderer {
     }
 
     @Override
-    public void deleteBuffer(final ShaderStorageBufferObject ssbo) {
+    public void deleteBuffer(final BufferObject bo) {
 
-        int bufferId = ssbo.getId();
+        int bufferId = bo.getId();
         if (bufferId == -1) {
             return;
         }
@@ -2611,12 +2642,7 @@ public final class GLRenderer implements Renderer {
 
         gl.glDeleteBuffers(intBuf1);
 
-        ssbo.resetObject();
-    }
-
-    @Override
-    public void deleteBuffer(BufferObject bo) {
-        //TODO
+        bo.resetObject();
     }
 
     public void clearVertexAttribs() {

+ 9 - 9
jme3-core/src/main/java/com/jme3/shader/BufferObject.java

@@ -40,7 +40,7 @@ public class BufferObject extends NativeObject {
     /**
      * The previous data buffer.
      */
-    private ByteBuffer previosData;
+    private ByteBuffer previousData;
 
     public BufferObject(final int binding, final Layout layout, final BufferObjectField... fields) {
         this.handleRef = new Object();
@@ -128,14 +128,14 @@ public class BufferObject extends NativeObject {
                 "maximum available size " + maxSize);
         }
 
-        if (previosData != null) {
-            if (previosData.capacity() < estimateSize) {
-                BufferUtils.destroyDirectBuffer(previosData);
-                previosData = null;
+        if (previousData != null) {
+            if (previousData.capacity() < estimateSize) {
+                BufferUtils.destroyDirectBuffer(previousData);
+                previousData = null;
             }
         }
 
-        final ByteBuffer data = previosData == null ? BufferUtils.createByteBuffer((int) (estimateSize * 1.1F)) : previosData;
+        final ByteBuffer data = previousData == null ? BufferUtils.createByteBuffer((int) (estimateSize * 1.1F)) : previousData;
 
         for (final Map.Entry<String, BufferObjectField> entry : fields.entrySet()) {
             writeField(entry.getValue(), data);
@@ -481,9 +481,9 @@ public class BufferObject extends NativeObject {
     @Override
     protected void deleteNativeBuffers() {
         super.deleteNativeBuffers();
-        if (previosData != null) {
-            BufferUtils.destroyDirectBuffer(previosData);
-            previosData = null;
+        if (previousData != null) {
+            BufferUtils.destroyDirectBuffer(previousData);
+            previousData = null;
         }
     }
 

+ 3 - 130
jme3-core/src/main/java/com/jme3/shader/ShaderStorageBufferObject.java

@@ -1,144 +1,17 @@
 package com.jme3.shader;
 
-import com.jme3.renderer.Renderer;
-import com.jme3.util.BufferUtils;
-import com.jme3.util.NativeObject;
-
-import java.nio.ByteBuffer;
-
 /**
  * The implementation of SSBO.
  *
  * @author JavaSaBr
  */
-public class ShaderStorageBufferObject extends NativeObject {
-
-    /**
-     * The buffer's data.
-     */
-    private ByteBuffer data;
+public class ShaderStorageBufferObject extends BufferObject {
 
-    /**
-     * The binding number.
-     */
-    private int binding;
-
-    public ShaderStorageBufferObject() {
-        this.handleRef = new Object();
-        this.binding = 1;
+    public ShaderStorageBufferObject(final int binding, final Layout layout, final BufferObjectField... fields) {
+        super(binding, layout, fields);
     }
 
     public ShaderStorageBufferObject(final int id) {
         super(id);
     }
-
-    /**
-     * Set the binding number.
-     *
-     * @param binding the binding number.
-     */
-    public void setBinding(final int binding) {
-        this.binding = binding;
-    }
-
-    /**
-     * Get the binding number.
-     *
-     * @return the binding number.
-     */
-    public int getBinding() {
-        return binding;
-    }
-
-    /**
-     * Called to initialize the data in the {@link ShaderStorageBufferObject}. Must only
-     * be called once.
-     *
-     * @param data the native byte buffer.
-     */
-    public void setupData(final ByteBuffer data) {
-
-        if (id != -1) {
-            throw new UnsupportedOperationException("Data has already been sent. Cannot setupData again.");
-        } else if (data.isReadOnly()) {
-            throw new IllegalArgumentException("VertexBuffer data cannot be read-only.");
-        }
-
-        this.data = data;
-
-        setUpdateNeeded();
-    }
-
-    /**
-     * Called to update the data in the buffer with new data. Can only
-     * be called after {@link #setupData(java.nio.ByteBuffer) }
-     * has been called. Note that it is fine to call this method on the
-     * data already set, e.g. ssbo.updateData(ssbo.getData()), this will just
-     * set the proper update flag indicating the data should be sent to the GPU
-     * again.
-     * <p>
-     * It is allowed to specify a buffer with different capacity than the
-     * originally set buffer.
-     *
-     * @param data the native data buffer to set.
-     */
-    public void updateData(final ByteBuffer data) {
-
-        if (data == null) {
-            throw new IllegalArgumentException("SSBO can't be without data buffer.");
-        }
-
-        // Check if the data buffer is read-only which is a sign
-        // of a bug on the part of the caller
-        if (data.isReadOnly()) {
-            throw new IllegalArgumentException("SSBO's data cannot be read-only.");
-        }
-
-        this.data = data;
-
-        setUpdateNeeded();
-    }
-
-    /**
-     * Get the buffer's data.
-     *
-     * @return the buffer's data.
-     */
-    public ByteBuffer getData() {
-        return data;
-    }
-
-    @Override
-    public void resetObject() {
-        this.id = -1;
-        setUpdateNeeded();
-    }
-
-    @Override
-    public void deleteObject(final Object rendererObject) {
-
-        if (!(rendererObject instanceof Renderer)) {
-            throw new IllegalArgumentException("This ssbo can't be deleted from " + rendererObject);
-        }
-
-        ((Renderer) rendererObject).deleteBuffer(this);
-    }
-
-    @Override
-    protected void deleteNativeBuffers() {
-        super.deleteNativeBuffers();
-        if (data != null) {
-            BufferUtils.destroyDirectBuffer(data);
-        }
-    }
-
-    @Override
-    public NativeObject createDestructableClone() {
-        return new ShaderStorageBufferObject(id);
-    }
-
-    @Override
-    public long getUniqueId() {
-        return ((long) OBJTYPE_SSBO << 32) | ((long) id);
-    }
 }

+ 17 - 0
jme3-core/src/main/java/com/jme3/shader/UniformBufferObject.java

@@ -0,0 +1,17 @@
+package com.jme3.shader;
+
+/**
+ * The implementation of UBO.
+ *
+ * @author JavaSaBr
+ */
+public class UniformBufferObject extends BufferObject {
+
+    public UniformBufferObject(final int binding, final Layout layout, final BufferObjectField... fields) {
+        super(binding, layout, fields);
+    }
+
+    public UniformBufferObject(final int id) {
+        super(id);
+    }
+}

+ 1 - 0
jme3-core/src/main/java/com/jme3/shader/VarType.java

@@ -58,6 +58,7 @@ public enum VarType {
     TextureArray(false,true,"sampler2DArray|sampler2DArrayShadow"),
     TextureCubeMap(false,true,"samplerCube"),
     Int("int"),
+    UniformBufferObject(false, false, "dynamic"),
     ShaderStorageBufferObject(false, false, "dynamic");
 
     private boolean usesMultiData = false;