diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index ec0d3d368..b4f94e0af 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -1,9 +1,7 @@ package com.jozufozu.flywheel.backend; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.annotation.Nullable; @@ -40,7 +38,6 @@ public class Backend { public GlCompat compat; public final Loader loader; - private final List> contexts = new ArrayList<>(); private final Map> materialRegistry = new HashMap<>(); private final Map programSpecRegistry = new HashMap<>(); @@ -74,14 +71,6 @@ public class Backend { return spec; } - /** - * Register a shader context. - */ - public > C register(C spec) { - contexts.add(spec); - return spec; - } - /** * Register an instancing material. */ @@ -96,6 +85,7 @@ public class Backend { return spec; } + @Nullable public ProgramSpec getSpec(ResourceLocation name) { return programSpecRegistry.get(name); } @@ -118,10 +108,6 @@ public class Backend { return programSpecRegistry.values(); } - public Collection> allContexts() { - return contexts; - } - public static boolean isOn() { return getInstance().engine != FlwEngine.OFF; } @@ -157,8 +143,6 @@ public class Backend { void _clearContexts() { GameStateRegistry.clear(); programSpecRegistry.clear(); - contexts.forEach(ShaderContext::delete); - contexts.clear(); materialRegistry.clear(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java index b9d411025..49d9a5fab 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java @@ -7,7 +7,6 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.source.Resolver; -import com.jozufozu.flywheel.backend.source.ShaderLoadingException; import com.jozufozu.flywheel.backend.source.ShaderSources; import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.core.shader.ProgramSpec; @@ -39,7 +38,6 @@ public class Loader implements ResourceManagerReloadListener { private static final Gson GSON = new GsonBuilder().create(); private final Backend backend; - private boolean shouldCrash; private boolean firstLoad = true; @@ -56,15 +54,10 @@ public class Loader implements ResourceManagerReloadListener { } } - public void notifyError() { - shouldCrash = true; - } - @Override public void onResourceManagerReload(ResourceManager manager) { backend.refresh(); - shouldCrash = false; backend._clearContexts(); Resolver.INSTANCE.invalidate(); @@ -75,17 +68,9 @@ public class Loader implements ResourceManagerReloadListener { loadProgramSpecs(manager); - Resolver.INSTANCE.resolve(sources); + Resolver.INSTANCE.run(sources); - for (ShaderContext context : backend.allContexts()) { - context.load(); - } - - if (shouldCrash) { - throw new ShaderLoadingException("Could not load all shaders, see log for details"); - } - - Backend.LOGGER.info("Loaded all shader programs."); + Backend.LOGGER.info("Loaded all shader sources."); ClientLevel world = Minecraft.getInstance().level; if (Backend.canUseInstancing(world)) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java deleted file mode 100644 index 1e3d68f8a..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.jozufozu.flywheel.backend; - -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -import net.minecraft.resources.ResourceLocation; - -public interface ShaderContext

{ - - P getProgram(ResourceLocation loc, VertexType vertexType, RenderLayer layer); - - /** - * Load all programs associated with this context. This might be just one, if the context is very specialized. - */ - void load(); - - void delete(); -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java index 432575f5e..c73a5f428 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java @@ -7,6 +7,8 @@ import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; import java.nio.FloatBuffer; +import javax.annotation.Nonnull; + import org.lwjgl.system.MemoryStack; import com.jozufozu.flywheel.backend.Backend; @@ -87,4 +89,13 @@ public abstract class GlProgram extends GlObject { public String toString() { return "program " + name; } + + /** + * A factory interface to create a {@link GlProgram}. + */ + public interface Factory

{ + + @Nonnull + P create(ResourceLocation name, int handle); + } } 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 c1f63c1bd..67e31c833 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 @@ -5,7 +5,7 @@ import org.lwjgl.opengl.GL20; import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.backend.source.ShaderLoadingException; -import com.jozufozu.flywheel.core.pipeline.ShaderCompiler; +import com.jozufozu.flywheel.core.compile.ShaderCompiler; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderType.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderType.java index a7146ef56..2b10e7578 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderType.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderType.java @@ -16,4 +16,8 @@ public enum ShaderType { this.define = define; this.glEnum = glEnum; } + + public String getDefineStatement() { + return "#define " + define + "\n"; + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java index 6d243973a..c16a9ef97 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java @@ -13,6 +13,7 @@ import com.jozufozu.flywheel.backend.model.FallbackAllocator; import com.jozufozu.flywheel.backend.model.ModelAllocator; import com.jozufozu.flywheel.backend.model.ModelPool; import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.core.compile.ProgramContext; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.util.Textures; import com.mojang.math.Matrix4f; @@ -78,8 +79,8 @@ public class InstancedMaterialGroup

implements MaterialG InstancedMaterial material = entry.getValue(); if (material.nothingToRender()) continue; - P program = owner.context.getProgram(entry.getKey() - .getProgramSpec(), Formats.POS_TEX_NORMAL, layer); + P program = owner.context.getProgram(ProgramContext.create(entry.getKey() + .getProgramSpec(), Formats.POS_TEX_NORMAL, layer)); program.bind(); program.uploadViewProjection(viewProjection); 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 5dc89870c..37f4669b0 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 @@ -13,7 +13,7 @@ import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.backend.instancing.TaskEngine; -import com.jozufozu.flywheel.core.WorldContext; +import com.jozufozu.flywheel.core.compile.ProgramCompiler; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.util.WeakHashSet; @@ -31,7 +31,7 @@ public class InstancingEngine

implements Engine { protected BlockPos originCoordinate = BlockPos.ZERO; - protected final WorldContext

context; + protected final ProgramCompiler

context; protected final GroupFactory

groupFactory; protected final boolean ignoreOriginCoordinate; @@ -39,15 +39,11 @@ public class InstancingEngine

implements Engine { private final WeakHashSet listeners; - public InstancingEngine(WorldContext

context, TaskEngine taskEngine) { - this(context, InstancedMaterialGroup::new, false); - } - - public static

Builder

builder(WorldContext

context) { + public static

Builder

builder(ProgramCompiler

context) { return new Builder<>(context); } - public InstancingEngine(WorldContext

context, GroupFactory

groupFactory, boolean ignoreOriginCoordinate) { + public InstancingEngine(ProgramCompiler

context, GroupFactory

groupFactory, boolean ignoreOriginCoordinate) { this.context = context; this.ignoreOriginCoordinate = ignoreOriginCoordinate; @@ -180,11 +176,11 @@ public class InstancingEngine

implements Engine { } public static class Builder

{ - protected final WorldContext

context; + protected final ProgramCompiler

context; protected GroupFactory

groupFactory = InstancedMaterialGroup::new; protected boolean ignoreOriginCoordinate; - public Builder(WorldContext

context) { + public Builder(ProgramCompiler

context) { this.context = context; } 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 42b5f8dac..9a5d2fd9c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/FileResolution.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.source; import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.source.error.ErrorBuilder; @@ -21,13 +22,13 @@ import net.minecraft.resources.ResourceLocation; public class FileResolution { /** - * Spans that have references that resolved to this. + * Extra info about where this resolution is required. Includes ProgramSpecs and shader Spans. */ - private final List foundSpans = new ArrayList<>(); + private final List> extraCrashInfoProviders = new ArrayList<>(); private final ResourceLocation fileLoc; private SourceFile file; - public FileResolution(ResourceLocation fileLoc) { + FileResolution(ResourceLocation fileLoc) { this.fileLoc = fileLoc; } @@ -35,6 +36,10 @@ public class FileResolution { return fileLoc; } + /** + * Non-null if this file is resolved because there would have been a crash otherwise. + * @return The file that this resolution resolves to. + */ public SourceFile getFile() { return file; } @@ -48,34 +53,44 @@ public class FileResolution { * @param span A span where this file is referenced. */ public FileResolution addSpan(Span span) { - foundSpans.add(span); + extraCrashInfoProviders.add(builder -> builder.pointAtFile(span.getSourceFile()) + .pointAt(span, 1)); return this; } + public void addSpec(ResourceLocation name) { + extraCrashInfoProviders.add(builder -> builder.extra("needed by spec: " + name + ".json")); + } + /** * Check to see if this file actually resolves to something. * *

* Called after all files are loaded. If we can't find the file here, it doesn't exist. *

+ * + * @return True if this file is resolved. */ - void resolve(SourceFinder sources) { + boolean resolve(SourceFinder sources) { file = sources.findSource(fileLoc); if (file == null) { ErrorBuilder builder = ErrorBuilder.error(String.format("could not find source for file %s", fileLoc)); - // print the location of all places where this file was referenced - for (Span span : foundSpans) { - builder.pointAtFile(span.getSourceFile()) - .pointAt(span, 1); + for (Consumer consumer : extraCrashInfoProviders) { + consumer.accept(builder); } Backend.LOGGER.error(builder.build()); - throw new ShaderLoadingException(); + + return false; } + + // Let the GC do its thing + extraCrashInfoProviders.clear(); + return true; } void invalidate() { - foundSpans.clear(); + extraCrashInfoProviders.clear(); file = null; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/source/Resolver.java b/src/main/java/com/jozufozu/flywheel/backend/source/Resolver.java index 202b7a94d..c48eb0b6e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/Resolver.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/Resolver.java @@ -9,29 +9,51 @@ import net.minecraft.resources.ResourceLocation; * Manages deferred file resolution. * *

- * Interns all referenced files in all sources, duplicating the final lookups and allowing for more dev-friendly - * error reporting. - *

- * See {@link FileResolution} for more information. + * Interns all file names in shader sources and program specs, deduplicating the final lookups and allowing for more + * dev-friendly error reporting. *

+ * + * @see FileResolution */ public class Resolver { public static final Resolver INSTANCE = new Resolver(); private final Map resolutions = new HashMap<>(); + private boolean hasRun = false; - public FileResolution findShader(ResourceLocation fileLoc) { - return resolutions.computeIfAbsent(fileLoc, FileResolution::new); + public FileResolution get(ResourceLocation file) { + if (!hasRun) { + return resolutions.computeIfAbsent(file, FileResolution::new); + } else { + // Lock the map after resolution has run. + FileResolution fileResolution = resolutions.get(file); + + // ...so crash immediately if the file isn't found. + if (fileResolution == null) { + throw new RuntimeException("could not find source for file: " + file); + } + + return fileResolution; + } } /** * Try and resolve all referenced source files, printing errors if any aren't found. */ - public void resolve(SourceFinder sources) { + public void run(SourceFinder sources) { + boolean needsCrash = false; for (FileResolution resolution : resolutions.values()) { - resolution.resolve(sources); + if (!resolution.resolve(sources)) { + needsCrash = true; + } } + + if (needsCrash) { + throw new ShaderLoadingException("Failed to resolve all source files, see log for details"); + } + + hasRun = true; } /** @@ -43,5 +65,6 @@ public class Resolver { */ public void invalidate() { resolutions.values().forEach(FileResolution::invalidate); + hasRun = false; } } 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 5692b5273..e69653336 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/SourceFile.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/SourceFile.java @@ -16,7 +16,7 @@ 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 com.jozufozu.flywheel.core.compile.FileIndex; import net.minecraft.resources.ResourceLocation; @@ -138,7 +138,7 @@ public class SourceFile { return "#use " + '"' + name + '"'; } - public void generateFinalSource(ShaderCompiler env, StringBuilder source) { + public void generateFinalSource(FileIndex env, StringBuilder source) { for (Import include : imports) { SourceFile file = include.getFile(); 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 d917ca186..afda73953 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 @@ -16,7 +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.core.compile.ShaderCompiler; import com.jozufozu.flywheel.util.FlwUtil; public class ErrorBuilder { @@ -127,6 +127,7 @@ public class ErrorBuilder { } StringBuilder builder = new StringBuilder(); + builder.append('\n'); for (ErrorLine line : lines) { int length = line.neededMargin(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/source/parse/Import.java b/src/main/java/com/jozufozu/flywheel/backend/source/parse/Import.java index 23a7f279a..239518d84 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/source/parse/Import.java +++ b/src/main/java/com/jozufozu/flywheel/backend/source/parse/Import.java @@ -26,7 +26,7 @@ public class Import extends AbstractShaderElement { super(self); this.file = file; - resolution = resolver.findShader(toRL(file)) + resolution = resolver.get(toRL(file)) .addSpan(file); IMPORTS.add(this); diff --git a/src/main/java/com/jozufozu/flywheel/core/Contexts.java b/src/main/java/com/jozufozu/flywheel/core/Contexts.java index 2d067a0b8..f4dc621cd 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Contexts.java +++ b/src/main/java/com/jozufozu/flywheel/core/Contexts.java @@ -1,13 +1,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.source.FileResolution; import com.jozufozu.flywheel.backend.source.Resolver; +import com.jozufozu.flywheel.core.compile.ProgramCompiler; 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.NormalDebugStateProvider; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.GatherContextEvent; @@ -20,22 +18,17 @@ import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) public class Contexts { - public static WorldContext WORLD; - public static WorldContext CRUMBLING; + public static ProgramCompiler WORLD; + public static ProgramCompiler CRUMBLING; public static void flwInit(GatherContextEvent event) { - Backend backend = event.getBackend(); - GameStateRegistry.register(NormalDebugStateProvider.INSTANCE); - FileResolution crumblingBuiltins = Resolver.INSTANCE.findShader(ResourceUtil.subPath(Names.CRUMBLING, ".glsl")); - FileResolution worldBuiltins = Resolver.INSTANCE.findShader(ResourceUtil.subPath(Names.WORLD, ".glsl")); + FileResolution worldBuiltins = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.WORLD, ".glsl")); + FileResolution crumblingBuiltins = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".glsl")); - 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)); + WORLD = Templates.INSTANCING.programCompiler(WorldProgram::new, worldBuiltins); + CRUMBLING = Templates.INSTANCING.programCompiler(CrumblingProgram::new, crumblingBuiltins); } public static class Names { diff --git a/src/main/java/com/jozufozu/flywheel/core/Materials.java b/src/main/java/com/jozufozu/flywheel/core/Materials.java index f5470dc83..238a6b052 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Materials.java +++ b/src/main/java/com/jozufozu/flywheel/core/Materials.java @@ -28,5 +28,6 @@ public class Materials { public static class Names { public static final ResourceLocation MODEL = Flywheel.rl("model"); public static final ResourceLocation ORIENTED = Flywheel.rl("oriented"); + public static final ResourceLocation PASSTHRU = Flywheel.rl("passthru"); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/Templates.java b/src/main/java/com/jozufozu/flywheel/core/Templates.java index df6f04b35..0946a6e94 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Templates.java +++ b/src/main/java/com/jozufozu/flywheel/core/Templates.java @@ -1,12 +1,12 @@ package com.jozufozu.flywheel.core; import com.jozufozu.flywheel.backend.gl.GLSLVersion; -import com.jozufozu.flywheel.core.pipeline.InstancingTemplateData; -import com.jozufozu.flywheel.core.pipeline.OneShotTemplateData; -import com.jozufozu.flywheel.core.pipeline.Template; +import com.jozufozu.flywheel.core.compile.InstancingTemplateData; +import com.jozufozu.flywheel.core.compile.OneShotTemplateData; +import com.jozufozu.flywheel.core.compile.Template; public class Templates { - public static final Template INSTANCING = new Template<>(GLSLVersion.V330, InstancingTemplateData::new); - public static final Template ONE_SHOT = new Template<>(GLSLVersion.V150, OneShotTemplateData::new); + public static final Template INSTANCING = new Template(GLSLVersion.V330, InstancingTemplateData::new); + public static final Template ONE_SHOT = new Template(GLSLVersion.V150, OneShotTemplateData::new); } diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java deleted file mode 100644 index fa56a87ba..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.jozufozu.flywheel.core; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.Supplier; -import java.util.stream.Stream; - -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.RenderLayer; -import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.source.ShaderLoadingException; -import com.jozufozu.flywheel.core.pipeline.CachingCompiler; -import com.jozufozu.flywheel.core.pipeline.CompilationContext; -import com.jozufozu.flywheel.core.pipeline.PipelineCompiler; -import com.jozufozu.flywheel.core.shader.ProgramSpec; -import com.jozufozu.flywheel.core.shader.WorldProgram; - -import net.minecraft.resources.ResourceLocation; - -public class WorldContext

implements ShaderContext

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

programCache; - - public WorldContext(Backend backend, ResourceLocation name, Supplier> specStream, PipelineCompiler

pipeline) { - this.backend = backend; - this.name = name; - this.specStream = specStream; - this.programCache = new CachingCompiler<>(pipeline); - } - - @Override - public void load() { - - Backend.LOGGER.info("Loading context '{}'", name); - - specStream.get() - .map(backend::getSpec) - .forEach(this::loadSpec); - } - - private void loadSpec(ProgramSpec spec) { - - try { - programs.put(spec.name, spec); - - Backend.LOGGER.debug("Loaded program {}", spec.name); - } catch (Exception e) { - Backend.LOGGER.error("Error loading program {}", spec.name); - if (!(e instanceof ShaderLoadingException)) { - Backend.LOGGER.error("", e); - } - backend.loader.notifyError(); - } - } - - @Override - public P getProgram(ResourceLocation loc, VertexType vertexType, RenderLayer layer) { - ProgramSpec spec = programs.get(loc); - - if (spec == null) { - throw new NullPointerException("Cannot compile shader because '" + loc + "' is not recognized."); - } - - return programCache.getProgram(CompilationContext.create(vertexType, layer, spec)); - } - - @Override - public void delete() { - programCache.invalidate(); - programs.clear(); - } - - public static Builder builder(Backend backend, ResourceLocation name) { - return new Builder(backend, name); - } - - public static class Builder { - private final Backend backend; - private final ResourceLocation name; - private Supplier> specStream; - - public Builder(Backend backend, ResourceLocation name) { - this.backend = backend; - this.name = name; - } - - public Builder setSpecStream(Supplier> specStream) { - this.specStream = specStream; - return this; - } - - public

WorldContext

build(PipelineCompiler

pipeline) { - if (specStream == null) { - specStream = () -> backend.allMaterials() - .stream() - .map(t -> t instanceof Instanced i ? i : null) - .filter(Objects::nonNull) - .map(Instanced::getProgramSpec); - } - return new WorldContext<>(backend, name, specStream, pipeline); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/FileIndex.java b/src/main/java/com/jozufozu/flywheel/core/compile/FileIndex.java new file mode 100644 index 000000000..ec08aade6 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/compile/FileIndex.java @@ -0,0 +1,13 @@ +package com.jozufozu.flywheel.core.compile; + +import com.jozufozu.flywheel.backend.source.SourceFile; + +public interface FileIndex { + /** + * 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. + */ + int getFileID(SourceFile sourceFile); +} diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/InstancingTemplateData.java b/src/main/java/com/jozufozu/flywheel/core/compile/InstancingTemplateData.java similarity index 97% rename from src/main/java/com/jozufozu/flywheel/core/pipeline/InstancingTemplateData.java rename to src/main/java/com/jozufozu/flywheel/core/compile/InstancingTemplateData.java index a18c08f3f..ba3db483c 100644 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/InstancingTemplateData.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/InstancingTemplateData.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.pipeline; +package com.jozufozu.flywheel.core.compile; import java.util.Optional; @@ -134,7 +134,7 @@ public class InstancingTemplateData implements TemplateData { )); } - public void fragmentFooter(StringBuilder template, ShaderCompiler shader) { + public void fragmentFooter(StringBuilder template, FileIndex shader) { Template.prefixFields(template, interpolant, "in", "v2f_"); template.append(String.format(""" diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/OneShotTemplateData.java b/src/main/java/com/jozufozu/flywheel/core/compile/OneShotTemplateData.java similarity index 96% rename from src/main/java/com/jozufozu/flywheel/core/pipeline/OneShotTemplateData.java rename to src/main/java/com/jozufozu/flywheel/core/compile/OneShotTemplateData.java index c000e506c..49d409faf 100644 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/OneShotTemplateData.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/OneShotTemplateData.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.pipeline; +package com.jozufozu.flywheel.core.compile; import java.util.Optional; @@ -99,7 +99,7 @@ public class OneShotTemplateData implements TemplateData { """); } - public void fragmentFooter(StringBuilder template, ShaderCompiler file) { + public void fragmentFooter(StringBuilder template, FileIndex file) { Template.prefixFields(template, interpolant, "in", "v2f_"); template.append(String.format(""" diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/ProgramAssembler.java b/src/main/java/com/jozufozu/flywheel/core/compile/ProgramAssembler.java similarity index 87% rename from src/main/java/com/jozufozu/flywheel/core/pipeline/ProgramAssembler.java rename to src/main/java/com/jozufozu/flywheel/core/compile/ProgramAssembler.java index c5fc72d63..420859520 100644 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/ProgramAssembler.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/ProgramAssembler.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.pipeline; +package com.jozufozu.flywheel.core.compile; import static org.lwjgl.opengl.GL11.GL_TRUE; import static org.lwjgl.opengl.GL20.GL_LINK_STATUS; @@ -11,9 +11,8 @@ import static org.lwjgl.opengl.GL20.glLinkProgram; import java.util.List; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlShader; -import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; -import com.jozufozu.flywheel.core.shader.WorldProgram; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.resources.ResourceLocation; @@ -61,7 +60,7 @@ public class ProgramAssembler { return this; } - public

P build(ExtensibleGlProgram.Factory

factory) { + public

P build(GlProgram.Factory

factory) { return factory.create(name, program); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/ProgramCompiler.java b/src/main/java/com/jozufozu/flywheel/core/compile/ProgramCompiler.java new file mode 100644 index 000000000..fe0f84423 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/compile/ProgramCompiler.java @@ -0,0 +1,58 @@ +package com.jozufozu.flywheel.core.compile; + +import java.util.HashMap; +import java.util.Map; + +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; +import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.source.FileResolution; + +/** + * A caching compiler. + * + *

+ * This class is responsible for compiling programs on the fly. An instance of this class will keep a cache of + * compiled programs, and will only compile a program if it is not already in the cache. + *

+ */ +public class ProgramCompiler

{ + + protected final Map cache = new HashMap<>(); + private final GlProgram.Factory

factory; + + private final Template template; + private final FileResolution header; + + public ProgramCompiler(GlProgram.Factory

factory, Template template, FileResolution header) { + this.factory = factory; + this.template = template; + this.header = header; + } + + /** + * Get or compile a spec to the given vertex type, accounting for all game state conditions specified by the spec. + * + * @param ctx The context of compilation. + * @return A compiled GlProgram. + */ + public P getProgram(ProgramContext ctx) { + return cache.computeIfAbsent(ctx, this::compile); + } + + public void invalidate() { + cache.values().forEach(P::delete); + cache.clear(); + } + + private P compile(ProgramContext ctx) { + ShaderCompiler compiler = new ShaderCompiler(ctx, 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/core/compile/ProgramContext.java b/src/main/java/com/jozufozu/flywheel/core/compile/ProgramContext.java new file mode 100644 index 000000000..6b0450ed0 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/compile/ProgramContext.java @@ -0,0 +1,71 @@ +package com.jozufozu.flywheel.core.compile; + +import java.util.Objects; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.RenderLayer; +import com.jozufozu.flywheel.backend.source.SourceFile; +import com.jozufozu.flywheel.core.shader.ProgramSpec; + +import net.minecraft.resources.ResourceLocation; + +/** + * Represents the entire context of a program's usage. + * + * @param alphaDiscard Alpha threshold below which pixels are discarded. + * @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 ProgramContext(float alphaDiscard, VertexType vertexType, ProgramSpec spec, long ctx) { + + /** + * Creates a compilation context for the given program, vertex type and render layer. + * + * @param programName The name of the program to use. + * @param vertexType The vertex type to use. + * @param layer If cutout, the alpha discard threshold is 0.1, otherwise 0. + * @return A compilation context. + */ + public static ProgramContext create(ResourceLocation programName, VertexType vertexType, @Nullable RenderLayer layer) { + ProgramSpec spec = Backend.getInstance() + .getSpec(programName); + + if (spec == null) { + throw new NullPointerException("Cannot compile shader because '" + programName + "' is not recognized."); + } + + return new ProgramContext(getAlphaDiscard(layer), vertexType, spec, spec.getCurrentStateID()); + } + + /** + * Gets the alpha discard threshold for the given render layer. + * + * @param layer The render layer to get the alpha discard threshold for. + * @return The alpha discard threshold. + */ + public static float getAlphaDiscard(@Nullable RenderLayer layer) { + return layer == RenderLayer.CUTOUT ? 0.1f : 0f; + } + + 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; + ProgramContext that = (ProgramContext) o; + // override for instance equality on vertexType + return alphaDiscard == that.alphaDiscard && ctx == that.ctx && vertexType == that.vertexType && spec.equals(that.spec); + } + + @Override + public int hashCode() { + return Objects.hash(alphaDiscard, vertexType, spec, ctx); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/ShaderCompiler.java b/src/main/java/com/jozufozu/flywheel/core/compile/ShaderCompiler.java similarity index 80% rename from src/main/java/com/jozufozu/flywheel/core/pipeline/ShaderCompiler.java rename to src/main/java/com/jozufozu/flywheel/core/compile/ShaderCompiler.java index c2da3e63a..fb5a3ffd5 100644 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/ShaderCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/ShaderCompiler.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.pipeline; +package com.jozufozu.flywheel.core.compile; import java.util.ArrayList; import java.util.List; @@ -7,7 +7,7 @@ import javax.annotation.Nullable; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.RenderLayer; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlShader; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.source.FileResolution; @@ -15,27 +15,50 @@ 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 net.minecraft.resources.ResourceLocation; -public class ShaderCompiler { +/** + * Compiles a shader program. + */ +public class ShaderCompiler implements FileIndex { + /** + * The name of the file responsible for this compilation. + */ public final ResourceLocation name; - public final Template template; + + /** + * The template we'll be using to generate the final source. + */ + public final Template template; + private final FileResolution header; + /** + * Extra {@code #define}s to be added to the shader. + */ private final List defines; - private final RenderLayer layer; + /** + * Alpha threshold below which pixels are discarded. + */ + private final float alphaDiscard; + + /** + * The vertex type to use. + */ public final VertexType vertexType; + /** + * The main file to compile. + */ public final SourceFile mainFile; private final List files = new ArrayList<>(); - public ShaderCompiler(CompilationContext context, Template template, FileResolution header) { + public ShaderCompiler(ProgramContext context, Template template, FileResolution header) { this.name = context.spec().name; this.template = template; this.header = header; @@ -43,7 +66,7 @@ public class ShaderCompiler { this.defines = context.spec() .getDefines(context.ctx()); this.vertexType = context.vertexType(); - layer = context.layer(); + this.alphaDiscard = context.alphaDiscard(); } public GlShader compile(ShaderType type) { @@ -55,11 +78,9 @@ public class ShaderCompiler { .append('\n') .append("#extension GL_ARB_explicit_attrib_location : enable\n") .append("#extension GL_ARB_conservative_depth : enable\n") - .append("#define ") - .append(type.define) // special case shader type declaration - .append('\n'); + .append(type.getDefineStatement()); // special case shader type declaration - if (layer == RenderLayer.CUTOUT) { + if (alphaDiscard > 0) { finalSource.append("#define ALPHA_DISCARD 0.1\n"); } @@ -91,7 +112,7 @@ public class ShaderCompiler { return new GlShader(this, type, finalSource.toString()); } - public

P compile(ExtensibleGlProgram.Factory

worldShaderPipeline) { + public

P compile(GlProgram.Factory

worldShaderPipeline) { return new ProgramAssembler(this.name) .attachShader(compile(ShaderType.VERTEX)) .attachShader(compile(ShaderType.FRAGMENT)) @@ -105,6 +126,7 @@ public class ShaderCompiler { * @param sourceFile The file to retrieve the ID for. * @return A file ID unique to the given sourceFile. */ + @Override public int getFileID(SourceFile sourceFile) { int i = files.indexOf(sourceFile); if (i != -1) { diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/Template.java b/src/main/java/com/jozufozu/flywheel/core/compile/Template.java similarity index 65% rename from src/main/java/com/jozufozu/flywheel/core/pipeline/Template.java rename to src/main/java/com/jozufozu/flywheel/core/compile/Template.java index 1a872d2b4..995218b2d 100644 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/Template.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/Template.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.pipeline; +package com.jozufozu.flywheel.core.compile; import java.util.HashMap; import java.util.Map; @@ -6,6 +6,8 @@ import java.util.function.Function; import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.backend.gl.GLSLVersion; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; +import com.jozufozu.flywheel.backend.source.FileResolution; import com.jozufozu.flywheel.backend.source.SourceFile; import com.jozufozu.flywheel.backend.source.parse.ShaderStruct; import com.jozufozu.flywheel.backend.source.parse.StructField; @@ -17,25 +19,35 @@ import com.jozufozu.flywheel.backend.source.parse.StructField; * Shader files are written somewhat abstractly. Subclasses of Template handle those abstractions, using SourceFile * metadata to generate shader code that OpenGL can use to call into our shader programs. *

- * @param Holds metadata, generates errors. */ -public class Template { +public class Template { - private final Map metadata = new HashMap<>(); + private final Map metadata = new HashMap<>(); - private final Function reader; + private final Function reader; private final GLSLVersion glslVersion; - public Template(GLSLVersion glslVersion, Function reader) { + public Template(GLSLVersion glslVersion, Function reader) { this.reader = reader; this.glslVersion = glslVersion; } - public D getMetadata(SourceFile file) { + public TemplateData getMetadata(SourceFile file) { // lazily read files, cache results return metadata.computeIfAbsent(file, reader); } + /** + * Creates a program compiler using this template. + * @param factory A factory to add meaning to compiled programs. + * @param header The header file to use for the program. + * @param

The type of program to compile. + * @return A program compiler. + */ + public

ProgramCompiler

programCompiler(GlProgram.Factory

factory, FileResolution header) { + return new ProgramCompiler<>(factory, this, header); + } + public GLSLVersion getVersion() { return glslVersion; } diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/TemplateData.java b/src/main/java/com/jozufozu/flywheel/core/compile/TemplateData.java similarity index 85% rename from src/main/java/com/jozufozu/flywheel/core/pipeline/TemplateData.java rename to src/main/java/com/jozufozu/flywheel/core/compile/TemplateData.java index 90ea7e01f..60c68d080 100644 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/TemplateData.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/TemplateData.java @@ -1,10 +1,10 @@ -package com.jozufozu.flywheel.core.pipeline; +package com.jozufozu.flywheel.core.compile; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; public interface TemplateData { void vertexFooter(StringBuilder builder, ShaderCompiler file); - void fragmentFooter(StringBuilder builder, ShaderCompiler file); + void fragmentFooter(StringBuilder builder, FileIndex file); /** * Generate the necessary glue code here. diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/TypeHelper.java b/src/main/java/com/jozufozu/flywheel/core/compile/TypeHelper.java similarity index 94% rename from src/main/java/com/jozufozu/flywheel/core/pipeline/TypeHelper.java rename to src/main/java/com/jozufozu/flywheel/core/compile/TypeHelper.java index 065755eaa..148168e7b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/TypeHelper.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/TypeHelper.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.pipeline; +package com.jozufozu.flywheel.core.compile; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/package-info.java b/src/main/java/com/jozufozu/flywheel/core/compile/package-info.java similarity index 79% rename from src/main/java/com/jozufozu/flywheel/core/pipeline/package-info.java rename to src/main/java/com/jozufozu/flywheel/core/compile/package-info.java index e51c6e616..d81aeffbb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/package-info.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/package-info.java @@ -1,5 +1,5 @@ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.jozufozu.flywheel.core.pipeline; +package com.jozufozu.flywheel.core.compile; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/CachingCompiler.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/CachingCompiler.java deleted file mode 100644 index b29b75c30..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/CachingCompiler.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.jozufozu.flywheel.core.pipeline; - -import java.util.HashMap; -import java.util.Map; - -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -/** - * Lazily compiles shader programs, caching the results. - * - * @param

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 context The context of compilation. - * @return A compiled GlProgram. - */ - public P getProgram(CompilationContext context) { - return cache.computeIfAbsent(context, 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 deleted file mode 100644 index 74cae594b..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/CompilationContext.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.jozufozu.flywheel.core.pipeline; - -import java.util.Objects; - -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.backend.RenderLayer; -import com.jozufozu.flywheel.backend.source.SourceFile; -import com.jozufozu.flywheel.core.shader.ProgramSpec; - -/** - * Represents the entire context of a program's usage. - * - * @param layer - * @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(RenderLayer layer, VertexType vertexType, ProgramSpec spec, long ctx) { - - public static CompilationContext create(VertexType vertexType, RenderLayer layer, ProgramSpec spec) { - return new CompilationContext(layer, vertexType, spec, spec.getCurrentStateID()); - } - - 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 layer == that.layer && ctx == that.ctx && vertexType == that.vertexType && spec.equals(that.spec); - } - - @Override - public int hashCode() { - return Objects.hash(layer, vertexType, spec, ctx); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/pipeline/PipelineCompiler.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/PipelineCompiler.java deleted file mode 100644 index a831480e5..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/PipelineCompiler.java +++ /dev/null @@ -1,13 +0,0 @@ -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/core/pipeline/WorldCompiler.java b/src/main/java/com/jozufozu/flywheel/core/pipeline/WorldCompiler.java deleted file mode 100644 index 5bf2980a8..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/pipeline/WorldCompiler.java +++ /dev/null @@ -1,33 +0,0 @@ -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/core/shader/ExtensibleGlProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/ExtensibleGlProgram.java deleted file mode 100644 index 927092e9b..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/shader/ExtensibleGlProgram.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.jozufozu.flywheel.core.shader; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nonnull; - -import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -import net.minecraft.resources.ResourceLocation; - -/** - * A shader program that be arbitrarily "extended". This class can take in any number of program extensions, and - * will initialize them and then call their {@link ExtensionInstance#bind() bind} function every subsequent time this - * program is bound. An "extension" is something that interacts with the shader program in a way that is invisible to - * the caller using the program. This is used by some programs to implement the different fog modes. Other uses might - * include binding extra textures to allow for blocks to have normal maps, for example. As the extensions are - * per-program, this also allows for same extra specialization within a - * {@link ShaderContext ShaderContext}. - */ -public class ExtensibleGlProgram extends GlProgram { - - protected final List extensions = new ArrayList<>(); - - public ExtensibleGlProgram(ResourceLocation name, int handle) { - super(name, handle); - } - - @Override - public void bind() { - super.bind(); - - extensions.forEach(ExtensionInstance::bind); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("program ") - .append(name) - .append('['); - - for (ExtensionInstance extension : extensions) { - builder.append(extension) - .append('+'); - } - - builder.append(']'); - - return builder.toString(); - } - - /** - * A factory interface to create {@link GlProgram}s parameterized by a list of extensions. This doesn't necessarily - * have to return an {@link ExtensibleGlProgram} if implementors want more flexibility for whatever reason. - */ - public interface Factory

{ - - @Nonnull - P create(ResourceLocation name, int handle); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/ProgramSpec.java b/src/main/java/com/jozufozu/flywheel/core/shader/ProgramSpec.java index d0ffe8068..34111f068 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/ProgramSpec.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/ProgramSpec.java @@ -43,12 +43,13 @@ public class ProgramSpec { public final ImmutableList states; public ProgramSpec(ResourceLocation source, List states) { - this.source = Resolver.INSTANCE.findShader(source); + this.source = Resolver.INSTANCE.get(source); this.states = ImmutableList.copyOf(states); } public void setName(ResourceLocation name) { this.name = name; + this.source.addSpec(name); } public ResourceLocation getSourceLoc() { diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java index 3754969b8..0dce27d7d 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java @@ -4,6 +4,7 @@ import static org.lwjgl.opengl.GL20.glUniform1f; import static org.lwjgl.opengl.GL20.glUniform2f; import static org.lwjgl.opengl.GL20.glUniform3f; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.util.AnimationTickHolder; import com.mojang.blaze3d.platform.Window; import com.mojang.math.Matrix4f; @@ -11,11 +12,12 @@ import com.mojang.math.Matrix4f; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; -public class WorldProgram extends ExtensibleGlProgram { +public class WorldProgram extends GlProgram { protected final int uTime = getUniformLocation("uTime"); protected final int uViewProjection = getUniformLocation("uViewProjection"); protected final int uCameraPos = getUniformLocation("uCameraPos"); protected final int uWindowSize = getUniformLocation("uWindowSize"); + private final WorldFog fog; protected int uBlockAtlas; protected int uLightMap; @@ -23,7 +25,7 @@ public class WorldProgram extends ExtensibleGlProgram { public WorldProgram(ResourceLocation name, int handle) { super(name, handle); - this.extensions.add(new WorldFog(this)); + fog = new WorldFog(this); super.bind(); registerSamplers(); @@ -66,7 +68,7 @@ public class WorldProgram extends ExtensibleGlProgram { @Override public void bind() { super.bind(); - + fog.bind(); uploadWindowSize(); uploadTime(AnimationTickHolder.getRenderTime()); } diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/package-info.java b/src/main/java/com/jozufozu/flywheel/core/shader/package-info.java new file mode 100644 index 000000000..d25693290 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/shader/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.core.shader; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/resources/assets/flywheel/flywheel/programs/passthru.json b/src/main/resources/assets/flywheel/flywheel/programs/passthru.json new file mode 100644 index 000000000..bdb8aabff --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/programs/passthru.json @@ -0,0 +1,9 @@ +{ + "source": "flywheel:passthru.vert", + "states": [ + { + "when": "flywheel:normal_debug", + "define": "DEBUG_NORMAL" + } + ] +} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/passthru.vert b/src/main/resources/assets/flywheel/flywheel/shaders/passthru.vert new file mode 100644 index 000000000..a598d8ebd --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/shaders/passthru.vert @@ -0,0 +1,7 @@ +#use "flywheel:block.frag" + +#if defined(VERTEX_SHADER) +void vertex(inout Vertex v) { + +} +#endif