diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/component/IndirectComponent.java b/src/main/java/com/jozufozu/flywheel/backend/compile/component/IndirectComponent.java index ca02a78b8..067f75377 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/component/IndirectComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/component/IndirectComponent.java @@ -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 layoutItems; - public IndirectComponent(List 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 diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/LayoutAttributes.java b/src/main/java/com/jozufozu/flywheel/backend/engine/LayoutAttributes.java new file mode 100644 index 000000000..291ca2d27 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/LayoutAttributes.java @@ -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 attributes(Layout layout) { + List 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 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 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; + }; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java index 371bb3b82..79c58c20d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java @@ -58,8 +58,8 @@ public class IndirectCullingGroup { 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); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java index 2b3dbb543..1e305ed97 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java @@ -20,9 +20,8 @@ public class IndirectInstancer extends AbstractInstancer public IndirectInstancer(InstanceType 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(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java index 998561485..7139e4c91 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java @@ -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 extends AbstractInstancer { - private final BufferLayout instanceFormat; + private final List instanceAttributes; private final int instanceStride; private final Set boundTo = new HashSet<>(); @@ -28,13 +29,14 @@ public class InstancedInstancer extends AbstractInstancer public InstancedInstancer(InstanceType 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 extends AbstractInstancer 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