Resolved to ashes

- FileResolution was implemented to support a two-pass
  preprocessor/compiler.
- The new architecture no longer needs its functionality.
- It doesn't make sense to have implementors individually apply the
  "checks" to ensure their components are sound.
- The component checking code
- Remove FileResolution, replace all references with ResourceLocation
- Small refactor to UniformBuffer to put everything into one UBO
- Remove BlockEntityRenderDispatcherAccessor
- Rename component resource location getters for consistency
- Small cleanups here and there
- Consolidate SourceChecks to SourceChecks.java for future use
This commit is contained in:
Jozufozu 2023-03-26 00:39:35 -07:00
parent 80001f0037
commit 39423090b4
36 changed files with 318 additions and 552 deletions

View file

@ -1,12 +1,13 @@
package com.jozufozu.flywheel.api.context;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.resources.ResourceLocation;
public interface Context {
void onProgramLink(GlProgram program);
FileResolution vertexShader();
ResourceLocation vertexShader();
FileResolution fragmentShader();
ResourceLocation fragmentShader();
}

View file

@ -2,17 +2,17 @@ package com.jozufozu.flywheel.api.material;
import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
public interface Material {
RenderStage getRenderStage();
FileResolution getVertexShader();
ResourceLocation vertexShader();
FileResolution getFragmentShader();
ResourceLocation fragmentShader();
void setup();

View file

@ -4,16 +4,17 @@ 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.core.SourceComponent;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.ShaderSources;
import net.minecraft.resources.ResourceLocation;
public interface Pipeline {
GLSLVersion glslVersion();
FileResolution vertex();
ResourceLocation vertexShader();
FileResolution fragment();
ResourceLocation fragmentShader();
/**
* Generate the source component necessary to convert a packed {@link StructType} into its shader representation.

View file

@ -3,9 +3,9 @@ package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.ResourceLocation;
/**
* A StructType contains metadata for a specific instance struct that Flywheel can interface with.
@ -25,7 +25,7 @@ public interface StructType<S extends InstancedPart> {
StructWriter<S> getWriter();
FileResolution getInstanceShader();
ResourceLocation instanceShader();
VertexTransformer<S> getVertexTransformer();

View file

@ -0,0 +1,29 @@
package com.jozufozu.flywheel.api.uniform;
import net.minecraft.resources.ResourceLocation;
public interface ShaderUniforms {
Provider activate(long ptr);
ResourceLocation uniformShader();
int byteSize();
interface Provider {
/**
* Delete this provider.<p>
* <p>
* Do not free the ptr passed to {@link #activate(long)}.<br>
* Clean up other resources, and unsubscribe from events.
*/
void delete();
/**
* Poll the provider for changes.
*
* @return {@code true} if the provider updated its backing store.
*/
boolean poll();
}
}

View file

@ -1,23 +0,0 @@
package com.jozufozu.flywheel.api.uniform;
import com.jozufozu.flywheel.core.source.FileResolution;
public interface UniformProvider {
int byteSize();
FileResolution uniformShader();
ActiveUniformProvider activate(long ptr);
interface ActiveUniformProvider {
void delete();
/**
* Poll the provider for changes.
*
* @return {@code true} if the provider updated its backing store.
*/
boolean poll();
}
}

View file

@ -1,7 +1,8 @@
package com.jozufozu.flywheel.api.vertex;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.resources.ResourceLocation;
/**
* A vertex type containing metadata about a specific vertex layout.
@ -13,7 +14,7 @@ public interface VertexType extends VertexListProvider {
*/
BufferLayout getLayout();
FileResolution getLayoutShader();
ResourceLocation layoutShader();
default int getStride() {
return getLayout().getStride();

View file

@ -1,6 +1,8 @@
package com.jozufozu.flywheel.backend.instancing.compile;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import java.util.ArrayList;
import java.util.HashMap;
@ -10,10 +12,9 @@ import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.uniform.UniformProvider;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
@ -23,6 +24,7 @@ import com.jozufozu.flywheel.backend.instancing.indirect.IndirectComponent;
import com.jozufozu.flywheel.core.ComponentRegistry;
import com.jozufozu.flywheel.core.Pipelines;
import com.jozufozu.flywheel.core.SourceComponent;
import com.jozufozu.flywheel.core.context.SimpleContext;
import com.jozufozu.flywheel.core.pipeline.SimplePipeline;
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
import com.jozufozu.flywheel.core.source.ShaderSources;
@ -76,8 +78,8 @@ public class FlwCompiler {
.build(sources);
this.uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms"))
.sources(ComponentRegistry.getAllUniformProviders()
.stream()
.map(UniformProvider::uniformShader)
.stream()
.map(ShaderUniforms::uniformShader)
.toList())
.build(sources);
@ -124,7 +126,7 @@ public class FlwCompiler {
shaderCompiler.delete();
}
public GlProgram getPipelineProgram(VertexType vertexType, StructType<?> structType, ContextShader contextShader, SimplePipeline pipelineShader) {
public GlProgram getPipelineProgram(VertexType vertexType, StructType<?> structType, SimpleContext contextShader, SimplePipeline pipelineShader) {
return pipelinePrograms.get(new PipelineContext(vertexType, structType, contextShader, pipelineShader));
}
@ -175,36 +177,29 @@ public class FlwCompiler {
.assemble(new Pipeline.InstanceAssemblerContext(sources, ctx.vertexType(), ctx.structType()));
var layout = sources.find(ctx.vertexType()
.getLayoutShader()
.resourceLocation());
.layoutShader());
var instance = sources.find(ctx.structType()
.getInstanceShader()
.resourceLocation());
.instanceShader());
var context = sources.find(ctx.contextShader()
.vertexShader()
.resourceLocation());
.vertexShader());
var pipeline = sources.find(ctx.pipelineShader()
.vertex()
.resourceLocation());
.vertexShader());
return ImmutableList.of(uniformComponent, vertexMaterialComponent, instanceAssembly, layout, instance, context, pipeline);
}
private ImmutableList<SourceComponent> getFragmentComponents(PipelineContext ctx) {
var context = sources.find(ctx.contextShader()
.fragmentShader()
.resourceLocation());
.fragmentShader());
var pipeline = sources.find(ctx.pipelineShader()
.fragment()
.resourceLocation());
.fragmentShader());
return ImmutableList.of(uniformComponent, fragmentMaterialComponent, context, pipeline);
}
private ImmutableList<SourceComponent> getComputeComponents(StructType<?> structType) {
var instanceAssembly = new IndirectComponent(sources, structType);
var instance = sources.find(structType.getInstanceShader()
.resourceLocation());
var pipeline = sources.find(Pipelines.Files.INDIRECT_CULL.resourceLocation());
var instance = sources.find(structType.instanceShader());
var pipeline = sources.find(Pipelines.Files.INDIRECT_CULL);
return ImmutableList.of(uniformComponent, instanceAssembly, instance, pipeline);
}

