A tribute from layouts

- Add utility to convert a Layout to a list of VertexAttributes.
This commit is contained in:
Jozufozu 2024-01-04 22:31:36 -08:00
parent 0b59067701
commit bd00bdff97
5 changed files with 116 additions and 14 deletions

View file

@ -6,6 +6,7 @@ import java.util.List;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.instance.InstanceType;
import com.jozufozu.flywheel.api.layout.Layout;
import com.jozufozu.flywheel.backend.compile.Pipeline;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
@ -23,10 +24,12 @@ public class IndirectComponent implements SourceComponent {
private static final String PACKED_STRUCT_NAME = "FlwPackedInstance";
private static final String UNPACK_FN_NAME = "_flw_unpackInstance";
private final Layout layout;
private final List<LayoutItem> layoutItems;
public IndirectComponent(List<LayoutItem> layoutItems) {
this.layoutItems = layoutItems;
public IndirectComponent(InstanceType<?> type) {
this.layoutItems = type.oldLayout().layoutItems;
this.layout = type.layout();
}
public static IndirectComponent create(Pipeline.InstanceAssemblerContext ctx) {
@ -34,7 +37,7 @@ public class IndirectComponent implements SourceComponent {
}
public static IndirectComponent create(InstanceType<?> instanceType) {
return new IndirectComponent(instanceType.oldLayout().layoutItems);
return new IndirectComponent(instanceType);
}
@Override

View file

@ -0,0 +1,98 @@
package com.jozufozu.flywheel.backend.engine;
import java.util.ArrayList;
import java.util.List;
import com.jozufozu.flywheel.api.layout.FloatRepr;
import com.jozufozu.flywheel.api.layout.IntegerRepr;
import com.jozufozu.flywheel.api.layout.Layout;
import com.jozufozu.flywheel.api.layout.MatrixElementType;
import com.jozufozu.flywheel.api.layout.ScalarElementType;
import com.jozufozu.flywheel.api.layout.UnsignedIntegerRepr;
import com.jozufozu.flywheel.api.layout.ValueRepr;
import com.jozufozu.flywheel.api.layout.VectorElementType;
import com.jozufozu.flywheel.gl.GlNumericType;
import com.jozufozu.flywheel.gl.array.VertexAttribute;
public class LayoutAttributes {
/**
* Collects the vertex attributes required from the given layout.
*
* @param layout The abstract layout definition.
* @return A concrete list of vertex attributes.
*/
public static List<VertexAttribute> attributes(Layout layout) {
List<VertexAttribute> out = new ArrayList<>();
for (Layout.Element element : layout.elements()) {
var type = element.type();
if (type instanceof ScalarElementType scalar) {
vector(out, scalar.repr(), 1);
} else if (type instanceof VectorElementType vector) {
vector(out, vector.repr(), vector.size());
} else if (type instanceof MatrixElementType matrix) {
matrix(out, matrix);
}
}
return out;
}
private static void matrix(List<VertexAttribute> out, MatrixElementType matrix) {
int size = matrix.columns();
var repr = matrix.repr();
var glType = toGlType(repr);
boolean normalized = normalized(repr);
for (int i = 0; i < matrix.rows(); i++) {
out.add(new VertexAttribute.Float(glType, size, normalized));
}
}
private static void vector(List<VertexAttribute> out, ValueRepr repr, int size) {
if (repr instanceof IntegerRepr integer) {
out.add(new VertexAttribute.Int(toGlType(integer), size));
} else if (repr instanceof UnsignedIntegerRepr integer) {
out.add(new VertexAttribute.Int(toGlType(integer), size));
} else if (repr instanceof FloatRepr floatRepr) {
out.add(new VertexAttribute.Float(toGlType(floatRepr), size, normalized(floatRepr)));
}
}
private static GlNumericType toGlType(IntegerRepr repr) {
return switch (repr) {
case BYTE -> GlNumericType.BYTE;
case SHORT -> GlNumericType.SHORT;
case INT -> GlNumericType.INT;
};
}
private static GlNumericType toGlType(UnsignedIntegerRepr repr) {
return switch (repr) {
case UNSIGNED_BYTE -> GlNumericType.UBYTE;
case UNSIGNED_SHORT -> GlNumericType.USHORT;
case UNSIGNED_INT -> GlNumericType.UINT;
};
}
private static GlNumericType toGlType(FloatRepr repr) {
return switch (repr) {
case BYTE, NORMALIZED_BYTE -> GlNumericType.BYTE;
case UNSIGNED_BYTE, NORMALIZED_UNSIGNED_BYTE -> GlNumericType.UBYTE;
case SHORT, NORMALIZED_SHORT -> GlNumericType.SHORT;
case UNSIGNED_SHORT, NORMALIZED_UNSIGNED_SHORT -> GlNumericType.USHORT;
case INT, NORMALIZED_INT -> GlNumericType.INT;
case UNSIGNED_INT, NORMALIZED_UNSIGNED_INT -> GlNumericType.UINT;
case FLOAT -> GlNumericType.FLOAT;
};
}
private static boolean normalized(FloatRepr repr) {
return switch (repr) {
case NORMALIZED_BYTE, NORMALIZED_UNSIGNED_BYTE, NORMALIZED_SHORT, NORMALIZED_UNSIGNED_SHORT, NORMALIZED_INT, NORMALIZED_UNSIGNED_INT ->
true;
default -> false;
};
}
}

View file

@ -58,8 +58,8 @@ public class IndirectCullingGroup<I extends Instance> {
applyProgram = programs.getApplyProgram();
drawProgram = programs.getIndirectProgram(instanceType, Contexts.DEFAULT);
objectStride = instanceType.oldLayout()
.getStride() + IndirectBuffers.INT_SIZE;
objectStride = instanceType.layout()
.byteSize() + IndirectBuffers.INT_SIZE;
buffers = new IndirectBuffers(objectStride);

View file

@ -20,9 +20,8 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
public IndirectInstancer(InstanceType<I> type) {
super(type);
long instanceStride = type.oldLayout()
.getStride();
this.objectStride = instanceStride + IndirectBuffers.INT_SIZE;
this.objectStride = type.layout()
.byteSize() + IndirectBuffers.INT_SIZE;
writer = this.type.writer();
}

View file

@ -10,14 +10,15 @@ import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.InstanceType;
import com.jozufozu.flywheel.api.instance.InstanceWriter;
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
import com.jozufozu.flywheel.backend.engine.LayoutAttributes;
import com.jozufozu.flywheel.gl.array.GlVertexArray;
import com.jozufozu.flywheel.gl.array.VertexAttribute;
import com.jozufozu.flywheel.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferUsage;
import com.jozufozu.flywheel.gl.buffer.MappedBuffer;
import com.jozufozu.flywheel.lib.layout.BufferLayout;
public class InstancedInstancer<I extends Instance> extends AbstractInstancer<I> {
private final BufferLayout instanceFormat;
private final List<VertexAttribute> instanceAttributes;
private final int instanceStride;
private final Set<GlVertexArray> boundTo = new HashSet<>();
@ -28,13 +29,14 @@ public class InstancedInstancer<I extends Instance> extends AbstractInstancer<I>
public InstancedInstancer(InstanceType<I> type) {
super(type);
instanceFormat = type.oldLayout();
instanceStride = instanceFormat.getStride();
var layout = type.layout();
instanceAttributes = LayoutAttributes.attributes(layout);
instanceStride = layout.byteSize();
writer = type.writer();
}
public int getAttributeCount() {
return instanceFormat.getAttributeCount();
return instanceAttributes.size();
}
public boolean isInvalid() {
@ -114,7 +116,7 @@ public class InstancedInstancer<I extends Instance> extends AbstractInstancer<I>
long offset = (long) baseInstance * instanceStride;
vao.bindVertexBuffer(1, vbo.handle(), offset, instanceStride);
vao.setBindingDivisor(1, 1);
vao.bindAttributes(1, startAttrib, instanceFormat.attributes());
vao.bindAttributes(1, startAttrib, instanceAttributes);
}
@Override