Instant legacy code 2: electric boogaloo

- Hardcode generation of unpacking structures/functions.
- Remove SourceLoader arg from InstanceAssemblerContext
- Remove types.glsl, move BoundingSphere to indirect_draw_command.glsl
- Remove extra methods from LayoutItem
- Tweak nested error lines
This commit is contained in:
Jozufozu 2023-05-15 16:57:22 -07:00
parent 06063cdb4b
commit 96493e1571
21 changed files with 193 additions and 134 deletions

View file

@ -3,6 +3,7 @@ package com.jozufozu.flywheel.api.layout;
import java.util.function.Consumer;
import com.jozufozu.flywheel.gl.array.VertexAttribute;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
public interface InputType {
@ -16,4 +17,6 @@ public interface InputType {
int attributeCount();
GlslExpr unpack(GlslExpr packed);
void declare(GlslBuilder builder);
}

View file

@ -1,19 +1,5 @@
package com.jozufozu.flywheel.api.layout;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.glsl.generate.GlslStruct;
public record LayoutItem(InputType type, String name) {
public GlslExpr unpackField(GlslExpr.Variable struct) {
return struct.access(name())
.transform(type()::unpack);
}
public void addToStruct(GlslStruct glslStruct) {
glslStruct.addField(type().typeName(), name());
}
public void addPackedToStruct(GlslStruct packed) {
packed.addField(type().packedTypeName(), name());
}
}

View file

@ -35,11 +35,11 @@ public class CullingCompiler extends AbstractCompiler<InstanceType<?>> {
@Nullable
@Override
protected GlProgram compile(InstanceType<?> key) {
var instanceAssembly = IndirectComponent.create(sourceLoader, key);
var instanceAssembly = IndirectComponent.create(key);
ResourceLocation rl = key.instanceShader();
var instance = sourceLoader.find(rl);
if (instanceAssembly == null || instance == null || uniformComponent == null || pipelineCompute == null) {
if (instance == null || uniformComponent == null || pipelineCompute == null) {
return null;
}

View file

@ -18,8 +18,7 @@ public record Pipeline(GLSLVersion glslVersion, ResourceLocation vertexShader, R
SourceComponent assemble(InstanceAssemblerContext context);
}
public record InstanceAssemblerContext(SourceLoader sourceLoader, VertexType vertexType,
InstanceType<?> instanceType) {
public record InstanceAssemblerContext(VertexType vertexType, InstanceType<?> instanceType) {
}
public static Builder builder() {

View file

@ -105,7 +105,7 @@ public class PipelineCompiler extends AbstractCompiler<PipelineProgramKey> {
@Nullable
private List<SourceComponent> getVertexComponents(PipelineProgramKey key) {
var instanceAssembly = pipeline.assembler()
.assemble(new Pipeline.InstanceAssemblerContext(sourceLoader, key.vertexType(), key.instanceType()));
.assemble(new Pipeline.InstanceAssemblerContext(key.vertexType(), key.instanceType()));
var layout = sourceLoader.find(key.vertexType()
.layoutShader());

View file

@ -28,7 +28,5 @@ public final class Pipelines {
public static final ResourceLocation INSTANCED_ARRAYS_DRAW = Flywheel.rl("internal/instanced_arrays_draw.vert");
public static final ResourceLocation INDIRECT_DRAW = Flywheel.rl("internal/indirect_draw.vert");
public static final ResourceLocation DRAW_FRAGMENT = Flywheel.rl("internal/draw.frag");
public static final ResourceLocation UTIL_TYPES = Flywheel.rl("util/types.glsl");
}
}

View file

@ -1,17 +1,14 @@
package com.jozufozu.flywheel.backend.compile.component;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.instance.InstanceType;
import com.jozufozu.flywheel.api.layout.LayoutItem;
import com.jozufozu.flywheel.backend.compile.Pipeline;
import com.jozufozu.flywheel.backend.compile.Pipelines;
import com.jozufozu.flywheel.backend.compile.SourceLoader;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
@ -27,30 +24,22 @@ public class IndirectComponent implements SourceComponent {
private static final String UNPACK_FN_NAME = "_flw_unpackInstance";
private final List<LayoutItem> layoutItems;
private final ImmutableList<SourceFile> included;
private IndirectComponent(List<LayoutItem> layoutItems, ImmutableList<SourceFile> included) {
public IndirectComponent(List<LayoutItem> layoutItems) {
this.layoutItems = layoutItems;
this.included = included;
}
public static IndirectComponent create(Pipeline.InstanceAssemblerContext ctx) {
return create(ctx.sourceLoader(), ctx.instanceType());
return create(ctx.instanceType());
}
public static IndirectComponent create(SourceLoader sourceLoader, InstanceType<?> instanceType) {
var util = sourceLoader.find(Pipelines.Files.UTIL_TYPES);
if (util == null) {
return null;
}
return new IndirectComponent(instanceType.getLayout().layoutItems, ImmutableList.of(util));
public static IndirectComponent create(InstanceType<?> instanceType) {
return new IndirectComponent(instanceType.getLayout().layoutItems);
}
@Override
public Collection<? extends SourceComponent> included() {
return included;
return Collections.emptyList();
}
@Override
@ -66,6 +55,11 @@ public class IndirectComponent implements SourceComponent {
public String generateIndirect() {
var builder = new GlslBuilder();
layoutItems.stream()
.map(LayoutItem::type)
.distinct()
.forEach(type -> type.declare(builder));
var instance = builder.struct();
instance.setName(STRUCT_NAME);
builder.blankLine();
@ -73,8 +67,10 @@ public class IndirectComponent implements SourceComponent {
packed.setName(PACKED_STRUCT_NAME);
for (var field : layoutItems) {
field.addPackedToStruct(packed);
field.addToStruct(instance);
packed.addField(field.type()
.packedTypeName(), field.name());
instance.addField(field.type()
.typeName(), field.name());
}
builder.blankLine();
@ -94,7 +90,8 @@ public class IndirectComponent implements SourceComponent {
private void generateUnpackingBody(GlslBlock b) {
var unpackedFields = layoutItems.stream()
.map(layoutItem -> layoutItem.unpackField(UNPACKING_VARIABLE))
.map(layoutItem -> UNPACKING_VARIABLE.access(layoutItem.name())
.transform(layoutItem.type()::unpack))
.toList();
b.ret(GlslExpr.call(STRUCT_NAME, unpackedFields));
}

View file

@ -63,7 +63,8 @@ public class InstancedArraysComponent implements SourceComponent {
structBuilder.setName(STRUCT_NAME);
for (var field : layoutItems) {
field.addToStruct(structBuilder);
structBuilder.addField(field.type()
.typeName(), field.name());
}
builder.blankLine();

View file

@ -3,6 +3,7 @@ package com.jozufozu.flywheel.glsl.error.lines;
public enum Divider {
BAR(" | "),
ARROW("-> "),
EQUALS(" = "),
;
private final String s;

View file

@ -5,4 +5,9 @@ public record NestedLine(String right) implements ErrorLine {
public String right() {
return right;
}
@Override
public Divider divider() {
return Divider.EQUALS;
}
}

View file

@ -36,4 +36,7 @@ public class GlslBlock {
.collect(Collectors.joining("\n"));
}
public void raw(String s) {
add(GlslStmt.raw(s));
}
}

View file

@ -1,6 +1,7 @@
package com.jozufozu.flywheel.glsl.generate;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -18,6 +19,10 @@ public interface GlslExpr {
return new Variable(name);
}
static FunctionCall call(String functionName, GlslExpr... args) {
return new FunctionCall(functionName, List.of(args));
}
static FunctionCall call(String functionName, Collection<? extends GlslExpr> args) {
return new FunctionCall(functionName, args);
}

View file

@ -13,6 +13,10 @@ public interface GlslStmt {
return new Return(value);
}
static GlslStmt raw(String s) {
return new Raw(s);
}
String prettyPrint();
record Eval(GlslExpr expr) implements GlslStmt {
@ -28,4 +32,11 @@ public interface GlslStmt {
return "return " + expr.prettyPrint() + ";";
}
}
record Raw(String glsl) implements GlslStmt {
@Override
public String prettyPrint() {
return glsl;
}
}
}

View file

@ -12,12 +12,14 @@ public class GlslStruct implements GlslBuilder.Declaration {
private final List<Pair<String, String>> fields = new ArrayList<>();
private String name;
public void setName(String name) {
public GlslStruct setName(String name) {
this.name = name;
return this;
}
public void addField(String type, String name) {
public GlslStruct addField(String type, String name) {
fields.add(Pair.of(type, name));
return this;
}
private String buildFields() {

View file

@ -2,6 +2,8 @@ package com.jozufozu.flywheel.lib.layout;
import com.jozufozu.flywheel.gl.GlNumericType;
import com.jozufozu.flywheel.gl.array.VertexAttribute;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
public class CommonItems {
private static final String VEC2_TYPE = "vec2";
@ -13,13 +15,20 @@ public class CommonItems {
private static final String IVEC2_TYPE = "ivec2";
private static final String FLOAT_TYPE = "float";
private static final String UINT_TYPE = "uint";
private static final String LIGHT_COORD_TYPE = "LightCoord";
private static final String LIGHT_COORD_TYPE = "uint";
public static final VecInput LIGHT_COORD = VecInput.builder()
.vertexAttribute(new VertexAttribute.Int(GlNumericType.USHORT, 2))
.typeName(IVEC2_TYPE)
.packedTypeName(LIGHT_COORD_TYPE)
.unpackingFunction(expr -> expr.callFunction("unpackLightCoord"))
.declaration(builder -> builder.function()
.signature(FnSignature.create()
.name("unpackLightCoord")
.returnType(IVEC2_TYPE)
.arg("uint", "light")
.build())
.body(block -> block.raw("return ivec2(light & 0xFFFFu, (light >> 16) & 0xFFFFu);")))
.build();
public static final VecInput FLOAT = VecInput.builder()
@ -52,18 +61,69 @@ public class CommonItems {
.typeName(VEC4_TYPE)
.packedTypeName(VEC4F_TYPE)
.unpackingFunction(expr -> expr.callFunction("unpackVec4F"))
.declaration(builder -> {
builder.struct()
.setName(VEC4F_TYPE)
.addField(FLOAT_TYPE, "x")
.addField(FLOAT_TYPE, "y")
.addField(FLOAT_TYPE, "z")
.addField(FLOAT_TYPE, "w");
builder.function()
.signature(FnSignature.create()
.name("unpackVec4F")
.returnType(VEC4_TYPE)
.arg(VEC4F_TYPE, "v")
.build())
.body(block -> {
var v = GlslExpr.variable("v");
block.ret(GlslExpr.call("vec4", v.access("x"), v.access("y"), v.access("z"), v.access("w")));
});
})
.build();
public static final VecInput VEC3 = VecInput.builder()
.vertexAttribute(new VertexAttribute.Float(GlNumericType.FLOAT, 3, false))
.typeName(VEC3_TYPE)
.packedTypeName(VEC3F_TYPE)
.unpackingFunction(expr -> expr.callFunction("unpackVec3F"))
.declaration(builder -> {
builder.struct()
.setName(VEC3F_TYPE)
.addField(FLOAT_TYPE, "x")
.addField(FLOAT_TYPE, "y")
.addField(FLOAT_TYPE, "z");
builder.function()
.signature(FnSignature.create()
.name("unpackVec3F")
.returnType(VEC3_TYPE)
.arg(VEC3F_TYPE, "v")
.build())
.body(block -> {
var v = GlslExpr.variable("v");
block.ret(GlslExpr.call("vec3", v.access("x"), v.access("y"), v.access("z")));
});
})
.build();
public static final VecInput VEC2 = VecInput.builder()
.vertexAttribute(new VertexAttribute.Float(GlNumericType.FLOAT, 2, false))
.typeName(VEC2_TYPE)
.packedTypeName(VEC2F_TYPE)
.unpackingFunction(expr -> expr.callFunction("unpackVec2F"))
.declaration(builder -> {
builder.struct()
.setName(VEC2F_TYPE)
.addField(FLOAT_TYPE, "x")
.addField(FLOAT_TYPE, "y");
builder.function()
.signature(FnSignature.create()
.name("unpackVec2F")
.returnType(VEC2_TYPE)
.arg(VEC2F_TYPE, "v")
.build())
.body(block -> {
var v = GlslExpr.variable("v");
block.ret(GlslExpr.call("vec2", v.access("x"), v.access("y")));
});
})
.build();
public static final MatInput MAT3 = new MatInput(3, 3, "mat3", "Mat3F", "unpackMat3F");

View file

@ -1,10 +1,14 @@
package com.jozufozu.flywheel.lib.layout;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import com.jozufozu.flywheel.api.layout.InputType;
import com.jozufozu.flywheel.gl.GlNumericType;
import com.jozufozu.flywheel.gl.array.VertexAttribute;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
public record MatInput(int rows, int cols, String typeName, String packedTypeName,
@ -26,4 +30,36 @@ public record MatInput(int rows, int cols, String typeName, String packedTypeNam
public GlslExpr unpack(GlslExpr packed) {
return packed.callFunction(unpackingFunction);
}
@Override
public void declare(GlslBuilder builder) {
var s = builder.struct();
s.setName(packedTypeName);
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
s.addField("float", "m" + c + r);
}
}
builder.function()
.signature(FnSignature.create()
.name(unpackingFunction)
.returnType(typeName)
.arg(packedTypeName, "p")
.build())
.body(block -> {
List<GlslExpr> args = new ArrayList<>();
var p = GlslExpr.variable("p");
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
args.add(p.access("m" + c + r));
}
}
block.ret(GlslExpr.call(typeName, args));
});
}
}

View file

@ -5,20 +5,22 @@ import java.util.function.Function;
import com.jozufozu.flywheel.api.layout.InputType;
import com.jozufozu.flywheel.gl.array.VertexAttribute;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
public class VecInput implements InputType {
private final VertexAttribute attribute;
private final String typeName;
private final String packedTypeName;
private final Function<GlslExpr, GlslExpr> unpackingFunction;
private final Consumer<GlslBuilder> declaration;
public VecInput(VertexAttribute attribute, String typeName, String packedTypeName, Function<GlslExpr, GlslExpr> unpackingFunction) {
public VecInput(VertexAttribute attribute, String typeName, String packedTypeName, Function<GlslExpr, GlslExpr> unpackingFunction, Consumer<GlslBuilder> declaration) {
this.attribute = attribute;
this.typeName = typeName;
this.packedTypeName = packedTypeName;
this.unpackingFunction = unpackingFunction;
this.declaration = declaration;
}
@Override
@ -50,11 +52,18 @@ public class VecInput implements InputType {
return unpackingFunction.apply(packed);
}
@Override
public void declare(GlslBuilder builder) {
declaration.accept(builder);
}
public static class Builder {
private VertexAttribute attribute;
private String typeName;
private String packedTypeName;
private Function<GlslExpr, GlslExpr> unpackingFunction = Function.identity();
private Consumer<GlslBuilder> declaration = $ -> {
};
public Builder vertexAttribute(VertexAttribute attribute) {
this.attribute = attribute;
@ -76,8 +85,13 @@ public class VecInput implements InputType {
return this;
}
public Builder declaration(Consumer<GlslBuilder> declaration) {
this.declaration = declaration;
return this;
}
public VecInput build() {
return new VecInput(attribute, typeName, packedTypeName, unpackingFunction);
return new VecInput(attribute, typeName, packedTypeName, unpackingFunction, declaration);
}
}
}

View file

@ -1,7 +1,6 @@
#define FLW_SUBGROUP_SIZE 32
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
#include "flywheel:util/types.glsl"
#include "flywheel:internal/indirect_draw_command.glsl"
// populated by instancers

View file

@ -1,13 +1,23 @@
#include "flywheel:util/types.glsl"
struct BoundingSphere {
float x;
float y;
float z;
float radius;
};
void unpackBoundingSphere(in BoundingSphere sphere, out vec3 center, out float radius) {
center = vec3(sphere.x, sphere.y, sphere.z);
radius = sphere.radius;
}
struct MeshDrawCommand {
uint indexCount;
uint instanceCount;
uint firstIndex;
uint vertexOffset;
uint baseInstance;
uint indexCount;
uint instanceCount;
uint firstIndex;
uint vertexOffset;
uint baseInstance;
BoundingSphere boundingSphere;
uint vertexMaterialID;
BoundingSphere boundingSphere;
uint vertexMaterialID;
uint fragmentMaterialID;
};

View file

@ -1,71 +0,0 @@
// Types intended for use is SSBOs to achieve tighter data packing.
struct Vec3F {
float x;
float y;
float z;
};
struct Vec4F {
float x;
float y;
float z;
float w;
};
struct Mat4F {
Vec4F c0;
Vec4F c1;
Vec4F c2;
Vec4F c3;
};
struct Mat3F {
Vec3F c0;
Vec3F c1;
Vec3F c2;
};
// 4-aligned instead of a 16-aligned vec4
struct BoundingSphere {
Vec3F center;
float radius;
};
struct LightCoord {
uint p;
};
vec3 unpackVec3F(in Vec3F v) {
return vec3(v.x, v.y, v.z);
}
vec4 unpackVec4F(in Vec4F v) {
return vec4(v.x, v.y, v.z, v.w);
}
mat4 unpackMat4F(in Mat4F m) {
return mat4(
unpackVec4F(m.c0),
unpackVec4F(m.c1),
unpackVec4F(m.c2),
unpackVec4F(m.c3)
);
}
mat3 unpackMat3F(in Mat3F m) {
return mat3(
unpackVec3F(m.c0),
unpackVec3F(m.c1),
unpackVec3F(m.c2)
);
}
void unpackBoundingSphere(in BoundingSphere sphere, out vec3 center, out float radius) {
center = unpackVec3F(sphere.center);
radius = sphere.radius;
}
ivec2 unpackLightCoord(in LightCoord light) {
return ivec2(light.p & 0xFFFFu, (light.p >> 16) & 0xFFFFu);
}

View file

@ -29,7 +29,7 @@ public class TestErrorMessages extends TestBase {
--> flywheel:a.glsl
1 | #include "flywheel:b.glsl"
| ^^^^^^^^^^^^^^^
| error: "flywheel:b.glsl" was not found
= error: "flywheel:b.glsl" was not found
""", sources, FLW_A);
}
@ -48,11 +48,11 @@ public class TestErrorMessages extends TestBase {
--> flywheel:a.glsl
1 | #include "flywheel:b.glsl"
| ^^^^^^^^^^^^^^^
| error: could not load "flywheel:b.glsl"
| --> flywheel:b.glsl
| 1 | #include "flywheel:c.glsl"
| | ^^^^^^^^^^^^^^^
| | error: "flywheel:c.glsl" was not found
= error: could not load "flywheel:b.glsl"
= --> flywheel:b.glsl
= 1 | #include "flywheel:c.glsl"
= | ^^^^^^^^^^^^^^^
= = error: "flywheel:c.glsl" was not found
""", sources, FLW_A);
}