mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 07:26:48 +01:00
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:
parent
bd00bdff97
commit
733ec60216
4 changed files with 137 additions and 50 deletions
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue