Assorted adjustments

- Add EmptyModel
- Move Flywheel.rl to ResourceUtil
- Move RenderContext from api to api.backend
- Improve LineModelBuilder
  - Fix exception when calling build twice in a row
  - Expose ensureCapacity
  - Return existing EmptyModel.INSTANCE when applicable
  - Try to shrink memory before finalizing model
This commit is contained in:
PepperCode1 2025-02-23 16:12:50 -08:00
parent 9975833650
commit d2a8d075a7
40 changed files with 176 additions and 128 deletions

View file

@ -1,14 +1,11 @@
package dev.engine_room.flywheel.api;
import net.minecraft.resources.ResourceLocation;
public final class Flywheel {
/**
* The mod ID and resource namespace of Flywheel.
*/
public static final String ID = "flywheel";
private Flywheel() {
}
public static ResourceLocation rl(String path) {
return new ResourceLocation(ID, path);
}
}

View file

@ -5,7 +5,6 @@ import java.util.List;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Range;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.task.Plan;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;

View file

@ -1,4 +1,4 @@
package dev.engine_room.flywheel.api;
package dev.engine_room.flywheel.api.backend;
import org.joml.Matrix4fc;

View file

@ -5,7 +5,7 @@ import java.util.SortedSet;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.RenderContext;
import dev.engine_room.flywheel.api.internal.FlwApiLink;
import dev.engine_room.flywheel.api.visual.Effect;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;

View file

