diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index 28366c73b..ae55cd5de 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -7,14 +7,13 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.ShadersModHandler; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.backend.instancing.PipelineCompiler; import com.jozufozu.flywheel.backend.instancing.batching.DrawBuffer; +import com.jozufozu.flywheel.backend.instancing.compile.FlwCompiler; import com.jozufozu.flywheel.config.BackendTypeArgument; import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.core.BackendTypes; import com.jozufozu.flywheel.core.Components; -import com.jozufozu.flywheel.core.DebugRender; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.core.QuadConverter; import com.jozufozu.flywheel.core.StitchedSprite; @@ -81,7 +80,7 @@ public class Flywheel { forgeEventBus.addListener(FlwCommands::registerClientCommands); forgeEventBus.addListener(EventPriority.HIGHEST, QuadConverter::onReloadRenderers); - forgeEventBus.addListener(PipelineCompiler::onReloadRenderers); + forgeEventBus.addListener(FlwCompiler::onReloadRenderers); forgeEventBus.addListener(Models::onReloadRenderers); forgeEventBus.addListener(DrawBuffer::onReloadRenderers); @@ -108,7 +107,6 @@ public class Flywheel { // forgeEventBus.addListener(ExampleEffect::onReload); Components.init(); - DebugRender.init(); VanillaInstances.init(); diff --git a/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java b/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java index 06716f2bc..7c0fd2a30 100644 --- a/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java +++ b/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java @@ -2,21 +2,21 @@ package com.jozufozu.flywheel.api.uniform; import com.jozufozu.flywheel.core.source.FileResolution; -public abstract class UniformProvider { +public interface UniformProvider { - protected long ptr; - protected Notifier notifier; + int byteSize(); - public abstract int getActualByteSize(); + FileResolution uniformShader(); - public void updatePtr(long ptr, Notifier notifier) { - this.ptr = ptr; - this.notifier = notifier; + ActiveUniformProvider activate(long ptr, Notifier notifier); + + interface ActiveUniformProvider { + void delete(); + + void poll(); } - public abstract FileResolution getUniformShader(); - - public interface Notifier { + interface Notifier { void signalChanged(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/BackendType.java b/src/main/java/com/jozufozu/flywheel/backend/BackendType.java index d7124a3d9..0c870193e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/BackendType.java +++ b/src/main/java/com/jozufozu/flywheel/backend/BackendType.java @@ -1,5 +1,8 @@ package com.jozufozu.flywheel.backend; +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.api.pipeline.PipelineShader; import com.jozufozu.flywheel.backend.instancing.Engine; import net.minecraft.network.chat.Component; @@ -17,4 +20,6 @@ public interface BackendType { BackendType findFallback(); boolean supported(); + + @Nullable PipelineShader pipelineShader(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java index 2524be426..d9c1f3067 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java @@ -1,23 +1,10 @@ package com.jozufozu.flywheel.backend; -import java.util.List; - -import com.jozufozu.flywheel.api.context.ContextShader; -import com.jozufozu.flywheel.api.material.Material; -import com.jozufozu.flywheel.api.pipeline.PipelineShader; -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.backend.instancing.PipelineCompiler; -import com.jozufozu.flywheel.backend.instancing.indirect.ComputeCullerCompiler; -import com.jozufozu.flywheel.core.ComponentRegistry; -import com.jozufozu.flywheel.core.Components; -import com.jozufozu.flywheel.core.compile.ShaderCompilationException; +import com.jozufozu.flywheel.backend.instancing.compile.FlwCompiler; import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.core.source.ShaderLoadingException; import com.jozufozu.flywheel.core.source.ShaderSources; import com.jozufozu.flywheel.core.source.error.ErrorReporter; -import com.jozufozu.flywheel.util.StringUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -68,46 +55,7 @@ public class Loader implements ResourceManagerReloadListener { Backend.LOGGER.info("All shaders passed checks."); - long compileStart = System.nanoTime(); - int programCounter = 0; - boolean crash = false; - - for (Material material : ComponentRegistry.materials) { - for (StructType structType : ComponentRegistry.structTypes) { - for (VertexType vertexType : ComponentRegistry.vertexTypes) { - for (ContextShader contextShader : ComponentRegistry.contextShaders) { - for (PipelineShader pipelineShader : List.of(Components.INSTANCED_ARRAYS, Components.INDIRECT)) { - var ctx = new PipelineCompiler.Context(vertexType, material, structType, contextShader, pipelineShader); - try { - PipelineCompiler.INSTANCE.getProgram(ctx); - } catch (ShaderCompilationException e) { - Backend.LOGGER.error(e.errors); - crash = true; - } - programCounter++; - } - } - } - } - } - - for (StructType structType : ComponentRegistry.structTypes) { - try { - ComputeCullerCompiler.INSTANCE.get(structType); - } catch (ShaderCompilationException e) { - Backend.LOGGER.error(e.errors); - crash = true; - } - programCounter++; - } - - long compileEnd = System.nanoTime(); - - Backend.LOGGER.info("Compiled " + programCounter + " programs in " + StringUtil.formatTime(compileEnd - compileStart)); - - if (crash) { - throw new ShaderLoadingException("Compilation failed"); - } + FlwCompiler.INSTANCE.run(); ClientLevel level = Minecraft.getInstance().level; if (Backend.canUseInstancing(level)) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/SimpleBackendType.java b/src/main/java/com/jozufozu/flywheel/backend/SimpleBackendType.java index 1269c08dd..d832b7691 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/SimpleBackendType.java +++ b/src/main/java/com/jozufozu/flywheel/backend/SimpleBackendType.java @@ -3,6 +3,9 @@ package com.jozufozu.flywheel.backend; import java.util.function.BooleanSupplier; import java.util.function.Supplier; +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.api.pipeline.PipelineShader; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.core.BackendTypes; @@ -17,14 +20,16 @@ public class SimpleBackendType implements BackendType { private final Supplier engineSupplier; private final Supplier fallback; private final BooleanSupplier isSupported; + private final PipelineShader pipelineShader; - public SimpleBackendType(String properName, String shortName, Component engineMessage, Supplier engineSupplier, Supplier fallback, BooleanSupplier isSupported) { + public SimpleBackendType(String properName, String shortName, Component engineMessage, Supplier engineSupplier, Supplier fallback, BooleanSupplier isSupported, @Nullable PipelineShader pipelineShader) { this.properName = properName; this.shortName = shortName; this.engineMessage = engineMessage; this.engineSupplier = engineSupplier; this.fallback = fallback; this.isSupported = isSupported; + this.pipelineShader = pipelineShader; } public static Builder builder() { @@ -66,6 +71,11 @@ public class SimpleBackendType implements BackendType { return isSupported.getAsBoolean(); } + @Override + public @Nullable PipelineShader pipelineShader() { + return pipelineShader; + } + public static class Builder { private String properName; private String shortName; @@ -73,6 +83,7 @@ public class SimpleBackendType implements BackendType { private Supplier engineSupplier; private Supplier fallback; private BooleanSupplier isSupported; + private PipelineShader pipelineShader; public Builder properName(String properName) { this.properName = properName; @@ -104,8 +115,13 @@ public class SimpleBackendType implements BackendType { return this; } + public Builder pipelineShader(PipelineShader pipelineShader) { + this.pipelineShader = pipelineShader; + return this; + } + public BackendType register() { - return BackendTypes.register(new SimpleBackendType(properName, shortName, engineMessage, engineSupplier, fallback, isSupported)); + return BackendTypes.register(new SimpleBackendType(properName, shortName, engineMessage, engineSupplier, fallback, isSupported, pipelineShader)); } } } 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 ea80d4cf5..cea2fcfa3 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 @@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.gl.shader; import static org.lwjgl.opengl.GL20.glDeleteProgram; import static org.lwjgl.opengl.GL20.glGetUniformLocation; import static org.lwjgl.opengl.GL20.glUniform1i; -import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; import org.jetbrains.annotations.NotNull; @@ -11,17 +10,13 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlObject; import com.mojang.blaze3d.shaders.ProgramManager; -import net.minecraft.resources.ResourceLocation; - public class GlProgram extends GlObject { - public final ResourceLocation name; - - public GlProgram(ResourceLocation name, int handle) { - this.name = name; + public GlProgram(int handle) { setHandle(handle); } + // TODO: Programs bind the uniform buffers they need public void bind() { ProgramManager.glUseProgram(handle()); } @@ -40,7 +35,7 @@ public class GlProgram extends GlObject { int index = glGetUniformLocation(this.handle(), uniform); if (index < 0) { - Backend.LOGGER.debug("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name); + Backend.LOGGER.debug("No active uniform '{}' exists. Could be unused.", uniform); } return index; @@ -69,17 +64,11 @@ public class GlProgram extends GlObject { glDeleteProgram(handle); } - @Override - public String toString() { - return "program " + name; - } - /** * A factory interface to create a {@link GlProgram}. */ public interface Factory { - @NotNull - GlProgram create(ResourceLocation name, int handle); + @NotNull GlProgram create(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 a93ec6046..0ffaa3485 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 @@ -10,7 +10,7 @@ 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.core.compile.ShaderCompilationException; +import com.jozufozu.flywheel.backend.instancing.compile.ShaderCompilationException; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/PipelineCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/PipelineCompiler.java deleted file mode 100644 index 5df7ae5b6..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/PipelineCompiler.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.jozufozu.flywheel.backend.instancing; - -import java.util.LinkedHashSet; -import java.util.List; - -import com.google.common.collect.ImmutableList; -import com.jozufozu.flywheel.api.context.ContextShader; -import com.jozufozu.flywheel.api.material.Material; -import com.jozufozu.flywheel.api.pipeline.PipelineShader; -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.backend.gl.GLSLVersion; -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.core.SourceComponent; -import com.jozufozu.flywheel.core.compile.CompileUtil; -import com.jozufozu.flywheel.core.compile.Memoizer; -import com.jozufozu.flywheel.core.compile.ProgramAssembler; -import com.jozufozu.flywheel.core.compile.ShaderCompilationException; -import com.jozufozu.flywheel.core.source.CompilationContext; -import com.jozufozu.flywheel.event.ReloadRenderersEvent; - -import net.minecraft.resources.ResourceLocation; - -/** - * 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. - *

- *

- * A ProgramCompiler is also responsible for deleting programs and shaders on renderer reload. - *

- */ -public class PipelineCompiler extends Memoizer { - - public static final PipelineCompiler INSTANCE = new PipelineCompiler(); - - private final ShaderCompiler shaderCompiler; - - private PipelineCompiler() { - this.shaderCompiler = new ShaderCompiler(); - } - - /** - * 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 GlProgram getProgram(PipelineCompiler.Context ctx) { - return super.get(ctx); - } - - @Override - public void invalidate() { - super.invalidate(); - shaderCompiler.invalidate(); - } - - @Override - protected GlProgram _create(PipelineCompiler.Context ctx) { - - var glslVersion = ctx.pipelineShader() - .glslVersion(); - - var vertex = new ShaderCompiler.Context(glslVersion, ShaderType.VERTEX, ctx.getVertexComponents()); - var fragment = new ShaderCompiler.Context(glslVersion, ShaderType.FRAGMENT, ctx.getFragmentComponents()); - - return new ProgramAssembler(ctx.structType.getInstanceShader() - .getFileLoc()).attachShader(shaderCompiler.get(vertex)) - .attachShader(shaderCompiler.get(fragment)) - .link() - .build(ctx.contextShader.factory()); - } - - @Override - protected void _destroy(GlProgram value) { - value.delete(); - } - - public static void onReloadRenderers(ReloadRenderersEvent event) { - INSTANCE.invalidate(); - } - - /** - * Represents the entire context of a program's usage. - * - * @param vertexType The vertexType the program should be adapted for. - * @param material The material shader to use. TODO: Flatten materials - * @param structType The instance shader to use. - * @param contextShader The context shader to use. - */ - public record Context(VertexType vertexType, Material material, StructType structType, - ContextShader contextShader, PipelineShader pipelineShader) { - - ImmutableList getVertexComponents() { - var layout = vertexType.getLayoutShader() - .getFile(); - var instanceAssembly = pipelineShader.assemble(vertexType, structType); - var instance = structType.getInstanceShader() - .getFile(); - var material = this.material.getVertexShader() - .getFile(); - var context = contextShader.getVertexShader(); - var pipeline = pipelineShader.vertex() - .getFile(); - return ImmutableList.of(layout, instanceAssembly, instance, material, context, pipeline); - } - - ImmutableList getFragmentComponents() { - var material = this.material.getFragmentShader() - .getFile(); - var context = contextShader.getFragmentShader(); - var pipeline = pipelineShader.fragment() - .getFile(); - return ImmutableList.of(material, context, pipeline); - } - } - - /** - * Handles compilation and deletion of vertex shaders. - */ - public static class ShaderCompiler extends Memoizer { - - private ShaderCompiler() { - } - - @Override - protected GlShader _create(Context key) { - StringBuilder finalSource = new StringBuilder(key.generateHeader()); - finalSource.append("#extension GL_ARB_explicit_attrib_location : enable\n"); - finalSource.append("#extension GL_ARB_conservative_depth : enable\n"); - - var ctx = new CompilationContext(); - - var names = ImmutableList.builder(); - var included = new LinkedHashSet(); // linked to preserve order - for (var component : key.sourceComponents) { - included.addAll(component.included()); - names.add(component.name()); - } - - for (var include : included) { - finalSource.append(include.source(ctx)); - } - - for (var component : key.sourceComponents) { - finalSource.append(component.source(ctx)); - } - - try { - return new GlShader(finalSource.toString(), key.shaderType, names.build()); - } catch (ShaderCompilationException e) { - throw e.withErrorLog(ctx); - } - } - - @Override - protected void _destroy(GlShader value) { - value.delete(); - } - - /** - * @param glslVersion The GLSL version to use. - * @param sourceComponents A list of shader components to stitch together, in order. - */ - public record Context(GLSLVersion glslVersion, ShaderType shaderType, List sourceComponents) { - - public String generateHeader() { - return CompileUtil.generateHeader(glslVersion, shaderType); - } - } - - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompilationEnvironment.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompilationEnvironment.java new file mode 100644 index 000000000..8f78af939 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompilationEnvironment.java @@ -0,0 +1,59 @@ +package com.jozufozu.flywheel.backend.instancing.compile; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import com.jozufozu.flywheel.api.context.ContextShader; +import com.jozufozu.flywheel.api.pipeline.PipelineShader; +import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.api.uniform.UniformProvider; +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.BackendTypes; +import com.jozufozu.flywheel.core.ComponentRegistry; +import com.jozufozu.flywheel.core.source.ShaderLoadingException; +import com.jozufozu.flywheel.util.StringUtil; + +class CompilationEnvironment { + final VertexMaterialComponent vertexMaterialComponent; + final FragmentMaterialComponent fragmentMaterialComponent; + + boolean needsCrash = false; + + final long compileStart = System.nanoTime(); + final Multimap, PipelineContext> uniformProviderGroups = ArrayListMultimap.create(); + final List pipelineContexts = new ArrayList<>(); + + CompilationEnvironment() { + for (PipelineShader pipelineShader : BackendTypes.availablePipelineShaders()) { + for (StructType structType : ComponentRegistry.structTypes) { + for (VertexType vertexType : ComponentRegistry.vertexTypes) { + for (ContextShader contextShader : ComponentRegistry.contextShaders) { + acknowledgeContext(new PipelineContext(vertexType, structType, contextShader, pipelineShader)); + } + } + } + } + this.vertexMaterialComponent = new VertexMaterialComponent(ComponentRegistry.materials.vertexSources()); + this.fragmentMaterialComponent = new FragmentMaterialComponent(ComponentRegistry.materials.fragmentSources()); + } + + private void acknowledgeContext(PipelineContext ctx) { + uniformProviderGroups.put(ctx.uniformProviders(), ctx); + + pipelineContexts.add(ctx); + } + + public void finish() { + long compileEnd = System.nanoTime(); + + Backend.LOGGER.info("Compiled " + pipelineContexts.size() + " programs in " + StringUtil.formatTime(compileEnd - compileStart)); + + if (needsCrash) { + throw new ShaderLoadingException("Compilation failed"); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/CompileUtil.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompileUtil.java similarity index 96% rename from src/main/java/com/jozufozu/flywheel/core/compile/CompileUtil.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompileUtil.java index 545055281..219b3802e 100644 --- a/src/main/java/com/jozufozu/flywheel/core/compile/CompileUtil.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompileUtil.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.compile; +package com.jozufozu.flywheel.backend.instancing.compile; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FlwCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FlwCompiler.java new file mode 100644 index 000000000..49109b6d5 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FlwCompiler.java @@ -0,0 +1,129 @@ +package com.jozufozu.flywheel.backend.instancing.compile; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.api.context.ContextShader; +import com.jozufozu.flywheel.api.pipeline.PipelineShader; +import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.gl.GLSLVersion; +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.instancing.indirect.IndirectComponent; +import com.jozufozu.flywheel.core.ComponentRegistry; +import com.jozufozu.flywheel.core.Components; +import com.jozufozu.flywheel.core.SourceComponent; +import com.jozufozu.flywheel.core.source.CompilationContext; +import com.jozufozu.flywheel.event.ReloadRenderersEvent; + +import net.minecraft.resources.ResourceLocation; + +public class FlwCompiler { + + public static final FlwCompiler INSTANCE = new FlwCompiler(); + + public static void onReloadRenderers(ReloadRenderersEvent t) { + + } + + private final ShaderCompiler shaderCompiler = new ShaderCompiler(); + public final Map pipelinePrograms = new HashMap<>(); + + public final Map, GlProgram> cullingPrograms = new HashMap<>(); + + private CompilationEnvironment environment; + + FlwCompiler() { + + } + + public void run() { + environment = new CompilationEnvironment(); + + for (PipelineContext context : environment.pipelineContexts) { + try { + var glProgram = compilePipelineContext(context); + pipelinePrograms.put(context, glProgram); + } catch (ShaderCompilationException e) { + environment.needsCrash = true; + Backend.LOGGER.error(e.errors); + } + } + + for (StructType type : ComponentRegistry.structTypes) { + try { + var glProgram = compileComputeCuller(type); + cullingPrograms.put(type, glProgram); + } catch (ShaderCompilationException e) { + environment.needsCrash = true; + Backend.LOGGER.error(e.errors); + } + } + + environment.finish(); + } + + public GlProgram getPipelineProgram(VertexType vertexType, StructType structType, ContextShader contextShader, PipelineShader pipelineShader) { + return pipelinePrograms.get(new PipelineContext(vertexType, structType, contextShader, pipelineShader)); + } + + public GlProgram getCullingProgram(StructType structType) { + return cullingPrograms.get(structType); + } + + protected GlProgram compilePipelineContext(PipelineContext ctx) throws ShaderCompilationException { + + var glslVersion = ctx.pipelineShader() + .glslVersion(); + + var vertex = new ShaderContext(glslVersion, ShaderType.VERTEX, ctx.getVertexComponents()); + var fragment = new ShaderContext(glslVersion, ShaderType.FRAGMENT, ctx.getFragmentComponents()); + + return ctx.contextShader() + .factory() + .create(new ProgramAssembler().attachShader(shaderCompiler.get(vertex)) + .attachShader(shaderCompiler.get(fragment)) + .link()); + } + + protected GlProgram compileComputeCuller(StructType structType) { + var location = structType.getInstanceShader(); + + var finalSource = new StringBuilder(); + CompilationContext context = new CompilationContext(); + var components = List.of(new IndirectComponent(structType.getLayout().layoutItems), location.getFile(), Components.Pipeline.INDIRECT_CULL.getFile()); + + var names = ImmutableList.builder(); + var included = new LinkedHashSet(); // linked to preserve order + for (var component : components) { + included.addAll(component.included()); + names.add(component.name()); + } + + finalSource.append(CompileUtil.generateHeader(GLSLVersion.V460, ShaderType.COMPUTE)); + for (var include : included) { + finalSource.append(include.source(context)); + } + + for (var component : components) { + finalSource.append(component.source(context)); + } + + try { + var fileLoc = location.getFileLoc(); + var shader = new GlShader(finalSource.toString(), ShaderType.COMPUTE, ImmutableList.of(fileLoc)); + + var program = new ProgramAssembler().attachShader(shader) + .link(); + return new GlProgram(program); + } catch (ShaderCompilationException e) { + throw e.withErrorLog(context); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FragmentMaterialComponent.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FragmentMaterialComponent.java new file mode 100644 index 000000000..85bb823c2 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FragmentMaterialComponent.java @@ -0,0 +1,49 @@ +package com.jozufozu.flywheel.backend.instancing.compile; + +import java.util.Collection; +import java.util.List; + +import com.jozufozu.flywheel.core.SourceComponent; +import com.jozufozu.flywheel.core.source.CompilationContext; +import com.jozufozu.flywheel.core.source.FileResolution; +import com.jozufozu.flywheel.core.source.generate.GlslExpr; +import com.jozufozu.flywheel.util.ResourceUtil; + +import net.minecraft.resources.ResourceLocation; + +public class FragmentMaterialComponent implements SourceComponent { + + private static final String flw_materialFragment = "flw_materialFragment"; + private static final String flw_discardPredicate = "flw_discardPredicate"; + private static final String flw_fogFilter = "flw_fogFilter"; + + private static final GlslExpr flw_materialFragmentID = GlslExpr.variable(flw_materialFragment + "ID"); + + private final List transformedMaterials; + + public FragmentMaterialComponent(List sourceMaterials) { + + this.transformedMaterials = sourceMaterials.stream() + .map(FileResolution::getFile) + .map(s -> { + var newName = flw_materialFragment + '_' + ResourceUtil.toSafeString(s.name()); + return new TransformedSourceComponent(s, flw_materialFragment, newName); + }) + .toList(); + } + + @Override + public Collection included() { + return transformedMaterials; + } + + @Override + public String source(CompilationContext ctx) { + return null; + } + + @Override + public ResourceLocation name() { + return null; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/PipelineContext.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/PipelineContext.java new file mode 100644 index 000000000..b074ce19e --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/PipelineContext.java @@ -0,0 +1,65 @@ +package com.jozufozu.flywheel.backend.instancing.compile; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.jetbrains.annotations.NotNull; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.api.context.ContextShader; +import com.jozufozu.flywheel.api.pipeline.PipelineShader; +import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.api.uniform.UniformProvider; +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.core.ComponentRegistry; +import com.jozufozu.flywheel.core.SourceComponent; + +/** + * Represents the entire context of a program's usage. + * + * @param vertexType The vertexType the program should be adapted for. + * @param structType The instance shader to use. + * @param contextShader The context shader to use. + */ +public record PipelineContext(VertexType vertexType, StructType structType, ContextShader contextShader, + PipelineShader pipelineShader) { + + @NotNull + public Set uniformProviders() { + var fragmentComponents = getFragmentComponents(); + var vertexComponents = getVertexComponents(); + + return Stream.concat(fragmentComponents.stream(), vertexComponents.stream()) + .map(SourceComponent::included) + .flatMap(Collection::stream) + .map(SourceComponent::name) + .mapMulti((component, consumer) -> { + var uniformProvider = ComponentRegistry.getUniformProvider(component); + if (uniformProvider != null) { + consumer.accept(uniformProvider); + } + }) + .collect(Collectors.toSet()); + } + + ImmutableList getVertexComponents() { + var layout = vertexType.getLayoutShader() + .getFile(); + var instanceAssembly = pipelineShader.assemble(vertexType, structType); + var instance = structType.getInstanceShader() + .getFile(); + var context = contextShader.getVertexShader(); + var pipeline = pipelineShader.vertex() + .getFile(); + return ImmutableList.of(layout, instanceAssembly, instance, context, pipeline); + } + + ImmutableList getFragmentComponents() { + var context = contextShader.getFragmentShader(); + var pipeline = pipelineShader.fragment() + .getFile(); + return ImmutableList.of(context, pipeline); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/ProgramAssembler.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ProgramAssembler.java similarity index 67% rename from src/main/java/com/jozufozu/flywheel/core/compile/ProgramAssembler.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ProgramAssembler.java index 8a549859d..75031a9ef 100644 --- a/src/main/java/com/jozufozu/flywheel/core/compile/ProgramAssembler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ProgramAssembler.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.compile; +package com.jozufozu.flywheel.backend.instancing.compile; import static org.lwjgl.opengl.GL11.GL_TRUE; import static org.lwjgl.opengl.GL20.GL_LINK_STATUS; @@ -9,30 +9,26 @@ import static org.lwjgl.opengl.GL20.glGetProgrami; import static org.lwjgl.opengl.GL20.glLinkProgram; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlShader; -import net.minecraft.resources.ResourceLocation; - +@Deprecated public class ProgramAssembler { - public final int program; - private final ResourceLocation name; + private final int program; - public ProgramAssembler(ResourceLocation name) { - this.name = name; + public ProgramAssembler() { this.program = glCreateProgram(); } /** * Links the attached shaders to this program. */ - public ProgramAssembler link() { + public int link() { glLinkProgram(this.program); String log = glGetProgramInfoLog(this.program); if (!log.isEmpty()) { - Backend.LOGGER.debug("Program link log for " + name + ": " + log); + Backend.LOGGER.debug("Program link log: " + log); } int result = glGetProgrami(this.program, GL_LINK_STATUS); @@ -41,15 +37,11 @@ public class ProgramAssembler { throw new RuntimeException("Shader program linking failed, see log for details"); } - return this; + return program; } public ProgramAssembler attachShader(GlShader glShader) { glAttachShader(this.program, glShader.handle()); return this; } - - public GlProgram build(GlProgram.Factory factory) { - return factory.create(name, program); - } } diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/ShaderCompilationException.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderCompilationException.java similarity index 92% rename from src/main/java/com/jozufozu/flywheel/core/compile/ShaderCompilationException.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderCompilationException.java index caa848fc0..e66a6a2a2 100644 --- a/src/main/java/com/jozufozu/flywheel/core/compile/ShaderCompilationException.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderCompilationException.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.compile; +package com.jozufozu.flywheel.backend.instancing.compile; import org.lwjgl.opengl.GL20; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderCompiler.java new file mode 100644 index 000000000..934ee2bbe --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderCompiler.java @@ -0,0 +1,64 @@ +package com.jozufozu.flywheel.backend.instancing.compile; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.backend.gl.GlObject; +import com.jozufozu.flywheel.backend.gl.shader.GlShader; +import com.jozufozu.flywheel.core.SourceComponent; +import com.jozufozu.flywheel.core.source.CompilationContext; + +import net.minecraft.resources.ResourceLocation; + +/** + * Handles compilation and deletion of vertex shaders. + */ +public class ShaderCompiler { + + private final Map map = new HashMap<>(); + + ShaderCompiler() { + } + + public GlShader get(ShaderContext key) { + return map.computeIfAbsent(key, this::_create); + } + + protected GlShader _create(ShaderContext key) { + StringBuilder finalSource = new StringBuilder(key.generateHeader()); + finalSource.append("#extension GL_ARB_explicit_attrib_location : enable\n"); + finalSource.append("#extension GL_ARB_conservative_depth : enable\n"); + + var ctx = new CompilationContext(); + + var names = ImmutableList.builder(); + var included = new LinkedHashSet(); // linked to preserve order + for (var component : key.sourceComponents()) { + included.addAll(component.included()); + names.add(component.name()); + } + + for (var include : included) { + finalSource.append(include.source(ctx)); + } + + for (var component : key.sourceComponents()) { + finalSource.append(component.source(ctx)); + } + + try { + return new GlShader(finalSource.toString(), key.shaderType(), names.build()); + } catch (ShaderCompilationException e) { + throw e.withErrorLog(ctx); + } + } + + public void invalidate() { + map.values() + .forEach(GlObject::delete); + map.clear(); + } + +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderContext.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderContext.java new file mode 100644 index 000000000..28f04f6d0 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/ShaderContext.java @@ -0,0 +1,18 @@ +package com.jozufozu.flywheel.backend.instancing.compile; + +import java.util.List; + +import com.jozufozu.flywheel.backend.gl.GLSLVersion; +import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.core.SourceComponent; + +/** + * @param glslVersion The GLSL version to use. + * @param sourceComponents A list of shader components to stitch together, in order. + */ +public record ShaderContext(GLSLVersion glslVersion, ShaderType shaderType, List sourceComponents) { + + public String generateHeader() { + return CompileUtil.generateHeader(glslVersion, shaderType); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/TransformedSourceComponent.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/TransformedSourceComponent.java new file mode 100644 index 000000000..b6faefa4a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/TransformedSourceComponent.java @@ -0,0 +1,37 @@ +package com.jozufozu.flywheel.backend.instancing.compile; + +import java.util.Collection; + +import com.jozufozu.flywheel.core.SourceComponent; +import com.jozufozu.flywheel.core.source.CompilationContext; +import com.jozufozu.flywheel.util.ResourceUtil; + +import net.minecraft.resources.ResourceLocation; + +public final class TransformedSourceComponent implements SourceComponent { + final SourceComponent source; + final String find; + final String replacement; + + public TransformedSourceComponent(SourceComponent source, String find, String replacement) { + this.source = source; + this.find = find; + this.replacement = replacement; + } + + @Override + public String source(CompilationContext ctx) { + return source.source(ctx) + .replace(find, replacement); + } + + @Override + public ResourceLocation name() { + return ResourceUtil.subPath(source.name(), "_renamed"); + } + + @Override + public Collection included() { + return source.included(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/VertexMaterialComponent.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/VertexMaterialComponent.java new file mode 100644 index 000000000..87b27e9d9 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/VertexMaterialComponent.java @@ -0,0 +1,71 @@ +package com.jozufozu.flywheel.backend.instancing.compile; + +import java.util.Collection; +import java.util.List; + +import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.core.SourceComponent; +import com.jozufozu.flywheel.core.source.CompilationContext; +import com.jozufozu.flywheel.core.source.FileResolution; +import com.jozufozu.flywheel.core.source.generate.GlslBuilder; +import com.jozufozu.flywheel.core.source.generate.GlslExpr; +import com.jozufozu.flywheel.util.ResourceUtil; + +import net.minecraft.resources.ResourceLocation; + +public class VertexMaterialComponent implements SourceComponent { + + private static final String flw_materialVertex = "flw_materialVertex"; + private static final GlslExpr flw_materialVertexID = GlslExpr.variable(flw_materialVertex + "ID"); + + private final List transformedMaterials; + + public VertexMaterialComponent(List sourceMaterials) { + + this.transformedMaterials = sourceMaterials.stream() + .map(FileResolution::getFile) + .map(s -> { + var newName = flw_materialVertex + '_' + ResourceUtil.toSafeString(s.name()); + return new TransformedSourceComponent(s, flw_materialVertex, newName); + }) + .toList(); + } + + @Override + public Collection included() { + return transformedMaterials; + } + + @Override + public String source(CompilationContext ctx) { + String out = genSource(); + return ctx.generatedHeader(out, "material adapter") + out; + } + + public String genSource() { + var builder = new GlslBuilder(); + + builder.function() + .returnType("void") + .name("flw_materialVertex") + .body(this::accept); + + return builder.build(); + } + + @Override + public ResourceLocation name() { + return Flywheel.rl("vertex_material_adapter"); + } + + private void accept(GlslBuilder.BlockBuilder body) { + var sw = new GlslBuilder.SwitchBuilder(flw_materialVertexID); + for (int i = 0; i < transformedMaterials.size(); i++) { + var variant = transformedMaterials.get(i).replacement; + + sw.case_(i, b -> b.eval(GlslExpr.call(variant)) + .break_()); + } + body.add(sw.build()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/package-info.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/package-info.java new file mode 100644 index 000000000..ddcf60e2e --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.backend.instancing.compile; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/ComputeCullerCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/ComputeCullerCompiler.java deleted file mode 100644 index 4efda5bc0..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/ComputeCullerCompiler.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.jozufozu.flywheel.backend.instancing.indirect; - -import java.util.LinkedHashSet; -import java.util.List; - -import com.google.common.collect.ImmutableList; -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.backend.gl.GLSLVersion; -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.core.Components; -import com.jozufozu.flywheel.core.SourceComponent; -import com.jozufozu.flywheel.core.compile.CompileUtil; -import com.jozufozu.flywheel.core.compile.Memoizer; -import com.jozufozu.flywheel.core.compile.ProgramAssembler; -import com.jozufozu.flywheel.core.compile.ShaderCompilationException; -import com.jozufozu.flywheel.core.source.CompilationContext; -import com.jozufozu.flywheel.event.ReloadRenderersEvent; - -import net.minecraft.resources.ResourceLocation; - -public class ComputeCullerCompiler extends Memoizer, GlProgram> { - - public static final ComputeCullerCompiler INSTANCE = new ComputeCullerCompiler(); - - private ComputeCullerCompiler() { - } - - @Override - protected GlProgram _create(StructType structType) { - var location = structType.getInstanceShader(); - - var finalSource = new StringBuilder(); - CompilationContext context = new CompilationContext(); - var components = List.of(new IndirectComponent(structType.getLayout().layoutItems), location.getFile(), Components.Pipeline.INDIRECT_CULL.getFile()); - - var names = ImmutableList.builder(); - var included = new LinkedHashSet(); // linked to preserve order - for (var component : components) { - included.addAll(component.included()); - names.add(component.name()); - } - - finalSource.append(CompileUtil.generateHeader(GLSLVersion.V460, ShaderType.COMPUTE)); - for (var include : included) { - finalSource.append(include.source(context)); - } - - for (var component : components) { - finalSource.append(component.source(context)); - } - - try { - var fileLoc = location.getFileLoc(); - var shader = new GlShader(finalSource.toString(), ShaderType.COMPUTE, ImmutableList.of(fileLoc)); - - return new ProgramAssembler(fileLoc).attachShader(shader) - .link() - .build(GlProgram::new); - } catch (ShaderCompilationException e) { - throw e.withErrorLog(context); - } - } - - @Override - protected void _destroy(GlProgram value) { - value.delete(); - } - - public static void invalidateAll(ReloadRenderersEvent ignored) { - INSTANCE.invalidate(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectComponent.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectComponent.java index 05f772b47..55668c4f7 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectComponent.java @@ -2,7 +2,6 @@ package com.jozufozu.flywheel.backend.instancing.indirect; import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.core.Components; @@ -60,17 +59,13 @@ public class IndirectComponent implements SourceComponent { builder.blankLine(); - var func = builder.function() + builder.function() .returnType(structName) .name("flw_unpackInstance") - .argumentIn(packedStructName, UNPACK_ARG); - - var args = layoutItems.stream() - .map(layoutItem -> layoutItem.unpackField(UNPACKING_VARIABLE)) - .map(GlslExpr::minPrint) - .collect(Collectors.joining(", ")); - - func.statement("return " + structName + "(" + args + ");"); + .argumentIn(packedStructName, UNPACK_ARG) + .body(b -> b.ret(GlslExpr.call(structName, layoutItems.stream() + .map(layoutItem -> layoutItem.unpackField(UNPACKING_VARIABLE)) + .toList()))); return builder.build(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java index fe426247d..9618c0f02 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java @@ -17,11 +17,9 @@ import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; -import com.jozufozu.flywheel.backend.instancing.PipelineCompiler; +import com.jozufozu.flywheel.backend.instancing.compile.FlwCompiler; import com.jozufozu.flywheel.core.Components; -import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.QuadConverter; -import com.jozufozu.flywheel.core.uniform.UniformBuffer; public class IndirectCullingGroup { @@ -65,8 +63,8 @@ public class IndirectCullingGroup { .quads2Tris(2048).buffer.handle(); setupVertexArray(); - compute = ComputeCullerCompiler.INSTANCE.get(structType); - draw = PipelineCompiler.INSTANCE.get(new PipelineCompiler.Context(vertexType, Materials.SHULKER, structType, Components.WORLD, Components.INDIRECT)); + compute = FlwCompiler.INSTANCE.getCullingProgram(structType); + draw = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, Components.WORLD, Components.INDIRECT); } private void setupVertexArray() { @@ -116,9 +114,6 @@ public class IndirectCullingGroup { uploadInstanceData(); uploadIndirectCommands(); - UniformBuffer.getInstance() - .sync(); - compute.bind(); buffers.bindAll(); @@ -137,9 +132,6 @@ public class IndirectCullingGroup { buffers.bindObjectAndTarget(); buffers.bindIndirectBuffer(); - UniformBuffer.getInstance() - .sync(); - memoryBarrier(); drawSet.submit(stage); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedArraysComponent.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedArraysComponent.java index 2a7f28f8e..84fdf8498 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedArraysComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedArraysComponent.java @@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.instancing.instancing; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.core.SourceComponent; @@ -68,16 +67,13 @@ public class InstancedArraysComponent implements SourceComponent { builder.blankLine(); - var func = builder.function() + // unpacking function + builder.function() .returnType(structName) - .name("flw_unpackInstance"); - - var args = layoutItems.stream() - .map(it -> new GlslExpr.Variable(it.name() + ATTRIBUTE_SUFFIX)) - .map(GlslExpr::minPrint) - .collect(Collectors.joining(", ")); - - func.statement("return " + structName + "(" + args + ");"); + .name("flw_unpackInstance") + .body(b -> b.ret(GlslExpr.call(structName, layoutItems.stream() + .map(it -> new GlslExpr.Variable(it.name() + ATTRIBUTE_SUFFIX)) + .toList()))); return builder.build(); } 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 47096cb01..89e82c1a4 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 @@ -16,11 +16,10 @@ import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.backend.instancing.InstanceManager; -import com.jozufozu.flywheel.backend.instancing.PipelineCompiler; import com.jozufozu.flywheel.backend.instancing.TaskEngine; +import com.jozufozu.flywheel.backend.instancing.compile.FlwCompiler; import com.jozufozu.flywheel.core.Components; import com.jozufozu.flywheel.core.RenderContext; -import com.jozufozu.flywheel.core.uniform.UniformBuffer; import com.jozufozu.flywheel.util.WeakHashSet; import com.mojang.blaze3d.systems.RenderSystem; @@ -124,12 +123,8 @@ public class InstancingEngine implements Engine { var structType = desc.instance(); var material = desc.material(); - var ctx = new PipelineCompiler.Context(vertexType, material, structType, context, Components.INSTANCED_ARRAYS); - - PipelineCompiler.INSTANCE.getProgram(ctx) + FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, context, Components.INSTANCED_ARRAYS) .bind(); - UniformBuffer.getInstance() - .sync(); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/BackendTypes.java b/src/main/java/com/jozufozu/flywheel/core/BackendTypes.java index 5436279ad..7b8e256dc 100644 --- a/src/main/java/com/jozufozu/flywheel/core/BackendTypes.java +++ b/src/main/java/com/jozufozu/flywheel/core/BackendTypes.java @@ -4,9 +4,12 @@ import java.util.Collection; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; +import com.jozufozu.flywheel.api.pipeline.PipelineShader; import com.jozufozu.flywheel.backend.BackendType; import com.jozufozu.flywheel.backend.ShadersModHandler; import com.jozufozu.flywheel.backend.SimpleBackendType; @@ -55,6 +58,7 @@ public class BackendTypes { .fallback(() -> BackendTypes.BATCHING) .supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance() .instancedArraysSupported()) + .pipelineShader(Components.INSTANCED_ARRAYS) .register(); /** @@ -68,6 +72,7 @@ public class BackendTypes { .fallback(() -> BackendTypes.INSTANCING) .supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance() .supportsIndirect()) + .pipelineShader(Components.INDIRECT) .register(); public static BackendType register(BackendType type) { @@ -94,4 +99,12 @@ public class BackendTypes { } + public static Collection availablePipelineShaders() { + return BACKEND_TYPES.values() + .stream() + .filter(BackendType::supported) + .map(BackendType::pipelineShader) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/ComponentRegistry.java b/src/main/java/com/jozufozu/flywheel/core/ComponentRegistry.java index c44251baf..4e0bf6b56 100644 --- a/src/main/java/com/jozufozu/flywheel/core/ComponentRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/core/ComponentRegistry.java @@ -3,22 +3,29 @@ package com.jozufozu.flywheel.core; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.api.context.ContextShader; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.uniform.UniformProvider; import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.api.context.ContextShader; +import com.jozufozu.flywheel.core.source.FileResolution; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; import net.minecraft.resources.ResourceLocation; public class ComponentRegistry { private static final Registry uniformProviders = new Registry<>(); - public static final Set materials = new HashSet<>(); + public static final MaterialRegistry materials = new MaterialRegistry(); public static final Set> structTypes = new HashSet<>(); public static final Set vertexTypes = new HashSet<>(); public static final Set contextShaders = new HashSet<>(); @@ -26,8 +33,7 @@ public class ComponentRegistry { // TODO: fill out the rest of the registry public static T register(T material) { - materials.add(material); - return material; + return materials.add(material); } public static > T register(T type) { @@ -46,7 +52,7 @@ public class ComponentRegistry { } public static T register(T provider) { - return uniformProviders.register(provider.getUniformShader() + return uniformProviders.register(provider.uniformShader() .getFileLoc(), provider); } @@ -54,17 +60,71 @@ public class ComponentRegistry { return Collections.unmodifiableCollection(uniformProviders.objects); } + @Nullable + public static UniformProvider getUniformProvider(ResourceLocation loc) { + return uniformProviders.get(loc); + } + private static class Registry { - private final Set files = new HashSet<>(); + private final Map files = new HashMap<>(); private final List objects = new ArrayList<>(); public O register(ResourceLocation loc, O object) { - if (files.contains(loc)) { + if (files.containsKey(loc)) { throw new IllegalArgumentException("Shader file already registered: " + loc); } - files.add(loc); + files.put(loc, object); objects.add(object); return object; } + + @Nullable + public T get(ResourceLocation loc) { + return files.get(loc); + } + } + + public static class MaterialRegistry { + + private final Set materials = new HashSet<>(); + private final MaterialSources vertexSources = new MaterialSources(); + private final MaterialSources fragmentSources = new MaterialSources(); + + public T add(T material) { + materials.add(material); + + vertexSources.register(material, material.getVertexShader()); + fragmentSources.register(material, material.getFragmentShader()); + + return material; + } + + /** + * @return a list of vertex shader sources where the index in the list is the shader's ID. + */ + public List vertexSources() { + return vertexSources.sourceView; + } + + /** + * @return a list of fragment shader sources where the index in the list is the shader's ID. + */ + public List fragmentSources() { + return fragmentSources.sourceView; + } + + private static class MaterialSources { + private final Set registered = new HashSet<>(); + private final List orderedSources = new ArrayList<>(); + private final Reference2IntMap material2ID = new Reference2IntOpenHashMap<>(); + private final List sourceView = Collections.unmodifiableList(orderedSources); + + public void register(Material material, FileResolution vertexShader) { + if (registered.add(vertexShader)) { + material2ID.put(material, orderedSources.size()); + orderedSources.add(vertexShader); + } + } + } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/DebugRender.java b/src/main/java/com/jozufozu/flywheel/core/DebugRender.java deleted file mode 100644 index 10c8e414c..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/DebugRender.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.jozufozu.flywheel.core; - -import org.lwjgl.opengl.GL46; -import org.lwjgl.system.MemoryStack; - -import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.backend.gl.GlStateTracker; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; -import com.jozufozu.flywheel.core.compile.DebugCompiler; -import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.util.Lazy; -import com.jozufozu.flywheel.util.joml.FrustumIntersection; -import com.mojang.blaze3d.systems.RenderSystem; - -public class DebugRender { - - private static final Lazy SHADER = Lazy.of(() -> DebugCompiler.INSTANCE.get(new DebugCompiler.Context(Files.VERTEX, Files.FRAGMENT))); - - private static final Lazy FRUSTUM_VBO = Lazy.of(Frustum::new); - - public static void init() { - Files.init(); - } - - public static void updateFrustum(FrustumIntersection culler) { - FRUSTUM_VBO.get() - .upload(culler); - } - - public static void drawFrustum() { - if (!FRUSTUM_VBO.isInitialized()) { - return; - } - - RenderSystem.disableCull(); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - - try (var ignored = GlStateTracker.getRestoreState()) { - SHADER.get() - .bind(); - FRUSTUM_VBO.get() - .draw(); - } - } - - public static class Files { - public static final FileResolution VERTEX = FileResolution.get(Flywheel.rl("debug/debug.vert")); - public static final FileResolution FRAGMENT = FileResolution.get(Flywheel.rl("debug/debug.frag")); - - public static void init() { - - } - } - - // FIXME: This never worked (and the thing it was meant to debug is already fixed), - // but it should be a quick turnaround - private static class Frustum { - private static final int[] indices = new int[]{ - 0, 2, 3, 0, 3, 1, - 2, 6, 7, 2, 7, 3, - 6, 4, 5, 6, 5, 7, - 4, 0, 1, 4, 1, 5, - 0, 4, 6, 0, 6, 2, - 1, 5, 7, 1, 7, 3, - }; - - private static final int elementCount = indices.length; - private static final int indicesSize = elementCount * 4; - private static final int verticesSize = 3 * 8 * 4; - private final int buffer; - private final int vao; - - public Frustum() { - // holy moly DSA is nice - buffer = GL46.glCreateBuffers(); - GL46.glNamedBufferStorage(buffer, verticesSize + indicesSize, GL46.GL_DYNAMIC_STORAGE_BIT); - GL46.glNamedBufferSubData(buffer, 0, indices); - - vao = GL46.glCreateVertexArrays(); - GL46.glEnableVertexArrayAttrib(vao, 0); - GL46.glVertexArrayElementBuffer(vao, buffer); - GL46.glVertexArrayVertexBuffer(vao, 0, buffer, indicesSize, 3 * 4); - GL46.glVertexArrayAttribFormat(vao, 0, 3, GL46.GL_FLOAT, false, 0); - } - - public void upload(FrustumIntersection culler) { - try (var stack = MemoryStack.stackPush()) { - var buf = stack.malloc(3 * 8 * 4); - - culler.getCorners(buf); - - GL46.glNamedBufferSubData(buffer, indicesSize, buf); - } - } - - public void draw() { - GL46.glEnableVertexArrayAttrib(vao, 0); - GL46.glVertexArrayElementBuffer(vao, buffer); - GL46.glBindVertexArray(vao); - GL46.glDrawElements(GL46.GL_TRIANGLES, elementCount, GL46.GL_UNSIGNED_INT, 0); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldProgram.java b/src/main/java/com/jozufozu/flywheel/core/WorldProgram.java index 0be9030ce..4d53fb194 100644 --- a/src/main/java/com/jozufozu/flywheel/core/WorldProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/WorldProgram.java @@ -2,8 +2,6 @@ package com.jozufozu.flywheel.core; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; -import net.minecraft.resources.ResourceLocation; - public class WorldProgram extends GlProgram { // TODO: sampler registry? @@ -11,8 +9,8 @@ public class WorldProgram extends GlProgram { protected int overlayTex; protected int lightTex; - public WorldProgram(ResourceLocation name, int handle) { - super(name, handle); + public WorldProgram(int handle) { + super(handle); bind(); registerSamplers(); diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/DebugCompiler.java b/src/main/java/com/jozufozu/flywheel/core/compile/DebugCompiler.java deleted file mode 100644 index 322d2777f..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/compile/DebugCompiler.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.jozufozu.flywheel.core.compile; - -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.gl.shader.GlShader; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; -import com.jozufozu.flywheel.core.source.CompilationContext; -import com.jozufozu.flywheel.core.source.FileResolution; -import com.jozufozu.flywheel.event.ReloadRenderersEvent; - -/** - * Simple shader compiler that pulls no excessive tricks.

- * Useful for writing experimental shaders or - */ -public class DebugCompiler extends Memoizer { - - public static final DebugCompiler INSTANCE = new DebugCompiler(); - - private final ShaderCompiler shaderCompiler; - - private DebugCompiler() { - this.shaderCompiler = new ShaderCompiler(); - } - - @Override - public void invalidate() { - super.invalidate(); - shaderCompiler.invalidate(); - } - - @Override - protected GlProgram _create(DebugCompiler.Context ctx) { - - return new ProgramAssembler(ctx.vertex.getFileLoc()) - .attachShader(shaderCompiler.vertex(ctx.vertex)) - .attachShader(shaderCompiler.fragment(ctx.fragment)) - .link() - .build(GlProgram::new); - } - - @Override - protected void _destroy(GlProgram value) { - value.delete(); - } - - public static void invalidateAll(ReloadRenderersEvent ignored) { - INSTANCE.invalidate(); - } - - public record Context(FileResolution vertex, FileResolution fragment) { - } - - /** - * Handles compilation and deletion of vertex shaders. - */ - private static class ShaderCompiler extends Memoizer { - - public GlShader vertex(FileResolution source) { - return get(new Context(source, ShaderType.VERTEX)); - } - - public GlShader fragment(FileResolution source) { - return get(new Context(source, ShaderType.FRAGMENT)); - } - - @Override - protected GlShader _create(Context ctx) { - var index = new CompilationContext(); - - StringBuilder source = new StringBuilder(CompileUtil.generateHeader(GLSLVersion.V420, ctx.type)); - - var file = ctx.source.getFile(); - for (var include : file.flattenedImports) { - source.append(include.source(index)); - } - - source.append(file.source(index)); - - try { - return new GlShader(source.toString(), ctx.type, ImmutableList.of(ctx.source.getFileLoc())); - } catch (ShaderCompilationException e) { - throw e.withErrorLog(index); - } - } - - @Override - protected void _destroy(GlShader value) { - value.delete(); - } - - public record Context(FileResolution source, ShaderType type) { - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/Memoizer.java b/src/main/java/com/jozufozu/flywheel/core/compile/Memoizer.java deleted file mode 100644 index f2dbc95f1..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/compile/Memoizer.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.jozufozu.flywheel.core.compile; - -import java.util.HashMap; -import java.util.Map; - -public abstract class Memoizer { - - private final Map map = new HashMap<>(); - - public V get(K key) { - return map.computeIfAbsent(key, this::_create); - } - - public void invalidate() { - map.values().forEach(this::_destroy); - map.clear(); - } - - protected abstract V _create(K key); - - protected abstract void _destroy(V value); -} diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java index 777112ee6..f5be39ec6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java @@ -2,11 +2,9 @@ package com.jozufozu.flywheel.core.crumbling; import com.jozufozu.flywheel.core.WorldProgram; -import net.minecraft.resources.ResourceLocation; - public class CrumblingProgram extends WorldProgram { - public CrumblingProgram(ResourceLocation name, int handle) { - super(name, handle); + public CrumblingProgram(int handle) { + super(handle); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/source/CompilationContext.java b/src/main/java/com/jozufozu/flywheel/core/source/CompilationContext.java index c962694d3..1f40d5ab5 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/CompilationContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/CompilationContext.java @@ -27,11 +27,11 @@ public class CompilationContext { generatedLines += lines; - if (comment != null) { - out += " // " + comment; + if (comment == null) { + comment = ""; } - return out + '\n'; + return out + " // (generated) " + comment + '\n'; } public boolean contains(SourceFile sourceFile) { diff --git a/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java b/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java index b90528ec9..8b8161145 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java @@ -80,7 +80,7 @@ public class SourceFile implements SourceComponent { @Override public String source(CompilationContext ctx) { - return ctx.sourceHeader(this) + this.elideImports(); + return ctx.sourceHeader(this) + this.genFinalSource(); } @Override @@ -188,7 +188,7 @@ public class SourceFile implements SourceComponent { return "Source for shader '" + name + "':\n" + lines.printLinesWithNumbers(); } - private CharSequence elideImports() { + private CharSequence genFinalSource() { StringBuilder out = new StringBuilder(); int lastEnd = 0; diff --git a/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslBuilder.java b/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslBuilder.java index b8d3bbd2a..ef31652f9 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslBuilder.java @@ -2,13 +2,15 @@ package com.jozufozu.flywheel.core.source.generate; import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; import java.util.stream.Collectors; import com.jozufozu.flywheel.util.Pair; public class GlslBuilder { + public static final String INDENT = " "; - private final List elements = new ArrayList<>(); + private final List elements = new ArrayList<>(); public void define(String name, String value) { add(new Define(name, value)); @@ -26,7 +28,7 @@ public class GlslBuilder { return add(new VertexInputBuilder()); } - public T add(T element) { + public T add(T element) { elements.add(element); return element; } @@ -37,15 +39,19 @@ public class GlslBuilder { public String build() { return elements.stream() - .map(SourceElement::build) + .map(GlslRootElement::minPrint) .collect(Collectors.joining("\n")); } - public interface SourceElement { - String build(); + public static String indent(int indentation) { + return INDENT.repeat(indentation); } - public enum Separators implements SourceElement { + public interface GlslRootElement { + String minPrint(); + } + + public enum Separators implements GlslRootElement { BLANK_LINE(""), ; @@ -54,21 +60,21 @@ public class GlslBuilder { Separators(String separator) { this.separator = separator; } + @Override - public String build() { + public String minPrint() { return separator; } - } - public record Define(String name, String value) implements SourceElement { + public record Define(String name, String value) implements GlslRootElement { @Override - public String build() { + public String minPrint() { return "#define " + name + " " + value; } } - public static class VertexInputBuilder implements SourceElement { + public static class VertexInputBuilder implements GlslRootElement { private int binding; private String type; @@ -90,12 +96,12 @@ public class GlslBuilder { } @Override - public String build() { + public String minPrint() { return "layout(location = " + binding + ") in " + type + " " + name + ";"; } } - public static class StructBuilder implements SourceElement { + public static class StructBuilder implements GlslRootElement { private final List> fields = new ArrayList<>(); private String name; @@ -110,11 +116,11 @@ public class GlslBuilder { private String buildFields() { return fields.stream() - .map(p -> '\t' + p.first() + ' ' + p.second() + ';') + .map(p -> INDENT + p.first() + ' ' + p.second() + ';') .collect(Collectors.joining("\n")); } - public String build() { + public String minPrint() { return """ struct %s { %s @@ -123,9 +129,9 @@ public class GlslBuilder { } } - public static class FunctionBuilder implements SourceElement { + public static class FunctionBuilder implements GlslRootElement { private final List> arguments = new ArrayList<>(); - private final List body = new ArrayList<>(); + private final BlockBuilder body = new BlockBuilder(); private String returnType; private String name; @@ -149,24 +155,17 @@ public class GlslBuilder { return this; } - public FunctionBuilder statement(String statement) { - this.body.add(statement); + public FunctionBuilder body(Consumer f) { + f.accept(body); return this; } - - public String build() { + public String minPrint() { return """ %s %s(%s) { %s } - """.formatted(returnType, name, buildArguments(), buildBody()); - } - - private String buildBody() { - return body.stream() - .map(s -> '\t' + s) - .collect(Collectors.joining("\n")); + """.formatted(returnType, name, buildArguments(), body.prettyPrint()); } private String buildArguments() { @@ -175,4 +174,61 @@ public class GlslBuilder { .collect(Collectors.joining(", ")); } } + + public static class BlockBuilder implements LangItem { + private final List body = new ArrayList<>(); + + public BlockBuilder add(GlslStmt stmt) { + body.add(stmt); + return this; + } + + public BlockBuilder eval(GlslExpr expr) { + return add(GlslStmt.eval(expr)); + } + + public BlockBuilder switchOn(GlslExpr expr, Consumer f) { + var builder = new SwitchBuilder(expr); + f.accept(builder); + return add(builder.build()); + } + + public void ret(GlslExpr call) { + add(GlslStmt.ret(call)); + } + + public void break_() { + add(GlslStmt.BREAK); + } + + @Override + public String prettyPrint() { + return body.stream() + .map(GlslStmt::prettyPrint) + .collect(Collectors.joining("\n")); + } + + } + + public static class SwitchBuilder { + + private final GlslExpr on; + + private final List> cases = new ArrayList<>(); + + public SwitchBuilder(GlslExpr on) { + this.on = on; + } + + public SwitchBuilder case_(int expr, Consumer f) { + var builder = new BlockBuilder(); + f.accept(builder); + cases.add(Pair.of(GlslExpr.literal(expr), builder)); + return this; + } + + public GlslStmt.Switch build() { + return new GlslStmt.Switch(on, cases); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslExpr.java b/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslExpr.java index 7ae03952b..5046e0afb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslExpr.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslExpr.java @@ -1,8 +1,12 @@ package com.jozufozu.flywheel.core.source.generate; +import java.util.Collection; import java.util.function.Function; +import java.util.stream.Collectors; -public sealed interface GlslExpr { +import com.google.common.collect.ImmutableList; + +public interface GlslExpr extends LangItem { /** * Create a glsl variable with the given name. @@ -14,7 +18,17 @@ public sealed interface GlslExpr { return new Variable(name); } - String minPrint(); + static FunctionCall call(String functionName, Collection args) { + return new FunctionCall(functionName, args); + } + + static FunctionCall0 call(String functionName) { + return new FunctionCall0(functionName); + } + + static GlslExpr literal(int expr) { + return new Literal(expr); + } /** * Call a one-parameter function with the given name on this expression. @@ -58,29 +72,55 @@ public sealed interface GlslExpr { record Variable(String name) implements GlslExpr { @Override - public String minPrint() { + public String prettyPrint() { return name; } + } - record FunctionCall(String name, GlslExpr target) implements GlslExpr { - @Override - public String minPrint() { - return name + "(" + target.minPrint() + ")"; + record FunctionCall(String name, Collection args) implements GlslExpr { + public FunctionCall(String name, GlslExpr target) { + this(name, ImmutableList.of(target)); } + + @Override + public String prettyPrint() { + var args = this.args.stream() + .map(GlslExpr::prettyPrint) + .collect(Collectors.joining(",")); + return name + "(" + args + ")"; + } + + } + + record FunctionCall0(String name) implements GlslExpr { + @Override + public String prettyPrint() { + return name + "()"; + } + } record Swizzle(GlslExpr target, String selection) implements GlslExpr { @Override - public String minPrint() { - return target.minPrint() + "." + selection; + public String prettyPrint() { + return target.prettyPrint() + "." + selection; } + } record Access(GlslExpr target, String argName) implements GlslExpr { @Override - public String minPrint() { - return target.minPrint() + "." + argName; + public String prettyPrint() { + return target.prettyPrint() + "." + argName; + } + + } + + record Literal(int value) implements GlslExpr { + @Override + public String prettyPrint() { + return Integer.toString(value); } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslStmt.java b/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslStmt.java new file mode 100644 index 000000000..241184112 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/source/generate/GlslStmt.java @@ -0,0 +1,60 @@ +package com.jozufozu.flywheel.core.source.generate; + +import java.util.List; +import java.util.stream.Collectors; + +import com.jozufozu.flywheel.util.Pair; + +public interface GlslStmt extends LangItem { + + static GlslStmt eval(GlslExpr expr) { + return new Eval(expr); + } + + static GlslStmt ret(GlslExpr value) { + return new Return(value); + } + + static GlslStmt BREAK = () -> "break;"; + + static GlslStmt CONTINUE = () -> "continue;"; + + static GlslStmt RETURN = () -> "return;"; + + record Eval(GlslExpr expr) implements GlslStmt { + @Override + public String prettyPrint() { + return expr.prettyPrint() + ";"; + } + } + + record Return(GlslExpr expr) implements GlslStmt { + @Override + public String prettyPrint() { + return "return " + expr.prettyPrint() + ";"; + } + } + + record Switch(GlslExpr expr, List> body) implements GlslStmt { + @Override + public String prettyPrint() { + var cases = body.stream() + .map(Switch::prettyPrintCase) + .collect(Collectors.joining("\n")); + return """ + switch (%s) { + %s + }""".formatted(expr.prettyPrint(), cases); + } + + private static String prettyPrintCase(Pair p) { + var variant = p.first() + .prettyPrint(); + var block = p.second() + .prettyPrint(); + return """ + case %s: + %s""".formatted(variant, block); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/source/generate/LangItem.java b/src/main/java/com/jozufozu/flywheel/core/source/generate/LangItem.java new file mode 100644 index 000000000..0ae9d4e6c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/source/generate/LangItem.java @@ -0,0 +1,7 @@ +package com.jozufozu.flywheel.core.source.generate; + +public interface LangItem { + + String prettyPrint(); + +} diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/package-info.java b/src/main/java/com/jozufozu/flywheel/core/source/generate/package-info.java similarity index 76% rename from src/main/java/com/jozufozu/flywheel/core/compile/package-info.java rename to src/main/java/com/jozufozu/flywheel/core/source/generate/package-info.java index d81aeffbb..6fa0c353e 100644 --- a/src/main/java/com/jozufozu/flywheel/core/compile/package-info.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/generate/package-info.java @@ -1,5 +1,5 @@ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.jozufozu.flywheel.core.compile; +package com.jozufozu.flywheel.core.source.generate; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java b/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java index 05cfdc8b3..c45806ace 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java @@ -7,33 +7,59 @@ import com.jozufozu.flywheel.core.Components; import com.jozufozu.flywheel.core.source.FileResolution; import com.mojang.blaze3d.systems.RenderSystem; -public class FogProvider extends UniformProvider { +public class FogProvider implements UniformProvider { + + public static boolean FOG_UPDATE = true; @Override - public int getActualByteSize() { + public int byteSize() { return 16 + 8 + 4; } - public void update() { - if (ptr == MemoryUtil.NULL) { - return; - } - - var color = RenderSystem.getShaderFogColor(); - - MemoryUtil.memPutFloat(ptr, color[0]); - MemoryUtil.memPutFloat(ptr + 4, color[1]); - MemoryUtil.memPutFloat(ptr + 8, color[2]); - MemoryUtil.memPutFloat(ptr + 12, color[3]); - MemoryUtil.memPutFloat(ptr + 16, RenderSystem.getShaderFogStart()); - MemoryUtil.memPutFloat(ptr + 20, RenderSystem.getShaderFogEnd()); - MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape().getIndex()); - - notifier.signalChanged(); + @Override + public FileResolution uniformShader() { + return Components.Files.FOG_UNIFORMS; } @Override - public FileResolution getUniformShader() { - return Components.Files.FOG_UNIFORMS; + public ActiveUniformProvider activate(long ptr, Notifier notifier) { + return new Active(ptr, notifier); + } + + public static class Active implements ActiveUniformProvider { + + private final long ptr; + private final Notifier notifier; + + public Active(long ptr, Notifier notifier) { + this.ptr = ptr; + this.notifier = notifier; + } + + @Override + public void delete() { + } + + @Override + public void poll() { + if (!FOG_UPDATE) { + return; + } + + var color = RenderSystem.getShaderFogColor(); + + MemoryUtil.memPutFloat(ptr, color[0]); + MemoryUtil.memPutFloat(ptr + 4, color[1]); + MemoryUtil.memPutFloat(ptr + 8, color[2]); + MemoryUtil.memPutFloat(ptr + 12, color[3]); + MemoryUtil.memPutFloat(ptr + 16, RenderSystem.getShaderFogStart()); + MemoryUtil.memPutFloat(ptr + 20, RenderSystem.getShaderFogEnd()); + MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape() + .getIndex()); + + notifier.signalChanged(); + + FOG_UPDATE = false; + } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/FrustumProvider.java b/src/main/java/com/jozufozu/flywheel/core/uniform/FrustumProvider.java index 0f8346cad..58d3d1474 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/FrustumProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/FrustumProvider.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.core.uniform; +import java.util.function.Consumer; + import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.uniform.UniformProvider; @@ -13,47 +15,71 @@ import net.minecraft.core.Vec3i; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.MinecraftForge; -public class FrustumProvider extends UniformProvider { +public class FrustumProvider implements UniformProvider { public static boolean PAUSED = false; public static boolean CAPTURE = false; - public FrustumProvider() { - MinecraftForge.EVENT_BUS.addListener(this::beginFrame); - } - @Override - public int getActualByteSize() { + public int byteSize() { return 96; } @Override - public FileResolution getUniformShader() { + public FileResolution uniformShader() { return Components.Files.FRUSTUM_UNIFORMS; } - public void beginFrame(BeginFrameEvent event) { - update(event.getContext()); + @Override + public ActiveUniformProvider activate(long ptr, Notifier notifier) { + return new Active(ptr, notifier); } - public void update(RenderContext context) { - if (ptr == MemoryUtil.NULL || (PAUSED && !CAPTURE)) { - return; + static class Active implements ActiveUniformProvider, Consumer { + + private final long ptr; + private final Notifier notifier; + + public Active(long ptr, Notifier notifier) { + this.ptr = ptr; + this.notifier = notifier; + MinecraftForge.EVENT_BUS.addListener(this); } - Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(context.level()); - Vec3 camera = context.camera() - .getPosition(); + @Override + public void delete() { + MinecraftForge.EVENT_BUS.unregister(this); + } - var camX = (float) (camera.x - originCoordinate.getX()); - var camY = (float) (camera.y - originCoordinate.getY()); - var camZ = (float) (camera.z - originCoordinate.getZ()); + @Override + public void poll() { - var shiftedCuller = RenderContext.createCuller(context.viewProjection(), -camX, -camY, -camZ); + } - shiftedCuller.getJozuPackedPlanes(ptr); + @Override + public void accept(BeginFrameEvent event) { + update(event.getContext()); + } - notifier.signalChanged(); - CAPTURE = false; + public void update(RenderContext context) { + if (ptr == MemoryUtil.NULL || (PAUSED && !CAPTURE)) { + return; + } + + Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(context.level()); + Vec3 camera = context.camera() + .getPosition(); + + var camX = (float) (camera.x - originCoordinate.getX()); + var camY = (float) (camera.y - originCoordinate.getY()); + var camZ = (float) (camera.z - originCoordinate.getZ()); + + var shiftedCuller = RenderContext.createCuller(context.viewProjection(), -camX, -camY, -camZ); + + shiftedCuller.getJozuPackedPlanes(ptr); + + notifier.signalChanged(); + CAPTURE = false; + } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java b/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java index e3ecee4ab..24d805012 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java @@ -45,7 +45,7 @@ public class UniformBuffer { int totalBytes = 0; int index = 0; for (UniformProvider provider : providers) { - int size = alignPo2(provider.getActualByteSize(), 16); + int size = align16(provider.byteSize()); builder.add(new Allocated(provider, totalBytes, size, index)); @@ -64,6 +64,7 @@ public class UniformBuffer { } public void sync() { + allocatedProviders.forEach(Allocated::pollActive); if (changedBytes.isEmpty()) { return; } @@ -88,8 +89,8 @@ public class UniformBuffer { } } - private static int alignPo2(int numToRound, int alignment) { - return (numToRound + alignment - 1) & -alignment; + private static int align16(int numToRound) { + return (numToRound + 16 - 1) & -16; } private class Allocated implements UniformProvider.Notifier { @@ -97,6 +98,7 @@ public class UniformBuffer { private final int offset; private final int size; private final int index; + private UniformProvider.ActiveUniformProvider activeProvider; private Allocated(UniformProvider provider, int offset, int size, int index) { this.provider = provider; @@ -111,7 +113,10 @@ public class UniformBuffer { } private void updatePtr(MemoryBlock bufferBase) { - provider.updatePtr(bufferBase.ptr() + offset, this); + if (activeProvider != null) { + activeProvider.delete(); + } + activeProvider = provider.activate(bufferBase.ptr() + offset, this); } public UniformProvider provider() { @@ -129,5 +134,11 @@ public class UniformBuffer { public int index() { return index; } + + public void pollActive() { + if (activeProvider != null) { + activeProvider.poll(); + } + } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java b/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java index 89175710e..9c82bf86f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.core.uniform; +import java.util.function.Consumer; + import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.uniform.UniformProvider; @@ -15,54 +17,75 @@ import net.minecraft.core.Vec3i; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.MinecraftForge; -public class ViewProvider extends UniformProvider { +public class ViewProvider implements UniformProvider { - public ViewProvider() { - MinecraftForge.EVENT_BUS.addListener(this::beginFrame); - } + public static final int SIZE = 4 * 16 + 16 + 4; - public void beginFrame(BeginFrameEvent event) { - update(event.getContext()); + @Override + public int byteSize() { + return SIZE; } @Override - public int getActualByteSize() { - return 4 * 16 + 16 + 4; - } - - public void update(RenderContext context) { - if (ptr == MemoryUtil.NULL) { - return; - } - - ClientLevel level = context.level(); - - int constantAmbientLight = level.effects() - .constantAmbientLight() ? 1 : 0; - - Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(level); - Vec3 camera = context.camera() - .getPosition(); - - var camX = (float) (camera.x - originCoordinate.getX()); - var camY = (float) (camera.y - originCoordinate.getY()); - var camZ = (float) (camera.z - originCoordinate.getZ()); - - // don't want to mutate viewProjection - var vp = context.viewProjection().copy(); - vp.multiplyWithTranslation(-camX, -camY, -camZ); - - MatrixWrite.writeUnsafe(vp, ptr); - MemoryUtil.memPutFloat(ptr + 64, camX); - MemoryUtil.memPutFloat(ptr + 68, camY); - MemoryUtil.memPutFloat(ptr + 72, camZ); - MemoryUtil.memPutInt(ptr + 76, constantAmbientLight); - - notifier.signalChanged(); - } - - @Override - public FileResolution getUniformShader() { + public FileResolution uniformShader() { return Components.Files.VIEW_UNIFORMS; } + + @Override + public ActiveUniformProvider activate(long ptr, Notifier notifier) { + return new Active(ptr, notifier); + } + + public static class Active implements ActiveUniformProvider, Consumer { + private final long ptr; + private final Notifier notifier; + + public Active(long ptr, Notifier notifier) { + this.ptr = ptr; + this.notifier = notifier; + MinecraftForge.EVENT_BUS.addListener(this); + } + + @Override + public void delete() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @Override + public void poll() { + } + + @Override + public void accept(BeginFrameEvent event) { + update(event.getContext()); + } + + public void update(RenderContext context) { + ClientLevel level = context.level(); + + int constantAmbientLight = level.effects() + .constantAmbientLight() ? 1 : 0; + + Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(level); + Vec3 camera = context.camera() + .getPosition(); + + var camX = (float) (camera.x - originCoordinate.getX()); + var camY = (float) (camera.y - originCoordinate.getY()); + var camZ = (float) (camera.z - originCoordinate.getZ()); + + // don't want to mutate viewProjection + var vp = context.viewProjection() + .copy(); + vp.multiplyWithTranslation(-camX, -camY, -camZ); + + MatrixWrite.writeUnsafe(vp, ptr); + MemoryUtil.memPutFloat(ptr + 64, camX); + MemoryUtil.memPutFloat(ptr + 68, camY); + MemoryUtil.memPutFloat(ptr + 72, camZ); + MemoryUtil.memPutInt(ptr + 76, constantAmbientLight); + + notifier.signalChanged(); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/FogUpdateMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/FogUpdateMixin.java index 832949e1a..061b297bf 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/FogUpdateMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/FogUpdateMixin.java @@ -5,14 +5,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.core.Components; +import com.jozufozu.flywheel.core.uniform.FogProvider; import net.minecraft.client.renderer.FogRenderer; @Mixin(FogRenderer.class) public class FogUpdateMixin { private static void flywheel$updateFog() { - Components.FOG_PROVIDER.update(); + FogProvider.FOG_UPDATE = true; } @Inject(method = "setupNoFog", at = @At("TAIL")) diff --git a/src/main/java/com/jozufozu/flywheel/util/Pair.java b/src/main/java/com/jozufozu/flywheel/util/Pair.java index 6b3a48d7d..bc7dd61bb 100644 --- a/src/main/java/com/jozufozu/flywheel/util/Pair.java +++ b/src/main/java/com/jozufozu/flywheel/util/Pair.java @@ -1,6 +1,7 @@ package com.jozufozu.flywheel.util; import java.util.Objects; +import java.util.function.Function; public record Pair(F first, S second) { @@ -8,6 +9,10 @@ public record Pair(F first, S second) { return new Pair<>(first, second); } + public static Function, Pair> both(Function map) { + return pair -> of(map.apply(pair.first), map.apply(pair.second)); + } + public Pair swap() { return Pair.of(second, first); } diff --git a/src/main/java/com/jozufozu/flywheel/util/ResourceUtil.java b/src/main/java/com/jozufozu/flywheel/util/ResourceUtil.java index 476ff33c8..c846f4203 100644 --- a/src/main/java/com/jozufozu/flywheel/util/ResourceUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/ResourceUtil.java @@ -1,9 +1,14 @@ package com.jozufozu.flywheel.util; +import java.util.regex.Pattern; + import net.minecraft.resources.ResourceLocation; public class ResourceUtil { + // Match the complement of alphanumeric and underscore. + private static final Pattern UNSAFE_CHARS = Pattern.compile("[^a-zA-Z0-9_]"); + public static ResourceLocation subPath(ResourceLocation root, String subPath) { return new ResourceLocation(root.getNamespace(), root.getPath() + subPath); } @@ -17,4 +22,9 @@ public class ResourceUtil { String path = loc.getPath(); return new ResourceLocation(loc.getNamespace(), path.substring(prefix.length(), path.length() - suffix.length())); } + + public static String toSafeString(ResourceLocation rl) { + return UNSAFE_CHARS.matcher(rl.toString()) + .replaceAll("_"); + } } diff --git a/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl b/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl index 11be92a1e..a8028e8b9 100644 --- a/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl +++ b/src/main/resources/assets/flywheel/flywheel/api/fragment.glsl @@ -13,6 +13,8 @@ in vec4 flw_var1; in vec4 flw_var2; in vec4 flw_var3; +flat in uint flw_materialFragmentID; + // /*const*/ vec4 flw_sampleColor; diff --git a/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl b/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl index c00b99cbd..f823366de 100644 --- a/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl +++ b/src/main/resources/assets/flywheel/flywheel/api/vertex.glsl @@ -1,4 +1,6 @@ #ifdef VERTEX_SHADER +uint flw_materialVertexID; + out vec4 flw_vertexPos; out vec4 flw_vertexColor; out vec2 flw_vertexTexCoord; @@ -12,4 +14,5 @@ out vec4 flw_var0; out vec4 flw_var1; out vec4 flw_var2; out vec4 flw_var3; +flat out uint flw_materialFragmentID; #endif diff --git a/src/main/resources/assets/flywheel/flywheel/compute/mat.glsl b/src/main/resources/assets/flywheel/flywheel/compute/mat.glsl new file mode 100644 index 000000000..4e0f5f8d1 --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/compute/mat.glsl @@ -0,0 +1,50 @@ +/* +This is what generated ubershaders should look like + +uint flw_materialVertexID = 0; +uint flw_materialFragmentID = 0; + +void flw_materialVertex() { + switch (flw_materialVertexID) { + case 0: flw_materialVertex_flywheel_cutout_vert(); break; + default: break; + } +} + +void flw_materialFragment() { + switch (flw_materialFragmentID) { + case 0: flw_materialFragment_flywheel_cutout_frag(); break; + default: break; + } +} + +bool flw_discardPredicate(vec4 finalColor) { + switch (flw_materialFragmentID) { + case 0: return flw_discardPredicate_flywheel_cutout_frag(finalColor); + default: return false; + } +} + +vec4 flw_fogFilter(vec4 color) { + switch (flw_materialFragmentID) { + case 0: return flw_fogFilter_flywheel_cutout_frag(color); + default: return color; + } +} + + +void flw_materialVertex_flywheel_cutout_vert() { +} + +void flw_materialFragment_flywheel_cutout_frag() { +} + +bool flw_discardPredicate_flywheel_cutout_frag(vec4 finalColor) { + return finalColor.a < 0.1; +} + +vec4 flw_fogFilter_flywheel_cutout_frag(vec4 color) { + return linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor); +} + +*/ diff --git a/src/main/resources/assets/flywheel/flywheel/uniform/fog.glsl b/src/main/resources/assets/flywheel/flywheel/uniform/fog.glsl index 2acbef9e1..8fc8ede95 100644 --- a/src/main/resources/assets/flywheel/flywheel/uniform/fog.glsl +++ b/src/main/resources/assets/flywheel/flywheel/uniform/fog.glsl @@ -1,5 +1,4 @@ -layout(std140, binding = 1) uniform flw_fog { - vec4 flw_fogColor; - vec2 flw_fogRange; - int flw_fogShape; -}; +// TODO: Transform uniform shaders +vec4 flw_fogColor; +vec2 flw_fogRange; +int flw_fogShape; diff --git a/src/main/resources/assets/flywheel/flywheel/uniform/frustum.glsl b/src/main/resources/assets/flywheel/flywheel/uniform/frustum.glsl index 39866a922..b619082cd 100644 --- a/src/main/resources/assets/flywheel/flywheel/uniform/frustum.glsl +++ b/src/main/resources/assets/flywheel/flywheel/uniform/frustum.glsl @@ -9,6 +9,4 @@ struct FLWPackedPlanes { vec2 zW; // }; -layout(std140, binding = 2) uniform FLWFrustum { - FLWPackedPlanes flw_planes; -}; +FLWPackedPlanes flw_planes; diff --git a/src/main/resources/assets/flywheel/flywheel/uniform/view.glsl b/src/main/resources/assets/flywheel/flywheel/uniform/view.glsl index 52170bccd..467d3fee9 100644 --- a/src/main/resources/assets/flywheel/flywheel/uniform/view.glsl +++ b/src/main/resources/assets/flywheel/flywheel/uniform/view.glsl @@ -1,5 +1,3 @@ -layout(std140, binding = 0) uniform flw_view { - mat4 flw_viewProjection; - vec4 flw_cameraPos; - int flw_constantAmbientLight; -}; +mat4 flw_viewProjection; +vec4 flw_cameraPos; +int flw_constantAmbientLight;