From 1b09c2c1eb74371541893d6c46c08b136014a5cd Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Fri, 31 Dec 2021 12:08:07 -0800 Subject: [PATCH] Compile everything on the fly - Simplify game state system - Need some way to re-add errors on load. - Streamline shader compilation, reduce map lookups - Move pipeline package from backend to core - Simplify interfaces and remove unnecessary classes --- .../flywheel/api/shader/FlexibleShader.java | 15 --- .../flywheel/backend/ShaderContext.java | 8 +- .../flywheel/backend/gl/shader/GlShader.java | 30 +---- .../instancing/InstancingEngine.java | 6 - .../backend/pipeline/LazyCompiler.java | 33 ------ .../flywheel/backend/pipeline/Shader.java | 6 - .../backend/pipeline/ShaderInput.java | 38 ------- .../backend/pipeline/ShaderPipeline.java | 16 --- .../backend/pipeline/WorldShaderPipeline.java | 40 ------- .../backend/source/FileResolution.java | 4 +- .../flywheel/backend/source/SourceFile.java | 20 +--- .../backend/source/error/ErrorBuilder.java | 2 +- .../com/jozufozu/flywheel/core/Contexts.java | 8 +- .../com/jozufozu/flywheel/core/Templates.java | 6 +- .../jozufozu/flywheel/core/WorldContext.java | 32 +++--- .../flywheel/core/materials/BasicData.java | 10 ++ .../core/pipeline/CachingCompiler.java | 38 +++++++ .../core/pipeline/CompilationContext.java | 35 ++++++ .../pipeline/InstancingTemplateData.java | 4 +- .../pipeline/OneShotTemplateData.java | 2 +- .../core/pipeline/PipelineCompiler.java | 13 +++ .../pipeline/ProgramAssembler.java | 2 +- .../pipeline/ShaderCompiler.java | 103 ++++++++++-------- .../{backend => core}/pipeline/Template.java | 2 +- .../pipeline/TemplateData.java | 2 +- .../pipeline/TypeHelper.java | 2 +- .../flywheel/core/pipeline/WorldCompiler.java | 33 ++++++ .../pipeline/package-info.java | 2 +- .../core/shader/ContextAwareProgram.java | 26 ----- .../core/shader/GameStateProgram.java | 62 ----------- .../shader/gamestate/IGameStateProvider.java | 2 +- .../gamestate/NormalDebugStateProvider.java | 3 +- .../spec/BooleanGameStateCondition.java | 37 ------- .../shader/spec/IBooleanStateProvider.java | 13 --- .../core/shader/spec/IGameStateCondition.java | 14 --- .../core/shader/spec/ProgramSpec.java | 40 ++++++- .../core/shader/spec/ProgramState.java | 21 +--- .../shader/spec/SpecificValueCondition.java | 43 -------- .../flywheel/flywheel/programs/model.json | 5 +- .../flywheel/flywheel/programs/oriented.json | 5 +- 40 files changed, 269 insertions(+), 514 deletions(-) delete mode 100644 src/main/java/com/jozufozu/flywheel/api/shader/FlexibleShader.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/LazyCompiler.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/Shader.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderInput.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderPipeline.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/pipeline/CachingCompiler.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/pipeline/CompilationContext.java rename src/main/java/com/jozufozu/flywheel/{backend => core}/pipeline/InstancingTemplateData.java (97%) rename src/main/java/com/jozufozu/flywheel/{backend => core}/pipeline/OneShotTemplateData.java (98%) create mode 100644 src/main/java/com/jozufozu/flywheel/core/pipeline/PipelineCompiler.java rename src/main/java/com/jozufozu/flywheel/{backend => core}/pipeline/ProgramAssembler.java (97%) rename src/main/java/com/jozufozu/flywheel/{backend => core}/pipeline/ShaderCompiler.java (62%) rename src/main/java/com/jozufozu/flywheel/{backend => core}/pipeline/Template.java (97%) rename src/main/java/com/jozufozu/flywheel/{backend => core}/pipeline/TemplateData.java (93%) rename src/main/java/com/jozufozu/flywheel/{backend => core}/pipeline/TypeHelper.java (94%) create mode 100644 src/main/java/com/jozufozu/flywheel/core/pipeline/WorldCompiler.java rename src/main/java/com/jozufozu/flywheel/{backend => core}/pipeline/package-info.java (78%) delete mode 100644 src/main/java/com/jozufozu/flywheel/core/shader/ContextAwareProgram.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/shader/GameStateProgram.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/shader/spec/BooleanGameStateCondition.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/shader/spec/IBooleanStateProvider.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/shader/spec/IGameStateCondition.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/shader/spec/SpecificValueCondition.java diff --git a/src/main/java/com/jozufozu/flywheel/api/shader/FlexibleShader.java b/src/main/java/com/jozufozu/flywheel/api/shader/FlexibleShader.java deleted file mode 100644 index a46802373..000000000 --- a/src/main/java/com/jozufozu/flywheel/api/shader/FlexibleShader.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.jozufozu.flywheel.api.shader; - -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -/** - * Represents a vertex format agnostic shader. - */ -public interface FlexibleShader

