|
|
@ -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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|