@ -1,6 +1,5 @@
package dev.engine_room.flywheel.backend;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.backend.Backend;
import dev.engine_room.flywheel.backend.compile.IndirectPrograms;
import dev.engine_room.flywheel.backend.compile.InstancingPrograms;
@ -10,6 +9,7 @@ import dev.engine_room.flywheel.backend.engine.instancing.InstancedDrawManager;
import dev.engine_room.flywheel.backend.gl.Driver;
import dev.engine_room.flywheel.backend.gl.GlCompat;
import dev.engine_room.flywheel.lib.backend.SimpleBackend;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import dev.engine_room.flywheel.lib.util.ShadersModHelper;
public final class Backends {
@ -20,7 +20,7 @@ public final class Backends {
.engineFactory(level -> new EngineImpl(level, new InstancedDrawManager(InstancingPrograms.get()), 256))
.priority(500)
.supported(() -> GlCompat.SUPPORTS_INSTANCING && InstancingPrograms.allLoaded() && !ShadersModHelper.isShaderPackInUse())
.register(Flywheel.rl("instancing"));
.register(ResourceUtil.rl("instancing"));
/**
* Use Compute shaders to cull instances.
@ -38,7 +38,7 @@ public final class Backends {
}
})
.supported(() -> GlCompat.SUPPORTS_INDIRECT && IndirectPrograms.allLoaded() && !ShadersModHelper.isShaderPackInUse())
.register(Flywheel.rl("indirect"));
.register(ResourceUtil.rl("indirect"));
private Backends() {
}

View file

@ -2,11 +2,11 @@ package dev.engine_room.flywheel.backend;
import java.util.List;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.layout.FloatRepr;
import dev.engine_room.flywheel.api.layout.Layout;
import dev.engine_room.flywheel.api.layout.LayoutBuilder;
import dev.engine_room.flywheel.backend.gl.array.VertexAttribute;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import dev.engine_room.flywheel.lib.vertex.FullVertexView;
import dev.engine_room.flywheel.lib.vertex.VertexView;
import net.minecraft.resources.ResourceLocation;
@ -24,7 +24,7 @@ public final class InternalVertex {
public static final List<VertexAttribute> ATTRIBUTES = LayoutAttributes.attributes(LAYOUT);
public static final int STRIDE = LAYOUT.byteSize();
public static final ResourceLocation LAYOUT_SHADER = Flywheel.rl("internal/vertex_input.vert");
public static final ResourceLocation LAYOUT_SHADER = ResourceUtil.rl("internal/vertex_input.vert");
private InternalVertex() {
}

View file

@ -8,13 +8,14 @@ import org.slf4j.LoggerFactory;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.backend.glsl.ShaderSources;
import dev.engine_room.flywheel.backend.glsl.SourceComponent;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
public final class FlwPrograms {
public static final Logger LOGGER = LoggerFactory.getLogger(Flywheel.ID + "/backend/shaders");
private static final ResourceLocation COMPONENTS_HEADER_FRAG = Flywheel.rl("internal/components_header.frag");
private static final ResourceLocation COMPONENTS_HEADER_FRAG = ResourceUtil.rl("internal/components_header.frag");
public static ShaderSources SOURCES;

View file

@ -6,7 +6,6 @@ import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.backend.compile.component.InstanceStructComponent;
@ -25,12 +24,12 @@ import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
public class IndirectPrograms extends AtomicReferenceCounted {
private static final ResourceLocation CULL_SHADER_API_IMPL = Flywheel.rl("internal/indirect/cull_api_impl.glsl");
private static final ResourceLocation CULL_SHADER_MAIN = Flywheel.rl("internal/indirect/cull.glsl");
private static final ResourceLocation APPLY_SHADER_MAIN = Flywheel.rl("internal/indirect/apply.glsl");
private static final ResourceLocation SCATTER_SHADER_MAIN = Flywheel.rl("internal/indirect/scatter.glsl");
private static final ResourceLocation DOWNSAMPLE_FIRST = Flywheel.rl("internal/indirect/downsample_first.glsl");
private static final ResourceLocation DOWNSAMPLE_SECOND = Flywheel.rl("internal/indirect/downsample_second.glsl");
private static final ResourceLocation CULL_SHADER_API_IMPL = ResourceUtil.rl("internal/indirect/cull_api_impl.glsl");
private static final ResourceLocation CULL_SHADER_MAIN = ResourceUtil.rl("internal/indirect/cull.glsl");
private static final ResourceLocation APPLY_SHADER_MAIN = ResourceUtil.rl("internal/indirect/apply.glsl");
private static final ResourceLocation SCATTER_SHADER_MAIN = ResourceUtil.rl("internal/indirect/scatter.glsl");
private static final ResourceLocation DOWNSAMPLE_FIRST = ResourceUtil.rl("internal/indirect/downsample_first.glsl");
private static final ResourceLocation DOWNSAMPLE_SECOND = ResourceUtil.rl("internal/indirect/downsample_second.glsl");
public static final List<ResourceLocation> UTIL_SHADERS = List.of(APPLY_SHADER_MAIN, SCATTER_SHADER_MAIN, DOWNSAMPLE_FIRST, DOWNSAMPLE_SECOND);
private static final Compile<InstanceType<?>> CULL = new Compile<>();

View file

@ -6,7 +6,6 @@ import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.material.LightShader;
import dev.engine_room.flywheel.api.material.Material;
@ -40,8 +39,8 @@ public final class PipelineCompiler {
private static UberShaderComponent FOG;
private static UberShaderComponent CUTOUT;
private static final ResourceLocation API_IMPL_VERT = Flywheel.rl("internal/api_impl.vert");
private static final ResourceLocation API_IMPL_FRAG = Flywheel.rl("internal/api_impl.frag");
private static final ResourceLocation API_IMPL_VERT = ResourceUtil.rl("internal/api_impl.vert");
private static final ResourceLocation API_IMPL_FRAG = ResourceUtil.rl("internal/api_impl.frag");
private final CompilationHarness<PipelineProgramKey> harness;
@ -184,7 +183,7 @@ public final class PipelineCompiler {
}
public static void createFogComponent() {
FOG = UberShaderComponent.builder(Flywheel.rl("fog"))
FOG = UberShaderComponent.builder(ResourceUtil.rl("fog"))
.materialSources(MaterialShaderIndices.fogSources()
.all())
.adapt(FnSignature.create()
@ -197,7 +196,7 @@ public final class PipelineCompiler {
}
private static void createCutoutComponent() {
CUTOUT = UberShaderComponent.builder(Flywheel.rl("cutout"))
CUTOUT = UberShaderComponent.builder(ResourceUtil.rl("cutout"))
.materialSources(MaterialShaderIndices.cutoutSources()
.all())
.adapt(FnSignature.create()

View file

@ -1,15 +1,15 @@
package dev.engine_room.flywheel.backend.compile;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.backend.Samplers;
import dev.engine_room.flywheel.backend.compile.component.BufferTextureInstanceComponent;
import dev.engine_room.flywheel.backend.compile.component.SsboInstanceComponent;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public final class Pipelines {
public static final Pipeline INSTANCING = Pipeline.builder()
.compilerMarker("instancing")
.vertexMain(Flywheel.rl("internal/instancing/main.vert"))
.fragmentMain(Flywheel.rl("internal/instancing/main.frag"))
.vertexMain(ResourceUtil.rl("internal/instancing/main.vert"))
.fragmentMain(ResourceUtil.rl("internal/instancing/main.frag"))
.assembler(BufferTextureInstanceComponent::new)
.onLink(program -> {
program.setSamplerBinding("_flw_instances", Samplers.INSTANCE_BUFFER);
@ -20,8 +20,8 @@ public final class Pipelines {
public static final Pipeline INDIRECT = Pipeline.builder()
.compilerMarker("indirect")
.vertexMain(Flywheel.rl("internal/indirect/main.vert"))
.fragmentMain(Flywheel.rl("internal/indirect/main.frag"))
.vertexMain(ResourceUtil.rl("internal/indirect/main.vert"))
.fragmentMain(ResourceUtil.rl("internal/indirect/main.frag"))
.assembler(SsboInstanceComponent::new)
.onLink($ -> {
})

View file

@ -2,7 +2,6 @@ package dev.engine_room.flywheel.backend.compile.component;
import java.util.ArrayList;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.layout.Layout;
import dev.engine_room.flywheel.backend.glsl.generate.FnSignature;
@ -11,6 +10,7 @@ import dev.engine_room.flywheel.backend.glsl.generate.GlslBuilder;
import dev.engine_room.flywheel.backend.glsl.generate.GlslExpr;
import dev.engine_room.flywheel.backend.glsl.generate.GlslStmt;
import dev.engine_room.flywheel.lib.math.MoreMath;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public class BufferTextureInstanceComponent extends InstanceAssemblerComponent {
private static final String[] SWIZZLE_SELECTORS = { "x", "y", "z", "w" };
@ -21,7 +21,7 @@ public class BufferTextureInstanceComponent extends InstanceAssemblerComponent {
@Override
public String name() {
return Flywheel.rl("buffer_texture_instance_assembler").toString();
return ResourceUtil.rl("buffer_texture_instance_assembler").toString();
}
@Override

View file

@ -3,12 +3,12 @@ package dev.engine_room.flywheel.backend.compile.component;
import java.util.Collection;
import java.util.Collections;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.layout.Layout;
import dev.engine_room.flywheel.backend.compile.LayoutInterpreter;
import dev.engine_room.flywheel.backend.glsl.SourceComponent;
import dev.engine_room.flywheel.backend.glsl.generate.GlslBuilder;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public class InstanceStructComponent implements SourceComponent {
private static final String STRUCT_NAME = "FlwInstance";
@ -21,7 +21,7 @@ public class InstanceStructComponent implements SourceComponent {
@Override
public String name() {
return Flywheel.rl("instance_struct").toString();
return ResourceUtil.rl("instance_struct").toString();
}
@Override

View file

@ -2,7 +2,6 @@ package dev.engine_room.flywheel.backend.compile.component;
import java.util.ArrayList;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.layout.Layout;
import dev.engine_room.flywheel.backend.engine.indirect.BufferBindings;
@ -12,6 +11,7 @@ import dev.engine_room.flywheel.backend.glsl.generate.GlslBuilder;
import dev.engine_room.flywheel.backend.glsl.generate.GlslExpr;
import dev.engine_room.flywheel.backend.glsl.generate.GlslStmt;
import dev.engine_room.flywheel.lib.math.MoreMath;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public class SsboInstanceComponent extends InstanceAssemblerComponent {
public SsboInstanceComponent(InstanceType<?> type) {
@ -20,7 +20,7 @@ public class SsboInstanceComponent extends InstanceAssemblerComponent {
@Override
public String name() {
return Flywheel.rl("ssbo_instance_assembler").toString();
return ResourceUtil.rl("ssbo_instance_assembler").toString();
}
@Override

View file

@ -3,8 +3,8 @@ package dev.engine_room.flywheel.backend.compile.component;
import java.util.Collection;
import java.util.Map;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.backend.glsl.SourceComponent;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public final class StringSubstitutionComponent implements SourceComponent {
private final SourceComponent source;
@ -42,7 +42,7 @@ public final class StringSubstitutionComponent implements SourceComponent {
@Override
public String name() {
return Flywheel.rl("string_substitution").toString() + " / " + source.name();
return ResourceUtil.rl("string_substitution").toString() + " / " + source.name();
}
@Override

View file

@ -10,7 +10,6 @@ import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.backend.glsl.ShaderSources;
import dev.engine_room.flywheel.backend.glsl.SourceComponent;
import dev.engine_room.flywheel.backend.glsl.SourceFile;
@ -19,6 +18,7 @@ import dev.engine_room.flywheel.backend.glsl.generate.GlslBlock;
import dev.engine_room.flywheel.backend.glsl.generate.GlslBuilder;
import dev.engine_room.flywheel.backend.glsl.generate.GlslExpr;
import dev.engine_room.flywheel.backend.glsl.generate.GlslSwitch;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
public class UberShaderComponent implements SourceComponent {
@ -40,7 +40,7 @@ public class UberShaderComponent implements SourceComponent {
@Override
public String name() {
return Flywheel.rl("uber_shader").toString() + " / " + name;
return ResourceUtil.rl("uber_shader").toString() + " / " + name;
}
@Override

View file

@ -8,18 +8,18 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.backend.glsl.SourceFile;
import dev.engine_room.flywheel.backend.glsl.SourceLines;
import dev.engine_room.flywheel.backend.glsl.error.ConsoleColors;
import dev.engine_room.flywheel.backend.glsl.error.ErrorBuilder;
import dev.engine_room.flywheel.backend.glsl.error.ErrorLevel;
import dev.engine_room.flywheel.backend.glsl.span.Span;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import dev.engine_room.flywheel.lib.util.StringUtil;
import net.minecraft.resources.ResourceLocation;
public class FailedCompilation {
public static final ResourceLocation GENERATED_SOURCE_NAME = Flywheel.rl("generated_source");
public static final ResourceLocation GENERATED_SOURCE_NAME = ResourceUtil.rl("generated_source");
private static final Pattern PATTERN_ONE = Pattern.compile("(\\d+)\\((\\d+)\\) : (.*)");
private static final Pattern PATTERN_TWO = Pattern.compile("(\\w+): (\\d+):(\\d+):(?: '(.+?)' :)?(.*)");
private final List<SourceFile> files;

View file

@ -12,8 +12,8 @@ import org.jetbrains.annotations.Nullable;
import com.mojang.datafixers.util.Pair;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.Engine;
import dev.engine_room.flywheel.api.backend.RenderContext;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.model.Model;

View file

@ -4,8 +4,8 @@ import java.util.List;
import com.mojang.blaze3d.systems.RenderSystem;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.Engine;
import dev.engine_room.flywheel.api.backend.RenderContext;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.instance.Instancer;

View file

@ -6,7 +6,7 @@ import org.joml.Vector2f;
import org.joml.Vector3f;
import org.lwjgl.system.MemoryUtil;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.RenderContext;
import dev.engine_room.flywheel.api.visualization.VisualizationManager;
import dev.engine_room.flywheel.backend.engine.indirect.DepthPyramid;
import dev.engine_room.flywheel.backend.mixin.LevelRendererAccessor;

View file

@ -2,7 +2,7 @@ package dev.engine_room.flywheel.backend.engine.uniform;
import org.joml.Vector3f;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.RenderContext;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;

View file

@ -2,7 +2,7 @@ package dev.engine_room.flywheel.backend.engine.uniform;
import org.jetbrains.annotations.Nullable;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.RenderContext;
import dev.engine_room.flywheel.backend.FlwBackendXplat;
import dev.engine_room.flywheel.backend.mixin.AbstractClientPlayerAccessor;
import net.minecraft.client.Minecraft;

View file

@ -1,6 +1,6 @@
package dev.engine_room.flywheel.backend.engine.uniform;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.RenderContext;
import dev.engine_room.flywheel.backend.gl.shader.GlProgram;
public final class Uniforms {

View file

@ -3,6 +3,9 @@ package dev.engine_room.flywheel.lib.backend;
import java.util.Objects;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import java.util.function.IntSupplier;
import org.jetbrains.annotations.Nullable;
import dev.engine_room.flywheel.api.backend.Backend;
import dev.engine_room.flywheel.api.backend.Engine;
@ -11,12 +14,12 @@ import net.minecraft.world.level.LevelAccessor;
public final class SimpleBackend implements Backend {
private final Function<LevelAccessor, Engine> engineFactory;
private final PriorityProvider priority;
private final IntSupplier priority;
private final BooleanSupplier isSupported;
public SimpleBackend(PriorityProvider priority, Function<LevelAccessor, Engine> engineFactory, BooleanSupplier isSupported) {
this.priority = priority;
public SimpleBackend(Function<LevelAccessor, Engine> engineFactory, IntSupplier priority, BooleanSupplier isSupported) {
this.engineFactory = engineFactory;
this.priority = priority;
this.isSupported = isSupported;
}
@ -31,7 +34,7 @@ public final class SimpleBackend implements Backend {
@Override
public int priority() {
return priority.get();
return priority.getAsInt();
}
@Override
@ -39,13 +42,11 @@ public final class SimpleBackend implements Backend {
return isSupported.getAsBoolean();
}
public interface PriorityProvider {
int get();
}
public static final class Builder {
@Nullable
private Function<LevelAccessor, Engine> engineFactory;
private PriorityProvider priority = () -> 0;
private IntSupplier priority = () -> 0;
@Nullable
private BooleanSupplier isSupported;
public Builder engineFactory(Function<LevelAccessor, Engine> engineFactory) {
@ -57,7 +58,7 @@ public final class SimpleBackend implements Backend {
return priority(() -> priority);
}
public Builder priority(PriorityProvider priority) {
public Builder priority(IntSupplier priority) {
this.priority = priority;
return this;
}
@ -71,7 +72,7 @@ public final class SimpleBackend implements Backend {
Objects.requireNonNull(engineFactory);
Objects.requireNonNull(isSupported);
return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(priority, engineFactory, isSupported));
return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(engineFactory, priority, isSupported));
}
}
}

View file

@ -2,12 +2,12 @@ package dev.engine_room.flywheel.lib.instance;
import org.lwjgl.system.MemoryUtil;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.layout.FloatRepr;
import dev.engine_room.flywheel.api.layout.IntegerRepr;
import dev.engine_room.flywheel.api.layout.LayoutBuilder;
import dev.engine_room.flywheel.lib.util.ExtraMemoryOps;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public final class InstanceTypes {
public static final InstanceType<TransformedInstance> TRANSFORMED = SimpleInstanceType.builder(TransformedInstance::new)
@ -26,8 +26,8 @@ public final class InstanceTypes {
ExtraMemoryOps.put2x16(ptr + 8, instance.light);
ExtraMemoryOps.putMatrix4f(ptr + 12, instance.pose);
})
.vertexShader(Flywheel.rl("instance/transformed.vert"))
.cullShader(Flywheel.rl("instance/cull/transformed.glsl"))
.vertexShader(ResourceUtil.rl("instance/transformed.vert"))
.cullShader(ResourceUtil.rl("instance/cull/transformed.glsl"))
.build();
public static final InstanceType<PosedInstance> POSED = SimpleInstanceType.builder(PosedInstance::new)
@ -48,8 +48,8 @@ public final class InstanceTypes {
ExtraMemoryOps.putMatrix4f(ptr + 12, instance.pose);
ExtraMemoryOps.putMatrix3f(ptr + 76, instance.normal);
})
.vertexShader(Flywheel.rl("instance/posed.vert"))
.cullShader(Flywheel.rl("instance/cull/posed.glsl"))
.vertexShader(ResourceUtil.rl("instance/posed.vert"))
.cullShader(ResourceUtil.rl("instance/cull/posed.glsl"))
.build();
public static final InstanceType<OrientedInstance> ORIENTED = SimpleInstanceType.builder(OrientedInstance::new)
@ -76,8 +76,8 @@ public final class InstanceTypes {
MemoryUtil.memPutFloat(ptr + 32, instance.pivotZ);
ExtraMemoryOps.putQuaternionf(ptr + 36, instance.rotation);
})
.vertexShader(Flywheel.rl("instance/oriented.vert"))
.cullShader(Flywheel.rl("instance/cull/oriented.glsl"))
.vertexShader(ResourceUtil.rl("instance/oriented.vert"))
.cullShader(ResourceUtil.rl("instance/cull/oriented.glsl"))
.build();
public static final InstanceType<ShadowInstance> SHADOW = SimpleInstanceType.builder(ShadowInstance::new)
@ -99,8 +99,8 @@ public final class InstanceTypes {
MemoryUtil.memPutFloat(ptr + 28, instance.alpha);
MemoryUtil.memPutFloat(ptr + 32, instance.radius);
})
.vertexShader(Flywheel.rl("instance/shadow.vert"))
.cullShader(Flywheel.rl("instance/cull/shadow.glsl"))
.vertexShader(ResourceUtil.rl("instance/shadow.vert"))
.cullShader(ResourceUtil.rl("instance/cull/shadow.glsl"))
.build();
private InstanceTypes() {

View file

@ -1,25 +1,25 @@
package dev.engine_room.flywheel.lib.material;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.material.CutoutShader;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public final class CutoutShaders {
/**
* Do not discard any fragments based on alpha.
*/
public static final CutoutShader OFF = new SimpleCutoutShader(Flywheel.rl("cutout/off.glsl"));
public static final CutoutShader OFF = new SimpleCutoutShader(ResourceUtil.rl("cutout/off.glsl"));
/**
* Discard fragments with alpha close to or equal to zero.
*/
public static final CutoutShader EPSILON = new SimpleCutoutShader(Flywheel.rl("cutout/epsilon.glsl"));
public static final CutoutShader EPSILON = new SimpleCutoutShader(ResourceUtil.rl("cutout/epsilon.glsl"));
/**
* Discard fragments with alpha less than to 0.1.
*/
public static final CutoutShader ONE_TENTH = new SimpleCutoutShader(Flywheel.rl("cutout/one_tenth.glsl"));
public static final CutoutShader ONE_TENTH = new SimpleCutoutShader(ResourceUtil.rl("cutout/one_tenth.glsl"));
/**
* Discard fragments with alpha less than to 0.5.
*/
public static final CutoutShader HALF = new SimpleCutoutShader(Flywheel.rl("cutout/half.glsl"));
public static final CutoutShader HALF = new SimpleCutoutShader(ResourceUtil.rl("cutout/half.glsl"));
private CutoutShaders() {
}

View file

@ -1,12 +1,12 @@
package dev.engine_room.flywheel.lib.material;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.material.FogShader;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public final class FogShaders {
public static final FogShader NONE = new SimpleFogShader(Flywheel.rl("fog/none.glsl"));
public static final FogShader LINEAR = new SimpleFogShader(Flywheel.rl("fog/linear.glsl"));
public static final FogShader LINEAR_FADE = new SimpleFogShader(Flywheel.rl("fog/linear_fade.glsl"));
public static final FogShader NONE = new SimpleFogShader(ResourceUtil.rl("fog/none.glsl"));
public static final FogShader LINEAR = new SimpleFogShader(ResourceUtil.rl("fog/linear.glsl"));
public static final FogShader LINEAR_FADE = new SimpleFogShader(ResourceUtil.rl("fog/linear_fade.glsl"));
private FogShaders() {
}

View file

@ -1,12 +1,12 @@
package dev.engine_room.flywheel.lib.material;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.material.LightShader;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public final class LightShaders {
public static final LightShader SMOOTH_WHEN_EMBEDDED = new SimpleLightShader(Flywheel.rl("light/smooth_when_embedded.glsl"));
public static final LightShader SMOOTH = new SimpleLightShader(Flywheel.rl("light/smooth.glsl"));
public static final LightShader FLAT = new SimpleLightShader(Flywheel.rl("light/flat.glsl"));
public static final LightShader SMOOTH_WHEN_EMBEDDED = new SimpleLightShader(ResourceUtil.rl("light/smooth_when_embedded.glsl"));
public static final LightShader SMOOTH = new SimpleLightShader(ResourceUtil.rl("light/smooth.glsl"));
public static final LightShader FLAT = new SimpleLightShader(ResourceUtil.rl("light/flat.glsl"));
private LightShaders() {
}

View file

@ -1,17 +1,17 @@
package dev.engine_room.flywheel.lib.material;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.material.MaterialShaders;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
public final class StandardMaterialShaders {
public static final MaterialShaders DEFAULT = new SimpleMaterialShaders(
Flywheel.rl("material/default.vert"), Flywheel.rl("material/default.frag"));
ResourceUtil.rl("material/default.vert"), ResourceUtil.rl("material/default.frag"));
public static final MaterialShaders WIREFRAME = new SimpleMaterialShaders(Flywheel.rl("material/wireframe.vert"), Flywheel.rl("material/wireframe.frag"));
public static final MaterialShaders WIREFRAME = new SimpleMaterialShaders(ResourceUtil.rl("material/wireframe.vert"), ResourceUtil.rl("material/wireframe.frag"));
public static final MaterialShaders LINE = new SimpleMaterialShaders(Flywheel.rl("material/lines.vert"), Flywheel.rl("material/lines.frag"));
public static final MaterialShaders LINE = new SimpleMaterialShaders(ResourceUtil.rl("material/lines.vert"), ResourceUtil.rl("material/lines.frag"));
public static final MaterialShaders GLINT = new SimpleMaterialShaders(Flywheel.rl("material/glint.vert"), Flywheel.rl("material/default.frag"));
public static final MaterialShaders GLINT = new SimpleMaterialShaders(ResourceUtil.rl("material/glint.vert"), ResourceUtil.rl("material/default.frag"));
private StandardMaterialShaders() {
}

View file

@ -0,0 +1,24 @@
package dev.engine_room.flywheel.lib.model;
import java.util.Collections;
import java.util.List;
import org.joml.Vector4f;
import org.joml.Vector4fc;
import dev.engine_room.flywheel.api.model.Model;
public final class EmptyModel implements Model {
private static final Vector4fc BOUNDING_SPHERE = new Vector4f(0, 0, 0, 0);
public static final EmptyModel INSTANCE = new EmptyModel();
@Override
public List<ConfiguredMesh> meshes() {
return Collections.emptyList();
}
@Override
public Vector4fc boundingSphere() {
return BOUNDING_SPHERE;
}
}

View file

@ -1,7 +1,6 @@
package dev.engine_room.flywheel.lib.model;
import org.jetbrains.annotations.UnknownNullability;
import org.joml.Vector4f;
import org.joml.Vector4fc;
import org.lwjgl.system.MemoryUtil;
@ -32,14 +31,37 @@ public final class LineModelBuilder {
private MemoryBlock data;
private int vertexCount = 0;
public LineModelBuilder(int segmentCount) {
vertexView = new FullVertexView();
data = MemoryBlock.mallocTracked(segmentCount * 4 * vertexView.stride());
vertexView.ptr(data.ptr());
public LineModelBuilder() {
}
public LineModelBuilder(int initialSegmentCount) {
ensureCapacity(initialSegmentCount);
}
public void ensureCapacity(int segmentCount) {
if (segmentCount < 0) {
throw new IllegalArgumentException("Segment count must be greater than or equal to 0");
} else if (segmentCount == 0) {
return;
}
if (data == null) {
vertexView = new FullVertexView();
data = MemoryBlock.mallocTracked(segmentCount * 4 * vertexView.stride());
vertexView.ptr(data.ptr());
vertexCount = 0;
} else {
long requiredCapacity = (vertexCount + segmentCount * 4) * vertexView.stride();
if (requiredCapacity > data.size()) {
data = data.realloc(requiredCapacity);
vertexView.ptr(data.ptr());
}
}
}
public LineModelBuilder line(float x1, float y1, float z1, float x2, float y2, float z2) {
ensureCapacity(vertexCount + 4);
ensureCapacity(1);
// We'll use the normal to figure out the orientation of the line in the vertex shader.
float dx = x2 - x1;
@ -79,8 +101,19 @@ public final class LineModelBuilder {
}
public Model build() {
vertexView.vertexCount(vertexCount);
if (vertexCount == 0) {
return EmptyModel.INSTANCE;
}
long requiredCapacity = vertexCount * vertexView.stride();
if (data.size() > requiredCapacity) {
data = data.realloc(requiredCapacity);
vertexView.ptr(data.ptr());
}
vertexView.nativeMemoryOwner(data);
vertexView.vertexCount(vertexCount);
var boundingSphere = ModelUtil.computeBoundingSphere(vertexView);
boundingSphere.w += 0.1f; // make the bounding sphere a little bigger to account for line width
@ -94,17 +127,6 @@ public final class LineModelBuilder {
return model;
}
private void ensureCapacity(int vertexCount) {
if (data == null) {
vertexView = new FullVertexView();
data = MemoryBlock.mallocTracked(vertexCount * vertexView.stride());
vertexView.ptr(data.ptr());
} else if (vertexCount * vertexView.stride() > data.size()) {
data = data.realloc(vertexCount * vertexView.stride());
vertexView.ptr(data.ptr());
}
}
private static class LineMesh implements Mesh {
private static final IndexSequence INDEX_SEQUENCE = (ptr, count) -> {
int numVertices = 2 * count / 3;
@ -124,9 +146,9 @@ public final class LineModelBuilder {
}
};
private final VertexList vertexList;
private final Vector4f boundingSphere;
private final Vector4fc boundingSphere;
public LineMesh(VertexList vertexList, Vector4f boundingSphere) {
public LineMesh(VertexList vertexList, Vector4fc boundingSphere) {
this.vertexList = vertexList;
this.boundingSphere = boundingSphere;
}

View file

@ -15,6 +15,10 @@ public final class ResourceUtil {
private ResourceUtil() {
}
public static ResourceLocation rl(String path) {
return new ResourceLocation(Flywheel.ID, path);
}
/**
* Same as {@link ResourceLocation#ResourceLocation(String)}, but defaults to Flywheel namespace.
*/

View file

@ -2,10 +2,10 @@ package dev.engine_room.flywheel.impl;
import java.util.ArrayList;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.backend.Backend;
import dev.engine_room.flywheel.impl.visualization.VisualizationManagerImpl;
import dev.engine_room.flywheel.lib.backend.SimpleBackend;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.ResourceLocation;
@ -15,7 +15,7 @@ public final class BackendManagerImpl {
throw new UnsupportedOperationException("Cannot create engine when backend is off.");
})
.supported(() -> true)
.register(Flywheel.rl("off"));
.register(ResourceUtil.rl("off"));
private static Backend backend = OFF_BACKEND;

View file

@ -5,7 +5,7 @@ import org.joml.Matrix4fc;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.RenderContext;
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.LevelRenderer;

View file

@ -9,9 +9,9 @@ import org.jetbrains.annotations.Nullable;
import org.joml.FrustumIntersection;
import org.joml.Matrix4f;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.BackendManager;
import dev.engine_room.flywheel.api.backend.Engine;
import dev.engine_room.flywheel.api.backend.RenderContext;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.task.Plan;
import dev.engine_room.flywheel.api.visual.DynamicVisual;

View file

@ -6,13 +6,13 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.List;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
public class TestBase {
public static final ResourceLocation FLW_A = Flywheel.rl("a.glsl");
public static final ResourceLocation FLW_B = Flywheel.rl("b.glsl");
public static final ResourceLocation FLW_C = Flywheel.rl("c.glsl");
public static final ResourceLocation FLW_A = ResourceUtil.rl("a.glsl");
public static final ResourceLocation FLW_B = ResourceUtil.rl("b.glsl");
public static final ResourceLocation FLW_C = ResourceUtil.rl("c.glsl");
public static <T> T assertSingletonList(List<T> list) {
assertEquals(1, list.size());

View file

@ -1,6 +1,6 @@
package dev.engine_room.flywheel.backend.compile;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
@ -8,7 +8,7 @@ import net.minecraft.server.packs.resources.ResourceManager;
public final class FlwProgramsReloader implements SimpleSynchronousResourceReloadListener {
public static final FlwProgramsReloader INSTANCE = new FlwProgramsReloader();
public static final ResourceLocation ID = Flywheel.rl("programs");
public static final ResourceLocation ID = ResourceUtil.rl("programs");
private FlwProgramsReloader() {
}

View file

@ -36,7 +36,7 @@ class MeshEmitter {
return bufferBuilder;
}
void prepareForGeometry(boolean shade) {
private void prepareForGeometry(boolean shade) {
if (!bufferBuilder.building()) {
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
} else if (shade != currentShade) {
@ -47,7 +47,7 @@ class MeshEmitter {
currentShade = shade;
}
void emit() {
private void emit() {
var renderedBuffer = bufferBuilder.endOrDiscardIfEmpty();
if (renderedBuffer != null) {

View file

@ -4,7 +4,7 @@ import java.util.List;
import org.jetbrains.annotations.ApiStatus;
import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.client.Minecraft;
@ -32,7 +32,7 @@ public final class PartialModelEventHandler {
public static final class ReloadListener implements SimpleSynchronousResourceReloadListener {
public static final ReloadListener INSTANCE = new ReloadListener();
public static final ResourceLocation ID = Flywheel.rl("partial_models");
public static final ResourceLocation ID = ResourceUtil.rl("partial_models");
public static final List<ResourceLocation> DEPENDENCIES = List.of(ResourceReloadListenerKeys.MODELS);
private ReloadListener() {

View file

@ -11,6 +11,7 @@ import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
import dev.engine_room.flywheel.lib.util.RendererReloadCache;
import dev.engine_room.flywheel.lib.util.ResourceReloadHolder;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
@ -60,9 +61,9 @@ public final class FlywheelFabric implements ClientModInitializer {
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) ->
BackendManagerImpl.onEndClientResourceReload(error.isPresent()));
ArgumentTypeRegistry.registerArgumentType(Flywheel.rl("backend"), BackendArgument.class, BackendArgument.INFO);
ArgumentTypeRegistry.registerArgumentType(Flywheel.rl("debug_mode"), DebugModeArgument.class, DebugModeArgument.INFO);
ArgumentTypeRegistry.registerArgumentType(Flywheel.rl("light_smoothness"), LightSmoothnessArgument.class, LightSmoothnessArgument.INFO);
ArgumentTypeRegistry.registerArgumentType(ResourceUtil.rl("backend"), BackendArgument.class, BackendArgument.INFO);
ArgumentTypeRegistry.registerArgumentType(ResourceUtil.rl("debug_mode"), DebugModeArgument.class, DebugModeArgument.INFO);
ArgumentTypeRegistry.registerArgumentType(ResourceUtil.rl("light_smoothness"), LightSmoothnessArgument.class, LightSmoothnessArgument.INFO);
}
private static void setupLib() {

View file

@ -14,6 +14,7 @@ import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
import dev.engine_room.flywheel.lib.util.LevelAttached;
import dev.engine_room.flywheel.lib.util.RendererReloadCache;
import dev.engine_room.flywheel.lib.util.ResourceReloadHolder;
import dev.engine_room.flywheel.lib.util.ResourceUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
import net.minecraftforge.api.distmarker.Dist;
@ -101,9 +102,9 @@ public final class FlywheelForge {
});
modEventBus.addListener((RegisterEvent e) -> {
if (e.getRegistryKey().equals(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES)) {
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, Flywheel.rl("backend"), () -> BackendArgument.INFO);
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, Flywheel.rl("debug_mode"), () -> DebugModeArgument.INFO);
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, Flywheel.rl("light_smoothness"), () -> LightSmoothnessArgument.INFO);
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, ResourceUtil.rl("backend"), () -> BackendArgument.INFO);
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, ResourceUtil.rl("debug_mode"), () -> DebugModeArgument.INFO);
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, ResourceUtil.rl("light_smoothness"), () -> LightSmoothnessArgument.INFO);
}
});
}