Instancing with Layouts

- InstancedArraysComponent now fully uses Layouts.
  - Trivial to get the glsl type name of a given Element.
  - Also quite easy to get the attribute count without actually
    creating the attribute list.
- IndirectComponent is WIP because unpacking is hard.
  - Reorganize so all the unpacking stuff is in one loop.
This commit is contained in:
Jozufozu 2024-01-04 23:44:35 -08:00
parent bd00bdff97
commit 733ec60216
4 changed files with 137 additions and 50 deletions

View file

@ -0,0 +1,62 @@
package com.jozufozu.flywheel.backend.compile;
import com.jozufozu.flywheel.api.layout.ElementType;
import com.jozufozu.flywheel.api.layout.FloatRepr;
import com.jozufozu.flywheel.api.layout.IntegerRepr;
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;
public class LayoutInterpreter {
public static int attributeCount(ElementType type) {
if (type instanceof ScalarElementType) {
return 1;
} else if (type instanceof VectorElementType) {
return 1;
} else if (type instanceof MatrixElementType matrix) {
return matrix.rows();
}
throw new IllegalArgumentException("Unknown type " + type);
}
public static String typeName(ElementType type) {
if (type instanceof ScalarElementType scalar) {
return scalarTypeName(scalar.repr());
} else if (type instanceof VectorElementType vector) {
return vectorTypeName(vector.repr(), vector.size());
} else if (type instanceof MatrixElementType matrix) {
return matrixTypeName(matrix);
}
throw new IllegalArgumentException("Unknown type " + type);
}
public static String matrixTypeName(MatrixElementType matrix) {
return "mat" + matrix.columns() + "x" + matrix.rows();
}
public static String vectorTypeName(ValueRepr repr, int size) {
if (repr instanceof IntegerRepr) {
return "ivec" + size;
} else if (repr instanceof UnsignedIntegerRepr) {
return "uvec" + size;
} else if (repr instanceof FloatRepr) {
return "vec" + size;
}
throw new IllegalArgumentException("Unknown repr " + repr);
}
public static String scalarTypeName(ValueRepr repr) {
if (repr instanceof IntegerRepr) {
return "int";
} else if (repr instanceof UnsignedIntegerRepr) {
return "uint";
} else if (repr instanceof FloatRepr) {
return "float";
}
throw new IllegalArgumentException("Unknown repr " + repr);
}
}

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend.compile.component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -7,6 +8,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.LayoutInterpreter;
import com.jozufozu.flywheel.backend.compile.Pipeline;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
@ -58,44 +60,58 @@ public class IndirectComponent implements SourceComponent {
public String generateIndirect() {
var builder = new GlslBuilder();
layoutItems.stream()
.map(LayoutItem::type)
.distinct()
.forEach(type -> type.declare(builder));
generateHeader(builder);
var instance = builder.struct();
instance.setName(STRUCT_NAME);
builder.blankLine();
var packed = builder.struct();
packed.setName(PACKED_STRUCT_NAME);
for (var field : layoutItems) {
packed.addField(field.type()
.packedTypeName(), field.name());
instance.addField(field.type()
.typeName(), field.name());
}
generateInstanceStruct(builder);
builder.blankLine();
builder.function()
.signature(FnSignature.create()
.returnType(STRUCT_NAME)
.name(UNPACK_FN_NAME)
.arg(PACKED_STRUCT_NAME, UNPACK_ARG)
.build())
.body(this::generateUnpackingBody);
generateUnpacking(builder);
builder.blankLine();
return builder.build();
}
private void generateUnpackingBody(GlslBlock b) {
var unpackedFields = layoutItems.stream()
.map(layoutItem -> UNPACKING_VARIABLE.access(layoutItem.name())
.transform(layoutItem.type()::unpack))
.toList();
b.ret(GlslExpr.call(STRUCT_NAME, unpackedFields));
private void generateHeader(GlslBuilder builder) {
layoutItems.stream()
.map(LayoutItem::type)
.distinct()
.forEach(type -> type.declare(builder));
}
private void generateInstanceStruct(GlslBuilder builder) {
var instance = builder.struct();
instance.setName(STRUCT_NAME);
for (var element : layout.elements()) {
instance.addField(LayoutInterpreter.typeName(element.type()), element.name());
}
}
private void generateUnpacking(GlslBuilder builder) {
var packed = builder.struct();
packed.setName(PACKED_STRUCT_NAME);
var unpackArgs = new ArrayList<GlslExpr>();
for (LayoutItem field : layoutItems) {
GlslExpr unpack = UNPACKING_VARIABLE.access(field.name())
.transform(field.type()::unpack);
unpackArgs.add(unpack);
packed.addField(field.type()
.packedTypeName(), field.name());
}
var block = new GlslBlock();
block.ret(GlslExpr.call(STRUCT_NAME, unpackArgs));
builder.blankLine();
builder.function()
.signature(FnSignature.create()
.returnType(STRUCT_NAME)
.name(UNPACK_FN_NAME)
.arg(PACKED_STRUCT_NAME, UNPACK_ARG)
.build())
.body(block);
}
}

View file

@ -2,16 +2,16 @@ package com.jozufozu.flywheel.backend.compile.component;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.layout.Layout;
import com.jozufozu.flywheel.backend.compile.LayoutInterpreter;
import com.jozufozu.flywheel.backend.compile.Pipeline;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.layout.LayoutItem;
import net.minecraft.resources.ResourceLocation;
@ -20,12 +20,12 @@ public class InstancedArraysComponent implements SourceComponent {
private static final String STRUCT_NAME = "FlwInstance";
private static final String UNPACK_FN_NAME = "_flw_unpackInstance";
private final List<LayoutItem> layoutItems;
private final Layout layout;
private final int baseIndex;
public InstancedArraysComponent(Pipeline.InstanceAssemblerContext ctx) {
this.layoutItems = ctx.instanceType()
.oldLayout().layoutItems;
this.layout = ctx.instanceType()
.layout();
this.baseIndex = ctx.baseAttribute();
}
@ -43,26 +43,15 @@ public class InstancedArraysComponent implements SourceComponent {
public String source() {
var builder = new GlslBuilder();
int i = baseIndex;
for (var field : layoutItems) {
builder.vertexInput()
.binding(i)
.type(field.type()
.typeName())
.name(ATTRIBUTE_PREFIX + field.name());
i += field.type()
.attributeCount();
}
generateVertexInput(builder);
builder.blankLine();
var structBuilder = builder.struct();
structBuilder.setName(STRUCT_NAME);
for (var field : layoutItems) {
structBuilder.addField(field.type()
.typeName(), field.name());
for (var element : layout.elements()) {
structBuilder.addField(LayoutInterpreter.typeName(element.type()), element.name());
}
builder.blankLine();
@ -77,8 +66,23 @@ public class InstancedArraysComponent implements SourceComponent {
return builder.build();
}
private void generateVertexInput(GlslBuilder builder) {
int i = baseIndex;
for (var element : layout.elements()) {
var type = element.type();
builder.vertexInput()
.binding(i)
.type(LayoutInterpreter.typeName(type))
.name(ATTRIBUTE_PREFIX + element.name());
i += LayoutInterpreter.attributeCount(type);
}
}
private void generateUnpackingBody(GlslBlock b) {
var fields = layoutItems.stream()
var fields = layout.elements()
.stream()
.map(it -> new GlslExpr.Variable(ATTRIBUTE_PREFIX + it.name()))
.toList();
b.ret(GlslExpr.call(STRUCT_NAME, fields));

View file

@ -5,7 +5,7 @@ import java.util.function.Consumer;
import com.jozufozu.flywheel.lib.util.StringUtil;
public class GlslFn implements GlslBuilder.Declaration {
private final GlslBlock body = new GlslBlock();
private GlslBlock body = new GlslBlock();
private FnSignature signature;
public GlslFn signature(FnSignature signature) {
@ -18,6 +18,11 @@ public class GlslFn implements GlslBuilder.Declaration {
return this;
}
public GlslFn body(GlslBlock block) {
body = block;
return this;
}
public String prettyPrint() {
return """
%s {