diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index 91c204ed2..d189bf662 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -5,7 +5,7 @@ import org.slf4j.Logger; import com.jozufozu.flywheel.backend.Backends; import com.jozufozu.flywheel.backend.Loader; -import com.jozufozu.flywheel.backend.Pipelines; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines; import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer; import com.jozufozu.flywheel.config.BackendArgument; diff --git a/src/main/java/com/jozufozu/flywheel/api/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/api/backend/Backend.java index 3a7cfb6bd..829721855 100644 --- a/src/main/java/com/jozufozu/flywheel/api/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/api/backend/Backend.java @@ -1,8 +1,5 @@ package com.jozufozu.flywheel.api.backend; -import org.jetbrains.annotations.Nullable; - -import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.registry.IdRegistry; import com.jozufozu.flywheel.impl.IdRegistryImpl; @@ -31,6 +28,4 @@ public interface Backend { * Check if this backend is supported. */ boolean isSupported(); - - @Nullable Pipeline pipelineShader(); } diff --git a/src/main/java/com/jozufozu/flywheel/api/pipeline/Pipeline.java b/src/main/java/com/jozufozu/flywheel/api/pipeline/Pipeline.java deleted file mode 100644 index 4e2d746ce..000000000 --- a/src/main/java/com/jozufozu/flywheel/api/pipeline/Pipeline.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.jozufozu.flywheel.api.pipeline; - -import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.gl.GLSLVersion; -import com.jozufozu.flywheel.glsl.ShaderSources; -import com.jozufozu.flywheel.glsl.SourceComponent; - -import net.minecraft.resources.ResourceLocation; - -public interface Pipeline { - GLSLVersion glslVersion(); - - ResourceLocation vertexShader(); - - ResourceLocation fragmentShader(); - - /** - * Generate the source component necessary to convert a packed {@link InstanceType} into its shader representation. - * - * @return A source component defining functions that unpack a representation of the given instance type. - */ - SourceComponent assemble(InstanceAssemblerContext context); - - record InstanceAssemblerContext(ShaderSources sources, VertexType vertexType, InstanceType instanceType) { - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backends.java b/src/main/java/com/jozufozu/flywheel/backend/Backends.java index 271976bb0..d2eae65f8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backends.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backends.java @@ -32,7 +32,6 @@ public class Backends { .fallback(() -> Backends.BATCHING) .supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance() .instancedArraysSupported()) - .pipelineShader(Pipelines.INSTANCED_ARRAYS) .register(Flywheel.rl("instancing")); /** @@ -44,7 +43,6 @@ public class Backends { .fallback(() -> Backends.INSTANCING) .supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance() .supportsIndirect()) - .pipelineShader(Pipelines.INDIRECT) .register(Flywheel.rl("indirect")); public static void init() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java index 362c401ec..1a113c117 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java @@ -1,8 +1,6 @@ package com.jozufozu.flywheel.backend; -import com.jozufozu.flywheel.backend.compile.FlwCompiler; -import com.jozufozu.flywheel.glsl.ShaderSources; -import com.jozufozu.flywheel.glsl.error.ErrorReporter; +import com.jozufozu.flywheel.backend.compile.FlwPrograms; import com.jozufozu.flywheel.impl.BackendManagerImpl; import net.minecraft.client.Minecraft; @@ -25,14 +23,7 @@ public class Loader implements ResourceManagerReloadListener { @Override public void onResourceManagerReload(ResourceManager manager) { - var errorReporter = new ErrorReporter(); - ShaderSources sources = new ShaderSources(errorReporter, manager); - - if (FlwCompiler.INSTANCE != null) { - FlwCompiler.INSTANCE.delete(); - } - - FlwCompiler.INSTANCE = new FlwCompiler(sources); + FlwPrograms.reload(manager); // TODO: Move this to the impl package BackendManagerImpl.refresh(Minecraft.getInstance().level); diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/Compilation.java b/src/main/java/com/jozufozu/flywheel/backend/compile/Compilation.java index 281541c1e..a4128cea5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/Compilation.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/Compilation.java @@ -40,7 +40,7 @@ public class Compilation { public Compilation(GLSLVersion glslVersion, ShaderType shaderType) { this.generatedSource = new StringBuilder(); - this.fullSource = new StringBuilder(CompileUtil.generateHeader(glslVersion, shaderType)); + this.fullSource = new StringBuilder(CompileUtil.generateHeader(glslVersion, shaderType)).append('\n'); this.glslVersion = glslVersion; this.shaderType = shaderType; } @@ -71,10 +71,6 @@ public class Compilation { .append(" : enable\n"); } - public void addComponentName(ResourceLocation name) { - componentNames.add(name); - } - public void appendComponent(SourceComponent component) { var source = component.source(); @@ -85,12 +81,12 @@ public class Compilation { .toString())); } - fullSource.append(source) - .append('\n'); + fullSource.append(source); + componentNames.add(component.name()); } private String sourceHeader(SourceFile sourceFile) { - return "#line " + 0 + ' ' + getOrCreateFileID(sourceFile) + " // " + sourceFile.name + '\n'; + return '\n' + "#line " + 0 + ' ' + getOrCreateFileID(sourceFile) + " // " + sourceFile.name + '\n'; } private String generatedHeader(String generatedCode, String comment) { @@ -98,7 +94,7 @@ public class Compilation { int lines = StringUtil.countLines(generatedCode); // all generated code is put in file 0, - var out = "#line " + generatedLines + ' ' + 0; + var out = '\n' + "#line " + generatedLines + ' ' + 0; generatedLines += lines; @@ -123,12 +119,13 @@ public class Compilation { @NotNull private String buildShaderName() { + // TODO: This name is so long it fails to create the file. Use index and map indices to component sources in separate file? var components = componentNames.stream() .map(ResourceLocation::toString) .map(s -> s.replaceAll("/", "_") .replaceAll(":", "\\$")) .collect(Collectors.joining(";")); - return shaderType.name + glslVersion + ';' + components; + return shaderType.name + glslVersion + ';' /*+ components*/; } private static void dumpSource(String source, String fileName) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/CompileUtil.java b/src/main/java/com/jozufozu/flywheel/backend/compile/CompileUtil.java index 6b5e0e290..58b27c65f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/CompileUtil.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/CompileUtil.java @@ -24,7 +24,7 @@ public class CompileUtil { public static final Pattern matType = Pattern.compile("^mat([234])(?:x([234]))?$"); public static String generateHeader(GLSLVersion version, ShaderType type) { - return version.getVersionLine() + type.getDefineStatement() + '\n'; + return version.getVersionLine() + type.getDefineStatement(); } public static int getElementCount(String type) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/CullingContext.java b/src/main/java/com/jozufozu/flywheel/backend/compile/CullingContext.java deleted file mode 100644 index 75ea4ab99..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/CullingContext.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.jozufozu.flywheel.backend.compile; - -import com.jozufozu.flywheel.api.instance.InstanceType; - -public record CullingContext(InstanceType instanceType) { -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/CullingContextSet.java b/src/main/java/com/jozufozu/flywheel/backend/compile/CullingContextSet.java deleted file mode 100644 index 6f7d98279..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/CullingContextSet.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.jozufozu.flywheel.backend.compile; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.jozufozu.flywheel.api.instance.InstanceType; - -public class CullingContextSet { - static CullingContextSet create() { - var builder = new CullingContextSet(); - for (InstanceType instanceType : InstanceType.REGISTRY) { - builder.add(instanceType); - } - return builder; - } - - private final List contexts = new ArrayList<>(); - private final List contextView = Collections.unmodifiableList(contexts); - - CullingContextSet() { - } - - public List all() { - return contextView; - } - - public int size() { - return contexts.size(); - } - - private void add(InstanceType instanceType) { - var ctx = new CullingContext(instanceType); - - contexts.add(ctx); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwCompiler.java index c280d0e49..da57af321 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwCompiler.java @@ -10,14 +10,14 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.jetbrains.annotations.Nullable; + import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.uniform.ShaderUniforms; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.backend.Pipelines; +import com.jozufozu.flywheel.backend.compile.FlwPrograms.PipelineProgramKey; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline; import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent; import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.shader.GlProgram; @@ -30,78 +30,164 @@ import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.lib.material.MaterialIndices; import com.jozufozu.flywheel.util.StringUtil; +import net.minecraft.resources.ResourceLocation; + public class FlwCompiler { + private final long compileStart = System.nanoTime(); - public static FlwCompiler INSTANCE; - - final long compileStart = System.nanoTime(); private final ShaderSources sources; - private final UniformComponent uniformComponent; + + private final ImmutableList pipelineKeys; + private final ImmutableList> cullingKeys; + + private final ShaderCompiler shaderCompiler; + private final List errors = new ArrayList<>(); + private final MaterialAdapterComponent vertexMaterialComponent; private final MaterialAdapterComponent fragmentMaterialComponent; + private final UniformComponent uniformComponent; - private final PipelineContextSet pipelineContexts; - private final CullingContextSet cullingContexts; + private final Map pipelinePrograms = new HashMap<>(); + private final Map, GlProgram> cullingPrograms = new HashMap<>(); - final ShaderCompiler shaderCompiler; - final Map pipelinePrograms = new HashMap<>(); - final Map, GlProgram> cullingPrograms = new HashMap<>(); - final List errors = new ArrayList<>(); + public FlwCompiler(ShaderSources sources, ImmutableList pipelineKeys, ImmutableList> cullingKeys) { + this.sources = sources; - public FlwCompiler(ShaderSources sources) { - this.shaderCompiler = ShaderCompiler.builder() + this.pipelineKeys = pipelineKeys; + this.cullingKeys = cullingKeys; + + shaderCompiler = ShaderCompiler.builder() .errorConsumer(errors::add) .build(); - this.sources = sources; - this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter")) + vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter")) .materialSources(MaterialIndices.getAllVertexShaders()) .adapt(FnSignature.ofVoid("flw_materialVertex")) - .switchOn(GlslExpr.variable("flw_materialVertexID")) + .switchOn(GlslExpr.variable("_flw_materialVertexID")) .build(sources); - this.fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter")) + fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter")) .materialSources(MaterialIndices.getAllFragmentShaders()) .adapt(FnSignature.ofVoid("flw_materialFragment")) .adapt(FnSignature.create() .returnType("bool") - .name("flw_discardPredicate") - .arg("vec4", "color") - .build(), GlslExpr.literal(false)) - .adapt(FnSignature.create() - .returnType("vec4") - .name("flw_fogFilter") - .arg("vec4", "color") - .build(), GlslExpr.variable("color")) - .switchOn(GlslExpr.variable("flw_materialFragmentID")) - .build(sources); - this.uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms")) + .name("flw_discardPredicate") + .arg("vec4", "color") + .build(), GlslExpr.literal(false)) + .adapt(FnSignature.create() + .returnType("vec4") + .name("flw_fogFilter") + .arg("vec4", "color") + .build(), GlslExpr.variable("color")) + .switchOn(GlslExpr.variable("_flw_materialFragmentID")) + .build(sources); + uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms")) .sources(ShaderUniforms.REGISTRY.getAll() .stream() .map(ShaderUniforms::uniformShader) - .toList()) + .toList()) .build(sources); + } - this.pipelineContexts = PipelineContextSet.create(); - this.cullingContexts = CullingContextSet.create(); - + public FlwPrograms compile() { doCompilation(); finish(); + + return new FlwPrograms(pipelinePrograms, cullingPrograms); } private void doCompilation() { - for (var ctx : pipelineContexts.all()) { - compilePipelineContext(ctx); + for (var key : pipelineKeys) { + GlProgram glProgram = compilePipelineProgram(key); + if (glProgram != null) { + pipelinePrograms.put(key, glProgram); + } } - for (var ctx : cullingContexts.all()) { - compileComputeCuller(ctx); + for (var key : cullingKeys) { + GlProgram glProgram = compileCullingProgram(key); + if (glProgram != null) { + cullingPrograms.put(key, glProgram); + } } } + private static GlProgram link(int... shaders) { + var handle = glCreateProgram(); + for (var shader : shaders) { + glAttachShader(handle, shader); + } + glLinkProgram(handle); + CompileUtil.checkLinkLog(handle); + return new GlProgram(handle); + } + + @Nullable + private GlProgram compilePipelineProgram(PipelineProgramKey key) { + var glslVersion = key.pipelineShader() + .glslVersion(); + + var vertex = shaderCompiler.compile(glslVersion, ShaderType.VERTEX, getVertexComponents(key)); + var fragment = shaderCompiler.compile(glslVersion, ShaderType.FRAGMENT, getFragmentComponents(key)); + + if (vertex == null || fragment == null) { + return null; + } + + var glProgram = link(vertex.handle(), fragment.handle()); + key.contextShader() + .onProgramLink(glProgram); + return glProgram; + } + + private ImmutableList getVertexComponents(PipelineProgramKey key) { + var instanceAssembly = key.pipelineShader() + .assembler() + .assemble(new Pipeline.InstanceAssemblerContext(sources, key.vertexType(), key.instanceType())); + + var layout = sources.find(key.vertexType() + .layoutShader()); + var instance = sources.find(key.instanceType() + .instanceShader()); + var context = sources.find(key.contextShader() + .vertexShader()); + var pipeline = sources.find(key.pipelineShader() + .vertexShader()); + + return ImmutableList.of(uniformComponent, vertexMaterialComponent, instanceAssembly, layout, instance, context, pipeline); + } + + private ImmutableList getFragmentComponents(PipelineProgramKey key) { + var context = sources.find(key.contextShader() + .fragmentShader()); + var pipeline = sources.find(key.pipelineShader() + .fragmentShader()); + return ImmutableList.of(uniformComponent, fragmentMaterialComponent, context, pipeline); + } + + @Nullable + private GlProgram compileCullingProgram(InstanceType key) { + var computeComponents = getComputeComponents(key); + var result = shaderCompiler.compile(GLSLVersion.V460, ShaderType.COMPUTE, computeComponents); + + if (result == null) { + return null; + } + + return link(result.handle()); + } + + private ImmutableList getComputeComponents(InstanceType instanceType) { + var instanceAssembly = new IndirectComponent(sources, instanceType); + var instance = sources.find(instanceType.instanceShader()); + var pipeline = sources.find(Files.INDIRECT_CULL); + + return ImmutableList.of(uniformComponent, instanceAssembly, instance, pipeline); + } + private void finish() { long compileEnd = System.nanoTime(); - int programCount = pipelineContexts.size() + InstanceType.REGISTRY.getAll().size(); + int programCount = pipelineKeys.size() + cullingKeys.size(); int shaderCount = shaderCompiler.shaderCount(); int errorCount = errors.size(); var elapsed = StringUtil.formatTime(compileEnd - compileStart); @@ -112,94 +198,16 @@ public class FlwCompiler { var details = errors.stream() .map(FailedCompilation::getMessage) .collect(Collectors.joining("\n")); -// throw new ShaderLoadingException("Compilation failed.\n" + details); + // TODO: disable backend instead of crashing if compilation fails + throw new ShaderLoadingException("Compilation failed.\n" + details); } } public void delete() { - pipelinePrograms.values() - .forEach(GlProgram::delete); - cullingPrograms.values() - .forEach(GlProgram::delete); shaderCompiler.delete(); } - public GlProgram getPipelineProgram(VertexType vertexType, InstanceType instanceType, Context contextShader, Pipeline pipelineShader) { - return pipelinePrograms.get(new PipelineContext(vertexType, instanceType, contextShader, pipelineShader)); + private static final class Files { + public static final ResourceLocation INDIRECT_CULL = Flywheel.rl("internal/indirect_cull.glsl"); } - - public GlProgram getCullingProgram(InstanceType instanceType) { - return cullingPrograms.get(instanceType); - } - - private void compilePipelineContext(PipelineContext ctx) { - var glslVersion = ctx.pipelineShader() - .glslVersion(); - - var vertex = shaderCompiler.compile(glslVersion, ShaderType.VERTEX, getVertexComponents(ctx)); - var fragment = shaderCompiler.compile(glslVersion, ShaderType.FRAGMENT, getFragmentComponents(ctx)); - - if (vertex == null || fragment == null) { - return; - } - - var glProgram = link(vertex.handle(), fragment.handle()); - ctx.contextShader() - .onProgramLink(glProgram); - pipelinePrograms.put(ctx, glProgram); - } - - private void compileComputeCuller(CullingContext ctx) { - var computeComponents = getComputeComponents(ctx.instanceType()); - var result = shaderCompiler.compile(GLSLVersion.V460, ShaderType.COMPUTE, computeComponents); - - if (result == null) { - return; - } - - cullingPrograms.put(ctx.instanceType(), link(result.handle())); - } - - private GlProgram link(int... shaders) { - var handle = glCreateProgram(); - for (var shader : shaders) { - glAttachShader(handle, shader); - } - glLinkProgram(handle); - CompileUtil.checkLinkLog(handle); - return new GlProgram(handle); - } - - private ImmutableList getVertexComponents(PipelineContext ctx) { - var instanceAssembly = ctx.pipelineShader() - .assemble(new Pipeline.InstanceAssemblerContext(sources, ctx.vertexType(), ctx.instanceType())); - - var layout = sources.find(ctx.vertexType() - .layoutShader()); - var instance = sources.find(ctx.instanceType() - .instanceShader()); - var context = sources.find(ctx.contextShader() - .vertexShader()); - var pipeline = sources.find(ctx.pipelineShader() - .vertexShader()); - - return ImmutableList.of(uniformComponent, vertexMaterialComponent, instanceAssembly, layout, instance, context, pipeline); - } - - private ImmutableList getFragmentComponents(PipelineContext ctx) { - var context = sources.find(ctx.contextShader() - .fragmentShader()); - var pipeline = sources.find(ctx.pipelineShader() - .fragmentShader()); - return ImmutableList.of(uniformComponent, fragmentMaterialComponent, context, pipeline); - } - - private ImmutableList getComputeComponents(InstanceType instanceType) { - var instanceAssembly = new IndirectComponent(sources, instanceType); - var instance = sources.find(instanceType.instanceShader()); - var pipeline = sources.find(Pipelines.Files.INDIRECT_CULL); - - return ImmutableList.of(uniformComponent, instanceAssembly, instance, pipeline); - } - } diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java new file mode 100644 index 000000000..1b8afb758 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java @@ -0,0 +1,94 @@ +package com.jozufozu.flywheel.backend.compile; + +import java.util.Map; + +import org.jetbrains.annotations.Nullable; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.api.context.Context; +import com.jozufozu.flywheel.api.instance.InstanceType; +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines; +import com.jozufozu.flywheel.gl.shader.GlProgram; +import com.jozufozu.flywheel.glsl.ShaderSources; +import com.jozufozu.flywheel.glsl.error.ErrorReporter; +import com.jozufozu.flywheel.lib.context.Contexts; + +import net.minecraft.server.packs.resources.ResourceManager; + +public class FlwPrograms { + private static FlwPrograms instance; + + private final Map pipelinePrograms; + private final Map, GlProgram> cullingPrograms; + + public FlwPrograms(Map pipelinePrograms, Map, GlProgram> cullingPrograms) { + this.pipelinePrograms = pipelinePrograms; + this.cullingPrograms = cullingPrograms; + } + + public static void reload(ResourceManager resourceManager) { + if (instance != null) { + instance.delete(); + } + + ErrorReporter errorReporter = new ErrorReporter(); + ShaderSources sources = new ShaderSources(errorReporter, resourceManager); + FlwCompiler compiler = new FlwCompiler(sources, createPipelineKeys(), createCullingKeys()); + instance = compiler.compile(); + compiler.delete(); + } + + private static ImmutableList createPipelineKeys() { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Pipeline pipelineShader : Pipelines.ALL) { + for (InstanceType instanceType : InstanceType.REGISTRY) { + for (VertexType vertexType : VertexType.REGISTRY) { + builder.add(new PipelineProgramKey(vertexType, instanceType, Contexts.WORLD, pipelineShader)); + } + } + } + return builder.build(); + } + + private static ImmutableList> createCullingKeys() { + ImmutableList.Builder> builder = ImmutableList.builder(); + for (InstanceType instanceType : InstanceType.REGISTRY) { + builder.add(instanceType); + } + return builder.build(); + } + + @Nullable + public static FlwPrograms get() { + return instance; + } + + public GlProgram getPipelineProgram(VertexType vertexType, InstanceType instanceType, Context contextShader, Pipeline pipelineShader) { + return pipelinePrograms.get(new PipelineProgramKey(vertexType, instanceType, contextShader, pipelineShader)); + } + + public GlProgram getCullingProgram(InstanceType instanceType) { + return cullingPrograms.get(instanceType); + } + + private void delete() { + pipelinePrograms.values() + .forEach(GlProgram::delete); + cullingPrograms.values() + .forEach(GlProgram::delete); + } + + /** + * Represents the entire context of a program's usage. + * + * @param vertexType The vertex type the program should be adapted for. + * @param instanceType The instance shader to use. + * @param contextShader The context shader to use. + * @param pipelineShader The pipeline shader to use. + */ + public record PipelineProgramKey(VertexType vertexType, InstanceType instanceType, Context contextShader, + Pipeline pipelineShader) { + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/MaterialAdapterComponent.java b/src/main/java/com/jozufozu/flywheel/backend/compile/MaterialAdapterComponent.java index f14483ca1..1e7ea6745 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/MaterialAdapterComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/MaterialAdapterComponent.java @@ -61,6 +61,8 @@ public class MaterialAdapterComponent implements SourceComponent { .body(body -> generateAdapter(body, adaptedFunction)); } + builder.blankLine(); + return builder.build(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineContext.java b/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineContext.java deleted file mode 100644 index 0fe8edc68..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineContext.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.jozufozu.flywheel.backend.compile; - -import com.jozufozu.flywheel.api.context.Context; -import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.api.pipeline.Pipeline; -import com.jozufozu.flywheel.api.vertex.VertexType; - -/** - * Represents the entire context of a program's usage. - * - * @param vertexType The vertexType the program should be adapted for. - * @param instanceType The instance shader to use. - * @param contextShader The context shader to use. - */ -public record PipelineContext(VertexType vertexType, InstanceType instanceType, Context contextShader, - Pipeline pipelineShader) { -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineContextSet.java b/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineContextSet.java deleted file mode 100644 index 2f4079168..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineContextSet.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.jozufozu.flywheel.backend.compile; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import com.jozufozu.flywheel.api.backend.Backend; -import com.jozufozu.flywheel.api.context.Context; -import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.api.pipeline.Pipeline; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.lib.context.Contexts; - -public class PipelineContextSet { - private final List contexts = new ArrayList<>(); - private final List contextView = Collections.unmodifiableList(contexts); - - PipelineContextSet() { - } - - static PipelineContextSet create() { - var builder = new PipelineContextSet(); - for (Pipeline pipelineShader : availablePipelineShaders()) { - for (InstanceType instanceType : InstanceType.REGISTRY) { - for (VertexType vertexType : VertexType.REGISTRY) { - builder.add(vertexType, instanceType, Contexts.WORLD, pipelineShader); - } - } - } - return builder; - } - - private static Collection availablePipelineShaders() { - return Backend.REGISTRY.getAll() - .stream() - .filter(Backend::isSupported) - .map(Backend::pipelineShader) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - public List all() { - return contextView; - } - - public int size() { - return contexts.size(); - } - - private void add(VertexType vertexType, InstanceType instanceType, Context world, Pipeline pipelineShader) { - var ctx = new PipelineContext(vertexType, instanceType, world, pipelineShader); - - contexts.add(ctx); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/UniformComponent.java b/src/main/java/com/jozufozu/flywheel/backend/compile/UniformComponent.java index 3a23b4da9..ba88a6bda 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/UniformComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/UniformComponent.java @@ -41,6 +41,8 @@ public class UniformComponent implements SourceComponent { .name("FLWUniforms") .member("flywheel_uniforms", "flywheel"); + builder.blankLine(); + return builder.build(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/pipeline/Pipeline.java b/src/main/java/com/jozufozu/flywheel/backend/compile/pipeline/Pipeline.java new file mode 100644 index 000000000..b29aada8f --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/pipeline/Pipeline.java @@ -0,0 +1,59 @@ +package com.jozufozu.flywheel.backend.compile.pipeline; + +import com.jozufozu.flywheel.api.instance.InstanceType; +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.gl.GLSLVersion; +import com.jozufozu.flywheel.glsl.ShaderSources; +import com.jozufozu.flywheel.glsl.SourceComponent; + +import net.minecraft.resources.ResourceLocation; + +public record Pipeline(GLSLVersion glslVersion, ResourceLocation vertexShader, ResourceLocation fragmentShader, InstanceAssembler assembler) { + @FunctionalInterface + public interface InstanceAssembler { + /** + * Generate the source component necessary to convert a packed {@link InstanceType} into its shader representation. + * + * @return A source component defining functions that unpack a representation of the given instance type. + */ + SourceComponent assemble(InstanceAssemblerContext context); + } + + public record InstanceAssemblerContext(ShaderSources sources, VertexType vertexType, InstanceType instanceType) { + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private GLSLVersion glslVersion; + private ResourceLocation vertex; + private ResourceLocation fragment; + private InstanceAssembler assembler; + + public Builder glslVersion(GLSLVersion glslVersion) { + this.glslVersion = glslVersion; + return this; + } + + public Builder vertex(ResourceLocation vertex) { + this.vertex = vertex; + return this; + } + + public Builder fragment(ResourceLocation fragment) { + this.fragment = fragment; + return this; + } + + public Builder assembler(InstanceAssembler assembler) { + this.assembler = assembler; + return this; + } + + public Pipeline build() { + return new Pipeline(glslVersion, vertex, fragment, assembler); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/Pipelines.java b/src/main/java/com/jozufozu/flywheel/backend/compile/pipeline/Pipelines.java similarity index 57% rename from src/main/java/com/jozufozu/flywheel/backend/Pipelines.java rename to src/main/java/com/jozufozu/flywheel/backend/compile/pipeline/Pipelines.java index 37b123de3..4cd1c9b11 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Pipelines.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/pipeline/Pipelines.java @@ -1,35 +1,38 @@ -package com.jozufozu.flywheel.backend; +package com.jozufozu.flywheel.backend.compile.pipeline; + +import java.util.List; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent; import com.jozufozu.flywheel.backend.engine.instancing.InstancedArraysComponent; import com.jozufozu.flywheel.gl.GLSLVersion; -import com.jozufozu.flywheel.lib.pipeline.SimplePipeline; import net.minecraft.resources.ResourceLocation; -public class Pipelines { - public static final SimplePipeline INSTANCED_ARRAYS = SimplePipeline.builder() +public final class Pipelines { + public static final Pipeline INSTANCED_ARRAYS = Pipeline.builder() .glslVersion(GLSLVersion.V420) .vertex(Files.INSTANCED_ARRAYS_DRAW) .fragment(Files.DRAW_FRAGMENT) - .assemblerFactory(InstancedArraysComponent::new) + .assembler(InstancedArraysComponent::new) .build(); - public static final SimplePipeline INDIRECT = SimplePipeline.builder() + public static final Pipeline INDIRECT = Pipeline.builder() .glslVersion(GLSLVersion.V460) .vertex(Files.INDIRECT_DRAW) .fragment(Files.DRAW_FRAGMENT) - .assemblerFactory(IndirectComponent::new) + .assembler(IndirectComponent::new) .build(); + public static final List ALL = List.of(INSTANCED_ARRAYS, INDIRECT); + public static void init() { } - public static class Files { - public static final ResourceLocation DRAW_FRAGMENT = Flywheel.rl("pipeline/draw.frag"); - public static final ResourceLocation INSTANCED_ARRAYS_DRAW = Flywheel.rl("pipeline/instanced_arrays_draw.vert"); - public static final ResourceLocation INDIRECT_DRAW = Flywheel.rl("pipeline/indirect_draw.vert"); - public static final ResourceLocation INDIRECT_CULL = Flywheel.rl("pipeline/indirect_cull.glsl"); + public static final class Files { + 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"); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectComponent.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectComponent.java index bc4129fc3..446c6702e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectComponent.java @@ -7,8 +7,8 @@ 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.api.pipeline.Pipeline; -import com.jozufozu.flywheel.backend.Pipelines; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines; import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.SourceComponent; import com.jozufozu.flywheel.glsl.SourceFile; @@ -57,6 +57,7 @@ public class IndirectComponent implements SourceComponent { var builder = new GlslBuilder(); builder.define("FlwInstance", STRUCT_NAME); builder.define("FlwPackedInstance", PACKED_STRUCT_NAME); + builder.blankLine(); var packed = builder.struct(); builder.blankLine(); @@ -74,11 +75,13 @@ public class IndirectComponent implements SourceComponent { builder.function() .signature(FnSignature.create() .returnType(STRUCT_NAME) - .name("flw_unpackInstance") + .name("_flw_unpackInstance") .arg(PACKED_STRUCT_NAME, UNPACK_ARG) .build()) .body(this::generateUnpackingBody); + builder.blankLine(); + return builder.build(); } 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 0b622ea7e..95f6071ba 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 @@ -15,8 +15,8 @@ import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.backend.Pipelines; -import com.jozufozu.flywheel.backend.compile.FlwCompiler; +import com.jozufozu.flywheel.backend.compile.FlwPrograms; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines; import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.lib.context.Contexts; @@ -62,8 +62,8 @@ public class IndirectCullingGroup { .quads2Tris(2048).glBuffer; setupVertexArray(); - compute = FlwCompiler.INSTANCE.getCullingProgram(instanceType); - draw = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, instanceType, Contexts.WORLD, Pipelines.INDIRECT); + compute = FlwPrograms.get().getCullingProgram(instanceType); + draw = FlwPrograms.get().getPipelineProgram(vertexType, instanceType, Contexts.WORLD, Pipelines.INDIRECT); } private void setupVertexArray() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedArraysComponent.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedArraysComponent.java index 363b52b1e..a56ee964f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedArraysComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedArraysComponent.java @@ -6,7 +6,7 @@ import java.util.List; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.layout.LayoutItem; -import com.jozufozu.flywheel.api.pipeline.Pipeline; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline; import com.jozufozu.flywheel.glsl.SourceComponent; import com.jozufozu.flywheel.glsl.generate.FnSignature; import com.jozufozu.flywheel.glsl.generate.GlslBlock; @@ -16,7 +16,7 @@ import com.jozufozu.flywheel.glsl.generate.GlslExpr; import net.minecraft.resources.ResourceLocation; public class InstancedArraysComponent implements SourceComponent { - private static final String ATTRIBUTE_SUFFIX = "_vertex_in"; + private static final String ATTRIBUTE_PREFIX = "_flw_i_"; private static final String STRUCT_NAME = "Instance"; private final List layoutItems; @@ -45,13 +45,15 @@ public class InstancedArraysComponent implements SourceComponent { var builder = new GlslBuilder(); builder.define("FlwInstance", STRUCT_NAME); + builder.blankLine(); + int i = baseIndex; for (var field : layoutItems) { builder.vertexInput() .binding(i) .type(field.type() .typeName()) - .name(field.name() + ATTRIBUTE_SUFFIX); + .name(ATTRIBUTE_PREFIX + field.name()); i += field.type() .attributeCount(); @@ -70,15 +72,17 @@ public class InstancedArraysComponent implements SourceComponent { // unpacking function builder.function() - .signature(FnSignature.of(STRUCT_NAME, "flw_unpackInstance")) + .signature(FnSignature.of(STRUCT_NAME, "_flw_unpackInstance")) .body(this::generateUnpackingBody); + builder.blankLine(); + return builder.build(); } private void generateUnpackingBody(GlslBlock b) { var fields = layoutItems.stream() - .map(it -> new GlslExpr.Variable(it.name() + ATTRIBUTE_SUFFIX)) + .map(it -> new GlslExpr.Variable(ATTRIBUTE_PREFIX + it.name())) .toList(); b.ret(GlslExpr.call(STRUCT_NAME, fields)); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java index 038511ca8..1562b861f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java @@ -13,8 +13,8 @@ import com.jozufozu.flywheel.api.instance.Instancer; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.task.Plan; import com.jozufozu.flywheel.api.task.TaskExecutor; -import com.jozufozu.flywheel.backend.Pipelines; -import com.jozufozu.flywheel.backend.compile.FlwCompiler; +import com.jozufozu.flywheel.backend.compile.FlwPrograms; +import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines; import com.jozufozu.flywheel.backend.engine.AbstractEngine; import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.gl.GlStateTracker; @@ -106,7 +106,7 @@ public class InstancingEngine extends AbstractEngine { var vertexType = desc.vertexType(); var instanceType = desc.instanceType(); - var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, instanceType, context, Pipelines.INSTANCED_ARRAYS); + var program = FlwPrograms.get().getPipelineProgram(vertexType, instanceType, context, Pipelines.INSTANCED_ARRAYS); UniformBuffer.syncAndBind(program); var uniformLocation = program.getUniformLocation("_flw_materialID_instancing"); diff --git a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslExpr.java b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslExpr.java index a5e6bf37e..aa07e8a14 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslExpr.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslExpr.java @@ -93,7 +93,7 @@ public interface GlslExpr { public String prettyPrint() { var args = this.args.stream() .map(GlslExpr::prettyPrint) - .collect(Collectors.joining(",")); + .collect(Collectors.joining(", ")); return name + "(" + args + ")"; } diff --git a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslFn.java b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslFn.java index 951dc8436..e17431e2d 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslFn.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslFn.java @@ -22,7 +22,6 @@ public class GlslFn implements GlslBuilder.Declaration { return """ %s { %s - } - """.formatted(signature.fullDeclaration(), StringUtil.indent(body.prettyPrint(), 4)); + }""".formatted(signature.fullDeclaration(), StringUtil.indent(body.prettyPrint(), 4)); } } diff --git a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslStruct.java b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslStruct.java index 3b7ff275c..31c6794b9 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslStruct.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslStruct.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.stream.Collectors; import com.jozufozu.flywheel.util.Pair; +import com.jozufozu.flywheel.util.StringUtil; public class GlslStruct implements GlslBuilder.Declaration { @@ -25,11 +26,11 @@ public class GlslStruct implements GlslBuilder.Declaration { .collect(Collectors.joining("\n")); } + @Override public String prettyPrint() { return """ struct %s { %s - }; - """.formatted(name, buildFields().indent(4)); + };""".formatted(name, StringUtil.indent(buildFields(), 4)); } } diff --git a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslUniformBlock.java b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslUniformBlock.java index 4a52addef..a139a08f9 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslUniformBlock.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslUniformBlock.java @@ -20,8 +20,7 @@ public class GlslUniformBlock implements GlslBuilder.Declaration { return """ layout(%s, binding = %d) uniform %s { %s - }; - """.formatted(qualifier, binding, name, StringUtil.indent(formatMembers(), 4)); + };""".formatted(qualifier, binding, name, StringUtil.indent(formatMembers(), 4)); } private String formatMembers() { diff --git a/src/main/java/com/jozufozu/flywheel/glsl/parse/ShaderFunction.java b/src/main/java/com/jozufozu/flywheel/glsl/parse/ShaderFunction.java index 6d6114da4..e9680ee41 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/parse/ShaderFunction.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/parse/ShaderFunction.java @@ -8,7 +8,6 @@ import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.glsl.span.Span; public class ShaderFunction { - // https://regexr.com/60n3d public static final Pattern PATTERN = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{"); @@ -86,11 +85,10 @@ public class ShaderFunction { @Override public String toString() { - String p = parameters.stream() .map(variable -> variable.type) .map(Span::get) - .collect(Collectors.joining(",")); + .collect(Collectors.joining(", ")); return type + " " + name + "(" + p + ")"; } diff --git a/src/main/java/com/jozufozu/flywheel/lib/backend/SimpleBackend.java b/src/main/java/com/jozufozu/flywheel/lib/backend/SimpleBackend.java index 8f1f80703..4a93b4f71 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/backend/SimpleBackend.java +++ b/src/main/java/com/jozufozu/flywheel/lib/backend/SimpleBackend.java @@ -4,12 +4,9 @@ import java.util.function.BooleanSupplier; import java.util.function.Function; import java.util.function.Supplier; -import org.jetbrains.annotations.Nullable; - import com.jozufozu.flywheel.api.backend.Backend; import com.jozufozu.flywheel.api.backend.BackendManager; import com.jozufozu.flywheel.api.backend.Engine; -import com.jozufozu.flywheel.api.pipeline.Pipeline; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -20,14 +17,12 @@ public class SimpleBackend implements Backend { private final Function engineFactory; private final Supplier fallback; private final BooleanSupplier isSupported; - private final Pipeline pipelineShader; - public SimpleBackend(Component engineMessage, Function engineFactory, Supplier fallback, BooleanSupplier isSupported, @Nullable Pipeline pipelineShader) { + public SimpleBackend(Component engineMessage, Function engineFactory, Supplier fallback, BooleanSupplier isSupported) { this.engineMessage = engineMessage; this.engineFactory = engineFactory; this.fallback = fallback; this.isSupported = isSupported; - this.pipelineShader = pipelineShader; } public static Builder builder() { @@ -59,17 +54,11 @@ public class SimpleBackend implements Backend { return isSupported.getAsBoolean(); } - @Override - public @Nullable Pipeline pipelineShader() { - return pipelineShader; - } - public static class Builder { private Component engineMessage; private Function engineFactory; private Supplier fallback = BackendManager::getOffBackend; private BooleanSupplier isSupported; - private Pipeline pipelineShader; public Builder engineMessage(Component engineMessage) { this.engineMessage = engineMessage; @@ -91,13 +80,8 @@ public class SimpleBackend implements Backend { return this; } - public Builder pipelineShader(Pipeline pipelineShader) { - this.pipelineShader = pipelineShader; - return this; - } - public Backend register(ResourceLocation id) { - return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(engineMessage, engineFactory, fallback, isSupported, pipelineShader)); + return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(engineMessage, engineFactory, fallback, isSupported)); } } } diff --git a/src/main/java/com/jozufozu/flywheel/lib/pipeline/SimplePipeline.java b/src/main/java/com/jozufozu/flywheel/lib/pipeline/SimplePipeline.java deleted file mode 100644 index 33fc8da4d..000000000 --- a/src/main/java/com/jozufozu/flywheel/lib/pipeline/SimplePipeline.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.jozufozu.flywheel.lib.pipeline; - -import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.api.pipeline.Pipeline; -import com.jozufozu.flywheel.gl.GLSLVersion; -import com.jozufozu.flywheel.glsl.SourceComponent; - -import net.minecraft.resources.ResourceLocation; - -public final class SimplePipeline implements Pipeline { - private final GLSLVersion glslVersion; - private final ResourceLocation vertex; - private final ResourceLocation fragment; - private final InstanceAssemblerFactory factory; - - public SimplePipeline(GLSLVersion glslVersion, ResourceLocation vertex, ResourceLocation fragment, InstanceAssemblerFactory factory) { - this.glslVersion = glslVersion; - this.vertex = vertex; - this.fragment = fragment; - this.factory = factory; - } - - /** - * Generate the source component necessary to convert a packed {@link InstanceType} into its shader representation. - * - * @return A source component defining functions that unpack a representation of the given instance type. - */ - @Override - public SourceComponent assemble(InstanceAssemblerContext context) { - return factory.apply(context); - } - - @Override - public GLSLVersion glslVersion() { - return glslVersion; - } - - @Override - public ResourceLocation vertexShader() { - return vertex; - } - - @Override - public ResourceLocation fragmentShader() { - return fragment; - } - - @FunctionalInterface - public interface InstanceAssemblerFactory { - SourceComponent apply(InstanceAssemblerContext context); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private GLSLVersion glslVersion; - private ResourceLocation vertex; - private ResourceLocation fragment; - private InstanceAssemblerFactory factory; - - public Builder glslVersion(GLSLVersion glslVersion) { - this.glslVersion = glslVersion; - return this; - } - - public Builder vertex(ResourceLocation vertex) { - this.vertex = vertex; - return this; - } - - public Builder fragment(ResourceLocation fragment) { - this.fragment = fragment; - return this; - } - - public Builder assemblerFactory(InstanceAssemblerFactory factory) { - this.factory = factory; - return this; - } - - public SimplePipeline build() { - return new SimplePipeline(glslVersion, vertex, fragment, factory); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/util/StringUtil.java b/src/main/java/com/jozufozu/flywheel/util/StringUtil.java index fdc2fa8a3..44cedf96b 100644 --- a/src/main/java/com/jozufozu/flywheel/util/StringUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/StringUtil.java @@ -24,6 +24,7 @@ public class StringUtil { private static final NumberFormat THREE_DECIMAL_PLACES = new DecimalFormat("#0.000"); + // FIXME: this method should count trailing newlines public static int countLines(String s) { return (int) s.lines() .count(); diff --git a/src/main/resources/assets/flywheel/flywheel/api/cull.glsl b/src/main/resources/assets/flywheel/flywheel/api/cull.glsl deleted file mode 100644 index d89bebbf3..000000000 --- a/src/main/resources/assets/flywheel/flywheel/api/cull.glsl +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef COMPUTE_SHADER -uint flw_objectID; -uint flw_batchID; -#endif diff --git a/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl b/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl index a8028e8b9..4aabc253e 100644 --- a/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl +++ b/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl @@ -13,7 +13,7 @@ in vec4 flw_var1; in vec4 flw_var2; in vec4 flw_var3; -flat in uint flw_materialFragmentID; +flat in uint _flw_materialFragmentID; // diff --git a/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl b/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl index f823366de..a57a89f6c 100644 --- a/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl +++ b/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl @@ -1,5 +1,5 @@ #ifdef VERTEX_SHADER -uint flw_materialVertexID; +uint _flw_materialVertexID; out vec4 flw_vertexPos; out vec4 flw_vertexColor; @@ -14,5 +14,5 @@ out vec4 flw_var0; out vec4 flw_var1; out vec4 flw_var2; out vec4 flw_var3; -flat out uint flw_materialFragmentID; +flat out uint _flw_materialFragmentID; #endif diff --git a/src/main/resources/assets/flywheel/flywheel/compute/mat.glsl b/src/main/resources/assets/flywheel/flywheel/compute/mat.glsl deleted file mode 100644 index 4e0f5f8d1..000000000 --- a/src/main/resources/assets/flywheel/flywheel/compute/mat.glsl +++ /dev/null @@ -1,50 +0,0 @@ -/* -This is what generated ubershaders should look like - -uint flw_materialVertexID = 0; -uint flw_materialFragmentID = 0; - -void flw_materialVertex() { - switch (flw_materialVertexID) { - case 0: flw_materialVertex_flywheel_cutout_vert(); break; - default: break; - } -} - -void flw_materialFragment() { - switch (flw_materialFragmentID) { - case 0: flw_materialFragment_flywheel_cutout_frag(); break; - default: break; - } -} - -bool flw_discardPredicate(vec4 finalColor) { - switch (flw_materialFragmentID) { - case 0: return flw_discardPredicate_flywheel_cutout_frag(finalColor); - default: return false; - } -} - -vec4 flw_fogFilter(vec4 color) { - switch (flw_materialFragmentID) { - case 0: return flw_fogFilter_flywheel_cutout_frag(color); - default: return color; - } -} - - -void flw_materialVertex_flywheel_cutout_vert() { -} - -void flw_materialFragment_flywheel_cutout_frag() { -} - -bool flw_discardPredicate_flywheel_cutout_frag(vec4 finalColor) { - return finalColor.a < 0.1; -} - -vec4 flw_fogFilter_flywheel_cutout_frag(vec4 color) { - return linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor); -} - -*/ diff --git a/src/main/resources/assets/flywheel/flywheel/compute/sphere_cull_frustum_experiment.glsl b/src/main/resources/assets/flywheel/flywheel/compute/sphere_cull_frustum_experiment.glsl deleted file mode 100644 index 43ef57f8b..000000000 --- a/src/main/resources/assets/flywheel/flywheel/compute/sphere_cull_frustum_experiment.glsl +++ /dev/null @@ -1,72 +0,0 @@ -#version 450 -#define FLW_SUBGROUP_SIZE 32 - -layout(local_size_x = FLW_SUBGROUP_SIZE) in; - - -// in uvec3 gl_NumWorkGroups; -// in uvec3 gl_WorkGroupID; -// in uvec3 gl_LocalInvocationID; -// in uvec3 gl_GlobalInvocationID; -// in uint gl_LocalInvocationIndex; - -layout(std430, binding = 0) buffer Frustum1 { - vec4 a1; // vec4(nx.x, px.x, ny.x, py.x) - vec4 a2; // vec4(nx.y, px.y, ny.y, py.y) - vec4 a3; // vec4(nx.z, px.z, ny.z, py.z) - vec4 a4; // vec4(nx.w, px.w, ny.w, py.w) - vec2 b1; // vec2(nz.x, pz.x) - vec2 b2; // vec2(nz.y, pz.y) - vec2 b3; // vec2(nz.z, pz.z) - vec2 b4; // vec2(nz.w, pz.w) -} frustum1; - -layout(binding = 1) buffer Frustum2 { - vec4 nx; - vec4 px; - vec4 ny; - vec4 py; - vec4 nz; - vec4 pz; -} frustum2; - -layout(binding = 2) buffer Result { - bool res1; - bool res2; - bool res3; -} result; - -// 83 - 27 = 56 spirv instruction results -bool testSphere1(vec4 sphere) { - return - all(lessThanEqual(fma(frustum1.a1, sphere.xxxx, fma(frustum1.a2, sphere.yyyy, fma(frustum1.a3, sphere.zzzz, frustum1.a4))), -sphere.wwww)) && - all(lessThanEqual(fma(frustum1.b1, sphere.xx, fma(frustum1.b2, sphere.yy, fma(frustum1.b3, sphere.zz, frustum1.b4))), -sphere.ww)); -} - -// 236 - 92 = 144 spirv instruction results -bool testSphere2(vec4 sphere) { - return - fma(frustum2.nx.x, sphere.x, fma(frustum2.nx.y, sphere.y, fma(frustum2.nx.z, sphere.z, frustum2.nx.w))) >= -sphere.w && - fma(frustum2.px.x, sphere.x, fma(frustum2.px.y, sphere.y, fma(frustum2.px.z, sphere.z, frustum2.px.w))) >= -sphere.w && - fma(frustum2.ny.x, sphere.x, fma(frustum2.ny.y, sphere.y, fma(frustum2.ny.z, sphere.z, frustum2.ny.w))) >= -sphere.w && - fma(frustum2.py.x, sphere.x, fma(frustum2.py.y, sphere.y, fma(frustum2.py.z, sphere.z, frustum2.py.w))) >= -sphere.w && - fma(frustum2.nz.x, sphere.x, fma(frustum2.nz.y, sphere.y, fma(frustum2.nz.z, sphere.z, frustum2.nz.w))) >= -sphere.w && - fma(frustum2.pz.x, sphere.x, fma(frustum2.pz.y, sphere.y, fma(frustum2.pz.z, sphere.z, frustum2.pz.w))) >= -sphere.w; -} - -// 322 - 240 = 82 spirv instruction results -bool testSphere3(vec4 sphere) { - return - (dot(frustum2.nx.xyz, sphere.xyz) + frustum2.nx.w) >= -sphere.w && - (dot(frustum2.px.xyz, sphere.xyz) + frustum2.px.w) >= -sphere.w && - (dot(frustum2.ny.xyz, sphere.xyz) + frustum2.ny.w) >= -sphere.w && - (dot(frustum2.py.xyz, sphere.xyz) + frustum2.py.w) >= -sphere.w && - (dot(frustum2.nz.xyz, sphere.xyz) + frustum2.nz.w) >= -sphere.w && - (dot(frustum2.pz.xyz, sphere.xyz) + frustum2.pz.w) >= -sphere.w; -} - -void main() { - result.res1 = testSphere1(vec4(0., 1., 0., 1.)); - result.res2 = testSphere2(vec4(0., 1., 0., 1.)); - result.res3 = testSphere3(vec4(0., 1., 0., 1.)); -} diff --git a/src/main/resources/assets/flywheel/flywheel/debug/debug.frag b/src/main/resources/assets/flywheel/flywheel/debug/debug.frag deleted file mode 100644 index ab41dc91f..000000000 --- a/src/main/resources/assets/flywheel/flywheel/debug/debug.frag +++ /dev/null @@ -1,5 +0,0 @@ -out vec4 fragColor; - -void main() { - fragColor = vec4(1.0, 1.0, 1.0, 0.2); -} diff --git a/src/main/resources/assets/flywheel/flywheel/debug/debug.vert b/src/main/resources/assets/flywheel/flywheel/debug/debug.vert deleted file mode 100644 index d6c1e3380..000000000 --- a/src/main/resources/assets/flywheel/flywheel/debug/debug.vert +++ /dev/null @@ -1,5 +0,0 @@ -layout(location = 0) in vec3 worldPos; - -void main() { - gl_Position = flywheel.viewProjection * vec4(worldPos, 1.0); -} diff --git a/src/main/resources/assets/flywheel/flywheel/pipeline/draw.frag b/src/main/resources/assets/flywheel/flywheel/internal/draw.frag similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/pipeline/draw.frag rename to src/main/resources/assets/flywheel/flywheel/internal/draw.frag diff --git a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl b/src/main/resources/assets/flywheel/flywheel/internal/indirect_cull.glsl similarity index 91% rename from src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl rename to src/main/resources/assets/flywheel/flywheel/internal/indirect_cull.glsl index 0362e33da..a8d3df9df 100644 --- a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl +++ b/src/main/resources/assets/flywheel/flywheel/internal/indirect_cull.glsl @@ -1,8 +1,8 @@ #define FLW_SUBGROUP_SIZE 32 layout(local_size_x = FLW_SUBGROUP_SIZE) in; -#use "flywheel:api/cull.glsl" + #use "flywheel:util/types.glsl" -#use "flywheel:pipeline/indirect_draw_command.glsl" +#use "flywheel:internal/indirect_draw_command.glsl" // populated by instancers layout(std430, binding = 0) restrict readonly buffer ObjectBuffer { @@ -21,6 +21,9 @@ layout(std430, binding = 3) restrict buffer DrawCommands { MeshDrawCommand drawCommands[]; }; +uint flw_objectID; +uint flw_batchID; + // 83 - 27 = 56 spirv instruction results bool testSphere(vec3 center, float radius) { bvec4 xyInside = greaterThanEqual(fma(flywheel.planes.xyX, center.xxxx, fma(flywheel.planes.xyY, center.yyyy, fma(flywheel.planes.xyZ, center.zzzz, flywheel.planes.xyW))), -radius.xxxx); @@ -36,7 +39,7 @@ bool isVisible() { float radius; unpackBoundingSphere(sphere, center, radius); - FlwInstance object = flw_unpackInstance(objects[flw_objectID]); + FlwInstance object = _flw_unpackInstance(objects[flw_objectID]); flw_transformBoundingSphere(object, center, radius); return testSphere(center, radius); diff --git a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw.vert b/src/main/resources/assets/flywheel/flywheel/internal/indirect_draw.vert similarity index 72% rename from src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw.vert rename to src/main/resources/assets/flywheel/flywheel/internal/indirect_draw.vert index 84abac66d..8b7230209 100644 --- a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw.vert +++ b/src/main/resources/assets/flywheel/flywheel/internal/indirect_draw.vert @@ -1,5 +1,5 @@ #use "flywheel:api/vertex.glsl" -#use "flywheel:pipeline/indirect_draw_command.glsl" +#use "flywheel:internal/indirect_draw_command.glsl" layout(std430, binding = 0) restrict readonly buffer ObjectBuffer { FlwPackedInstance objects[]; @@ -20,10 +20,10 @@ layout(std430, binding = 3) restrict readonly buffer DrawCommands { void main() { uint instanceIndex = objectIDs[gl_BaseInstance + gl_InstanceID]; uint batchID = batchIDs[instanceIndex]; - FlwInstance i = flw_unpackInstance(objects[instanceIndex]); + FlwInstance i = _flw_unpackInstance(objects[instanceIndex]); - flw_materialVertexID = drawCommands[batchID].vertexMaterialID; - flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID; + _flw_materialVertexID = drawCommands[batchID].vertexMaterialID; + _flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID; flw_layoutVertex(); flw_instanceVertex(i); diff --git a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw_command.glsl b/src/main/resources/assets/flywheel/flywheel/internal/indirect_draw_command.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw_command.glsl rename to src/main/resources/assets/flywheel/flywheel/internal/indirect_draw_command.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/pipeline/instanced_arrays_draw.vert b/src/main/resources/assets/flywheel/flywheel/internal/instanced_arrays_draw.vert similarity index 54% rename from src/main/resources/assets/flywheel/flywheel/pipeline/instanced_arrays_draw.vert rename to src/main/resources/assets/flywheel/flywheel/internal/instanced_arrays_draw.vert index 4e69ffbc7..a3680d8d4 100644 --- a/src/main/resources/assets/flywheel/flywheel/pipeline/instanced_arrays_draw.vert +++ b/src/main/resources/assets/flywheel/flywheel/internal/instanced_arrays_draw.vert @@ -5,10 +5,10 @@ uniform uvec2 _flw_materialID_instancing; void main() { flw_layoutVertex(); - flw_materialVertexID = _flw_materialID_instancing.x; - flw_materialFragmentID = _flw_materialID_instancing.y; + _flw_materialVertexID = _flw_materialID_instancing.x; + _flw_materialFragmentID = _flw_materialID_instancing.y; - FlwInstance i = flw_unpackInstance(); + FlwInstance i = _flw_unpackInstance(); flw_instanceVertex(i); flw_materialVertex(); flw_contextVertex(); diff --git a/src/main/resources/assets/flywheel/flywheel/uniform/flywheel.glsl b/src/main/resources/assets/flywheel/flywheel/uniform/flywheel.glsl index 645929821..0032a6388 100644 --- a/src/main/resources/assets/flywheel/flywheel/uniform/flywheel.glsl +++ b/src/main/resources/assets/flywheel/flywheel/uniform/flywheel.glsl @@ -1,12 +1,12 @@ struct FLWPackedPlanes { - vec4 xyX;// - vec4 xyY;// - vec4 xyZ;// - vec4 xyW;// - vec2 zX;// - vec2 zY;// - vec2 zZ;// - vec2 zW;// + vec4 xyX; // + vec4 xyY; // + vec4 xyZ; // + vec4 xyW; // + vec2 zX; // + vec2 zY; // + vec2 zZ; // + vec2 zW; // }; struct flywheel_uniforms {