{ - - /** - * Get a version of this shader that accepts the given VertexType as input. - */ - P get(VertexType type); -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java index 96c5e563d..4367194eb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java @@ -1,6 +1,5 @@ package com.jozufozu.flywheel.backend; -import com.jozufozu.flywheel.api.shader.FlexibleShader; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; @@ -8,12 +7,7 @@ import net.minecraft.resources.ResourceLocation; public interface ShaderContext

{ - default P getProgram(ResourceLocation loc, VertexType inputType) { - return this.getProgramSupplier(loc) - .get(inputType); - } - - FlexibleShader

getProgramSupplier(ResourceLocation loc); + P getProgram(ResourceLocation loc, VertexType vertexType); /** * Load all programs associated with this context. This might be just one, if the context is very specialized. diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java index bde532d88..c1f63c1bd 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java @@ -1,16 +1,11 @@ package com.jozufozu.flywheel.backend.gl.shader; -import java.util.List; - import org.lwjgl.opengl.GL20; -import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; -import com.jozufozu.flywheel.backend.pipeline.ShaderCompiler; import com.jozufozu.flywheel.backend.source.ShaderLoadingException; -import com.jozufozu.flywheel.backend.source.error.ErrorBuilder; -import com.jozufozu.flywheel.backend.source.error.ErrorReporter; +import com.jozufozu.flywheel.core.pipeline.ShaderCompiler; import net.minecraft.resources.ResourceLocation; @@ -30,27 +25,7 @@ public class GlShader extends GlObject { String log = GL20.glGetShaderInfoLog(handle); if (!log.isEmpty()) { - List lines = log.lines() - .toList(); - - boolean needsSourceDump = false; - - StringBuilder errors = new StringBuilder(); - for (String line : lines) { - ErrorBuilder builder = env.parseCompilerError(line); - - if (builder != null) { - errors.append(builder.build()); - } else { - errors.append(line).append('\n'); - needsSourceDump = true; - } - } - Backend.LOGGER.error("Errors compiling '" + name + "': \n" + errors); - if (needsSourceDump) { - // TODO: generated code gets its own "file" - ErrorReporter.printLines(source); - } + env.printShaderInfoLog(source, log, this.name); } if (GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS) != GL20.GL_TRUE) { @@ -64,4 +39,5 @@ public class GlShader extends GlObject { protected void deleteInternal(int handle) { GL20.glDeleteShader(handle); } + } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java index 4366b5091..41b102cff 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java @@ -8,7 +8,6 @@ import java.util.stream.Stream; import javax.annotation.Nullable; import com.jozufozu.flywheel.api.MaterialGroup; -import com.jozufozu.flywheel.api.shader.FlexibleShader; import com.jozufozu.flywheel.backend.RenderLayer; import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; @@ -24,7 +23,6 @@ import net.minecraft.client.Camera; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; -import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; public class InstancingEngine

implements Engine { @@ -126,10 +124,6 @@ public class InstancingEngine

implements Engine { } } - public FlexibleShader

getProgram(ResourceLocation name) { - return context.getProgramSupplier(name); - } - @Override public Vec3i getOriginCoordinate() { return originCoordinate; diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/LazyCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/LazyCompiler.java deleted file mode 100644 index a8b57c4ba..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/LazyCompiler.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.jozufozu.flywheel.backend.pipeline; - -import java.util.HashMap; -import java.util.Map; - -import com.jozufozu.flywheel.api.shader.FlexibleShader; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.core.shader.ContextAwareProgram; -import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; - -public class LazyCompiler

implements FlexibleShader

{ - - private final ShaderPipeline

pipeline; - private final ProgramSpec spec; - - private final Map> cache = new HashMap<>(); - - public LazyCompiler(ShaderPipeline

pipeline, ProgramSpec spec) { - - this.pipeline = pipeline; - this.spec = spec; - } - - public void delete() { - cache.values().forEach(ContextAwareProgram::delete); - } - - @Override - public P get(VertexType type) { - return cache.computeIfAbsent(type, t -> pipeline.compile(spec, t)).get(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/Shader.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/Shader.java deleted file mode 100644 index bf7aece43..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/Shader.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.jozufozu.flywheel.backend.pipeline; - -public class Shader { - - -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderInput.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderInput.java deleted file mode 100644 index bf9b3b95c..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderInput.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.jozufozu.flywheel.backend.pipeline; - -import java.util.Collection; -import java.util.stream.Collectors; - -import com.jozufozu.flywheel.backend.source.parse.ShaderStruct; -import com.jozufozu.flywheel.backend.source.parse.StructField; - -/** - * A single input to a shader. - */ -public class ShaderInput { - public final CharSequence name; - public final int attribCount; - - public ShaderInput(CharSequence name, int attribCount) { - this.name = name; - this.attribCount = attribCount; - } - - public ShaderInput withPrefix(CharSequence prefix) { - return new ShaderInput(prefix.toString() + name, attribCount); - } - - public static Collection fromStruct(ShaderStruct struct, String prefix) { - return struct.getFields() - .stream() - .map(ShaderInput::from) - .map(a -> a.withPrefix(prefix)) - .collect(Collectors.toList()); - } - - public static ShaderInput from(StructField field) { - int attributeCount = TypeHelper.getAttributeCount(field.type); - - return new ShaderInput(field.name, attributeCount); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderPipeline.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderPipeline.java deleted file mode 100644 index a6f94413f..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderPipeline.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.jozufozu.flywheel.backend.pipeline; - -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.core.shader.ContextAwareProgram; -import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; - -/** - * The main interface for compiling usable shaders from program specs. - * @param

the type of the program that this pipeline compiles. - */ -public interface ShaderPipeline

{ - - ContextAwareProgram

compile(ProgramSpec spec, VertexType vertexType); - -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java deleted file mode 100644 index c46dcbe28..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.jozufozu.flywheel.backend.pipeline; - -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.backend.source.FileResolution; -import com.jozufozu.flywheel.backend.source.SourceFile; -import com.jozufozu.flywheel.core.shader.ContextAwareProgram; -import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; -import com.jozufozu.flywheel.core.shader.GameStateProgram; -import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; -import com.jozufozu.flywheel.core.shader.spec.ProgramState; - -public class WorldShaderPipeline

implements ShaderPipeline

{ - - private final ExtensibleGlProgram.Factory

factory; - - private final Template template; - private final FileResolution header; - - public WorldShaderPipeline(ExtensibleGlProgram.Factory

factory, Template template, FileResolution header) { - this.factory = factory; - this.template = template; - this.header = header; - } - - public ContextAwareProgram

compile(ProgramSpec spec, VertexType vertexType) { - - SourceFile file = spec.getSource().getFile(); - - ShaderCompiler shader = new ShaderCompiler(spec.name, file, template, header, vertexType); - - GameStateProgram.Builder

builder = GameStateProgram.builder(shader.compile(this.factory)); - for (ProgramState variant : spec.getStates()) { - shader.setVariant(variant); - builder.withVariant(variant.context(), shader.compile(this.factory)); - } - - return builder.build(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java b/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java index f186543aa..42b5f8dac 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java @@ -3,8 +3,6 @@ package com.jozufozu.flywheel.backend.source; import java.util.ArrayList; import java.util.List; -import javax.annotation.Nullable; - import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.source.error.ErrorBuilder; import com.jozufozu.flywheel.backend.source.span.Span; @@ -37,7 +35,6 @@ public class FileResolution { return fileLoc; } - @Nullable public SourceFile getFile() { return file; } @@ -73,6 +70,7 @@ public class FileResolution { .pointAt(span, 1); } Backend.LOGGER.error(builder.build()); + throw new ShaderLoadingException(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/source/SourceFile.java b/src/main/java/com/jozufozu/flywheel/backend/source/SourceFile.java index 2b93d7168..65ba34a3e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/SourceFile.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/SourceFile.java @@ -10,13 +10,13 @@ import java.util.regex.Pattern; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.jozufozu.flywheel.backend.pipeline.ShaderCompiler; import com.jozufozu.flywheel.backend.source.parse.Import; import com.jozufozu.flywheel.backend.source.parse.ShaderFunction; import com.jozufozu.flywheel.backend.source.parse.ShaderStruct; import com.jozufozu.flywheel.backend.source.span.ErrorSpan; import com.jozufozu.flywheel.backend.source.span.Span; import com.jozufozu.flywheel.backend.source.span.StringSpan; +import com.jozufozu.flywheel.core.pipeline.ShaderCompiler; import net.minecraft.resources.ResourceLocation; @@ -138,12 +138,6 @@ public class SourceFile { return "#use " + '"' + name + '"'; } - public CharSequence generateFinalSource(ShaderCompiler env) { - StringBuilder builder = new StringBuilder(); - generateFinalSource(env, builder); - return builder; - } - public void generateFinalSource(ShaderCompiler env, StringBuilder source) { for (Import include : imports) { SourceFile file = include.getFile(); @@ -151,24 +145,16 @@ public class SourceFile { if (file != null) file.generateFinalSource(env, source); } - int i = env.allocateFile(this); source.append("#line ") .append(0) .append(' ') - .append(i) + .append(env.getFileID(this)) .append('\n'); source.append(elided); } public String printSource() { - StringBuilder builder = new StringBuilder(); - - builder.append("Source for shader '") - .append(name) - .append("':\n") - .append(lines.printLinesWithNumbers()); - - return builder.toString(); + return "Source for shader '" + name + "':\n" + lines.printLinesWithNumbers(); } private static CharSequence elideSource(String source, List elisions) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/source/error/ErrorBuilder.java b/src/main/java/com/jozufozu/flywheel/backend/source/error/ErrorBuilder.java index b1ef7b2b5..d917ca186 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/error/ErrorBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/error/ErrorBuilder.java @@ -7,7 +7,6 @@ import java.util.regex.Pattern; import javax.annotation.Nullable; -import com.jozufozu.flywheel.backend.pipeline.ShaderCompiler; import com.jozufozu.flywheel.backend.source.SourceFile; import com.jozufozu.flywheel.backend.source.SourceLines; import com.jozufozu.flywheel.backend.source.error.lines.ErrorLine; @@ -17,6 +16,7 @@ import com.jozufozu.flywheel.backend.source.error.lines.SourceLine; import com.jozufozu.flywheel.backend.source.error.lines.SpanHighlightLine; import com.jozufozu.flywheel.backend.source.error.lines.TextLine; import com.jozufozu.flywheel.backend.source.span.Span; +import com.jozufozu.flywheel.core.pipeline.ShaderCompiler; import com.jozufozu.flywheel.util.FlwUtil; public class ErrorBuilder { diff --git a/src/main/java/com/jozufozu/flywheel/core/Contexts.java b/src/main/java/com/jozufozu/flywheel/core/Contexts.java index 3261cd19d..0180f98a8 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Contexts.java +++ b/src/main/java/com/jozufozu/flywheel/core/Contexts.java @@ -3,11 +3,11 @@ package com.jozufozu.flywheel.core; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.GameStateRegistry; -import com.jozufozu.flywheel.backend.pipeline.ShaderPipeline; -import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline; import com.jozufozu.flywheel.backend.source.FileResolution; import com.jozufozu.flywheel.backend.source.Resolver; import com.jozufozu.flywheel.core.crumbling.CrumblingProgram; +import com.jozufozu.flywheel.core.pipeline.PipelineCompiler; +import com.jozufozu.flywheel.core.pipeline.WorldCompiler; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.gamestate.NormalDebugStateProvider; import com.jozufozu.flywheel.event.GatherContextEvent; @@ -31,8 +31,8 @@ public class Contexts { FileResolution crumblingBuiltins = Resolver.INSTANCE.findShader(ResourceUtil.subPath(Names.CRUMBLING, ".glsl")); FileResolution worldBuiltins = Resolver.INSTANCE.findShader(ResourceUtil.subPath(Names.WORLD, ".glsl")); - ShaderPipeline crumblingPipeline = new WorldShaderPipeline<>(CrumblingProgram::new, Templates.INSTANCING, crumblingBuiltins); - ShaderPipeline worldPipeline = new WorldShaderPipeline<>(WorldProgram::new, Templates.INSTANCING, worldBuiltins); + PipelineCompiler crumblingPipeline = new WorldCompiler<>(CrumblingProgram::new, Templates.INSTANCING, crumblingBuiltins); + PipelineCompiler worldPipeline = new WorldCompiler<>(WorldProgram::new, Templates.INSTANCING, worldBuiltins); CRUMBLING = backend.register(WorldContext.builder(backend, Names.CRUMBLING).build(crumblingPipeline)); WORLD = backend.register(WorldContext.builder(backend, Names.WORLD).build(worldPipeline)); diff --git a/src/main/java/com/jozufozu/flywheel/core/Templates.java b/src/main/java/com/jozufozu/flywheel/core/Templates.java index 7bd3f718f..df6f04b35 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Templates.java +++ b/src/main/java/com/jozufozu/flywheel/core/Templates.java @@ -1,9 +1,9 @@ package com.jozufozu.flywheel.core; import com.jozufozu.flywheel.backend.gl.GLSLVersion; -import com.jozufozu.flywheel.backend.pipeline.InstancingTemplateData; -import com.jozufozu.flywheel.backend.pipeline.OneShotTemplateData; -import com.jozufozu.flywheel.backend.pipeline.Template; +import com.jozufozu.flywheel.core.pipeline.InstancingTemplateData; +import com.jozufozu.flywheel.core.pipeline.OneShotTemplateData; +import com.jozufozu.flywheel.core.pipeline.Template; public class Templates { diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java index de1d1bea5..6b3cd99b0 100644 --- a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java @@ -6,13 +6,13 @@ import java.util.Objects; import java.util.function.Supplier; import java.util.stream.Stream; -import com.jozufozu.flywheel.api.shader.FlexibleShader; import com.jozufozu.flywheel.api.struct.Instanced; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.pipeline.LazyCompiler; -import com.jozufozu.flywheel.backend.pipeline.ShaderPipeline; import com.jozufozu.flywheel.backend.source.ShaderLoadingException; +import com.jozufozu.flywheel.core.pipeline.CachingCompiler; +import com.jozufozu.flywheel.core.pipeline.PipelineCompiler; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; @@ -20,17 +20,16 @@ import net.minecraft.resources.ResourceLocation; public class WorldContext

implements ShaderContext

{ public final Backend backend; - protected final Map> programs = new HashMap<>(); + protected final Map programs = new HashMap<>(); protected final ResourceLocation name; protected final Supplier> specStream; + private final CachingCompiler

programCache; - public final ShaderPipeline

pipeline; - - public WorldContext(Backend backend, ResourceLocation name, Supplier> specStream, ShaderPipeline

pipeline) { + public WorldContext(Backend backend, ResourceLocation name, Supplier> specStream, PipelineCompiler

pipeline) { this.backend = backend; this.name = name; this.specStream = specStream; - this.pipeline = pipeline; + this.programCache = new CachingCompiler<>(pipeline); } @Override @@ -46,7 +45,7 @@ public class WorldContext

implements ShaderContext

{ private void loadSpec(ProgramSpec spec) { try { - programs.put(spec.name, new LazyCompiler<>(pipeline, spec)); + programs.put(spec.name, spec); Backend.LOGGER.debug("Loaded program {}", spec.name); } catch (Exception e) { @@ -59,14 +58,19 @@ public class WorldContext

implements ShaderContext

{ } @Override - public FlexibleShader

getProgramSupplier(ResourceLocation spec) { - return programs.get(spec); + public P getProgram(ResourceLocation loc, VertexType vertexType) { + ProgramSpec spec = programs.get(loc); + + if (spec == null) { + throw new NullPointerException("Cannot compile shader because '" + loc + "' is not recognized."); + } + + return programCache.getProgram(spec, vertexType); } @Override public void delete() { - programs.values() - .forEach(LazyCompiler::delete); + programCache.invalidate(); programs.clear(); } @@ -89,7 +93,7 @@ public class WorldContext

implements ShaderContext

{ return this; } - public

WorldContext

build(ShaderPipeline

pipeline) { + public

WorldContext

build(PipelineCompiler

pipeline) { if (specStream == null) { specStream = () -> backend.allMaterials() .stream() diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/BasicData.java b/src/main/java/com/jozufozu/flywheel/core/materials/BasicData.java index 955aba918..8f1e07de8 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/BasicData.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/BasicData.java @@ -1,6 +1,7 @@ package com.jozufozu.flywheel.core.materials; import com.jozufozu.flywheel.api.InstanceData; +import com.jozufozu.flywheel.util.Color; import net.minecraft.client.renderer.LightTexture; @@ -33,6 +34,15 @@ public abstract class BasicData extends InstanceData implements FlatLit The class that the PipelineCompiler outputs. + */ +public class CachingCompiler

{ + protected final Map cache = new HashMap<>(); + private final PipelineCompiler

pipeline; + + public CachingCompiler(PipelineCompiler

pipeline) { + this.pipeline = pipeline; + } + + /** + * Get or compile a spec to the given vertex type, accounting for all game state conditions specified by the spec. + * + * @param spec The ProgramSpec to target. + * @param vertexType The VertexType to target. + * @return A compiled GlProgram. + */ + public P getProgram(ProgramSpec spec, VertexType vertexType) { + return cache.computeIfAbsent(new CompilationContext(vertexType, spec, spec.getCurrentStateID()), this.pipeline::compile); + } + + public void invalidate() { + cache.values().forEach(P::delete); + cache.clear(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/CompilationContext.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/CompilationContext.java new file mode 100644 index 000000000..b05da4d35 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/CompilationContext.java @@ -0,0 +1,35 @@ +package com.jozufozu.flywheel.core.pipeline; + +import java.util.Objects; + +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.source.SourceFile; +import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; + +/** + * Represents the entire context of a program's usage. + * + * @param vertexType The vertexType the program should be adapted for. + * @param spec The generic program name. + * @param ctx An ID representing the state at the time of usage. + */ +public record CompilationContext(VertexType vertexType, ProgramSpec spec, long ctx) { + + public SourceFile getFile() { + return spec().getSource(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CompilationContext that = (CompilationContext) o; + // override for instance equality on vertexType + return ctx == that.ctx && vertexType == that.vertexType && spec.equals(that.spec); + } + + @Override + public int hashCode() { + return Objects.hash(vertexType, spec, ctx); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/InstancingTemplateData.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/InstancingTemplateData.java similarity index 97% rename from src/main/java/com/jozufozu/flywheel/backend/pipeline/InstancingTemplateData.java rename to src/main/java/com/jozufozu/flywheel/core/pipeline/InstancingTemplateData.java index 2eb6f74be..a18c08f3f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/InstancingTemplateData.java +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/InstancingTemplateData.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.pipeline; +package com.jozufozu.flywheel.core.pipeline; import java.util.Optional; @@ -107,7 +107,7 @@ public class InstancingTemplateData implements TemplateData { .append("a_i_") .append(field.name) .append(";\n"); - attributeBinding += ShaderInput.from(field).attribCount; + attributeBinding += TypeHelper.getAttributeCount(field.type); } Template.prefixFields(template, interpolant, "out", "v2f_"); diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotTemplateData.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/OneShotTemplateData.java similarity index 98% rename from src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotTemplateData.java rename to src/main/java/com/jozufozu/flywheel/core/pipeline/OneShotTemplateData.java index b46945cfa..c000e506c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotTemplateData.java +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/OneShotTemplateData.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.pipeline; +package com.jozufozu.flywheel.core.pipeline; import java.util.Optional; diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/PipelineCompiler.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/PipelineCompiler.java new file mode 100644 index 000000000..a831480e5 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/PipelineCompiler.java @@ -0,0 +1,13 @@ +package com.jozufozu.flywheel.core.pipeline; + +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; + +/** + * The main interface for compiling usable shaders from program specs. + * @param

the type of the program that this pipeline compiles. + */ +public interface PipelineCompiler

{ + + P compile(CompilationContext vertexType); + +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ProgramAssembler.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/ProgramAssembler.java similarity index 97% rename from src/main/java/com/jozufozu/flywheel/backend/pipeline/ProgramAssembler.java rename to src/main/java/com/jozufozu/flywheel/core/pipeline/ProgramAssembler.java index 09cc90041..c5fc72d63 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ProgramAssembler.java +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/ProgramAssembler.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.pipeline; +package com.jozufozu.flywheel.core.pipeline; import static org.lwjgl.opengl.GL11.GL_TRUE; import static org.lwjgl.opengl.GL20.GL_LINK_STATUS; diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderCompiler.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/ShaderCompiler.java similarity index 62% rename from src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderCompiler.java rename to src/main/java/com/jozufozu/flywheel/core/pipeline/ShaderCompiler.java index cd1ce9608..11a451a4f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/ShaderCompiler.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.pipeline; +package com.jozufozu.flywheel.core.pipeline; import java.util.ArrayList; import java.util.List; @@ -6,15 +6,16 @@ import java.util.List; import javax.annotation.Nullable; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.shader.GlShader; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.source.FileResolution; import com.jozufozu.flywheel.backend.source.SourceFile; import com.jozufozu.flywheel.backend.source.error.ErrorBuilder; +import com.jozufozu.flywheel.backend.source.error.ErrorReporter; import com.jozufozu.flywheel.backend.source.span.Span; import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.core.shader.spec.ProgramState; import net.minecraft.resources.ResourceLocation; @@ -24,27 +25,22 @@ public class ShaderCompiler { public final Template template; private final FileResolution header; - @Nullable - private ProgramState variant; + private final List defines; public final VertexType vertexType; - public SourceFile mainFile; + public final SourceFile mainFile; - public ShaderCompiler(ResourceLocation name, SourceFile mainSource, Template template, FileResolution header, VertexType vertexType) { - this.name = name; + private final List files = new ArrayList<>(); + + public ShaderCompiler(CompilationContext usage, Template template, FileResolution header) { + this.name = usage.spec().name; this.template = template; this.header = header; - this.mainFile = mainSource; - this.vertexType = vertexType; - } - - public ShaderCompiler setMainSource(SourceFile file) { - if (mainFile == file) return this; - - mainFile = file; - - return this; + this.mainFile = usage.getFile(); + this.defines = usage.spec() + .getDefines(usage.ctx()); + this.vertexType = usage.vertexType(); } public GlShader compile(ShaderType type) { @@ -60,13 +56,10 @@ public class ShaderCompiler { .append(type.define) // special case shader type declaration .append('\n'); - ProgramState variant = getVariant(); - if (variant != null) { - for (String def : variant.defines()) { - finalSource.append("#define ") - .append(def) - .append('\n'); - } + for (String def : defines) { + finalSource.append("#define ") + .append(def) + .append('\n'); } if (type == ShaderType.VERTEX) { @@ -83,9 +76,7 @@ public class ShaderCompiler { } files.clear(); - if (header.getFile() != null) { - header.getFile().generateFinalSource(this, finalSource); - } + header.getFile().generateFinalSource(this, finalSource); mainFile.generateFinalSource(this, finalSource); template.getMetadata(mainFile).generateFooter(finalSource, type, this); @@ -93,18 +84,21 @@ public class ShaderCompiler { return new GlShader(this, type, finalSource.toString()); } - @Nullable - public ProgramState getVariant() { - return variant; + public

P compile(ExtensibleGlProgram.Factory

worldShaderPipeline) { + return new ProgramAssembler(this.name) + .attachShader(compile(ShaderType.VERTEX)) + .attachShader(compile(ShaderType.FRAGMENT)) + .link() + .deleteLinkedShaders() + .build(worldShaderPipeline); } - public void setVariant(@Nullable ProgramState variant) { - this.variant = variant; - } - - private final List files = new ArrayList<>(); - - public int allocateFile(SourceFile sourceFile) { + /** + * Returns an arbitrary file ID for use this compilation context, or generates one if missing. + * @param sourceFile The file to retrieve the ID for. + * @return A file ID unique to the given sourceFile. + */ + public int getFileID(SourceFile sourceFile) { int i = files.indexOf(sourceFile); if (i != -1) { return i; @@ -121,8 +115,32 @@ public class ShaderCompiler { return file.getLineSpanNoWhitespace(lineNo); } + public void printShaderInfoLog(String source, String log, ResourceLocation name) { + List lines = log.lines() + .toList(); + + boolean needsSourceDump = false; + + StringBuilder errors = new StringBuilder(); + for (String line : lines) { + ErrorBuilder builder = parseCompilerError(line); + + if (builder != null) { + errors.append(builder.build()); + } else { + errors.append(line).append('\n'); + needsSourceDump = true; + } + } + Backend.LOGGER.error("Errors compiling '" + name + "': \n" + errors); + if (needsSourceDump) { + // TODO: generated code gets its own "file" + ErrorReporter.printLines(source); + } + } + @Nullable - public ErrorBuilder parseCompilerError(String line) { + private ErrorBuilder parseCompilerError(String line) { try { ErrorBuilder error = ErrorBuilder.fromLogLine(this, line); if (error != null) { @@ -133,13 +151,4 @@ public class ShaderCompiler { return null; } - - public

P compile(ExtensibleGlProgram.Factory

worldShaderPipeline) { - return new ProgramAssembler(this.name) - .attachShader(compile(ShaderType.VERTEX)) - .attachShader(compile(ShaderType.FRAGMENT)) - .link() - .deleteLinkedShaders() - .build(worldShaderPipeline); - } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/Template.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/Template.java similarity index 97% rename from src/main/java/com/jozufozu/flywheel/backend/pipeline/Template.java rename to src/main/java/com/jozufozu/flywheel/core/pipeline/Template.java index 3906cbecc..1a872d2b4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/Template.java +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/Template.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.pipeline; +package com.jozufozu.flywheel.core.pipeline; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/TemplateData.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/TemplateData.java similarity index 93% rename from src/main/java/com/jozufozu/flywheel/backend/pipeline/TemplateData.java rename to src/main/java/com/jozufozu/flywheel/core/pipeline/TemplateData.java index 50603fdf0..90ea7e01f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/TemplateData.java +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/TemplateData.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.pipeline; +package com.jozufozu.flywheel.core.pipeline; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/TypeHelper.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/TypeHelper.java similarity index 94% rename from src/main/java/com/jozufozu/flywheel/backend/pipeline/TypeHelper.java rename to src/main/java/com/jozufozu/flywheel/core/pipeline/TypeHelper.java index 283f51a69..065755eaa 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/TypeHelper.java +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/TypeHelper.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.pipeline; +package com.jozufozu.flywheel.core.pipeline; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/WorldCompiler.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/WorldCompiler.java new file mode 100644 index 000000000..5bf2980a8 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/WorldCompiler.java @@ -0,0 +1,33 @@ +package com.jozufozu.flywheel.core.pipeline; + +import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.source.FileResolution; +import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; +import com.jozufozu.flywheel.core.shader.WorldProgram; + +public class WorldCompiler

implements PipelineCompiler

{ + + private final ExtensibleGlProgram.Factory

factory; + + private final Template template; + private final FileResolution header; + + public WorldCompiler(ExtensibleGlProgram.Factory

factory, Template template, FileResolution header) { + this.factory = factory; + this.template = template; + this.header = header; + } + + @Override + public P compile(CompilationContext usage) { + ShaderCompiler compiler = new ShaderCompiler(usage, template, header); + + return new ProgramAssembler(compiler.name) + .attachShader(compiler.compile(ShaderType.VERTEX)) + .attachShader(compiler.compile(ShaderType.FRAGMENT)) + .link() + .deleteLinkedShaders() + .build(this.factory); + } + +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/package-info.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/package-info.java similarity index 78% rename from src/main/java/com/jozufozu/flywheel/backend/pipeline/package-info.java rename to src/main/java/com/jozufozu/flywheel/core/pipeline/package-info.java index 25c300762..e51c6e616 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/package-info.java +++ b/src/main/java/com/jozufozu/flywheel/core/pipeline/package-info.java @@ -1,5 +1,5 @@ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.jozufozu.flywheel.backend.pipeline; +package com.jozufozu.flywheel.core.pipeline; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/ContextAwareProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/ContextAwareProgram.java deleted file mode 100644 index c10affa04..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/shader/ContextAwareProgram.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.jozufozu.flywheel.core.shader; - -import java.util.function.Supplier; - -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -/** - * Encapsulates any number of shader programs for use in similar contexts. - * Allows the implementor to choose which shader program to use based on arbitrary state. - * - * @param

- */ -public interface ContextAwareProgram

extends Supplier

{ - - /** - * Get the shader program most suited for the current game state. - * - * @return The one true program. - */ - P get(); - - /** - * Delete all shader programs encapsulated by your implementation. - */ - void delete(); -} diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/GameStateProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/GameStateProgram.java deleted file mode 100644 index 12bc659ad..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/shader/GameStateProgram.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.jozufozu.flywheel.core.shader; - -import java.util.ArrayList; -import java.util.List; - -import com.google.common.collect.ImmutableList; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; -import com.jozufozu.flywheel.core.shader.spec.IGameStateCondition; -import com.jozufozu.flywheel.util.Pair; - -public class GameStateProgram

implements ContextAwareProgram

{ - - private final List> variants; - private final P fallback; - - protected GameStateProgram(List> variants, P fallback) { - this.variants = variants; - this.fallback = fallback; - } - - @Override - public P get() { - for (Pair variant : variants) { - if (variant.first() - .isMet()) return variant.second(); - } - - return fallback; - } - - @Override - public void delete() { - for (Pair variant : variants) { - variant.second() - .delete(); - } - - fallback.delete(); - } - - public static

Builder

builder(P fallback) { - return new Builder<>(fallback); - } - - public static class Builder

{ - private final P fallback; - private final List> variants = new ArrayList<>(); - - public Builder(P fallback) { - this.fallback = fallback; - } - - public Builder

withVariant(IGameStateCondition condition, P program) { - variants.add(Pair.of(condition, program)); - return this; - } - - public ContextAwareProgram

build() { - return new GameStateProgram<>(ImmutableList.copyOf(variants), fallback); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/IGameStateProvider.java b/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/IGameStateProvider.java index 8e472de72..78fb00d07 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/IGameStateProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/IGameStateProvider.java @@ -11,5 +11,5 @@ public interface IGameStateProvider { ResourceLocation getID(); - Object getValue(); + boolean isTrue(); } diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/NormalDebugStateProvider.java b/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/NormalDebugStateProvider.java index f7ddbbea0..73b0a2f9b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/NormalDebugStateProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/gamestate/NormalDebugStateProvider.java @@ -2,11 +2,10 @@ package com.jozufozu.flywheel.core.shader.gamestate; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.config.FlwConfig; -import com.jozufozu.flywheel.core.shader.spec.IBooleanStateProvider; import net.minecraft.resources.ResourceLocation; -public class NormalDebugStateProvider implements IBooleanStateProvider { +public class NormalDebugStateProvider implements IGameStateProvider { public static final NormalDebugStateProvider INSTANCE = new NormalDebugStateProvider(); public static final ResourceLocation NAME = Flywheel.rl("normal_debug"); diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/spec/BooleanGameStateCondition.java b/src/main/java/com/jozufozu/flywheel/core/shader/spec/BooleanGameStateCondition.java deleted file mode 100644 index 6293ade94..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/shader/spec/BooleanGameStateCondition.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.jozufozu.flywheel.core.shader.spec; - -import com.jozufozu.flywheel.core.shader.gamestate.IGameStateProvider; -import com.mojang.serialization.Codec; - -import net.minecraft.resources.ResourceLocation; - -public class BooleanGameStateCondition implements IGameStateCondition { - - public static final Codec BOOLEAN_SUGAR = IGameStateProvider.CODEC.xmap(gameContext -> { - if (gameContext instanceof IBooleanStateProvider) { - return new BooleanGameStateCondition(((IBooleanStateProvider) gameContext)); - } - - return null; - }, IGameStateCondition::getStateProvider); - protected final IBooleanStateProvider context; - - public BooleanGameStateCondition(IBooleanStateProvider context) { - this.context = context; - } - - @Override - public ResourceLocation getID() { - return context.getID(); - } - - @Override - public IGameStateProvider getStateProvider() { - return context; - } - - @Override - public boolean isMet() { - return context.isTrue(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/spec/IBooleanStateProvider.java b/src/main/java/com/jozufozu/flywheel/core/shader/spec/IBooleanStateProvider.java deleted file mode 100644 index 1f1265724..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/shader/spec/IBooleanStateProvider.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.jozufozu.flywheel.core.shader.spec; - -import com.jozufozu.flywheel.core.shader.gamestate.IGameStateProvider; - -public interface IBooleanStateProvider extends IGameStateProvider { - - boolean isTrue(); - - @Override - default Boolean getValue() { - return isTrue(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/spec/IGameStateCondition.java b/src/main/java/com/jozufozu/flywheel/core/shader/spec/IGameStateCondition.java deleted file mode 100644 index 08fd87dc3..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/shader/spec/IGameStateCondition.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.jozufozu.flywheel.core.shader.spec; - -import com.jozufozu.flywheel.core.shader.gamestate.IGameStateProvider; - -import net.minecraft.resources.ResourceLocation; - -public interface IGameStateCondition { - - ResourceLocation getID(); - - IGameStateProvider getStateProvider(); - - boolean isMet(); -} diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramSpec.java b/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramSpec.java index 3716caef2..f9e105f98 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramSpec.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramSpec.java @@ -1,8 +1,10 @@ package com.jozufozu.flywheel.core.shader.spec; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.backend.source.FileResolution; import com.jozufozu.flywheel.backend.source.Resolver; import com.jozufozu.flywheel.backend.source.SourceFile; @@ -38,11 +40,11 @@ public class ProgramSpec { public ResourceLocation name; public final FileResolution source; - public final List states; + public final ImmutableList states; public ProgramSpec(ResourceLocation source, List states) { this.source = Resolver.INSTANCE.findShader(source); - this.states = states; + this.states = ImmutableList.copyOf(states); } public void setName(ResourceLocation name) { @@ -53,12 +55,40 @@ public class ProgramSpec { return source.getFileLoc(); } - public FileResolution getSource() { - return source; + public SourceFile getSource() { + return source.getFile(); } - public List getStates() { + public ImmutableList getStates() { return states; } + /** + * Calculate a unique ID representing the current game state. + */ + public long getCurrentStateID() { + long ctx = 0; + for (ProgramState state : states) { + if (state.context().isTrue()) { + ctx |= 1; + } + ctx <<= 1; + } + return ctx; + } + + /** + * Given the stateID, get a list of defines to include at the top of a compiling program. + */ + public List getDefines(long stateID) { + List defines = new ArrayList<>(); + + for (ProgramState state : states) { + if ((stateID & 1) == 1) { + defines.addAll(state.defines()); + } + stateID >>= 1; + } + return defines; + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramState.java b/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramState.java index e680c4e85..6f2b08bd9 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramState.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramState.java @@ -3,29 +3,14 @@ package com.jozufozu.flywheel.core.shader.spec; import java.util.Collections; import java.util.List; +import com.jozufozu.flywheel.core.shader.gamestate.IGameStateProvider; import com.jozufozu.flywheel.util.CodecUtil; -import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; -public record ProgramState(IGameStateCondition context, List defines) { +public record ProgramState(IGameStateProvider context, List defines) { - // TODO: Use Codec.dispatch - private static final Codec WHEN = Codec.either(BooleanGameStateCondition.BOOLEAN_SUGAR, SpecificValueCondition.CODEC) - .flatXmap(either -> either.map(DataResult::success, DataResult::success), any -> { - if (any instanceof BooleanGameStateCondition) { - return DataResult.success(Either.left((BooleanGameStateCondition) any)); - } - - if (any instanceof SpecificValueCondition) { - return DataResult.success(Either.right((SpecificValueCondition) any)); - } - - return DataResult.error("unknown context condition"); - }); - - public static final Codec CODEC = RecordCodecBuilder.create(state -> state.group(WHEN.fieldOf("when") + public static final Codec CODEC = RecordCodecBuilder.create(state -> state.group(IGameStateProvider.CODEC.fieldOf("when") .forGetter(ProgramState::context), CodecUtil.oneOrMore(Codec.STRING) .optionalFieldOf("define", Collections.emptyList()) .forGetter(ProgramState::defines)) diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/spec/SpecificValueCondition.java b/src/main/java/com/jozufozu/flywheel/core/shader/spec/SpecificValueCondition.java deleted file mode 100644 index 69e40a08d..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/shader/spec/SpecificValueCondition.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.jozufozu.flywheel.core.shader.spec; - -import com.jozufozu.flywheel.core.shader.gamestate.IGameStateProvider; -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; - -import net.minecraft.resources.ResourceLocation; - -public class SpecificValueCondition implements IGameStateCondition { - - public static final Codec CODEC = RecordCodecBuilder.create(condition -> condition.group(IGameStateProvider.CODEC.fieldOf("provider") - .forGetter(SpecificValueCondition::getStateProvider), Codec.STRING.fieldOf("value") - .forGetter(SpecificValueCondition::getValue)) - .apply(condition, SpecificValueCondition::new)); - - private final String required; - private final IGameStateProvider context; - - public SpecificValueCondition(IGameStateProvider context, String required) { - this.required = required; - this.context = context; - } - - @Override - public ResourceLocation getID() { - return context.getID(); - } - - public String getValue() { - return required; - } - - @Override - public IGameStateProvider getStateProvider() { - return context; - } - - @Override - public boolean isMet() { - return required.equals(context.getValue() - .toString()); - } -} diff --git a/src/main/resources/assets/flywheel/flywheel/programs/model.json b/src/main/resources/assets/flywheel/flywheel/programs/model.json index 1352b31b2..921a6e093 100644 --- a/src/main/resources/assets/flywheel/flywheel/programs/model.json +++ b/src/main/resources/assets/flywheel/flywheel/programs/model.json @@ -2,10 +2,7 @@ "source": "flywheel:model.vert", "states": [ { - "when": { - "provider": "flywheel:normal_debug", - "value": "true" - }, + "when": "flywheel:normal_debug", "define": "DEBUG_NORMAL" } ] diff --git a/src/main/resources/assets/flywheel/flywheel/programs/oriented.json b/src/main/resources/assets/flywheel/flywheel/programs/oriented.json index a22a568cf..9f0709ebf 100644 --- a/src/main/resources/assets/flywheel/flywheel/programs/oriented.json +++ b/src/main/resources/assets/flywheel/flywheel/programs/oriented.json @@ -2,10 +2,7 @@ "source": "flywheel:oriented.vert", "states": [ { - "when": { - "provider": "flywheel:normal_debug", - "value": "true" - }, + "when": "flywheel:normal_debug", "define": "DEBUG_NORMAL" } ]