|
@@ -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<String, BufferObjectField> 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<String, BufferObjectField> 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<String, BufferObjectField> 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());
|
|
|
}
|
|
|
|
|
|
/**
|