From 863958fb004e9ca003331c2d02be8a0b548ad0a8 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Thu, 18 May 2023 00:03:53 -0700 Subject: [PATCH] Building shade - Use builder pattern for defining shader compiler flows - If only java had type inference extending to builders :whywheel: - Support glsl 330 on instancing again - Set uniform block binding at link time - Remove associated glsl builder code - Use explicit uint literals in material adapter switch cases - No need to enable GL_ARB_explicit_attrib_location --- .../flywheel/api/context/Context.java | 4 +- ...tCompiler.java => CompilationHarness.java} | 21 ++- .../flywheel/backend/compile/Compile.java | 132 +++++++++++++ .../backend/compile/CullingCompiler.java | 59 ------ .../flywheel/backend/compile/FlwPrograms.java | 6 +- .../backend/compile/IndirectPrograms.java | 28 ++- .../backend/compile/InstancingPrograms.java | 5 +- .../backend/compile/PipelineCompiler.java | 173 +++--------------- .../flywheel/backend/compile/Pipelines.java | 2 +- .../component/MaterialAdapterComponent.java | 2 +- .../compile/component/UniformComponent.java | 1 - .../backend/compile/core/ProgramLinker.java | 6 +- .../backend/compile/core/ShaderCompiler.java | 1 - .../backend/compile/package-info.java | 6 + .../flywheel/gl/shader/GlProgram.java | 20 +- .../flywheel/glsl/generate/GlslExpr.java | 21 ++- .../flywheel/glsl/generate/GlslSwitch.java | 8 +- .../glsl/generate/GlslUniformBlock.java | 28 +-- .../flywheel/util/NonNullSupplier.java | 1 - .../flywheel/util/NotNullFunction.java | 8 + 20 files changed, 276 insertions(+), 256 deletions(-) rename src/main/java/com/jozufozu/flywheel/backend/compile/{AbstractCompiler.java => CompilationHarness.java} (68%) create mode 100644 src/main/java/com/jozufozu/flywheel/backend/compile/Compile.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/compile/CullingCompiler.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/compile/package-info.java create mode 100644 src/main/java/com/jozufozu/flywheel/util/NotNullFunction.java diff --git a/src/main/java/com/jozufozu/flywheel/api/context/Context.java b/src/main/java/com/jozufozu/flywheel/api/context/Context.java index fe60f9294..caa031a5a 100644 --- a/src/main/java/com/jozufozu/flywheel/api/context/Context.java +++ b/src/main/java/com/jozufozu/flywheel/api/context/Context.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.api.context; +import org.jetbrains.annotations.NotNull; + import com.jozufozu.flywheel.api.registry.Registry; import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.impl.RegistryImpl; @@ -9,7 +11,7 @@ import net.minecraft.resources.ResourceLocation; public interface Context { static Registry REGISTRY = RegistryImpl.create(); - void onProgramLink(GlProgram program); + void onProgramLink(@NotNull GlProgram program); ResourceLocation vertexShader(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/AbstractCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/compile/CompilationHarness.java similarity index 68% rename from src/main/java/com/jozufozu/flywheel/backend/compile/AbstractCompiler.java rename to src/main/java/com/jozufozu/flywheel/backend/compile/CompilationHarness.java index 09924ca12..5aebabf8e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/AbstractCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/CompilationHarness.java @@ -13,30 +13,29 @@ import com.jozufozu.flywheel.backend.compile.core.ShaderCompiler; import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.glsl.ShaderSources; -public abstract class AbstractCompiler { - protected final SourceLoader sourceLoader; - protected final ShaderCompiler shaderCompiler; - protected final ProgramLinker programLinker; +public class CompilationHarness { + private final KeyCompiler compiler; + private final SourceLoader sourceLoader; + private final ShaderCompiler shaderCompiler; + private final ProgramLinker programLinker; private final ImmutableList keys; private final CompilerStats stats = new CompilerStats(); - public AbstractCompiler(ShaderSources sources, ImmutableList keys) { + public CompilationHarness(ShaderSources sources, ImmutableList keys, KeyCompiler compiler) { this.keys = keys; + this.compiler = compiler; sourceLoader = new SourceLoader(sources, stats); shaderCompiler = new ShaderCompiler(stats); programLinker = new ProgramLinker(stats); } - @Nullable - protected abstract GlProgram compile(K key); - @Nullable public Map compileAndReportErrors() { stats.start(); Map out = new HashMap<>(); for (var key : keys) { - GlProgram glProgram = compile(key); + GlProgram glProgram = compiler.compile(key, sourceLoader, shaderCompiler, programLinker); if (out != null && glProgram != null) { out.put(key, glProgram); } else { @@ -56,4 +55,8 @@ public abstract class AbstractCompiler { public void delete() { shaderCompiler.delete(); } + + public interface KeyCompiler { + @Nullable GlProgram compile(K key, SourceLoader loader, ShaderCompiler shaderCompiler, ProgramLinker programLinker); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/Compile.java b/src/main/java/com/jozufozu/flywheel/backend/compile/Compile.java new file mode 100644 index 000000000..6ccfbdddf --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/Compile.java @@ -0,0 +1,132 @@ +package com.jozufozu.flywheel.backend.compile; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; + +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.backend.compile.core.ProgramLinker; +import com.jozufozu.flywheel.backend.compile.core.ShaderCompiler; +import com.jozufozu.flywheel.gl.shader.GlProgram; +import com.jozufozu.flywheel.gl.shader.GlShader; +import com.jozufozu.flywheel.gl.shader.ShaderType; +import com.jozufozu.flywheel.glsl.GLSLVersion; +import com.jozufozu.flywheel.glsl.SourceComponent; +import com.jozufozu.flywheel.util.NotNullFunction; + +import net.minecraft.resources.ResourceLocation; + +public class Compile { + public static ShaderCompilerBuilder shader(GLSLVersion glslVersion, ShaderType shaderType) { + return new ShaderCompilerBuilder<>(glslVersion, shaderType); + } + + public static ProgramLinkBuilder program() { + return new ProgramLinkBuilder<>(); + } + + public static class ProgramLinkBuilder implements CompilationHarness.KeyCompiler { + private final Map> compilers = new EnumMap<>(ShaderType.class); + private BiConsumer onLink = (k, p) -> { + }; + + public ProgramLinkBuilder link(ShaderCompilerBuilder compilerBuilder) { + if (compilers.containsKey(compilerBuilder.shaderType)) { + throw new IllegalArgumentException("Duplicate shader type: " + compilerBuilder.shaderType); + } + compilers.put(compilerBuilder.shaderType, compilerBuilder); + return this; + } + + public ProgramLinkBuilder then(BiConsumer onLink) { + this.onLink = onLink; + return this; + } + + @Override + @Nullable + public GlProgram compile(K key, SourceLoader loader, ShaderCompiler shaderCompiler, ProgramLinker programLinker) { + if (compilers.isEmpty()) { + throw new IllegalStateException("No shader compilers were added!"); + } + + List shaders = new ArrayList<>(); + + boolean ok = true; + for (ShaderCompilerBuilder compiler : compilers.values()) { + var shader = compiler.compile(key, shaderCompiler, loader); + if (shader == null) { + ok = false; + } + shaders.add(shader); + } + + if (!ok) { + return null; + } + + var out = programLinker.link(shaders); + + if (out != null) { + onLink.accept(key, out); + } + + return out; + } + } + + public static class ShaderCompilerBuilder { + private final GLSLVersion glslVersion; + private final ShaderType shaderType; + private final List> fetchers = new ArrayList<>(); + + public ShaderCompilerBuilder(GLSLVersion glslVersion, ShaderType shaderType) { + this.glslVersion = glslVersion; + this.shaderType = shaderType; + } + + public ShaderCompilerBuilder with(BiFunction fetch) { + fetchers.add(fetch); + return this; + } + + public ShaderCompilerBuilder withComponent(SourceComponent component) { + return withComponent($ -> component); + } + + public ShaderCompilerBuilder withComponent(NotNullFunction sourceFetcher) { + return with((key, $) -> sourceFetcher.apply(key)); + } + + public ShaderCompilerBuilder withResource(NotNullFunction sourceFetcher) { + return with((key, loader) -> loader.find(sourceFetcher.apply(key))); + } + + public ShaderCompilerBuilder withResource(ResourceLocation resourceLocation) { + return withResource($ -> resourceLocation); + } + + @Nullable + private GlShader compile(K key, ShaderCompiler compiler, SourceLoader loader) { + var components = new ArrayList(); + boolean ok = true; + for (var fetcher : fetchers) { + SourceComponent apply = fetcher.apply(key, loader); + if (apply == null) { + ok = false; + } + components.add(apply); + } + + if (!ok) { + return null; + } + + return compiler.compile(glslVersion, shaderType, components); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/CullingCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/compile/CullingCompiler.java deleted file mode 100644 index 3ba003536..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/CullingCompiler.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.jozufozu.flywheel.backend.compile; - -import org.jetbrains.annotations.Nullable; - -import com.google.common.collect.ImmutableList; -import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.backend.compile.component.IndirectComponent; -import com.jozufozu.flywheel.backend.compile.component.UniformComponent; -import com.jozufozu.flywheel.gl.shader.GlProgram; -import com.jozufozu.flywheel.gl.shader.ShaderType; -import com.jozufozu.flywheel.glsl.GLSLVersion; -import com.jozufozu.flywheel.glsl.ShaderSources; -import com.jozufozu.flywheel.glsl.SourceFile; - -import net.minecraft.resources.ResourceLocation; - -public class CullingCompiler extends AbstractCompiler> { - private final UniformComponent uniformComponent; - private final SourceFile pipelineCompute; - - public static CullingCompiler create(SourceLoader sourceLoader, ImmutableList> keys, UniformComponent uniformComponent) { - var sourceFile = sourceLoader.find(Files.INDIRECT_CULL); - - return new CullingCompiler(sourceLoader.sources, keys, uniformComponent, sourceFile); - } - - private CullingCompiler(ShaderSources sources, ImmutableList> keys, UniformComponent uniformComponent, SourceFile pipeline) { - super(sources, keys); - - this.uniformComponent = uniformComponent; - this.pipelineCompute = pipeline; - } - - @Nullable - @Override - protected GlProgram compile(InstanceType key) { - var instanceAssembly = IndirectComponent.create(key); - ResourceLocation rl = key.instanceShader(); - var instance = sourceLoader.find(rl); - - if (instance == null || uniformComponent == null || pipelineCompute == null) { - return null; - } - - var computeComponents = ImmutableList.of(uniformComponent, instanceAssembly, instance, pipelineCompute); - var compute = shaderCompiler.compile(GLSLVersion.V460, ShaderType.COMPUTE, computeComponents); - - if (compute == null) { - return null; - } - - return programLinker.link(compute); - } - - private static final class Files { - public static final ResourceLocation INDIRECT_CULL = Flywheel.rl("internal/indirect_cull.glsl"); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java index 082250e0e..c42f4a254 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java @@ -31,8 +31,8 @@ public class FlwPrograms { var vertexMaterialComponent = createVertexMaterialComponent(loadChecker); var fragmentMaterialComponent = createFragmentMaterialComponent(loadChecker); - InstancingPrograms.reload(loadChecker, pipelineKeys, uniformComponent, vertexMaterialComponent, fragmentMaterialComponent); - IndirectPrograms.reload(loadChecker, pipelineKeys, uniformComponent, vertexMaterialComponent, fragmentMaterialComponent); + InstancingPrograms.reload(sources, pipelineKeys, uniformComponent, vertexMaterialComponent, fragmentMaterialComponent); + IndirectPrograms.reload(sources, pipelineKeys, uniformComponent, vertexMaterialComponent, fragmentMaterialComponent); if (preLoadStats.errored()) { Flywheel.LOGGER.error(preLoadStats.generateErrorLog()); @@ -47,7 +47,7 @@ public class FlwPrograms { .returnType("bool") .name("flw_discardPredicate") .arg("vec4", "color") - .build(), GlslExpr.literal(false)) + .build(), GlslExpr.boolLiteral(false)) .adapt(FnSignature.create() .returnType("vec4") .name("flw_fogFilter") diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/IndirectPrograms.java b/src/main/java/com/jozufozu/flywheel/backend/compile/IndirectPrograms.java index b1503a55a..650016caf 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/IndirectPrograms.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/IndirectPrograms.java @@ -9,9 +9,15 @@ import com.jozufozu.flywheel.Flywheel; 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.component.IndirectComponent; import com.jozufozu.flywheel.backend.compile.component.MaterialAdapterComponent; import com.jozufozu.flywheel.backend.compile.component.UniformComponent; import com.jozufozu.flywheel.gl.shader.GlProgram; +import com.jozufozu.flywheel.gl.shader.ShaderType; +import com.jozufozu.flywheel.glsl.GLSLVersion; +import com.jozufozu.flywheel.glsl.ShaderSources; + +import net.minecraft.resources.ResourceLocation; public class IndirectPrograms { public static IndirectPrograms instance; @@ -23,10 +29,10 @@ public class IndirectPrograms { this.culling = culling; } - static void reload(SourceLoader loadChecker, ImmutableList pipelineKeys, UniformComponent uniformComponent, MaterialAdapterComponent vertexMaterialComponent, MaterialAdapterComponent fragmentMaterialComponent) { + static void reload(ShaderSources sources, ImmutableList pipelineKeys, UniformComponent uniformComponent, MaterialAdapterComponent vertexMaterialComponent, MaterialAdapterComponent fragmentMaterialComponent) { _delete(); - var pipelineCompiler = PipelineCompiler.create(loadChecker, Pipelines.INDIRECT, pipelineKeys, uniformComponent, vertexMaterialComponent, fragmentMaterialComponent); - var cullingCompiler = CullingCompiler.create(loadChecker, createCullingKeys(), uniformComponent); + var pipelineCompiler = PipelineCompiler.create(sources, Pipelines.INDIRECT, pipelineKeys, uniformComponent, vertexMaterialComponent, fragmentMaterialComponent); + var cullingCompiler = createCullingCompiler(uniformComponent, sources); try { var pipelineResult = pipelineCompiler.compileAndReportErrors(); @@ -66,6 +72,18 @@ public class IndirectPrograms { } } + private static CompilationHarness> createCullingCompiler(UniformComponent uniformComponent, ShaderSources sources) { + return new CompilationHarness<>(sources, createCullingKeys(), Compile.>program() + .link(Compile.>shader(GLSLVersion.V460, ShaderType.COMPUTE) + .withComponent(uniformComponent) + .withComponent(IndirectComponent::create) + .withResource(InstanceType::instanceShader) + .withResource(Files.INDIRECT_CULL)) + .then((InstanceType key, GlProgram program) -> { + program.setUniformBlockBinding("FLWUniforms", 0); + })); + } + public GlProgram getIndirectProgram(VertexType vertexType, InstanceType instanceType, Context contextShader) { return pipeline.get(new PipelineProgramKey(vertexType, instanceType, contextShader)); } @@ -80,4 +98,8 @@ public class IndirectPrograms { culling.values() .forEach(GlProgram::delete); } + + private static final class Files { + public static final ResourceLocation INDIRECT_CULL = Flywheel.rl("internal/indirect_cull.glsl"); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/InstancingPrograms.java b/src/main/java/com/jozufozu/flywheel/backend/compile/InstancingPrograms.java index 75558eb6d..c2900ae69 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/InstancingPrograms.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/InstancingPrograms.java @@ -12,6 +12,7 @@ import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.compile.component.MaterialAdapterComponent; import com.jozufozu.flywheel.backend.compile.component.UniformComponent; import com.jozufozu.flywheel.gl.shader.GlProgram; +import com.jozufozu.flywheel.glsl.ShaderSources; public class InstancingPrograms { static InstancingPrograms instance; @@ -21,9 +22,9 @@ public class InstancingPrograms { this.pipeline = pipeline; } - static void reload(SourceLoader loadChecker, ImmutableList pipelineKeys, UniformComponent uniformComponent, MaterialAdapterComponent vertexMaterialComponent, MaterialAdapterComponent fragmentMaterialComponent) { + static void reload(ShaderSources sources, ImmutableList pipelineKeys, UniformComponent uniformComponent, MaterialAdapterComponent vertexMaterialComponent, MaterialAdapterComponent fragmentMaterialComponent) { _delete(); - var instancingCompiler = PipelineCompiler.create(loadChecker, Pipelines.INSTANCED_ARRAYS, pipelineKeys, uniformComponent, vertexMaterialComponent, fragmentMaterialComponent); + var instancingCompiler = PipelineCompiler.create(sources, Pipelines.INSTANCED_ARRAYS, pipelineKeys, uniformComponent, vertexMaterialComponent, fragmentMaterialComponent); try { var result = instancingCompiler.compileAndReportErrors(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java index 6a0648295..63393874b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java @@ -1,158 +1,37 @@ package com.jozufozu.flywheel.backend.compile; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.jetbrains.annotations.Nullable; - import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.backend.compile.component.MaterialAdapterComponent; import com.jozufozu.flywheel.backend.compile.component.UniformComponent; import com.jozufozu.flywheel.gl.shader.GlProgram; -import com.jozufozu.flywheel.gl.shader.GlShader; import com.jozufozu.flywheel.gl.shader.ShaderType; import com.jozufozu.flywheel.glsl.ShaderSources; -import com.jozufozu.flywheel.glsl.SourceComponent; -import net.minecraft.resources.ResourceLocation; - -public class PipelineCompiler extends AbstractCompiler { - private final Pipeline pipeline; - private final List vertexPrelude = new ArrayList<>(); - private final List vertexPostlude = new ArrayList<>(); - private final List fragmentPrelude = new ArrayList<>(); - private final List fragmentPostlude = new ArrayList<>(); - - public PipelineCompiler(ShaderSources sources, ImmutableList keys, Pipeline pipeline) { - super(sources, keys); - this.pipeline = pipeline; - } - - static PipelineCompiler create(SourceLoader sourceLoader, Pipeline pipeline, ImmutableList pipelineKeys, UniformComponent uniformComponent, MaterialAdapterComponent vertexMaterialComponent, MaterialAdapterComponent fragmentMaterialComponent) { - var fragmentPipeline = sourceLoader.find(pipeline.fragmentShader()); - var vertexPipeline = sourceLoader.find(pipeline.vertexShader()); - - return new PipelineCompiler(sourceLoader.sources, pipelineKeys, pipeline).addPrelude(uniformComponent) - .addFragmentPrelude(fragmentMaterialComponent) - .addVertexPrelude(vertexMaterialComponent) - .addFragmentPostlude(fragmentPipeline) - .addVertexPostlude(vertexPipeline); - } - - public PipelineCompiler addPrelude(SourceComponent component) { - addVertexPrelude(component); - addFragmentPrelude(component); - return this; - } - - public PipelineCompiler addVertexPrelude(SourceComponent component) { - vertexPrelude.add(component); - return this; - } - - public PipelineCompiler addVertexPostlude(SourceComponent component) { - vertexPostlude.add(component); - return this; - } - - public PipelineCompiler addFragmentPrelude(SourceComponent component) { - fragmentPrelude.add(component); - return this; - } - - public PipelineCompiler addFragmentPostlude(SourceComponent component) { - fragmentPostlude.add(component); - return this; - } - - @Nullable - @Override - protected GlProgram compile(PipelineProgramKey key) { - GlShader vertex = compileVertex(key); - GlShader fragment = compileFragment(key); - - if (vertex == null || fragment == null) { - return null; - } - - var glProgram = programLinker.link(vertex, fragment); - key.contextShader() - .onProgramLink(glProgram); - return glProgram; - } - - @Nullable - private GlShader compileVertex(PipelineProgramKey key) { - var vertexComponents = getVertexComponents(key); - if (vertexComponents == null) { - return null; - } - - return shaderCompiler.compile(pipeline.glslVersion(), ShaderType.VERTEX, vertexComponents); - } - - @Nullable - private GlShader compileFragment(PipelineProgramKey key) { - var fragmentComponents = getFragmentComponents(key); - if (fragmentComponents == null) { - return null; - } - - return shaderCompiler.compile(pipeline.glslVersion(), ShaderType.FRAGMENT, fragmentComponents); - } - - @Nullable - private List getVertexComponents(PipelineProgramKey key) { - var instanceAssembly = pipeline.assembler() - .assemble(new Pipeline.InstanceAssemblerContext(key.vertexType(), key.instanceType())); - - var layout = sourceLoader.find(key.vertexType() - .layoutShader()); - var instance = sourceLoader.find(key.instanceType() - .instanceShader()); - var context = sourceLoader.find(key.contextShader() - .vertexShader()); - - if (instanceAssembly == null || layout == null || instance == null || context == null) { - return null; - } - - // Check this here to do a full dry-run in case of a preloading error. - if (vertexPrelude.stream() - .anyMatch(Objects::isNull) || vertexPostlude.stream() - .anyMatch(Objects::isNull)) { - return null; - } - - return ImmutableList.builder() - .addAll(vertexPrelude) - .add(instanceAssembly, layout, instance, context) - .addAll(vertexPostlude) - .build(); - } - - @Nullable - private List getFragmentComponents(PipelineProgramKey key) { - ResourceLocation rl = key.contextShader() - .fragmentShader(); - var context = sourceLoader.find(rl); - - if (context == null) { - return null; - } - - // Check this here to do a full dry-run in case of a preloading error. - if (fragmentPrelude.stream() - .anyMatch(Objects::isNull) || fragmentPostlude.stream() - .anyMatch(Objects::isNull)) { - return null; - } - - return ImmutableList.builder() - .addAll(fragmentPrelude) - .add(context) - .addAll(fragmentPostlude) - .build(); +public class PipelineCompiler { + static CompilationHarness create(ShaderSources sources, Pipeline pipeline, ImmutableList pipelineKeys, UniformComponent uniformComponent, MaterialAdapterComponent vertexMaterialComponent, MaterialAdapterComponent fragmentMaterialComponent) { + return new CompilationHarness<>(sources, pipelineKeys, Compile.program() + .link(Compile.shader(pipeline.glslVersion(), ShaderType.VERTEX) + .withComponent(uniformComponent) + .withComponent(vertexMaterialComponent) + .withComponent(key -> pipeline.assembler() + .assemble(new Pipeline.InstanceAssemblerContext(key.vertexType(), key.instanceType()))) + .withResource(key -> key.vertexType() + .layoutShader()) + .withResource(key -> key.instanceType() + .instanceShader()) + .withResource(key -> key.contextShader() + .vertexShader()) + .withResource(pipeline.vertexShader())) + .link(Compile.shader(pipeline.glslVersion(), ShaderType.FRAGMENT) + .withComponent(uniformComponent) + .withComponent(fragmentMaterialComponent) + .withResource(key -> key.contextShader() + .fragmentShader()) + .withResource(pipeline.fragmentShader())) + .then((PipelineProgramKey key, GlProgram program) -> { + key.contextShader() + .onProgramLink(program); + program.setUniformBlockBinding("FLWUniforms", 0); + })); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/Pipelines.java b/src/main/java/com/jozufozu/flywheel/backend/compile/Pipelines.java index 02ec49bf6..04ad2d099 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/Pipelines.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/Pipelines.java @@ -9,7 +9,7 @@ import net.minecraft.resources.ResourceLocation; public final class Pipelines { public static final Pipeline INSTANCED_ARRAYS = Pipeline.builder() - .glslVersion(GLSLVersion.V420) + .glslVersion(GLSLVersion.V330) .vertex(Files.INSTANCED_ARRAYS_DRAW) .fragment(Files.DRAW_FRAGMENT) .assembler(InstancedArraysComponent::new) diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/component/MaterialAdapterComponent.java b/src/main/java/com/jozufozu/flywheel/backend/compile/component/MaterialAdapterComponent.java index ce834dd30..84f6d9f9d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/component/MaterialAdapterComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/component/MaterialAdapterComponent.java @@ -87,7 +87,7 @@ public class MaterialAdapterComponent implements SourceComponent { block.ret(adaptedCall); } - sw.intCase(i, block); + sw.uintCase(i, block); } if (!isVoid) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/component/UniformComponent.java b/src/main/java/com/jozufozu/flywheel/backend/compile/component/UniformComponent.java index fae9cc9e6..1552bddf3 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/component/UniformComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/component/UniformComponent.java @@ -36,7 +36,6 @@ public class UniformComponent implements SourceComponent { builder.uniformBlock() .layout("std140") - .binding(0) .name("FLWUniforms") .member("flywheel_uniforms", "flywheel"); diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/core/ProgramLinker.java b/src/main/java/com/jozufozu/flywheel/backend/compile/core/ProgramLinker.java index b04065fb7..424730f46 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/core/ProgramLinker.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/core/ProgramLinker.java @@ -8,6 +8,8 @@ import static org.lwjgl.opengl.GL20.glGetProgramInfoLog; import static org.lwjgl.opengl.GL20.glGetProgrami; import static org.lwjgl.opengl.GL20.glLinkProgram; +import java.util.List; + import org.jetbrains.annotations.Nullable; import com.jozufozu.flywheel.gl.shader.GlProgram; @@ -21,14 +23,14 @@ public class ProgramLinker { } @Nullable - public GlProgram link(GlShader... shaders) { + public GlProgram link(List shaders) { // this probably doesn't need caching var linkResult = linkInternal(shaders); stats.linkResult(linkResult); return linkResult.unwrap(); } - private LinkResult linkInternal(GlShader... shaders) { + private LinkResult linkInternal(List shaders) { int handle = glCreateProgram(); for (GlShader shader : shaders) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/core/ShaderCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/compile/core/ShaderCompiler.java index 8fec7bec8..16803c88e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/core/ShaderCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/core/ShaderCompiler.java @@ -32,7 +32,6 @@ public class ShaderCompiler { } Compilation ctx = new Compilation(glslVersion, shaderType); - ctx.enableExtension("GL_ARB_explicit_attrib_location"); ctx.enableExtension("GL_ARB_conservative_depth"); expand(sourceComponents, ctx::appendComponent); diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/package-info.java b/src/main/java/com/jozufozu/flywheel/backend/compile/package-info.java new file mode 100644 index 000000000..4b1ce0738 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/package-info.java @@ -0,0 +1,6 @@ +@MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault +package com.jozufozu.flywheel.backend.compile; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/gl/shader/GlProgram.java index d2172a2cb..2bb8b4771 100644 --- a/src/main/java/com/jozufozu/flywheel/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/gl/shader/GlProgram.java @@ -1,8 +1,11 @@ package com.jozufozu.flywheel.gl.shader; -import static org.lwjgl.opengl.GL20.glDeleteProgram; -import static org.lwjgl.opengl.GL20.glGetUniformLocation; -import static org.lwjgl.opengl.GL20.glUniform1i; +import static org.lwjgl.opengl.GL31.GL_INVALID_INDEX; +import static org.lwjgl.opengl.GL31.glGetUniformBlockIndex; +import static org.lwjgl.opengl.GL31.glUniformBlockBinding; +import static org.lwjgl.opengl.GL32.glDeleteProgram; +import static org.lwjgl.opengl.GL32.glGetUniformLocation; +import static org.lwjgl.opengl.GL32.glUniform1i; import org.slf4j.Logger; @@ -55,6 +58,17 @@ public class GlProgram extends GlObject { } } + public void setUniformBlockBinding(String name, int binding) { + int index = glGetUniformBlockIndex(handle(), name); + + if (index == GL_INVALID_INDEX) { + LOGGER.debug("No active uniform block '{}' exists. Could be unused.", name); + return; + } + + glUniformBlockBinding(handle(), index, binding); + } + @Override protected void deleteInternal(int handle) { glDeleteProgram(handle); 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 4fd24414a..5103a6d86 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslExpr.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslExpr.java @@ -31,11 +31,15 @@ public interface GlslExpr { return new FunctionCall0(functionName); } - static GlslExpr literal(int expr) { + static GlslExpr intLiteral(int expr) { return new IntLiteral(expr); } - static GlslExpr literal(boolean expr) { + static GlslExpr uintLiteral(int expr) { + return new UIntLiteral(expr); + } + + static GlslExpr boolLiteral(boolean expr) { return new BoolLiteral(expr); } @@ -135,6 +139,19 @@ public interface GlslExpr { } } + record UIntLiteral(int value) implements GlslExpr { + public UIntLiteral { + if (value < 0) { + throw new IllegalArgumentException("UIntLiteral must be positive"); + } + } + + @Override + public String prettyPrint() { + return Integer.toString(value) + 'u'; + } + } + record BoolLiteral(boolean value) implements GlslExpr { @Override public String prettyPrint() { diff --git a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslSwitch.java b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslSwitch.java index 0aebc8327..a8e6ad8d4 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslSwitch.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslSwitch.java @@ -25,7 +25,11 @@ public class GlslSwitch implements GlslStmt { } public void intCase(int expr, GlslBlock block) { - cases.add(Pair.of(GlslExpr.literal(expr), block)); + cases.add(Pair.of(GlslExpr.intLiteral(expr), block)); + } + + public void uintCase(int expr, GlslBlock block) { + cases.add(Pair.of(GlslExpr.uintLiteral(expr), block)); } public void defaultCase(GlslBlock block) { @@ -35,7 +39,7 @@ public class GlslSwitch implements GlslStmt { @Override public String prettyPrint() { return """ - switch (%s) { + switch (%s) { %s }""".formatted(on.prettyPrint(), formatCases()); } 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 a139a08f9..c0a4026a5 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslUniformBlock.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/generate/GlslUniformBlock.java @@ -8,19 +8,16 @@ import com.jozufozu.flywheel.util.Pair; import com.jozufozu.flywheel.util.StringUtil; public class GlslUniformBlock implements GlslBuilder.Declaration { - - private String qualifier; - private int binding; - private String name; - private final List> members = new ArrayList<>(); + private String name; + private final List> members = new ArrayList<>(); @Override public String prettyPrint() { - return """ - layout(%s, binding = %d) uniform %s { - %s - };""".formatted(qualifier, binding, name, StringUtil.indent(formatMembers(), 4)); + return """ + layout(%s) uniform %s { + %s + };""".formatted(qualifier, name, StringUtil.indent(formatMembers(), 4)); } private String formatMembers() { @@ -34,15 +31,10 @@ public class GlslUniformBlock implements GlslBuilder.Declaration { return this; } - public GlslUniformBlock binding(int i) { - binding = i; - return this; - } - - public GlslUniformBlock name(String name) { - this.name = name; - return this; - } + public GlslUniformBlock name(String name) { + this.name = name; + return this; + } public GlslUniformBlock member(String typeName, String variableName) { members.add(Pair.of(typeName, variableName)); diff --git a/src/main/java/com/jozufozu/flywheel/util/NonNullSupplier.java b/src/main/java/com/jozufozu/flywheel/util/NonNullSupplier.java index c53e3d8c4..7c41f2404 100644 --- a/src/main/java/com/jozufozu/flywheel/util/NonNullSupplier.java +++ b/src/main/java/com/jozufozu/flywheel/util/NonNullSupplier.java @@ -4,7 +4,6 @@ import org.jetbrains.annotations.NotNull; @FunctionalInterface public interface NonNullSupplier { - @NotNull T get(); } diff --git a/src/main/java/com/jozufozu/flywheel/util/NotNullFunction.java b/src/main/java/com/jozufozu/flywheel/util/NotNullFunction.java new file mode 100644 index 000000000..fd83d37c3 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/NotNullFunction.java @@ -0,0 +1,8 @@ +package com.jozufozu.flywheel.util; + +import org.jetbrains.annotations.NotNull; + +@FunctionalInterface +public interface NotNullFunction { + @NotNull R apply(T t); +}