mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-06 04:16:36 +01:00
Reorganize/rename
- No more set in builders - Move generated components to backend packages - Fix code organization
This commit is contained in:
parent
03c2df4664
commit
cab922f187
15 changed files with 329 additions and 312 deletions
|
@ -72,40 +72,40 @@ public class SimpleBackendType implements BackendType {
|
|||
private Component engineMessage;
|
||||
private Supplier<Engine> engineSupplier;
|
||||
private Supplier<BackendType> fallback;
|
||||
private BooleanSupplier booleanSupplier;
|
||||
private BooleanSupplier isSupported;
|
||||
|
||||
public Builder setProperName(String properName) {
|
||||
public Builder properName(String properName) {
|
||||
this.properName = properName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setShortName(String shortName) {
|
||||
public Builder shortName(String shortName) {
|
||||
this.shortName = shortName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEngineMessage(Component engineMessage) {
|
||||
public Builder engineMessage(Component engineMessage) {
|
||||
this.engineMessage = engineMessage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEngineSupplier(Supplier<Engine> engineSupplier) {
|
||||
public Builder engineSupplier(Supplier<Engine> engineSupplier) {
|
||||
this.engineSupplier = engineSupplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFallback(Supplier<BackendType> fallback) {
|
||||
public Builder fallback(Supplier<BackendType> fallback) {
|
||||
this.fallback = fallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder supported(BooleanSupplier booleanSupplier) {
|
||||
this.booleanSupplier = booleanSupplier;
|
||||
public Builder supported(BooleanSupplier isSupported) {
|
||||
this.isSupported = isSupported;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BackendType register() {
|
||||
return BackendTypes.register(new SimpleBackendType(properName, shortName, engineMessage, engineSupplier, fallback, booleanSupplier));
|
||||
return BackendTypes.register(new SimpleBackendType(properName, shortName, engineMessage, engineSupplier, fallback, isSupported));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,7 @@ public class ComputeCullerCompiler extends Memoizer<StructType<?>, GlProgram> {
|
|||
|
||||
var finalSource = new StringBuilder();
|
||||
CompilationContext context = new CompilationContext();
|
||||
var components = List.of(structType.getLayout()
|
||||
.getIndirectComponent(), location.getFile(), Components.Pipeline.INDIRECT_CULL.getFile());
|
||||
var components = List.of(new IndirectComponent(structType.getLayout().layoutItems), location.getFile(), Components.Pipeline.INDIRECT_CULL.getFile());
|
||||
|
||||
var names = ImmutableList.<ResourceLocation>builder();
|
||||
var included = new LinkedHashSet<SourceComponent>(); // linked to preserve order
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.indirect;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.SourceComponent;
|
||||
import com.jozufozu.flywheel.core.layout.LayoutItem;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslBuilder;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslExpr;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class IndirectComponent implements SourceComponent {
|
||||
|
||||
private static final String UNPACK_ARG = "p";
|
||||
private static final GlslExpr.Variable UNPACKING_VARIABLE = GlslExpr.variable(UNPACK_ARG);
|
||||
|
||||
private final List<LayoutItem> layoutItems;
|
||||
|
||||
public IndirectComponent(List<LayoutItem> layoutItems) {
|
||||
this.layoutItems = layoutItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends SourceComponent> included() {
|
||||
return List.of(Components.UTIL_TYPES.getFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation name() {
|
||||
return Flywheel.rl("generated_indirect");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String source(CompilationContext ctx) {
|
||||
var generated = generateIndirect("IndirectStruct");
|
||||
return ctx.generatedHeader(generated, name().toString()) + generated;
|
||||
}
|
||||
|
||||
public String generateIndirect(String structName) {
|
||||
var builder = new GlslBuilder();
|
||||
final var packedStructName = structName + "_packed";
|
||||
builder.define("FlwInstance", structName);
|
||||
builder.define("FlwPackedInstance", packedStructName);
|
||||
|
||||
var packed = builder.struct();
|
||||
builder.blankLine();
|
||||
var instance = builder.struct();
|
||||
packed.setName(packedStructName);
|
||||
instance.setName(structName);
|
||||
|
||||
for (var field : layoutItems) {
|
||||
field.addPackedToStruct(packed);
|
||||
field.addToStruct(instance);
|
||||
}
|
||||
|
||||
builder.blankLine();
|
||||
|
||||
var func = builder.function()
|
||||
.returnType(structName)
|
||||
.name("flw_unpackInstance")
|
||||
.argumentIn(packedStructName, UNPACK_ARG);
|
||||
|
||||
var args = layoutItems.stream()
|
||||
.map(layoutItem -> layoutItem.unpackField(UNPACKING_VARIABLE))
|
||||
.map(GlslExpr::minPrint)
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
func.statement("return " + structName + "(" + args + ");");
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.instancing;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.core.SourceComponent;
|
||||
import com.jozufozu.flywheel.core.layout.LayoutItem;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslBuilder;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslExpr;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class InstancedArraysComponent implements SourceComponent {
|
||||
private static final String ATTRIBUTE_SUFFIX = "_vertex_in";
|
||||
|
||||
private final List<LayoutItem> layoutItems;
|
||||
private final int baseIndex;
|
||||
|
||||
public InstancedArraysComponent(List<LayoutItem> layoutItems, int baseIndex) {
|
||||
this.layoutItems = layoutItems;
|
||||
this.baseIndex = baseIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends SourceComponent> included() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String source(CompilationContext ctx) {
|
||||
var generated = generateInstancedArrays("Instance");
|
||||
return ctx.generatedHeader(generated, name().toString()) + generated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation name() {
|
||||
return Flywheel.rl("generated_instanced_arrays");
|
||||
}
|
||||
|
||||
public String generateInstancedArrays(String structName) {
|
||||
var builder = new GlslBuilder();
|
||||
builder.define("FlwInstance", structName);
|
||||
|
||||
int i = baseIndex;
|
||||
for (var field : layoutItems) {
|
||||
builder.vertexInput()
|
||||
.binding(i)
|
||||
.type(field.type()
|
||||
.typeName())
|
||||
.name(field.name() + ATTRIBUTE_SUFFIX);
|
||||
|
||||
i += field.type()
|
||||
.attributeCount();
|
||||
}
|
||||
|
||||
builder.blankLine();
|
||||
|
||||
var structBuilder = builder.struct();
|
||||
structBuilder.setName(structName);
|
||||
|
||||
for (var field : layoutItems) {
|
||||
field.addToStruct(structBuilder);
|
||||
}
|
||||
|
||||
builder.blankLine();
|
||||
|
||||
var func = builder.function()
|
||||
.returnType(structName)
|
||||
.name("flw_unpackInstance");
|
||||
|
||||
var args = layoutItems.stream()
|
||||
.map(it -> new GlslExpr.Variable(it.name() + ATTRIBUTE_SUFFIX))
|
||||
.map(GlslExpr::minPrint)
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
func.statement("return " + structName + "(" + args + ");");
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
|
@ -21,74 +21,74 @@ import net.minecraft.network.chat.TextComponent;
|
|||
public class BackendTypes {
|
||||
public static final Map<String, BackendType> BACKEND_TYPES = new HashMap<>();
|
||||
|
||||
public static final BackendType OFF = SimpleBackendType.builder()
|
||||
.properName("Off")
|
||||
.shortName("off")
|
||||
.engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED))
|
||||
.engineSupplier(() -> {
|
||||
throw new IllegalStateException("Cannot create engine when backend is off.");
|
||||
})
|
||||
.fallback(() -> BackendTypes.OFF)
|
||||
.supported(() -> true)
|
||||
.register();
|
||||
|
||||
/**
|
||||
* Use a thread pool to buffer instances in parallel on the CPU.
|
||||
*/
|
||||
public static final BackendType BATCHING = SimpleBackendType.builder()
|
||||
.properName("Parallel Batching")
|
||||
.shortName("batching")
|
||||
.engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN))
|
||||
.engineSupplier(BatchingEngine::new)
|
||||
.fallback(() -> BackendTypes.OFF)
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse())
|
||||
.register();
|
||||
|
||||
/**
|
||||
* Use GPU instancing to render everything.
|
||||
*/
|
||||
public static final BackendType INSTANCING = SimpleBackendType.builder()
|
||||
.properName("GL33 Instanced Arrays")
|
||||
.shortName("instancing")
|
||||
.engineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN))
|
||||
.engineSupplier(() -> new InstancingEngine(Components.WORLD, 100 * 100))
|
||||
.fallback(() -> BackendTypes.BATCHING)
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
|
||||
.instancedArraysSupported())
|
||||
.register();
|
||||
|
||||
/**
|
||||
* Use Compute shaders to cull instances.
|
||||
*/
|
||||
public static final BackendType INDIRECT = SimpleBackendType.builder()
|
||||
.properName("GL46 Compute Culling")
|
||||
.shortName("indirect")
|
||||
.engineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN))
|
||||
.engineSupplier(() -> new IndirectEngine(Components.WORLD))
|
||||
.fallback(() -> BackendTypes.INSTANCING)
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
|
||||
.supportsIndirect())
|
||||
.register();
|
||||
|
||||
public static BackendType register(BackendType type) {
|
||||
BACKEND_TYPES.put(type.getShortName(), type);
|
||||
return type;
|
||||
}
|
||||
|
||||
public static final BackendType OFF = SimpleBackendType.builder()
|
||||
.setProperName("Off")
|
||||
.setShortName("off")
|
||||
.setEngineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED))
|
||||
.setEngineSupplier(() -> {
|
||||
throw new IllegalStateException("Cannot create engine when backend is off.");
|
||||
})
|
||||
.setFallback(() -> BackendTypes.OFF)
|
||||
.supported(() -> true)
|
||||
.register();
|
||||
|
||||
public static BackendType defaultForCurrentPC() {
|
||||
// TODO: Automatically select the best default config based on the user's driver
|
||||
return INDIRECT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a thread pool to buffer instances in parallel on the CPU.
|
||||
*/
|
||||
public static final BackendType BATCHING = SimpleBackendType.builder()
|
||||
.setProperName("Parallel Batching")
|
||||
.setShortName("batching")
|
||||
.setEngineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN))
|
||||
.setEngineSupplier(BatchingEngine::new)
|
||||
.setFallback(() -> BackendTypes.OFF)
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse())
|
||||
.register();
|
||||
|
||||
@Nullable
|
||||
public static BackendType getBackendType(String name) {
|
||||
return BACKEND_TYPES.get(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use GPU instancing to render everything.
|
||||
*/
|
||||
public static final BackendType INSTANCING = SimpleBackendType.builder()
|
||||
.setProperName("GL33 Instanced Arrays")
|
||||
.setShortName("instancing")
|
||||
.setEngineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN))
|
||||
.setEngineSupplier(() -> new InstancingEngine(Components.WORLD, 100 * 100))
|
||||
.setFallback(() -> BackendTypes.BATCHING)
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
|
||||
.instancedArraysSupported())
|
||||
.register();
|
||||
|
||||
public static Collection<String> validNames() {
|
||||
return BACKEND_TYPES.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use Compute shaders to cull instances.
|
||||
*/
|
||||
public static final BackendType INDIRECT = SimpleBackendType.builder()
|
||||
.setProperName("GL46 Compute Culling")
|
||||
.setShortName("indirect")
|
||||
.setEngineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN))
|
||||
.setEngineSupplier(() -> new IndirectEngine(Components.WORLD))
|
||||
.setFallback(() -> BackendTypes.INSTANCING)
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
|
||||
.supportsIndirect())
|
||||
.register();
|
||||
|
||||
public static void init() {
|
||||
// noop
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import com.jozufozu.flywheel.Flywheel;
|
|||
import com.jozufozu.flywheel.api.context.ContextShader;
|
||||
import com.jozufozu.flywheel.api.pipeline.PipelineShader;
|
||||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.backend.instancing.indirect.IndirectComponent;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.InstancedArraysComponent;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceChecks;
|
||||
|
@ -29,11 +31,9 @@ public class Components {
|
|||
public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(WorldProgram::new, Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
|
||||
public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(CrumblingProgram::new, Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
|
||||
|
||||
public static final PipelineShader INSTANCED_ARRAYS = new PipelineShader(GLSLVersion.V420, Pipeline.INSTANCED_ARRAYS_DRAW, Pipeline.DRAW_FRAGMENT, (vertexType, structType) -> structType.getLayout()
|
||||
.getInstancedArraysComponent(vertexType.getLayout()
|
||||
.getAttributeCount()));
|
||||
public static final PipelineShader INDIRECT = new PipelineShader(GLSLVersion.V460, Pipeline.INDIRECT_DRAW, Pipeline.DRAW_FRAGMENT, (vertexType, structType) -> structType.getLayout()
|
||||
.getIndirectComponent());
|
||||
public static final PipelineShader INSTANCED_ARRAYS = new PipelineShader(GLSLVersion.V420, Pipeline.INSTANCED_ARRAYS_DRAW, Pipeline.DRAW_FRAGMENT, (vertexType, structType) -> new InstancedArraysComponent(structType.getLayout().layoutItems, vertexType.getLayout()
|
||||
.getAttributeCount()));
|
||||
public static final PipelineShader INDIRECT = new PipelineShader(GLSLVersion.V460, Pipeline.INDIRECT_DRAW, Pipeline.DRAW_FRAGMENT, (vertexType, structType) -> new IndirectComponent(structType.getLayout().layoutItems));
|
||||
public static final FileResolution UTIL_TYPES = FileResolution.get(Flywheel.rl("util/types.glsl"));
|
||||
|
||||
public static void init() {
|
||||
|
@ -117,14 +117,13 @@ public class Components {
|
|||
|
||||
public static class Checks {
|
||||
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> LAYOUT_VERTEX = SourceChecks.checkFunctionArity("flw_layoutVertex", 0)
|
||||
.andThen(SourceChecks.checkDefine("FLW_INSTANCE_BASE_INDEX"));
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> INSTANCE_VERTEX = SourceChecks.checkFunctionParameterTypeExists("flw_instanceVertex", 1, 0)
|
||||
.andThen(SourceChecks.checkDefine("FLW_INSTANCE_STRUCT"));
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> LAYOUT_VERTEX = SourceChecks.checkFunctionArity("flw_layoutVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> INSTANCE_VERTEX = SourceChecks.checkFunctionParameterTypeExists("flw_instanceVertex", 1, 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> MATERIAL_VERTEX = SourceChecks.checkFunctionArity("flw_materialVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> MATERIAL_FRAGMENT = SourceChecks.checkFunctionArity("flw_materialFragment", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_VERTEX = SourceChecks.checkFunctionArity("flw_contextVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_FRAGMENT = SourceChecks.checkFunctionArity("flw_contextFragment", 0).andThen(SourceChecks.checkFunctionArity("flw_initFragment", 0));
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_FRAGMENT = SourceChecks.checkFunctionArity("flw_contextFragment", 0)
|
||||
.andThen(SourceChecks.checkFunctionArity("flw_initFragment", 0));
|
||||
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> PIPELINE = SourceChecks.checkFunctionArity("main", 0);
|
||||
}
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
package com.jozufozu.flywheel.core.layout;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.array.VertexAttribute;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.SourceComponent;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslBuilder;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslExpr;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Classic Vertex Format struct with a clever name.
|
||||
|
@ -39,8 +28,9 @@ public class BufferLayout {
|
|||
|
||||
ImmutableList.Builder<VertexAttribute> attributes = ImmutableList.builder();
|
||||
|
||||
for (var item : layoutItems) {
|
||||
item.type.provideAttributes(attributes::add);
|
||||
for (var item : this.layoutItems) {
|
||||
item.type()
|
||||
.provideAttributes(attributes::add);
|
||||
}
|
||||
|
||||
this.attributes = attributes.build();
|
||||
|
@ -59,14 +49,6 @@ public class BufferLayout {
|
|||
return stride;
|
||||
}
|
||||
|
||||
public InstancedArraysComponent getInstancedArraysComponent(int baseIndex) {
|
||||
return new InstancedArraysComponent(baseIndex);
|
||||
}
|
||||
|
||||
public IndirectComponent getIndirectComponent() {
|
||||
return new IndirectComponent();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
@ -102,136 +84,4 @@ public class BufferLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public record LayoutItem(InputType type, String name) {
|
||||
public String unpack(String argName) {
|
||||
return argName + '.' + name;
|
||||
}
|
||||
}
|
||||
|
||||
public class InstancedArraysComponent implements SourceComponent {
|
||||
private static final String ATTRIBUTE_SUFFIX = "_vertex_in";
|
||||
|
||||
private final int baseIndex;
|
||||
|
||||
public InstancedArraysComponent(int baseIndex) {
|
||||
this.baseIndex = baseIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends SourceComponent> included() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String source(CompilationContext ctx) {
|
||||
var generated = generateInstancedArrays("Instance");
|
||||
return ctx.generatedHeader(generated, name().toString()) + generated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation name() {
|
||||
return Flywheel.rl("generated_instanced_arrays");
|
||||
}
|
||||
|
||||
public String generateInstancedArrays(String structName) {
|
||||
var builder = new GlslBuilder();
|
||||
builder.define("FlwInstance", structName);
|
||||
|
||||
int i = baseIndex;
|
||||
for (var field : layoutItems) {
|
||||
builder.vertexInput()
|
||||
.binding(i)
|
||||
.type(field.type.typeName())
|
||||
.name(field.name + ATTRIBUTE_SUFFIX);
|
||||
|
||||
i += field.type.attributeCount();
|
||||
}
|
||||
|
||||
builder.blankLine();
|
||||
|
||||
var structBuilder = builder.struct();
|
||||
structBuilder.setName(structName);
|
||||
|
||||
for (var field : layoutItems) {
|
||||
structBuilder.addField(field.type.typeName(), field.name);
|
||||
}
|
||||
|
||||
builder.blankLine();
|
||||
|
||||
var func = builder.function()
|
||||
.returnType(structName)
|
||||
.name("flw_unpackInstance");
|
||||
|
||||
var args = layoutItems.stream()
|
||||
.map(it -> new GlslExpr.Variable(it.name + ATTRIBUTE_SUFFIX))
|
||||
.map(GlslExpr::minPrint)
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
func.statement("return " + structName + "(" + args + ");");
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
public class IndirectComponent implements SourceComponent {
|
||||
|
||||
private static final String UNPACK_ARG = "p";
|
||||
|
||||
private static GlslExpr genGlslForLayoutItem(LayoutItem layoutItem) {
|
||||
return GlslExpr.variable(UNPACK_ARG)
|
||||
.access(layoutItem.name)
|
||||
.transform(layoutItem.type::unpack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends SourceComponent> included() {
|
||||
return List.of(Components.UTIL_TYPES.getFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation name() {
|
||||
return Flywheel.rl("generated_indirect");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String source(CompilationContext ctx) {
|
||||
var generated = generateIndirect("IndirectStruct");
|
||||
return ctx.generatedHeader(generated, name().toString()) + generated;
|
||||
}
|
||||
|
||||
public String generateIndirect(String structName) {
|
||||
var builder = new GlslBuilder();
|
||||
final var packedStructName = structName + "_packed";
|
||||
builder.define("FlwInstance", structName);
|
||||
builder.define("FlwPackedInstance", packedStructName);
|
||||
|
||||
var packed = builder.struct();
|
||||
builder.blankLine();
|
||||
var instance = builder.struct();
|
||||
packed.setName(packedStructName);
|
||||
instance.setName(structName);
|
||||
|
||||
for (var field : layoutItems) {
|
||||
packed.addField(field.type.packedTypeName(), field.name);
|
||||
instance.addField(field.type.typeName(), field.name);
|
||||
}
|
||||
|
||||
builder.blankLine();
|
||||
|
||||
var func = builder.function()
|
||||
.returnType(structName)
|
||||
.name("flw_unpackInstance")
|
||||
.argumentIn(packedStructName, UNPACK_ARG);
|
||||
|
||||
var args = layoutItems.stream()
|
||||
.map(IndirectComponent::genGlslForLayoutItem)
|
||||
.map(GlslExpr::minPrint)
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
func.statement("return " + structName + "(" + args + ");");
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,70 +6,69 @@ import com.jozufozu.flywheel.backend.gl.array.VertexAttributeI;
|
|||
|
||||
public class CommonItems {
|
||||
|
||||
private static final String VEC2_TYPE = "vec2";
|
||||
private static final String VEC3_TYPE = "vec3";
|
||||
private static final String VEC4_TYPE = "vec4";
|
||||
private static final String VEC2_TYPE = "vec2";
|
||||
private static final String FLOAT_TYPE = "float";
|
||||
private static final String IVEC2_TYPE = "ivec2";
|
||||
private static final String UINT_TYPE = "uint";
|
||||
private static final String VEC4F_TYPE = "Vec4F";
|
||||
private static final String VEC3F_TYPE = "Vec3F";
|
||||
private static final String LIGHT_COORD_TYPE = "LightCoord";
|
||||
public static final PrimitiveItem LIGHT_COORD = PrimitiveItem.builder()
|
||||
.setAttribute(new VertexAttributeI(GlNumericType.USHORT, 2))
|
||||
.setTypeName(IVEC2_TYPE)
|
||||
.setPackedTypeName(LIGHT_COORD_TYPE)
|
||||
.unpack(expr -> expr.callFunction("unpackLightCoord"))
|
||||
.createPrimitiveItem();
|
||||
|
||||
public static final PrimitiveItem FLOAT = PrimitiveItem.builder()
|
||||
.setAttribute(new VertexAttributeF(GlNumericType.FLOAT, 1, false))
|
||||
.setTypeName(FLOAT_TYPE)
|
||||
.setPackedTypeName(FLOAT_TYPE)
|
||||
.createPrimitiveItem();
|
||||
public static final PrimitiveItem NORM_3x8 = PrimitiveItem.builder()
|
||||
.setAttribute(new VertexAttributeF(GlNumericType.BYTE, 3, true))
|
||||
.setTypeName(VEC3_TYPE)
|
||||
.setPackedTypeName(UINT_TYPE)
|
||||
.unpack(expr -> expr.callFunction("unpackSnorm4x8")
|
||||
.swizzle("xyz"))
|
||||
.createPrimitiveItem();
|
||||
public static final PrimitiveItem UNORM_4x8 = PrimitiveItem.builder()
|
||||
.setAttribute(new VertexAttributeF(GlNumericType.UBYTE, 4, true))
|
||||
.setTypeName(VEC4_TYPE)
|
||||
.setPackedTypeName(UINT_TYPE)
|
||||
.unpack(expr -> expr.callFunction("unpackUnorm4x8"))
|
||||
.createPrimitiveItem();
|
||||
public static final PrimitiveItem UNORM_3x8 = PrimitiveItem.builder()
|
||||
.setAttribute(new VertexAttributeF(GlNumericType.UBYTE, 3, true))
|
||||
.setTypeName(VEC3_TYPE)
|
||||
.setPackedTypeName(UINT_TYPE)
|
||||
.unpack(expr -> expr.callFunction("unpackUnorm4x8")
|
||||
.swizzle("xyz"))
|
||||
.createPrimitiveItem();
|
||||
public static final PrimitiveItem VEC4 = PrimitiveItem.builder()
|
||||
.setAttribute(new VertexAttributeF(GlNumericType.FLOAT, 4, false))
|
||||
.setTypeName(VEC4_TYPE)
|
||||
.setPackedTypeName(VEC4F_TYPE)
|
||||
.unpack(expr -> expr.callFunction("unpackVec4F"))
|
||||
.createPrimitiveItem();
|
||||
public static final PrimitiveItem VEC3 = PrimitiveItem.builder()
|
||||
.setAttribute(new VertexAttributeF(GlNumericType.FLOAT, 3, false))
|
||||
.setTypeName(VEC3_TYPE)
|
||||
.setPackedTypeName(VEC3F_TYPE)
|
||||
.unpack(expr -> expr.callFunction("unpackVec3F"))
|
||||
.createPrimitiveItem();
|
||||
public static final PrimitiveItem VEC2 = PrimitiveItem.builder()
|
||||
.setAttribute(new VertexAttributeF(GlNumericType.FLOAT, 2, false))
|
||||
.setTypeName(VEC2_TYPE)
|
||||
.setPackedTypeName(VEC2F_TYPE)
|
||||
.unpack(expr -> expr.callFunction("unpackVec2F"))
|
||||
.createPrimitiveItem();
|
||||
private static final String VEC2F_TYPE = "Vec2F";
|
||||
private static final String VEC3F_TYPE = "Vec3F";
|
||||
private static final String VEC4F_TYPE = "Vec4F";
|
||||
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";
|
||||
public static final VecInput LIGHT_COORD = VecInput.builder()
|
||||
.vertexAttribute(new VertexAttributeI(GlNumericType.USHORT, 2))
|
||||
.typeName(IVEC2_TYPE)
|
||||
.packedTypeName(LIGHT_COORD_TYPE)
|
||||
.unpackingFunction(expr -> expr.callFunction("unpackLightCoord"))
|
||||
.build();
|
||||
|
||||
public static final VecInput FLOAT = VecInput.builder()
|
||||
.vertexAttribute(new VertexAttributeF(GlNumericType.FLOAT, 1, false))
|
||||
.typeName(FLOAT_TYPE)
|
||||
.packedTypeName(FLOAT_TYPE)
|
||||
.build();
|
||||
public static final VecInput NORM_3x8 = VecInput.builder()
|
||||
.vertexAttribute(new VertexAttributeF(GlNumericType.BYTE, 3, true))
|
||||
.typeName(VEC3_TYPE)
|
||||
.packedTypeName(UINT_TYPE)
|
||||
.unpackingFunction(expr -> expr.callFunction("unpackSnorm4x8")
|
||||
.swizzle("xyz"))
|
||||
.build();
|
||||
public static final VecInput UNORM_4x8 = VecInput.builder()
|
||||
.vertexAttribute(new VertexAttributeF(GlNumericType.UBYTE, 4, true))
|
||||
.typeName(VEC4_TYPE)
|
||||
.packedTypeName(UINT_TYPE)
|
||||
.unpackingFunction(expr -> expr.callFunction("unpackUnorm4x8"))
|
||||
.build();
|
||||
public static final VecInput UNORM_3x8 = VecInput.builder()
|
||||
.vertexAttribute(new VertexAttributeF(GlNumericType.UBYTE, 3, true))
|
||||
.typeName(VEC3_TYPE)
|
||||
.packedTypeName(UINT_TYPE)
|
||||
.unpackingFunction(expr -> expr.callFunction("unpackUnorm4x8")
|
||||
.swizzle("xyz"))
|
||||
.build();
|
||||
public static final VecInput VEC4 = VecInput.builder()
|
||||
.vertexAttribute(new VertexAttributeF(GlNumericType.FLOAT, 4, false))
|
||||
.typeName(VEC4_TYPE)
|
||||
.packedTypeName(VEC4F_TYPE)
|
||||
.unpackingFunction(expr -> expr.callFunction("unpackVec4F"))
|
||||
.build();
|
||||
public static final VecInput VEC3 = VecInput.builder()
|
||||
.vertexAttribute(new VertexAttributeF(GlNumericType.FLOAT, 3, false))
|
||||
.typeName(VEC3_TYPE)
|
||||
.packedTypeName(VEC3F_TYPE)
|
||||
.unpackingFunction(expr -> expr.callFunction("unpackVec3F"))
|
||||
.build();
|
||||
public static final VecInput VEC2 = VecInput.builder()
|
||||
.vertexAttribute(new VertexAttributeF(GlNumericType.FLOAT, 2, false))
|
||||
.typeName(VEC2_TYPE)
|
||||
.packedTypeName(VEC2F_TYPE)
|
||||
.unpackingFunction(expr -> expr.callFunction("unpackVec2F"))
|
||||
.build();
|
||||
|
||||
public static final MatrixItem MAT3 = new MatrixItem(3, 3, "mat3", "Mat3F", "unpackMat3F");
|
||||
public static final MatrixItem MAT4 = new MatrixItem(4, 4, "mat4", "Mat4F", "unpackMat4F");
|
||||
public static final MatInput MAT3 = new MatInput(3, 3, "mat3", "Mat3F", "unpackMat3F");
|
||||
public static final MatInput MAT4 = new MatInput(4, 4, "mat4", "Mat4F", "unpackMat4F");
|
||||
|
||||
private static class Unpacking {
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.jozufozu.flywheel.core.layout;
|
||||
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslBuilder;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslExpr;
|
||||
|
||||
public record LayoutItem(InputType type, String name) {
|
||||
public GlslExpr unpackField(GlslExpr.Variable struct) {
|
||||
return struct.access(name())
|
||||
.transform(type()::unpack);
|
||||
}
|
||||
|
||||
public void addToStruct(GlslBuilder.StructBuilder structBuilder) {
|
||||
structBuilder.addField(type().typeName(), name());
|
||||
}
|
||||
|
||||
public void addPackedToStruct(GlslBuilder.StructBuilder packed) {
|
||||
packed.addField(type().packedTypeName(), name());
|
||||
}
|
||||
}
|
|
@ -7,8 +7,8 @@ import com.jozufozu.flywheel.backend.gl.array.VertexAttribute;
|
|||
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeF;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslExpr;
|
||||
|
||||
public record MatrixItem(int rows, int cols, String typeName, String packedTypeName,
|
||||
String unpackingFunction) implements InputType {
|
||||
public record MatInput(int rows, int cols, String typeName, String packedTypeName,
|
||||
String unpackingFunction) implements InputType {
|
||||
|
||||
@Override
|
||||
public void provideAttributes(Consumer<VertexAttribute> consumer) {
|
|
@ -6,14 +6,14 @@ import java.util.function.Function;
|
|||
import com.jozufozu.flywheel.backend.gl.array.VertexAttribute;
|
||||
import com.jozufozu.flywheel.core.source.generate.GlslExpr;
|
||||
|
||||
public class PrimitiveItem implements InputType {
|
||||
public class VecInput implements InputType {
|
||||
|
||||
private final VertexAttribute attribute;
|
||||
private final String typeName;
|
||||
private final String packedTypeName;
|
||||
private final Function<GlslExpr, GlslExpr> unpackingFunction;
|
||||
|
||||
public PrimitiveItem(VertexAttribute attribute, String typeName, String packedTypeName, Function<GlslExpr, GlslExpr> unpackingFunction) {
|
||||
public VecInput(VertexAttribute attribute, String typeName, String packedTypeName, Function<GlslExpr, GlslExpr> unpackingFunction) {
|
||||
this.attribute = attribute;
|
||||
this.typeName = typeName;
|
||||
this.packedTypeName = packedTypeName;
|
||||
|
@ -40,8 +40,8 @@ public class PrimitiveItem implements InputType {
|
|||
return 1;
|
||||
}
|
||||
|
||||
public static PrimitiveItemBuilder builder() {
|
||||
return new PrimitiveItemBuilder();
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,34 +49,34 @@ public class PrimitiveItem implements InputType {
|
|||
return unpackingFunction.apply(packed);
|
||||
}
|
||||
|
||||
public static class PrimitiveItemBuilder {
|
||||
public static class Builder {
|
||||
private VertexAttribute attribute;
|
||||
private String typeName;
|
||||
private String packedTypeName;
|
||||
private Function<GlslExpr, GlslExpr> unpackingFunction = Function.identity();
|
||||
|
||||
public PrimitiveItemBuilder setAttribute(VertexAttribute attribute) {
|
||||
public Builder vertexAttribute(VertexAttribute attribute) {
|
||||
this.attribute = attribute;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PrimitiveItemBuilder setTypeName(String typeName) {
|
||||
public Builder typeName(String typeName) {
|
||||
this.typeName = typeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PrimitiveItemBuilder setPackedTypeName(String packedTypeName) {
|
||||
public Builder packedTypeName(String packedTypeName) {
|
||||
this.packedTypeName = packedTypeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PrimitiveItemBuilder unpack(Function<GlslExpr, GlslExpr> f) {
|
||||
public Builder unpackingFunction(Function<GlslExpr, GlslExpr> f) {
|
||||
this.unpackingFunction = f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PrimitiveItem createPrimitiveItem() {
|
||||
return new PrimitiveItem(attribute, typeName, packedTypeName, unpackingFunction);
|
||||
public VecInput build() {
|
||||
return new VecInput(attribute, typeName, packedTypeName, unpackingFunction);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,12 +54,4 @@ public class SourceChecks {
|
|||
|
||||
return func;
|
||||
}
|
||||
|
||||
public static BiConsumer<? super ErrorReporter, ? super SourceFile> checkDefine(String define) {
|
||||
return (errorReporter, file) -> {
|
||||
// if (!file.hasDefine(define)) {
|
||||
// errorReporter.generateMissingDefine(file, define, "\"" + define + "\" define not defined");
|
||||
// }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ public class GlslBuilder {
|
|||
private final List<SourceElement> elements = new ArrayList<>();
|
||||
|
||||
public void define(String name, String value) {
|
||||
elements.add(new Define(name, value));
|
||||
add(new Define(name, value));
|
||||
}
|
||||
|
||||
public StructBuilder struct() {
|
||||
|
@ -31,6 +31,9 @@ public class GlslBuilder {
|
|||
return element;
|
||||
}
|
||||
|
||||
public void blankLine() {
|
||||
elements.add(Separators.BLANK_LINE);
|
||||
}
|
||||
|
||||
public String build() {
|
||||
return elements.stream()
|
||||
|
@ -38,8 +41,8 @@ public class GlslBuilder {
|
|||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
public void blankLine() {
|
||||
elements.add(Separators.BLANK_LINE);
|
||||
public interface SourceElement {
|
||||
String build();
|
||||
}
|
||||
|
||||
public enum Separators implements SourceElement {
|
||||
|
@ -51,15 +54,11 @@ public class GlslBuilder {
|
|||
Separators(String separator) {
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String build() {
|
||||
return separator;
|
||||
}
|
||||
}
|
||||
|
||||
public interface SourceElement {
|
||||
String build();
|
||||
}
|
||||
|
||||
public record Define(String name, String value) implements SourceElement {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#use "flywheel:api/vertex.glsl"
|
||||
#use "flywheel:util/quaternion.glsl"
|
||||
#use "flywheel:util/types.glsl"
|
||||
|
||||
void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius) {
|
||||
vec4 rotation = i.rotation;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#use "flywheel:api/vertex.glsl"
|
||||
#use "flywheel:util/types.glsl"
|
||||
|
||||
void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius) {
|
||||
mat4 pose = i.pose;
|
||||
|
|
Loading…
Reference in a new issue