View file

@ -12,9 +12,12 @@ import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.core.SourceComponent;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.ShaderSources;
import com.jozufozu.flywheel.core.source.generate.*;
import com.jozufozu.flywheel.core.source.generate.FnSignature;
import com.jozufozu.flywheel.core.source.generate.GlslBlock;
import com.jozufozu.flywheel.core.source.generate.GlslBuilder;
import com.jozufozu.flywheel.core.source.generate.GlslExpr;
import com.jozufozu.flywheel.core.source.generate.GlslSwitch;
import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
@ -100,27 +103,12 @@ public class MaterialAdapterComponent implements SourceComponent {
body.add(sw);
}
@NotNull
private static HashMap<String, String> createAdapterMap(List<AdaptedFn> adaptedFunctions, ResourceLocation loc) {
HashMap<String, String> out = new HashMap<>();
var suffix = '_' + ResourceUtil.toSafeString(loc);
for (var adapted : adaptedFunctions) {
var fnName = adapted.signature()
.name();
out.put(fnName, fnName + suffix);
}
return out;
}
private record AdaptedFn(FnSignature signature, @Nullable GlslExpr defaultReturn) {
}
public static class Builder {
private final ResourceLocation name;
private final List<FileResolution> sourceMaterials = new ArrayList<>();
private final List<ResourceLocation> materialSources = new ArrayList<>();
private final List<AdaptedFn> adaptedFunctions = new ArrayList<>();
private GlslExpr switchArg;
@ -128,8 +116,8 @@ public class MaterialAdapterComponent implements SourceComponent {
this.name = name;
}
public Builder materialSources(List<FileResolution> sources) {
this.sourceMaterials.addAll(sources);
public Builder materialSources(List<ResourceLocation> sources) {
this.materialSources.addAll(sources);
return this;
}
@ -155,14 +143,31 @@ public class MaterialAdapterComponent implements SourceComponent {
var transformed = ImmutableList.<StringSubstitutionSourceComponent>builder();
for (FileResolution fileResolution : sourceMaterials) {
var loc = fileResolution.resourceLocation();
var sourceFile = sources.find(loc);
transformed.add(new StringSubstitutionSourceComponent(sourceFile, createAdapterMap(adaptedFunctions, loc)));
for (var rl : materialSources) {
var sourceFile = sources.find(rl);
var adapterMap = createAdapterMap(adaptedFunctions, getSuffix(rl));
transformed.add(new StringSubstitutionSourceComponent(sourceFile, adapterMap));
}
return new MaterialAdapterComponent(name, switchArg, adaptedFunctions, transformed.build());
}
}
@NotNull
private static HashMap<String, String> createAdapterMap(List<AdaptedFn> adaptedFunctions, String suffix) {
HashMap<String, String> out = new HashMap<>();
for (var adapted : adaptedFunctions) {
var fnName = adapted.signature()
.name();
out.put(fnName, fnName + suffix);
}
return out;
}
@NotNull
private static String getSuffix(ResourceLocation rl) {
return '_' + ResourceUtil.toSafeString(rl);
}
}

View file

@ -1,9 +1,9 @@
package com.jozufozu.flywheel.backend.instancing.compile;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.pipeline.SimplePipeline;
/**
* Represents the entire context of a program's usage.
@ -12,6 +12,6 @@ import com.jozufozu.flywheel.core.pipeline.SimplePipeline;
* @param structType The instance shader to use.
* @param contextShader The context shader to use.
*/
public record PipelineContext(VertexType vertexType, StructType<?> structType, ContextShader contextShader,
SimplePipeline pipelineShader) {
public record PipelineContext(VertexType vertexType, StructType<?> structType, Context contextShader,
Pipeline pipelineShader) {
}

View file

@ -4,12 +4,12 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.BackendTypes;
import com.jozufozu.flywheel.core.ComponentRegistry;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.context.SimpleContext;
import com.jozufozu.flywheel.core.pipeline.SimplePipeline;
public class PipelineContextSet {
@ -39,7 +39,7 @@ public class PipelineContextSet {
return contexts.size();
}
private void add(VertexType vertexType, StructType<?> structType, ContextShader world, SimplePipeline pipelineShader) {
private void add(VertexType vertexType, StructType<?> structType, SimpleContext world, SimplePipeline pipelineShader) {
var ctx = new PipelineContext(vertexType, structType, world, pipelineShader);

View file

@ -6,7 +6,6 @@ import java.util.List;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.core.SourceComponent;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.ShaderSources;
import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.generate.GlslBuilder;
@ -53,22 +52,22 @@ public class UniformComponent implements SourceComponent {
public static class Builder {
private final ResourceLocation name;
private final List<FileResolution> uniformShaders = new ArrayList<>();
private final List<ResourceLocation> uniformShaders = new ArrayList<>();
public Builder(ResourceLocation name) {
this.name = name;
}
public Builder sources(List<FileResolution> sources) {
this.uniformShaders.addAll(sources);
return this;
}
public Builder sources(List<ResourceLocation> sources) {
this.uniformShaders.addAll(sources);
return this;
}
public UniformComponent build(ShaderSources sources) {
var out = ImmutableList.<SourceFile>builder();
for (var fileResolution : uniformShaders) {
out.add(sources.find(fileResolution.resourceLocation()));
out.add(sources.find(fileResolution));
}
return new UniformComponent(name, out.build());

View file

@ -35,7 +35,7 @@ public class IndirectComponent implements SourceComponent {
public IndirectComponent(ShaderSources sources, StructType<?> structType) {
this.layoutItems = structType.getLayout().layoutItems;
included = ImmutableList.of(sources.find(Pipelines.Files.UTIL_TYPES.resourceLocation()));
included = ImmutableList.of(sources.find(Pipelines.Files.UTIL_TYPES));
}
@Override

View file

@ -9,7 +9,6 @@ import org.jetbrains.annotations.NotNull;
import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
@ -18,6 +17,7 @@ import com.jozufozu.flywheel.backend.instancing.Engine;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.context.SimpleContext;
import com.jozufozu.flywheel.util.WeakHashSet;
import com.mojang.blaze3d.systems.RenderSystem;
@ -38,12 +38,12 @@ public class IndirectEngine implements Engine {
*/
private final WeakHashSet<InstanceManager<?>> instanceManagers = new WeakHashSet<>();
protected final ContextShader context;
protected final SimpleContext context;
protected final int sqrMaxOriginDistance;
protected BlockPos originCoordinate = BlockPos.ZERO;
public IndirectEngine(ContextShader context, int sqrMaxOriginDistance) {
public IndirectEngine(SimpleContext context, int sqrMaxOriginDistance) {
this.context = context;
this.sqrMaxOriginDistance = sqrMaxOriginDistance;
}

View file

@ -9,7 +9,6 @@ import org.jetbrains.annotations.NotNull;
import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
@ -20,6 +19,7 @@ import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.backend.instancing.compile.FlwCompiler;
import com.jozufozu.flywheel.core.Pipelines;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.context.SimpleContext;
import com.jozufozu.flywheel.util.WeakHashSet;
import com.mojang.blaze3d.systems.RenderSystem;
@ -40,12 +40,12 @@ public class InstancingEngine implements Engine {
*/
private final WeakHashSet<InstanceManager<?>> instanceManagers = new WeakHashSet<>();
protected final ContextShader context;
protected final SimpleContext context;
protected final int sqrMaxOriginDistance;
protected BlockPos originCoordinate = BlockPos.ZERO;
public InstancingEngine(ContextShader context, int sqrMaxOriginDistance) {
public InstancingEngine(SimpleContext context, int sqrMaxOriginDistance) {
this.context = context;
this.sqrMaxOriginDistance = sqrMaxOriginDistance;
}

View file

@ -8,7 +8,7 @@ import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.BackendType;
import com.jozufozu.flywheel.backend.SimpleBackendType;
import com.jozufozu.flywheel.core.BackendTypes;
import com.jozufozu.flywheel.core.uniform.FlwUniformProvider;
import com.jozufozu.flywheel.core.uniform.FlwShaderUniforms;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
@ -111,17 +111,17 @@ public class FlwCommands {
commandBuilder.command.then(Commands.literal("debugFrustum")
.then(Commands.literal("pause")
.executes(context -> {
FlwUniformProvider.FRUSTUM_PAUSED = true;
FlwShaderUniforms.FRUSTUM_PAUSED = true;
return 1;
}))
.then(Commands.literal("unpause")
.executes(context -> {
FlwUniformProvider.FRUSTUM_PAUSED = false;
FlwShaderUniforms.FRUSTUM_PAUSED = false;
return 1;
}))
.then(Commands.literal("capture")
.executes(context -> {
FlwUniformProvider.FRUSTUM_CAPTURE = true;
FlwShaderUniforms.FRUSTUM_CAPTURE = true;
return 1;
})));

View file

@ -1,25 +1,31 @@
package com.jozufozu.flywheel.core;
import java.util.*;
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.context.Context;
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.uniform.ShaderUniforms;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.resources.ResourceLocation;
public class ComponentRegistry {
private static final Registry<UniformProvider> uniformProviders = new Registry<>();
private static final Registry<ShaderUniforms> uniformProviders = new Registry<>();
public static final MaterialRegistry materials = new MaterialRegistry();
public static final Set<StructType<?>> structTypes = new HashSet<>();
public static final Set<VertexType> vertexTypes = new HashSet<>();
public static final Set<ContextShader> contextShaders = new HashSet<>();
public static final Set<Context> contextShaders = new HashSet<>();
// TODO: fill out the rest of the registry
@ -37,22 +43,21 @@ public class ComponentRegistry {
return vertexType;
}
public static ContextShader register(ContextShader contextShader) {
public static <T extends Context> T register(T contextShader) {
contextShaders.add(contextShader);
return contextShader;
}
public static <T extends UniformProvider> T register(T provider) {
return uniformProviders.register(provider.uniformShader()
.resourceLocation(), provider);
public static <T extends ShaderUniforms> T register(T provider) {
return uniformProviders.register(provider.uniformShader(), provider);
}
public static Collection<UniformProvider> getAllUniformProviders() {
public static Collection<ShaderUniforms> getAllUniformProviders() {
return Collections.unmodifiableCollection(uniformProviders.objects);
}
@Nullable
public static UniformProvider getUniformProvider(ResourceLocation loc) {
public static ShaderUniforms getUniformProvider(ResourceLocation loc) {
return uniformProviders.get(loc);
}
@ -84,8 +89,8 @@ public class ComponentRegistry {
public <T extends Material> T add(T material) {
materials.add(material);
vertexSources.register(material.getVertexShader());
fragmentSources.register(material.getFragmentShader());
vertexSources.register(material.vertexShader());
fragmentSources.register(material.fragmentShader());
return material;
}
@ -93,31 +98,31 @@ public class ComponentRegistry {
/**
* @return a list of vertex shader sources where the index in the list is the shader's ID.
*/
public List<FileResolution> vertexSources() {
public List<ResourceLocation> vertexSources() {
return vertexSources.sourceView;
}
/**
* @return a list of fragment shader sources where the index in the list is the shader's ID.
*/
public List<FileResolution> fragmentSources() {
public List<ResourceLocation> fragmentSources() {
return fragmentSources.sourceView;
}
public int getVertexID(Material material) {
return vertexSources.orderedSources.indexOf(material.getVertexShader());
return vertexSources.orderedSources.indexOf(material.vertexShader());
}
public int getFragmentID(Material material) {
return fragmentSources.orderedSources.indexOf(material.getFragmentShader());
return fragmentSources.orderedSources.indexOf(material.fragmentShader());
}
private static class MaterialSources {
private final Set<FileResolution> registered = new HashSet<>();
private final List<FileResolution> orderedSources = new ArrayList<>();
private final List<FileResolution> sourceView = Collections.unmodifiableList(orderedSources);
private final Set<ResourceLocation> registered = new HashSet<>();
private final List<ResourceLocation> orderedSources = new ArrayList<>();
private final List<ResourceLocation> sourceView = Collections.unmodifiableList(orderedSources);
public void register(FileResolution vertexShader) {
public void register(ResourceLocation vertexShader) {
if (registered.add(vertexShader)) {
orderedSources.add(vertexShader);
}

View file

@ -1,15 +1,9 @@
package com.jozufozu.flywheel.core;
import java.util.function.BiConsumer;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.SourceChecks;
import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
import com.jozufozu.flywheel.core.context.SimpleContext;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.uniform.FlwUniformProvider;
import com.jozufozu.flywheel.core.uniform.FlwShaderUniforms;
import com.jozufozu.flywheel.core.vertex.Formats;
import com.jozufozu.flywheel.util.ResourceUtil;
@ -18,12 +12,11 @@ import net.minecraft.resources.ResourceLocation;
public class Components {
public static final FlwUniformProvider UNIFORM_PROVIDER = ComponentRegistry.register(new FlwUniformProvider());
public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
public static final FlwShaderUniforms UNIFORM_PROVIDER = ComponentRegistry.register(new FlwShaderUniforms());
public static final SimpleContext WORLD = ComponentRegistry.register(new SimpleContext(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
public static final SimpleContext CRUMBLING = ComponentRegistry.register(new SimpleContext(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
public static void init() {
Files.init();
Formats.init();
StructTypes.init();
Materials.init();
@ -32,73 +25,19 @@ public class Components {
public static class Files {
public static final FileResolution UNIFORMS = uniform(Flywheel.rl("uniform/flywheel.glsl"));
public static final FileResolution BLOCK_LAYOUT = layoutVertex(ResourceUtil.subPath(Names.BLOCK, ".vert"));
public static final FileResolution POS_TEX_NORMAL_LAYOUT = layoutVertex(ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert"));
public static final FileResolution TRANSFORMED = instanceVertex(ResourceUtil.subPath(Names.TRANSFORMED, ".vert"));
public static final FileResolution ORIENTED = instanceVertex(ResourceUtil.subPath(Names.ORIENTED, ".vert"));
public static final FileResolution DEFAULT_VERTEX = materialVertex(ResourceUtil.subPath(Names.DEFAULT, ".vert"));
public static final FileResolution SHADED_VERTEX = materialVertex(ResourceUtil.subPath(Names.SHADED, ".vert"));
public static final FileResolution DEFAULT_FRAGMENT = materialFragment(ResourceUtil.subPath(Names.DEFAULT, ".frag"));
public static final FileResolution CUTOUT_FRAGMENT = materialFragment(ResourceUtil.subPath(Names.CUTOUT, ".frag"));
public static final FileResolution WORLD_VERTEX = contextVertex(ResourceUtil.subPath(Names.WORLD, ".vert"));
public static final FileResolution WORLD_FRAGMENT = contextFragment(ResourceUtil.subPath(Names.WORLD, ".frag"));
public static final FileResolution CRUMBLING_VERTEX = contextVertex(ResourceUtil.subPath(Names.CRUMBLING, ".vert"));
public static final FileResolution CRUMBLING_FRAGMENT = contextFragment(ResourceUtil.subPath(Names.CRUMBLING, ".frag"));
private static FileResolution compute(ResourceLocation rl) {
return FileResolution.get(rl);
}
private static FileResolution uniform(ResourceLocation location) {
return FileResolution.get(location);
}
private static FileResolution layoutVertex(ResourceLocation location) {
return FileResolution.get(location)
.validateWith(Checks.LAYOUT_VERTEX);
}
private static FileResolution instanceVertex(ResourceLocation location) {
return FileResolution.get(location); // .validateWith(Checks.INSTANCE_VERTEX);
}
private static FileResolution materialVertex(ResourceLocation location) {
return FileResolution.get(location)
.validateWith(Checks.MATERIAL_VERTEX);
}
private static FileResolution materialFragment(ResourceLocation location) {
return FileResolution.get(location)
.validateWith(Checks.MATERIAL_FRAGMENT);
}
private static FileResolution contextVertex(ResourceLocation location) {
return FileResolution.get(location)
.validateWith(Checks.CONTEXT_VERTEX);
}
private static FileResolution contextFragment(ResourceLocation location) {
return FileResolution.get(location)
.validateWith(Checks.CONTEXT_FRAGMENT);
}
public static void init() {
// noop, just in case
}
}
public static class Checks {
public static final BiConsumer<ErrorReporter, SourceFile> LAYOUT_VERTEX = SourceChecks.checkFunctionArity("flw_layoutVertex", 0);
public static final BiConsumer<ErrorReporter, SourceFile> INSTANCE_VERTEX = SourceChecks.checkFunctionParameterTypeExists("flw_instanceVertex", 1, 0);
public static final BiConsumer<ErrorReporter, SourceFile> MATERIAL_VERTEX = SourceChecks.checkFunctionArity("flw_materialVertex", 0);
public static final BiConsumer<ErrorReporter, SourceFile> MATERIAL_FRAGMENT = SourceChecks.checkFunctionArity("flw_materialFragment", 0);
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_VERTEX = SourceChecks.checkFunctionArity("flw_contextVertex", 0);
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_FRAGMENT = SourceChecks.checkFunctionArity("flw_contextFragment", 0)
.andThen(SourceChecks.checkFunctionArity("flw_initFragment", 0));
public static final BiConsumer<ErrorReporter, SourceFile> PIPELINE = SourceChecks.checkFunctionArity("main", 0);
public static final ResourceLocation UNIFORMS = Flywheel.rl("uniform/flywheel.glsl");
public static final ResourceLocation BLOCK_LAYOUT = ResourceUtil.subPath(Names.BLOCK, ".vert");
public static final ResourceLocation POS_TEX_NORMAL_LAYOUT = ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert");
public static final ResourceLocation TRANSFORMED = ResourceUtil.subPath(Names.TRANSFORMED, ".vert");
public static final ResourceLocation ORIENTED = ResourceUtil.subPath(Names.ORIENTED, ".vert");
public static final ResourceLocation DEFAULT_VERTEX = ResourceUtil.subPath(Names.DEFAULT, ".vert");
public static final ResourceLocation SHADED_VERTEX = ResourceUtil.subPath(Names.SHADED, ".vert");
public static final ResourceLocation DEFAULT_FRAGMENT = ResourceUtil.subPath(Names.DEFAULT, ".frag");
public static final ResourceLocation CUTOUT_FRAGMENT = ResourceUtil.subPath(Names.CUTOUT, ".frag");
public static final ResourceLocation WORLD_VERTEX = ResourceUtil.subPath(Names.WORLD, ".vert");
public static final ResourceLocation WORLD_FRAGMENT = ResourceUtil.subPath(Names.WORLD, ".frag");
public static final ResourceLocation CRUMBLING_VERTEX = ResourceUtil.subPath(Names.CRUMBLING, ".vert");
public static final ResourceLocation CRUMBLING_FRAGMENT = ResourceUtil.subPath(Names.CRUMBLING, ".frag");
}
public static class Names {

View file

@ -5,7 +5,8 @@ import com.jozufozu.flywheel.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.backend.instancing.indirect.IndirectComponent;
import com.jozufozu.flywheel.backend.instancing.instancing.InstancedArraysComponent;
import com.jozufozu.flywheel.core.pipeline.SimplePipeline;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.resources.ResourceLocation;
public class Pipelines {
public static final SimplePipeline INSTANCED_ARRAYS = SimplePipeline.builder()
@ -26,15 +27,10 @@ public class Pipelines {
}
public static class Files {
public static final FileResolution DRAW_FRAGMENT = pipeline("pipeline/draw.frag");
public static final FileResolution INSTANCED_ARRAYS_DRAW = pipeline("pipeline/instanced_arrays_draw.vert");
public static final FileResolution INDIRECT_DRAW = pipeline("pipeline/indirect_draw.vert");
public static final FileResolution INDIRECT_CULL = pipeline("pipeline/indirect_cull.glsl");
public static final FileResolution UTIL_TYPES = FileResolution.get(Flywheel.rl("util/types.glsl"));
private static FileResolution pipeline(String name) {
return FileResolution.get(Flywheel.rl(name))
.validateWith(Components.Checks.PIPELINE);
}
public static final ResourceLocation DRAW_FRAGMENT = Flywheel.rl("pipeline/draw.frag");
public static final ResourceLocation INSTANCED_ARRAYS_DRAW = Flywheel.rl("pipeline/instanced_arrays_draw.vert");
public static final ResourceLocation INDIRECT_DRAW = Flywheel.rl("pipeline/indirect_draw.vert");
public static final ResourceLocation INDIRECT_CULL = Flywheel.rl("pipeline/indirect_cull.glsl");
public static final ResourceLocation UTIL_TYPES = Flywheel.rl("util/types.glsl");
}
}

View file

@ -1,9 +1,11 @@
package com.jozufozu.flywheel.api.context;
package com.jozufozu.flywheel.core.context;
import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.core.source.FileResolution;
public record ContextShader(FileResolution vertexShader, FileResolution fragmentShader) implements Context {
import net.minecraft.resources.ResourceLocation;
public record SimpleContext(ResourceLocation vertexShader, ResourceLocation fragmentShader) implements Context {
@Override
public void onProgramLink(GlProgram program) {
program.bind();
@ -14,12 +16,12 @@ public record ContextShader(FileResolution vertexShader, FileResolution fragment
}
@Override
public FileResolution vertexShader() {
public ResourceLocation vertexShader() {
return vertexShader;
}
@Override
public FileResolution fragmentShader() {
public ResourceLocation fragmentShader() {
return fragmentShader;
}
}

View file

@ -4,21 +4,21 @@ import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.core.ComponentRegistry;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
public class SimpleMaterial implements Material {
protected final RenderStage stage;
protected final FileResolution vertexShader;
protected final FileResolution fragmentShader;
protected final ResourceLocation vertexShader;
protected final ResourceLocation fragmentShader;
protected final Runnable setup;
protected final Runnable clear;
protected final RenderType batchingRenderType;
protected final VertexTransformer vertexTransformer;
public SimpleMaterial(RenderStage stage, FileResolution vertexShader, FileResolution fragmentShader, Runnable setup, Runnable clear, RenderType batchingRenderType, VertexTransformer vertexTransformer) {
public SimpleMaterial(RenderStage stage, ResourceLocation vertexShader, ResourceLocation fragmentShader, Runnable setup, Runnable clear, RenderType batchingRenderType, VertexTransformer vertexTransformer) {
this.stage = stage;
this.vertexShader = vertexShader;
this.fragmentShader = fragmentShader;
@ -38,12 +38,12 @@ public class SimpleMaterial implements Material {
}
@Override
public FileResolution getVertexShader() {
public ResourceLocation vertexShader() {
return vertexShader;
}
@Override
public FileResolution getFragmentShader() {
public ResourceLocation fragmentShader() {
return fragmentShader;
}
@ -69,12 +69,15 @@ public class SimpleMaterial implements Material {
public static class Builder {
protected RenderStage stage = RenderStage.AFTER_SOLID_TERRAIN;
protected FileResolution vertexShader = Components.Files.DEFAULT_VERTEX;
protected FileResolution fragmentShader = Components.Files.DEFAULT_FRAGMENT;
protected Runnable setup = () -> {};
protected Runnable clear = () -> {};
protected ResourceLocation vertexShader = Components.Files.DEFAULT_VERTEX;
protected ResourceLocation fragmentShader = Components.Files.DEFAULT_FRAGMENT;
protected Runnable setup = () -> {
};
protected Runnable clear = () -> {
};
protected RenderType batchingRenderType = RenderType.solid();
protected VertexTransformer vertexTransformer = (vertexList, level) -> {};
protected VertexTransformer vertexTransformer = (vertexList, level) -> {
};
public Builder() {
}
@ -84,12 +87,12 @@ public class SimpleMaterial implements Material {
return this;
}
public Builder vertexShader(FileResolution vertexShader) {
public Builder vertexShader(ResourceLocation vertexShader) {
this.vertexShader = vertexShader;
return this;
}
public Builder fragmentShader(FileResolution fragmentShader) {
public Builder fragmentShader(ResourceLocation fragmentShader) {
this.fragmentShader = fragmentShader;
return this;
}

View file

@ -4,15 +4,16 @@ import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.core.SourceComponent;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.resources.ResourceLocation;
public final class SimplePipeline implements Pipeline {
private final GLSLVersion glslVersion;
private final FileResolution vertex;
private final FileResolution fragment;
private final ResourceLocation vertex;
private final ResourceLocation fragment;
private final InstanceAssemblerFactory factory;
public SimplePipeline(GLSLVersion glslVersion, FileResolution vertex, FileResolution fragment, InstanceAssemblerFactory factory) {
public SimplePipeline(GLSLVersion glslVersion, ResourceLocation vertex, ResourceLocation fragment, InstanceAssemblerFactory factory) {
this.glslVersion = glslVersion;
this.vertex = vertex;
this.fragment = fragment;
@ -35,12 +36,12 @@ public final class SimplePipeline implements Pipeline {
}
@Override
public FileResolution vertex() {
public ResourceLocation vertexShader() {
return vertex;
}
@Override
public FileResolution fragment() {
public ResourceLocation fragmentShader() {
return fragment;
}
@ -55,8 +56,8 @@ public final class SimplePipeline implements Pipeline {
public static class Builder {
private GLSLVersion glslVersion;
private FileResolution vertex;
private FileResolution fragment;
private ResourceLocation vertex;
private ResourceLocation fragment;
private InstanceAssemblerFactory factory;
public Builder glslVersion(GLSLVersion glslVersion) {
@ -64,12 +65,12 @@ public final class SimplePipeline implements Pipeline {
return this;
}
public Builder vertex(FileResolution vertex) {
public Builder vertex(ResourceLocation vertex) {
this.vertex = vertex;
return this;
}
public Builder fragment(FileResolution fragment) {
public Builder fragment(ResourceLocation fragment) {
this.fragment = fragment;
return this;
}

View file

@ -1,149 +0,0 @@
package com.jozufozu.flywheel.core.source;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import com.jozufozu.flywheel.core.source.error.ErrorBuilder;
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
import com.jozufozu.flywheel.core.source.span.Span;
import net.minecraft.resources.ResourceLocation;
/**
* A reference to a source file that might not be loaded when the owning object is created.
*
* <p>
* FileResolutions are used primarily while parsing import statements. {@link FileResolution#file} is initially
* null, but will be populated later on, after <em>all</em> SourceFiles are loaded (assuming
* {@link FileResolution#fileLoc} references an actual file).
* </p>
*/
public class FileResolution {
private static final Map<ResourceLocation, FileResolution> ALL = new HashMap<>();
private static final Map<ResourceLocation, FileResolution> WEAK = new HashMap<>();
private static boolean tooLate = false;
/**
* Extra info about where this resolution is required. Includes shader Spans.
*/
private final List<Span> neededAt = new ArrayList<>();
private final List<BiConsumer<ErrorReporter, SourceFile>> checks = new ArrayList<>();
private final ResourceLocation fileLoc;
private final boolean weak;
private FileResolution(ResourceLocation fileLoc, boolean weak) {
this.fileLoc = fileLoc;
this.weak = weak;
}
public static FileResolution get(ResourceLocation file) {
if (!tooLate) {
return ALL.computeIfAbsent(file, loc -> new FileResolution(loc, false));
} else {
// Lock the map after resolution has run.
FileResolution fileResolution = ALL.get(file);
// ...so crash immediately if the file isn't found.
if (fileResolution == null) {
throw new ShaderLoadingException("could not find source for file: " + file);
}
return fileResolution;
}
}
/**
* Weak resolutions don't persist through resource reloads.<p>
* This should be used inside parsing code.
*
* @param file The location of the file to resolve.
* @return A weak resolution for the given file.
*/
public static FileResolution weak(ResourceLocation file) {
FileResolution fileResolution = ALL.get(file);
if (fileResolution != null) {
return fileResolution;
}
// never too late for weak resolutions.
return WEAK.computeIfAbsent(file, loc -> new FileResolution(loc, true));
}
public static void checkAll(ErrorReporter errorReporter) {
for (FileResolution resolution : ALL.values()) {
resolution.runChecks(errorReporter);
}
}
private void reportMissing(ErrorReporter errorReporter) {
ErrorBuilder builder = errorReporter.error(String.format("could not find source for file %s", fileLoc));
for (Span location : neededAt) {
builder.pointAtFile(location.getSourceFile())
.pointAt(location);
}
}
private void runChecks(ErrorReporter errorReporter) {
// for (var check : checks) {
// check.accept(errorReporter, file);
// }
}
public ResourceLocation resourceLocation() {
return fileLoc;
}
public boolean isWeak() {
return weak;
}
/**
* Store the given span so this resolution can know all the places that reference the file.
*
* <p>
* Used for error reporting.
* </p>
* @param span A span where this file is referenced.
*/
public FileResolution addSpan(Span span) {
neededAt.add(span);
return this;
}
public FileResolution validateWith(BiConsumer<ErrorReporter, SourceFile> check) {
checks.add(check);
return this;
}
@Override
public String toString() {
return "FileResolution[" + fileLoc + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
FileResolution that = (FileResolution) o;
return fileLoc.equals(that.fileLoc);
}
@Override
public int hashCode() {
// FileResolutions are interned and therefore can be hashed based on object identity.
// Overriding this to make it explicit.
return System.identityHashCode(this);
}
}

View file

@ -28,7 +28,7 @@ public class ShaderSources {
private final Map<ResourceLocation, SourceFile> cache = new HashMap<>();
/**
* Tracks
* Tracks where we are in the mutual recursion to detect circular imports.
*/
private final Deque<ResourceLocation> findStack = new ArrayDeque<>();
@ -42,17 +42,14 @@ public class ShaderSources {
@Nonnull
public SourceFile find(ResourceLocation location) {
if (findStack.contains(location)) {
generateRecursiveImportException(location);
}
findStack.add(location);
pushFindStack(location);
// Can't use computeIfAbsent because mutual recursion causes ConcurrentModificationExceptions
var out = cache.get(location);
if (out == null) {
out = load(location);
cache.put(location, out);
}
findStack.pop();
popFindStack();
return out;
}
@ -78,4 +75,15 @@ public class ShaderSources {
findStack.clear();
throw new ShaderLoadingException("recursive import: " + path);
}
private void pushFindStack(ResourceLocation location) {
if (findStack.contains(location)) {
generateRecursiveImportException(location);
}
findStack.add(location);
}
private void popFindStack() {
findStack.pop();
}
}

View file

@ -12,6 +12,17 @@ import com.jozufozu.flywheel.core.source.parse.ShaderVariable;
public class SourceChecks {
// TODO: recycle to be invoked by the shader compiler
public static final BiConsumer<ErrorReporter, SourceFile> LAYOUT_VERTEX = checkFunctionArity("flw_layoutVertex", 0);
public static final BiConsumer<ErrorReporter, SourceFile> INSTANCE_VERTEX = checkFunctionParameterTypeExists("flw_instanceVertex", 1, 0);
public static final BiConsumer<ErrorReporter, SourceFile> MATERIAL_VERTEX = checkFunctionArity("flw_materialVertex", 0);
public static final BiConsumer<ErrorReporter, SourceFile> MATERIAL_FRAGMENT = checkFunctionArity("flw_materialFragment", 0);
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_VERTEX = checkFunctionArity("flw_contextVertex", 0);
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_FRAGMENT = checkFunctionArity("flw_contextFragment", 0).andThen(checkFunctionArity("flw_initFragment", 0));
public static final BiConsumer<ErrorReporter, SourceFile> PIPELINE = checkFunctionArity("main", 0);
public static BiConsumer<ErrorReporter, SourceFile> checkFunctionArity(String name, int arity) {
return (errorReporter, file) -> checkFunctionArity(errorReporter, file, name, arity);
}

View file

@ -5,13 +5,14 @@ import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import com.mojang.math.Vector4f;
import net.minecraft.resources.ResourceLocation;
public class OrientedType implements StructType<OrientedPart> {
public static final BufferLayout FORMAT = BufferLayout.builder()
@ -38,7 +39,7 @@ public class OrientedType implements StructType<OrientedPart> {
}
@Override
public FileResolution getInstanceShader() {
public ResourceLocation instanceShader() {
return Components.Files.ORIENTED;
}

View file

@ -5,10 +5,11 @@ import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.mojang.math.Vector3f;
import com.mojang.math.Vector4f;
import net.minecraft.resources.ResourceLocation;
public class TransformedType implements StructType<TransformedPart> {
public static final BufferLayout FORMAT = BufferLayout.builder()
@ -34,7 +35,7 @@ public class TransformedType implements StructType<TransformedPart> {
}
@Override
public FileResolution getInstanceShader() {
public ResourceLocation instanceShader() {
return Components.Files.TRANSFORMED;
}

View file

@ -4,21 +4,20 @@ import java.util.function.Consumer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.uniform.UniformProvider;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.extension.MatrixWrite;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.MinecraftForge;
public class FlwUniformProvider implements UniformProvider {
public class FlwShaderUniforms implements ShaderUniforms {
public static final int SIZE = 224;
@ -32,16 +31,16 @@ public class FlwUniformProvider implements UniformProvider {
}
@Override
public FileResolution uniformShader() {
public ResourceLocation uniformShader() {
return Components.Files.UNIFORMS;
}
@Override
public ActiveUniformProvider activate(long ptr) {
public Provider activate(long ptr) {
return new Active(ptr);
}
public static class Active implements ActiveUniformProvider, Consumer<BeginFrameEvent> {
public static class Active implements Provider, Consumer<BeginFrameEvent> {
private final long ptr;
private boolean dirty;
@ -66,8 +65,41 @@ public class FlwUniformProvider implements UniformProvider {
@Override
public void accept(BeginFrameEvent event) {
updateFrustum(event.getContext());
updateView(event.getContext());
if (ptr == MemoryUtil.NULL) {
return;
}
RenderContext context = event.getContext();
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());
// don't want to mutate viewProjection
var vp = context.viewProjection()
.copy();
vp.multiplyWithTranslation(-camX, -camY, -camZ);
MatrixWrite.writeUnsafe(vp, ptr + 32);
MemoryUtil.memPutFloat(ptr + 96, camX);
MemoryUtil.memPutFloat(ptr + 100, camY);
MemoryUtil.memPutFloat(ptr + 104, camZ);
MemoryUtil.memPutFloat(ptr + 108, 0f); // vec4 alignment
MemoryUtil.memPutInt(ptr + 112, getConstantAmbientLightFlag(context));
updateFrustum(context, camX, camY, camZ);
dirty = true;
}
private static int getConstantAmbientLightFlag(RenderContext context) {
var constantAmbientLight = context.level()
.effects()
.constantAmbientLight();
return constantAmbientLight ? 1 : 0;
}
private boolean maybeUpdateFog() {
@ -84,65 +116,23 @@ public class FlwUniformProvider implements UniformProvider {
MemoryUtil.memPutFloat(ptr + 16, RenderSystem.getShaderFogStart());
MemoryUtil.memPutFloat(ptr + 20, RenderSystem.getShaderFogEnd());
MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape()
.getIndex());
.getIndex());
FOG_UPDATE = false;
return true;
}
public void updateFrustum(RenderContext context) {
if (ptr == MemoryUtil.NULL || (FRUSTUM_PAUSED && !FRUSTUM_CAPTURE)) {
private void updateFrustum(RenderContext context, float camX, float camY, float camZ) {
if (FRUSTUM_PAUSED && !FRUSTUM_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 + 128);
dirty = true;
FRUSTUM_CAPTURE = false;
}
public void updateView(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 + 32);
MemoryUtil.memPutFloat(ptr + 96, camX);
MemoryUtil.memPutFloat(ptr + 100, camY);
MemoryUtil.memPutFloat(ptr + 104, camZ);
MemoryUtil.memPutFloat(ptr + 108, 0f); // vec4 alignment
MemoryUtil.memPutInt(ptr + 112, constantAmbientLight);
dirty = true;
}
}
}

View file

@ -1,17 +1,17 @@
package com.jozufozu.flywheel.core.uniform;
import java.util.BitSet;
import java.util.Collection;
import java.util.List;
import org.lwjgl.opengl.GL32;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.uniform.UniformProvider;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
import com.jozufozu.flywheel.core.ComponentRegistry;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.RenderMath;
public class UniformBuffer {
@ -22,7 +22,7 @@ public class UniformBuffer {
private static final boolean PO2_ALIGNMENT = RenderMath.isPowerOf2(OFFSET_ALIGNMENT);
private static UniformBuffer instance;
private final AllocatedProviderSet providerSet;
private final ProviderSet providerSet;
public static UniformBuffer getInstance() {
if (instance == null) {
@ -34,20 +34,16 @@ public class UniformBuffer {
private final GlBuffer buffer;
private UniformBuffer() {
// TODO: put everything into one ubo
buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER);
providerSet = new AllocatedProviderSet(ComponentRegistry.getAllUniformProviders());
providerSet = new ProviderSet(ComponentRegistry.getAllUniformProviders());
}
public void sync() {
providerSet.sync();
buffer.upload(providerSet.data);
int handle = buffer.handle();
for (Allocated p : providerSet.allocatedProviders) {
GL32.glBindBufferRange(GL32.GL_UNIFORM_BUFFER, p.index, handle, p.offset, p.size);
if (providerSet.pollUpdates()) {
buffer.upload(providerSet.data);
}
GL32.glBindBufferRange(GL32.GL_UNIFORM_BUFFER, 0, buffer.handle(), 0, providerSet.data.size());
}
// https://stackoverflow.com/questions/3407012/rounding-up-to-the-nearest-multiple-of-a-number
@ -59,22 +55,16 @@ public class UniformBuffer {
}
}
private static int align16(int numToRound) {
return (numToRound + 16 - 1) & -16;
}
private static class Allocated {
private final UniformProvider provider;
private static class LiveProvider {
private final ShaderUniforms provider;
private final int offset;
private final int size;
private final int index;
private UniformProvider.ActiveUniformProvider activeProvider;
private ShaderUniforms.Provider activeProvider;
private Allocated(UniformProvider provider, int offset, int size, int index) {
private LiveProvider(ShaderUniforms provider, int offset, int size) {
this.provider = provider;
this.offset = offset;
this.size = size;
this.index = index;
}
private void updatePtr(MemoryBlock bufferBase) {
@ -84,59 +74,42 @@ public class UniformBuffer {
activeProvider = provider.activate(bufferBase.ptr() + offset);
}
public int offset() {
return offset;
}
public int size() {
return size;
}
public int index() {
return index;
}
public boolean maybePoll() {
return activeProvider != null && activeProvider.poll();
}
}
private static class AllocatedProviderSet {
private final List<Allocated> allocatedProviders;
private static class ProviderSet {
private final List<LiveProvider> allocatedProviders;
private final MemoryBlock data;
private final BitSet changedBytes;
private AllocatedProviderSet(final Collection<UniformProvider> providers) {
var builder = ImmutableList.<Allocated>builder();
private ProviderSet(final Collection<ShaderUniforms> providers) {
var builder = ImmutableList.<LiveProvider>builder();
int totalBytes = 0;
int index = 0;
for (UniformProvider provider : providers) {
int size = align16(provider.byteSize());
for (ShaderUniforms provider : providers) {
int size = FlwUtil.align16(provider.byteSize());
builder.add(new Allocated(provider, totalBytes, size, index));
builder.add(new LiveProvider(provider, totalBytes, size));
totalBytes = alignUniformBuffer(totalBytes + size);
index++;
totalBytes += size;
}
allocatedProviders = builder.build();
data = MemoryBlock.mallocTracked(totalBytes);
changedBytes = new BitSet(totalBytes);
for (Allocated p : allocatedProviders) {
for (LiveProvider p : allocatedProviders) {
p.updatePtr(data);
}
}
public void sync() {
for (Allocated p : allocatedProviders) {
if (p.maybePoll()) {
changedBytes.set(p.offset(), p.offset() + p.size());
}
public boolean pollUpdates() {
boolean changed = false;
for (LiveProvider p : allocatedProviders) {
changed |= p.maybePoll();
}
return changed;
}
}
}

View file

@ -4,7 +4,8 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.resources.ResourceLocation;
public class BlockVertex implements VertexType {
public static final BufferLayout FORMAT = BufferLayout.builder()
@ -22,7 +23,7 @@ public class BlockVertex implements VertexType {
}
@Override
public FileResolution getLayoutShader() {
public ResourceLocation layoutShader() {
return Components.Files.BLOCK_LAYOUT;
}

View file

@ -4,7 +4,8 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.resources.ResourceLocation;
public class PosTexNormalVertex implements VertexType {
public static final BufferLayout FORMAT = BufferLayout.builder()
@ -19,7 +20,7 @@ public class PosTexNormalVertex implements VertexType {
}
@Override
public FileResolution getLayoutShader() {
public ResourceLocation layoutShader() {
return Components.Files.POS_TEX_NORMAL_LAYOUT;
}

View file

@ -1,16 +0,0 @@
package com.jozufozu.flywheel.mixin;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.world.level.block.entity.BlockEntityType;
@Mixin(BlockEntityRenderDispatcher.class)
public interface BlockEntityRenderDispatcherAccessor {
@Accessor("renderers")
Map<BlockEntityType<?>, BlockEntityRenderer<?>> flywheel$getRenderers();
}

View file

@ -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.uniform.FlwUniformProvider;
import com.jozufozu.flywheel.core.uniform.FlwShaderUniforms;
import net.minecraft.client.renderer.FogRenderer;
@Mixin(FogRenderer.class)
public class FogUpdateMixin {
private static void flywheel$updateFog() {
FlwUniformProvider.FOG_UPDATE = true;
FlwShaderUniforms.FOG_UPDATE = true;
}
@Inject(method = "setupNoFog", at = @At("TAIL"))

View file

@ -3,24 +3,10 @@ package com.jozufozu.flywheel.util;
import java.util.Map;
import java.util.stream.Stream;
import com.jozufozu.flywheel.mixin.BlockEntityRenderDispatcherAccessor;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.world.level.block.entity.BlockEntityType;
public class FlwUtil {
/**
* Get the (effectively global) map of BlockEntityTypes to Renderers.
* @return An immutable map of BlockEntityTypes to BlockEntityRenderers.
*/
public static Map<BlockEntityType<?>, BlockEntityRenderer<?>> getBlockEntityRenderers() {
Minecraft mc = Minecraft.getInstance();
return ((BlockEntityRenderDispatcherAccessor) mc.getBlockEntityRenderDispatcher()).flywheel$getRenderers();
}
public static PoseStack copyPoseStack(PoseStack stack) {
PoseStack copy = new PoseStack();
copy.last().pose().load(stack.last().pose());
@ -77,4 +63,8 @@ public class FlwUtil {
public static <T> void noop(T object) {
// noop
}
public static int align16(int numToRound) {
return (numToRound + 16 - 1) & -16;
}
}

View file

@ -18,7 +18,7 @@ public enum Mods {
}
/**
* @return a boolean of whether the mod is loaded or not based on mod id
* @return a whether the mod is loaded or not based on mod id
*/
public boolean isLoaded() {
return ModList.get().isLoaded(id);
@ -30,8 +30,10 @@ public enum Mods {
* @return Optional.empty() if the mod is not loaded, otherwise an Optional of the return value of the given supplier
*/
public <T> Optional<T> runIfInstalled(Supplier<Supplier<T>> toRun) {
if (isLoaded())
return Optional.of(toRun.get().get());
if (isLoaded()) {
return Optional.of(toRun.get()
.get());
}
return Optional.empty();
}

View file

@ -5,7 +5,6 @@
"compatibilityLevel": "JAVA_17",
"refmap": "flywheel.refmap.json",
"client": [
"BlockEntityRenderDispatcherAccessor",
"BlockEntityTypeMixin",
"BufferBuilderMixin",
"ChunkRebuildHooksMixin",