Registry refactors and namespaced backends

This commit is contained in:
PepperCode1 2023-04-02 23:58:28 -07:00
parent 59773125b2
commit 2c010ffa06
111 changed files with 1214 additions and 884 deletions

View file

@ -3,17 +3,21 @@ package com.jozufozu.flywheel;
import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.slf4j.Logger; import org.slf4j.Logger;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.Loader;
import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer; import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.config.BackendTypeArgument; import com.jozufozu.flywheel.config.BackendArgument;
import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.handler.EntityWorldHandler; import com.jozufozu.flywheel.handler.EntityWorldHandler;
import com.jozufozu.flywheel.handler.ForgeEvents; import com.jozufozu.flywheel.handler.ForgeEvents;
import com.jozufozu.flywheel.lib.backend.BackendTypes; import com.jozufozu.flywheel.impl.IdRegistryImpl;
import com.jozufozu.flywheel.impl.RegistryImpl;
import com.jozufozu.flywheel.lib.backend.Backends;
import com.jozufozu.flywheel.lib.context.Contexts; import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.Models; import com.jozufozu.flywheel.lib.model.Models;
import com.jozufozu.flywheel.lib.model.PartialModel; import com.jozufozu.flywheel.lib.model.PartialModel;
@ -61,7 +65,7 @@ public class Flywheel {
.getModEventBus(); .getModEventBus();
modEventBus.addListener(Flywheel::setup); modEventBus.addListener(Flywheel::setup);
FlwConfig.init(); FlwConfig.get().registerSpecs(modLoadingContext);
modLoadingContext.registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest( modLoadingContext.registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(
() -> NetworkConstants.IGNORESERVERONLY, () -> NetworkConstants.IGNORESERVERONLY,
@ -72,12 +76,6 @@ public class Flywheel {
} }
private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) { private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) {
CrashReportCallables.registerCrashCallable("Flywheel Backend", Backend::getBackendDescriptor);
ShadersModHandler.init();
BackendTypes.init();
Backend.init();
forgeEventBus.addListener(FlwCommands::registerClientCommands); forgeEventBus.addListener(FlwCommands::registerClientCommands);
forgeEventBus.addListener(EventPriority.HIGHEST, QuadConverter::onReloadRenderers); forgeEventBus.addListener(EventPriority.HIGHEST, QuadConverter::onReloadRenderers);
@ -102,14 +100,23 @@ public class Flywheel {
// forgeEventBus.addListener(ExampleEffect::tick); // forgeEventBus.addListener(ExampleEffect::tick);
// forgeEventBus.addListener(ExampleEffect::onReload); // forgeEventBus.addListener(ExampleEffect::onReload);
ShadersModHandler.init();
Backends.init();
Loader.init();
Formats.init(); Formats.init();
StructTypes.init(); StructTypes.init();
Materials.init(); Materials.init();
Contexts.init(); Contexts.init();
Pipelines.init(); Pipelines.init();
MaterialIndicies.init();
VanillaInstances.init(); VanillaInstances.init();
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManager::getBackendDescriptor);
// https://github.com/Jozufozu/Flywheel/issues/69 // https://github.com/Jozufozu/Flywheel/issues/69
// Weird issue with accessor loading. // Weird issue with accessor loading.
// Only thing I've seen that's close to a fix is to force the class to load before trying to use it. // Only thing I've seen that's close to a fix is to force the class to load before trying to use it.
@ -119,7 +126,10 @@ public class Flywheel {
} }
private static void setup(final FMLCommonSetupEvent event) { private static void setup(final FMLCommonSetupEvent event) {
ArgumentTypes.register(rl("engine").toString(), BackendTypeArgument.class, new EmptyArgumentSerializer<>(BackendTypeArgument::getInstance)); ArgumentTypes.register(rl("backend").toString(), BackendArgument.class, new EmptyArgumentSerializer<>(BackendArgument::getInstance));
RegistryImpl.freezeAll();
IdRegistryImpl.freezeAll();
} }
public static ArtifactVersion getVersion() { public static ArtifactVersion getVersion() {

View file

@ -0,0 +1,26 @@
package com.jozufozu.flywheel.api.backend;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.registry.IdRegistry;
import com.jozufozu.flywheel.impl.IdRegistryImpl;
import net.minecraft.network.chat.Component;
public interface Backend {
static IdRegistry<Backend> REGISTRY = IdRegistryImpl.create();
// TODO: remove and use ID instead? Currently this is only used for the crash log string.
String getProperName();
Component getEngineMessage();
Engine createEngine();
Backend findFallback();
boolean isSupported();
@Nullable Pipeline pipelineShader();
}

View file

@ -0,0 +1,38 @@
package com.jozufozu.flywheel.api.backend;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.impl.BackendManagerImpl;
public final class BackendManager {
/**
* Get the current backend.
*/
@Nullable
public static Backend getBackend() {
return BackendManagerImpl.getBackend();
}
/**
* Get a string describing the current backend.
*/
public static String getBackendDescriptor() {
return BackendManagerImpl.getBackendDescriptor();
}
public static boolean isOn() {
return BackendManagerImpl.isOn();
}
// TODO: definitively sort existing calls to this method into API (include behavior in javadoc) or default backend code
public static void refresh() {
BackendManagerImpl.refresh();
}
public static Backend getDefaultBackend() {
return BackendManagerImpl.getDefaultBackend();
}
private BackendManager() {
}
}

View file

@ -1,24 +0,0 @@
package com.jozufozu.flywheel.api.backend;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import net.minecraft.network.chat.Component;
public interface BackendType {
String getProperName();
String getShortName();
Component getEngineMessage();
Engine createEngine();
BackendType findFallback();
boolean supported();
@Nullable Pipeline pipelineShader();
}

View file

@ -2,10 +2,10 @@ package com.jozufozu.flywheel.api.backend;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
public interface Engine extends RenderDispatcher, InstancerManager { public interface Engine extends RenderDispatcher, InstancerProvider {
void attachManagers(InstanceManager<?>... listener); void attachManagers(InstanceManager<?>... listener);
void addDebugInfo(List<String> info); void addDebugInfo(List<String> info);

View file

@ -1,140 +0,0 @@
package com.jozufozu.flywheel.api.component;
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.Context;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.api.vertex.VertexType;
import net.minecraft.resources.ResourceLocation;
public class ComponentRegistry {
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<Context> contextShaders = new HashSet<>();
// TODO: fill out the rest of the registry
public static <T extends Material> T register(T material) {
return materials.add(material);
}
public static <T extends StructType<?>> T register(T type) {
structTypes.add(type);
return type;
}
public static <T extends VertexType> T register(T vertexType) {
vertexTypes.add(vertexType);
return vertexType;
}
public static <T extends Context> T register(T contextShader) {
contextShaders.add(contextShader);
return contextShader;
}
public static <T extends ShaderUniforms> T register(T provider) {
return uniformProviders.register(provider.uniformShader(), provider);
}
public static Collection<ShaderUniforms> getAllUniformProviders() {
return Collections.unmodifiableCollection(uniformProviders.objects);
}
@Nullable
public static ShaderUniforms getUniformProvider(ResourceLocation loc) {
return uniformProviders.get(loc);
}
private static class Registry<T> {
private final Map<ResourceLocation, T> files = new HashMap<>();
private final List<T> objects = new ArrayList<>();
public <O extends T> O register(ResourceLocation loc, O object) {
if (files.containsKey(loc)) {
throw new IllegalArgumentException("Shader file already registered: " + loc);
}
files.put(loc, object);
objects.add(object);
return object;
}
@Nullable
public T get(ResourceLocation loc) {
return files.get(loc);
}
}
public static class MaterialRegistry {
private final Set<Material> materials = new HashSet<>();
private final List<Material> materialsOrdered = new ArrayList<>();
private final MaterialSources vertexSources = new MaterialSources();
private final MaterialSources fragmentSources = new MaterialSources();
public <T extends Material> T add(T material) {
if (materials.add(material)) {
materialsOrdered.add(material);
vertexSources.register(material.vertexShader());
fragmentSources.register(material.fragmentShader());
} else {
throw new IllegalArgumentException("Material already registered: " + material);
}
return material;
}
/**
* @return a list of vertex shader sources where the index in the list is the shader's ID.
*/
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<ResourceLocation> fragmentSources() {
return fragmentSources.sourceView;
}
public int getVertexID(Material material) {
return vertexSources.orderedSources.indexOf(material.vertexShader());
}
public int getFragmentID(Material material) {
return fragmentSources.orderedSources.indexOf(material.fragmentShader());
}
public int getMaterialID(Material material) {
return materialsOrdered.indexOf(material);
}
private static class MaterialSources {
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(ResourceLocation vertexShader) {
if (registered.add(vertexShader)) {
orderedSources.add(vertexShader);
}
}
}
}
}

View file

@ -1,9 +0,0 @@
package com.jozufozu.flywheel.api.component;
public enum ComponentType {
MATERIAL,
INSTANCE,
LAYOUT,
CONTEXT,
UNIFORM_PROVIDER
}

View file

@ -1,10 +1,14 @@
package com.jozufozu.flywheel.api.context; package com.jozufozu.flywheel.api.context;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface Context { public interface Context {
static Registry<Context> REGISTRY = RegistryImpl.create();
void onProgramLink(GlProgram program); void onProgramLink(GlProgram program);
ResourceLocation vertexShader(); ResourceLocation vertexShader();

View file

@ -1,18 +1,12 @@
package com.jozufozu.flywheel.backend.instancing; package com.jozufozu.flywheel.api.instance;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstancingController;
import com.jozufozu.flywheel.backend.instancing.blockentity.SimpleBlockEntityInstancingController;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstancingController;
import com.jozufozu.flywheel.backend.instancing.entity.SimpleEntityInstancingController;
import com.jozufozu.flywheel.extension.BlockEntityTypeExtension; import com.jozufozu.flywheel.extension.BlockEntityTypeExtension;
import com.jozufozu.flywheel.extension.EntityTypeExtension; import com.jozufozu.flywheel.extension.EntityTypeExtension;
@ -54,7 +48,7 @@ public class InstancedRenderRegistry {
* @return An instance of the block entity, or {@code null} if the block entity cannot be instanced. * @return An instance of the block entity, or {@code null} if the block entity cannot be instanced.
*/ */
@Nullable @Nullable
public static <T extends BlockEntity> BlockEntityInstance<? super T> createInstance(InstancerManager instancerManager, T blockEntity) { public static <T extends BlockEntity> BlockEntityInstance<? super T> createInstance(InstancerProvider instancerManager, T blockEntity) {
BlockEntityInstancingController<? super T> controller = getController(getType(blockEntity)); BlockEntityInstancingController<? super T> controller = getController(getType(blockEntity));
if (controller == null) { if (controller == null) {
return null; return null;
@ -70,7 +64,7 @@ public class InstancedRenderRegistry {
* @return An instance of the entity, or {@code null} if the entity cannot be instanced. * @return An instance of the entity, or {@code null} if the entity cannot be instanced.
*/ */
@Nullable @Nullable
public static <T extends Entity> EntityInstance<? super T> createInstance(InstancerManager instancerManager, T entity) { public static <T extends Entity> EntityInstance<? super T> createInstance(InstancerProvider instancerManager, T entity) {
EntityInstancingController<? super T> controller = getController(getType(entity)); EntityInstancingController<? super T> controller = getController(getType(entity));
if (controller == null) { if (controller == null) {
return null; return null;
@ -106,26 +100,6 @@ public class InstancedRenderRegistry {
return controller.shouldSkipRender(entity); return controller.shouldSkipRender(entity);
} }
/**
* Get an object to configure the instancing controller for the given block entity type.
* @param type The block entity type to configure.
* @param <T> The type of the block entity.
* @return The configuration object.
*/
public static <T extends BlockEntity> BlockEntityConfig<T> configure(BlockEntityType<T> type) {
return new BlockEntityConfig<>(type);
}
/**
* Get an object to configure the instancing controller for the given entity type.
* @param type The entity type to configure.
* @param <T> The type of the entity.
* @return The configuration object.
*/
public static <T extends Entity> EntityConfig<T> configure(EntityType<T> type) {
return new EntityConfig<>(type);
}
/** /**
* Gets the instancing controller for the given block entity type, if one exists. * Gets the instancing controller for the given block entity type, if one exists.
* @param type The block entity type to get the instancing controller for. * @param type The block entity type to get the instancing controller for.
@ -187,118 +161,4 @@ public class InstancedRenderRegistry {
public static <T extends Entity> EntityType<? super T> getType(T entity) { public static <T extends Entity> EntityType<? super T> getType(T entity) {
return (EntityType<? super T>) entity.getType(); return (EntityType<? super T>) entity.getType();
} }
/**
* An object to configure the instancing controller for a block entity.
* @param <T> The type of the block entity.
*/
public static class BlockEntityConfig<T extends BlockEntity> {
protected BlockEntityType<T> type;
protected BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public BlockEntityConfig(BlockEntityType<T> type) {
this.type = type;
}
/**
* Sets the instance factory for the block entity.
* @param instanceFactory The instance factory.
* @return {@code this}
*/
public BlockEntityConfig<T> factory(BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory) {
this.instanceFactory = instanceFactory;
return this;
}
/**
* Sets a predicate to determine whether to skip rendering a block entity.
* @param skipRender The predicate.
* @return {@code this}
*/
public BlockEntityConfig<T> skipRender(Predicate<T> skipRender) {
this.skipRender = skipRender;
return this;
}
/**
* Sets a predicate to always skip rendering for block entities of this type.
* @return {@code this}
*/
public BlockEntityConfig<T> alwaysSkipRender() {
this.skipRender = be -> true;
return this;
}
/**
* Constructs the block entity instancing controller, and sets it for the block entity type.
* @return The block entity instancing controller.
*/
public SimpleBlockEntityInstancingController<T> apply() {
Objects.requireNonNull(instanceFactory, "Instance factory cannot be null!");
if (skipRender == null) {
skipRender = be -> false;
}
SimpleBlockEntityInstancingController<T> controller = new SimpleBlockEntityInstancingController<>(instanceFactory, skipRender);
setController(type, controller);
return controller;
}
}
/**
* An object to configure the instancing controller for an entity.
* @param <T> The type of the entity.
*/
public static class EntityConfig<T extends Entity> {
protected EntityType<T> type;
protected BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public EntityConfig(EntityType<T> type) {
this.type = type;
}
/**
* Sets the instance factory for the entity.
* @param instanceFactory The instance factory.
* @return {@code this}
*/
public EntityConfig<T> factory(BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory) {
this.instanceFactory = instanceFactory;
return this;
}
/**
* Sets a predicate to determine whether to skip rendering an entity.
* @param skipRender The predicate.
* @return {@code this}
*/
public EntityConfig<T> skipRender(Predicate<T> skipRender) {
this.skipRender = skipRender;
return this;
}
/**
* Sets a predicate to always skip rendering for entities of this type.
* @return {@code this}
*/
public EntityConfig<T> alwaysSkipRender() {
this.skipRender = entity -> true;
return this;
}
/**
* Constructs the entity instancing controller, and sets it for the entity type.
* @return The entity instancing controller.
*/
public SimpleEntityInstancingController<T> apply() {
Objects.requireNonNull(instanceFactory, "Instance factory cannot be null!");
if (skipRender == null) {
skipRender = entity -> false;
}
SimpleEntityInstancingController<T> controller = new SimpleEntityInstancingController<>(instanceFactory, skipRender);
setController(type, controller);
return controller;
}
}
} }

View file

@ -1,12 +1,13 @@
package com.jozufozu.flywheel.backend.instancing.blockentity; package com.jozufozu.flywheel.api.instance.blockentity;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
/** /**
* An instancing controller that will be keyed to a block entity type. * An instancing controller that will be keyed to a block entity type.
* @param <T> The type of block entity this controller is for. * @param <T> The block entity type.
*/ */
public interface BlockEntityInstancingController<T extends BlockEntity> { public interface BlockEntityInstancingController<T extends BlockEntity> {
/** /**
@ -15,7 +16,7 @@ public interface BlockEntityInstancingController<T extends BlockEntity> {
* @param blockEntity The block entity to construct an instance for. * @param blockEntity The block entity to construct an instance for.
* @return The instance. * @return The instance.
*/ */
BlockEntityInstance<? super T> createInstance(InstancerManager instancerManager, T blockEntity); BlockEntityInstance<? super T> createInstance(InstancerProvider instancerManager, T blockEntity);
/** /**
* Checks if the given block entity should not be rendered normally. * Checks if the given block entity should not be rendered normally.

View file

@ -1,6 +1,7 @@
package com.jozufozu.flywheel.backend.instancing.entity; package com.jozufozu.flywheel.api.instance.entity;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -15,7 +16,7 @@ public interface EntityInstancingController<T extends Entity> {
* @param entity The entity to construct an instance for. * @param entity The entity to construct an instance for.
* @return The instance. * @return The instance.
*/ */
EntityInstance<? super T> createInstance(InstancerManager instancerManager, T entity); EntityInstance<? super T> createInstance(InstancerProvider instancerManager, T entity);
/** /**
* Checks if the given entity should not render normally. * Checks if the given entity should not render normally.

View file

@ -1,20 +0,0 @@
package com.jozufozu.flywheel.api.instancer;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.StructType;
import net.minecraft.core.Vec3i;
public interface InstancerManager {
/**
* Get an instancer for the given struct type and model. Calling this method twice with the same arguments will return the same instancer.
*
* @return An instancer for the given struct type and model.
*/
<D extends InstancedPart> Instancer<D> instancer(StructType<D> type, Model model, RenderStage stage);
Vec3i getOriginCoordinate();
}

View file

@ -0,0 +1,19 @@
package com.jozufozu.flywheel.api.instancer;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.StructType;
import net.minecraft.core.Vec3i;
public interface InstancerProvider {
/**
* Get an instancer for the given struct type, model, and render stage. Calling this method twice with the same arguments will return the same instancer.
*
* @return An instancer for the given struct type, model, and render stage.
*/
<D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model, RenderStage stage);
// TODO: this method does not belong in the interface
Vec3i getOriginCoordinate();
}

View file

@ -5,7 +5,6 @@ import java.util.List;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.gl.array.VertexAttribute; import com.jozufozu.flywheel.gl.array.VertexAttribute;
import com.jozufozu.flywheel.lib.layout.LayoutItem;
/** /**
* Classic Vertex Format struct with a clever name. * Classic Vertex Format struct with a clever name.

View file

@ -1,6 +1,5 @@
package com.jozufozu.flywheel.lib.layout; package com.jozufozu.flywheel.api.layout;
import com.jozufozu.flywheel.api.layout.InputType;
import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.glsl.generate.GlslStruct; import com.jozufozu.flywheel.glsl.generate.GlslStruct;

View file

@ -1,12 +1,16 @@
package com.jozufozu.flywheel.api.material; package com.jozufozu.flywheel.api.material;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface Material { public interface Material {
static Registry<Material> REGISTRY = RegistryImpl.create();
ResourceLocation vertexShader(); ResourceLocation vertexShader();
ResourceLocation fragmentShader(); ResourceLocation fragmentShader();

View file

@ -4,7 +4,7 @@ import org.joml.Vector4fc;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.engine.instancing.ElementBuffer; import com.jozufozu.flywheel.gl.buffer.ElementBuffer;
import com.jozufozu.flywheel.lib.util.QuadConverter; import com.jozufozu.flywheel.lib.util.QuadConverter;
/** /**

View file

@ -4,6 +4,7 @@ import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;

View file

@ -0,0 +1,33 @@
package com.jozufozu.flywheel.api.registry;
import java.util.Collection;
import java.util.Set;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import net.minecraft.resources.ResourceLocation;
@ApiStatus.NonExtendable
public interface IdRegistry<T> extends Iterable<T> {
void register(ResourceLocation id, T object);
<S extends T> S registerAndGet(ResourceLocation id, S object);
@Nullable
T get(ResourceLocation id);
@Nullable
ResourceLocation getId(T object);
@Unmodifiable
Set<ResourceLocation> getAllIds();
@Unmodifiable
Collection<T> getAll();
void addFreezeCallback(Runnable callback);
boolean isFrozen();
}

View file

@ -0,0 +1,20 @@
package com.jozufozu.flywheel.api.registry;
import java.util.Set;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Unmodifiable;
@ApiStatus.NonExtendable
public interface Registry<T> extends Iterable<T> {
void register(T object);
<S extends T> S registerAndGet(S object);
@Unmodifiable
Set<T> getAll();
void addFreezeCallback(Runnable callback);
boolean isFrozen();
}

View file

@ -1,10 +0,0 @@
package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
public interface StorageBufferWriter<T extends InstancedPart> {
void write(final long ptr, final T instance);
int getAlignment();
}

View file

@ -2,7 +2,9 @@ package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.layout.BufferLayout;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -12,6 +14,7 @@ import net.minecraft.resources.ResourceLocation;
* @param <S> The java representation of the instance struct. * @param <S> The java representation of the instance struct.
*/ */
public interface StructType<S extends InstancedPart> { public interface StructType<S extends InstancedPart> {
static Registry<StructType<?>> REGISTRY = RegistryImpl.create();
/** /**
* @return A new, zeroed instance of S. * @return A new, zeroed instance of S.

View file

@ -1,8 +1,12 @@
package com.jozufozu.flywheel.api.uniform; package com.jozufozu.flywheel.api.uniform;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface ShaderUniforms { public interface ShaderUniforms {
static Registry<ShaderUniforms> REGISTRY = RegistryImpl.createForShaderUniforms();
Provider activate(long ptr); Provider activate(long ptr);

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.api.vertex; package com.jozufozu.flywheel.api.vertex;
import com.jozufozu.flywheel.backend.vertex.InferredVertexListProviderImpl;
import com.jozufozu.flywheel.extension.VertexFormatExtension; import com.jozufozu.flywheel.extension.VertexFormatExtension;
import com.jozufozu.flywheel.impl.vertex.InferredVertexListProviderImpl;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
public interface VertexListProvider { public interface VertexListProvider {

View file

@ -1,6 +1,8 @@
package com.jozufozu.flywheel.api.vertex; package com.jozufozu.flywheel.api.vertex;
import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.layout.BufferLayout;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -8,6 +10,7 @@ import net.minecraft.resources.ResourceLocation;
* A vertex type containing metadata about a specific vertex layout. * A vertex type containing metadata about a specific vertex layout.
*/ */
public interface VertexType extends VertexListProvider { public interface VertexType extends VertexListProvider {
static Registry<VertexType> REGISTRY = RegistryImpl.create();
/** /**
* The layout of this type of vertex when buffered. * The layout of this type of vertex when buffered.

View file

@ -1,114 +0,0 @@
package com.jozufozu.flywheel.backend;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import com.jozufozu.flywheel.api.FlywheelLevel;
import com.jozufozu.flywheel.api.backend.BackendType;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.lib.backend.BackendTypes;
import com.mojang.logging.LogUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
public class Backend {
public static final Logger LOGGER = LogUtils.getLogger();
public static final boolean DUMP_SHADER_SOURCE = System.getProperty("flw.dumpShaderSource") != null;
private static BackendType TYPE;
private static ParallelTaskExecutor EXECUTOR;
private static final Loader LOADER = new Loader();
/**
* Get the current Flywheel backend type.
*/
public static BackendType getBackendType() {
return TYPE;
}
/**
* Get a thread pool for running Flywheel related work in parallel.
* @return A global Flywheel thread pool.
*/
public static ParallelTaskExecutor getTaskExecutor() {
if (EXECUTOR == null) {
EXECUTOR = new ParallelTaskExecutor("Flywheel");
EXECUTOR.startWorkers();
}
return EXECUTOR;
}
/**
* Get a string describing the Flywheel backend. When there are eventually multiple backends
* (Meshlet, MDI, GL31 Draw Instanced are planned), this will name which one is in use.
*/
public static String getBackendDescriptor() {
return TYPE == null ? "Uninitialized" : TYPE.getProperName();
}
public static void refresh() {
TYPE = chooseEngine();
}
public static boolean isOn() {
return TYPE != BackendTypes.OFF;
}
@Contract("null -> false")
public static boolean canUseInstancing(@Nullable Level level) {
return isOn() && isFlywheelLevel(level);
}
/**
* Used to avoid calling Flywheel functions on (fake) levels that don't specifically support it.
*/
public static boolean isFlywheelLevel(@Nullable LevelAccessor level) {
if (level == null) return false;
if (!level.isClientSide()) return false;
if (level instanceof FlywheelLevel && ((FlywheelLevel) level).supportsFlywheel()) return true;
return level == Minecraft.getInstance().level;
}
public static boolean isGameActive() {
return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null);
}
public static void reloadWorldRenderers() {
Minecraft.getInstance().levelRenderer.allChanged();
}
private static BackendType chooseEngine() {
var preferred = FlwConfig.get()
.getBackendType();
if (preferred == null) {
return BackendTypes.defaultForCurrentPC();
}
var actual = preferred.findFallback();
if (preferred != actual) {
LOGGER.warn("Flywheel backend fell back from '{}' to '{}'", preferred.getShortName(), actual.getShortName());
}
return actual;
}
public static void init() {
// noop
}
private Backend() {
throw new UnsupportedOperationException("Backend is a static class!");
}
}

View file

@ -0,0 +1,57 @@
package com.jozufozu.flywheel.backend;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.FlywheelLevel;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import net.minecraft.client.Minecraft;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
public class BackendUtil {
public static final boolean DUMP_SHADER_SOURCE = System.getProperty("flw.dumpShaderSource") != null;
private static ParallelTaskExecutor executor;
/**
* Get a thread pool for running Flywheel related work in parallel.
* @return A global Flywheel thread pool.
*/
public static ParallelTaskExecutor getTaskExecutor() {
if (executor == null) {
executor = new ParallelTaskExecutor("Flywheel");
executor.startWorkers();
}
return executor;
}
@Contract("null -> false")
public static boolean canUseInstancing(@Nullable Level level) {
return BackendManager.isOn() && isFlywheelLevel(level);
}
/**
* Used to avoid calling Flywheel functions on (fake) levels that don't specifically support it.
*/
public static boolean isFlywheelLevel(@Nullable LevelAccessor level) {
if (level == null) return false;
if (!level.isClientSide()) return false;
if (level instanceof FlywheelLevel && ((FlywheelLevel) level).supportsFlywheel()) return true;
return level == Minecraft.getInstance().level;
}
public static boolean isGameActive() {
return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null);
}
public static void reloadWorldRenderers() {
Minecraft.getInstance().levelRenderer.allChanged();
}
}

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend; package com.jozufozu.flywheel.backend;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.compile.FlwCompiler; import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.ShaderSources;
@ -19,22 +20,14 @@ import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
* </p> * </p>
*/ */
public class Loader implements ResourceManagerReloadListener { public class Loader implements ResourceManagerReloadListener {
public static final Loader INSTANCE = new Loader();
Loader() { private Loader() {
// Can be null when running datagenerators due to the unfortunate time we call this
Minecraft minecraft = Minecraft.getInstance();
if (minecraft == null) {
return;
}
if (minecraft.getResourceManager() instanceof ReloadableResourceManager reloadable) {
reloadable.registerReloadListener(this);
}
} }
@Override @Override
public void onResourceManagerReload(ResourceManager manager) { public void onResourceManagerReload(ResourceManager manager) {
Backend.refresh(); BackendManager.refresh();
var errorReporter = new ErrorReporter(); var errorReporter = new ErrorReporter();
ShaderSources sources = new ShaderSources(errorReporter, manager); ShaderSources sources = new ShaderSources(errorReporter, manager);
@ -46,9 +39,20 @@ public class Loader implements ResourceManagerReloadListener {
FlwCompiler.INSTANCE = new FlwCompiler(sources); FlwCompiler.INSTANCE = new FlwCompiler(sources);
ClientLevel level = Minecraft.getInstance().level; ClientLevel level = Minecraft.getInstance().level;
if (Backend.canUseInstancing(level)) { if (BackendUtil.canUseInstancing(level)) {
InstancedRenderDispatcher.resetInstanceLevel(level); InstancedRenderDispatcher.resetInstanceLevel(level);
} }
}
public static void init() {
// Can be null when running datagenerators due to the unfortunate time we call this
Minecraft minecraft = Minecraft.getInstance();
if (minecraft == null) {
return;
}
if (minecraft.getResourceManager() instanceof ReloadableResourceManager reloadable) {
reloadable.registerReloadListener(INSTANCE);
}
} }
} }

View file

@ -9,12 +9,13 @@ import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import com.jozufozu.flywheel.api.pipeline.SourceComponent; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlShader; import com.jozufozu.flywheel.gl.shader.GlShader;
import com.jozufozu.flywheel.gl.shader.ShaderType; import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.gl.versioned.GlCompat; import com.jozufozu.flywheel.gl.versioned.GlCompat;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile; import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.util.StringUtil; import com.jozufozu.flywheel.util.StringUtil;
@ -130,7 +131,7 @@ public class Compilation {
} }
private static void dumpSource(String source, String fileName) { private static void dumpSource(String source, String fileName) {
if (!Backend.DUMP_SHADER_SOURCE) { if (!BackendUtil.DUMP_SHADER_SOURCE) {
return; return;
} }
@ -140,7 +141,7 @@ public class Compilation {
try (FileWriter writer = new FileWriter(file)) { try (FileWriter writer = new FileWriter(file)) {
writer.write(source); writer.write(source);
} catch (Exception e) { } catch (Exception e) {
Backend.LOGGER.error("Could not dump source.", e); Flywheel.LOGGER.error("Could not dump source.", e);
} }
} }

View file

@ -13,7 +13,7 @@ import java.util.stream.Stream;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.ShaderType; import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.glsl.SourceFile; import com.jozufozu.flywheel.glsl.SourceFile;
@ -76,7 +76,7 @@ public class CompileUtil {
String log = glGetProgramInfoLog(handle); String log = glGetProgramInfoLog(handle);
if (!log.isEmpty()) { if (!log.isEmpty()) {
Backend.LOGGER.debug("Program link log: " + log); Flywheel.LOGGER.debug("Program link log: " + log);
} }
int result = glGetProgrami(handle, GL_LINK_STATUS); int result = glGetProgrami(handle, GL_LINK_STATUS);

View file

@ -4,13 +4,12 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
public class CullingContextSet { public class CullingContextSet {
static CullingContextSet create() { static CullingContextSet create() {
var builder = new CullingContextSet(); var builder = new CullingContextSet();
for (StructType<?> structType : ComponentRegistry.structTypes) { for (StructType<?> structType : StructType.REGISTRY.getAll()) {
builder.add(structType); builder.add(structType);
} }
return builder; return builder;

View file

@ -12,22 +12,21 @@ import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent; import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.gl.shader.ShaderType; import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.glsl.ShaderLoadingException; import com.jozufozu.flywheel.glsl.ShaderLoadingException;
import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.generate.FnSignature; import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.util.StringUtil; import com.jozufozu.flywheel.util.StringUtil;
@ -56,12 +55,12 @@ public class FlwCompiler {
this.sources = sources; this.sources = sources;
this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter")) this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
.materialSources(ComponentRegistry.materials.vertexSources()) .materialSources(MaterialIndicies.getAllVertexShaders())
.adapt(FnSignature.ofVoid("flw_materialVertex")) .adapt(FnSignature.ofVoid("flw_materialVertex"))
.switchOn(GlslExpr.variable("flw_materialVertexID")) .switchOn(GlslExpr.variable("flw_materialVertexID"))
.build(sources); .build(sources);
this.fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter")) this.fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter"))
.materialSources(ComponentRegistry.materials.fragmentSources()) .materialSources(MaterialIndicies.getAllFragmentShaders())
.adapt(FnSignature.ofVoid("flw_materialFragment")) .adapt(FnSignature.ofVoid("flw_materialFragment"))
.adapt(FnSignature.create() .adapt(FnSignature.create()
.returnType("bool") .returnType("bool")
@ -76,7 +75,7 @@ public class FlwCompiler {
.switchOn(GlslExpr.variable("flw_materialFragmentID")) .switchOn(GlslExpr.variable("flw_materialFragmentID"))
.build(sources); .build(sources);
this.uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms")) this.uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms"))
.sources(ComponentRegistry.getAllUniformProviders() .sources(ShaderUniforms.REGISTRY.getAll()
.stream() .stream()
.map(ShaderUniforms::uniformShader) .map(ShaderUniforms::uniformShader)
.toList()) .toList())
@ -102,12 +101,12 @@ public class FlwCompiler {
private void finish() { private void finish() {
long compileEnd = System.nanoTime(); long compileEnd = System.nanoTime();
int programCount = pipelineContexts.size() + ComponentRegistry.structTypes.size(); int programCount = pipelineContexts.size() + StructType.REGISTRY.getAll().size();
int shaderCount = shaderCompiler.shaderCount(); int shaderCount = shaderCompiler.shaderCount();
int errorCount = errors.size(); int errorCount = errors.size();
var elapsed = StringUtil.formatTime(compileEnd - compileStart); var elapsed = StringUtil.formatTime(compileEnd - compileStart);
Backend.LOGGER.info("Compiled " + programCount + " programs and " + shaderCount + " shaders in " + elapsed + " with " + errorCount + " errors."); Flywheel.LOGGER.info("Compiled " + programCount + " programs and " + shaderCount + " shaders in " + elapsed + " with " + errorCount + " errors.");
if (errorCount > 0) { if (errorCount > 0) {
var details = errors.stream() var details = errors.stream()

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.backend.compile;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.pipeline.SourceComponent; import com.jozufozu.flywheel.glsl.SourceComponent;
/** /**
* A component of a ShaderCompiler, responsible for expanding root sources into the complete set of included sources. * A component of a ShaderCompiler, responsible for expanding root sources into the complete set of included sources.

View file

@ -11,8 +11,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.generate.FnSignature; import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock; import com.jozufozu.flywheel.glsl.generate.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder; import com.jozufozu.flywheel.glsl.generate.GlslBuilder;

View file

@ -1,23 +1,31 @@
package com.jozufozu.flywheel.backend.compile; package com.jozufozu.flywheel.backend.compile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import com.jozufozu.flywheel.api.component.ComponentRegistry; import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.lib.backend.BackendTypes;
import com.jozufozu.flywheel.lib.context.Contexts; import com.jozufozu.flywheel.lib.context.Contexts;
public class PipelineContextSet { public class PipelineContextSet {
private final List<PipelineContext> contexts = new ArrayList<>();
private final List<PipelineContext> contextView = Collections.unmodifiableList(contexts);
PipelineContextSet() {
}
static PipelineContextSet create() { static PipelineContextSet create() {
var builder = new PipelineContextSet(); var builder = new PipelineContextSet();
for (Pipeline pipelineShader : BackendTypes.availablePipelineShaders()) { for (Pipeline pipelineShader : availablePipelineShaders()) {
for (StructType<?> structType : ComponentRegistry.structTypes) { for (StructType<?> structType : StructType.REGISTRY.getAll()) {
for (VertexType vertexType : ComponentRegistry.vertexTypes) { for (VertexType vertexType : VertexType.REGISTRY.getAll()) {
builder.add(vertexType, structType, Contexts.WORLD, pipelineShader); builder.add(vertexType, structType, Contexts.WORLD, pipelineShader);
} }
} }
@ -25,10 +33,13 @@ public class PipelineContextSet {
return builder; return builder;
} }
private final List<PipelineContext> contexts = new ArrayList<>(); private static Collection<Pipeline> availablePipelineShaders() {
private final List<PipelineContext> contextView = Collections.unmodifiableList(contexts); return Backend.REGISTRY.getAll()
.stream()
PipelineContextSet() { .filter(Backend::isSupported)
.map(Backend::pipelineShader)
.filter(Objects::nonNull)
.collect(Collectors.toList());
} }
public List<PipelineContext> all() { public List<PipelineContext> all() {
@ -42,7 +53,6 @@ public class PipelineContextSet {
private void add(VertexType vertexType, StructType<?> structType, Context world, Pipeline pipelineShader) { private void add(VertexType vertexType, StructType<?> structType, Context world, Pipeline pipelineShader) {
var ctx = new PipelineContext(vertexType, structType, world, pipelineShader); var ctx = new PipelineContext(vertexType, structType, world, pipelineShader);
contexts.add(ctx); contexts.add(ctx);
} }
} }

View file

@ -5,7 +5,7 @@ import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.pipeline.SourceComponent; import com.jozufozu.flywheel.glsl.SourceComponent;
public class RecursiveIncluder implements Includer { public class RecursiveIncluder implements Includer {

View file

@ -9,10 +9,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlShader; import com.jozufozu.flywheel.gl.shader.GlShader;
import com.jozufozu.flywheel.gl.shader.ShaderType; import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.FlwUtil;
public class ShaderCompiler { public class ShaderCompiler {

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.backend.compile;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import com.jozufozu.flywheel.api.pipeline.SourceComponent; import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.util.ResourceUtil; import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;

View file

@ -5,8 +5,8 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile; import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder; import com.jozufozu.flywheel.glsl.generate.GlslBuilder;

View file

@ -25,7 +25,7 @@ public class BatchingEngine implements Engine {
protected final BatchingDrawTracker drawTracker = new BatchingDrawTracker(); protected final BatchingDrawTracker drawTracker = new BatchingDrawTracker();
@Override @Override
public <D extends InstancedPart> Instancer<D> instancer(StructType<D> type, Model model, RenderStage stage) { public <D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model, RenderStage stage) {
return transformManager.getInstancer(type, model, stage); return transformManager.getInstancer(type, model, stage);
} }

View file

@ -5,16 +5,16 @@ import java.util.List;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.layout.LayoutItem;
import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile; import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.glsl.generate.FnSignature; import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock; import com.jozufozu.flywheel.glsl.generate.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder; import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.layout.LayoutItem;
import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;

View file

@ -16,6 +16,7 @@ import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.compile.FlwCompiler; import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.uniform.UniformBuffer;
import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.lib.context.Contexts; import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.pipeline.Pipelines;
@ -112,7 +113,7 @@ public class IndirectCullingGroup<T extends InstancedPart> {
uploadInstanceData(); uploadInstanceData();
uploadIndirectCommands(); uploadIndirectCommands();
compute.bind(); UniformBuffer.syncAndBind(compute);
buffers.bindForCompute(); buffers.bindForCompute();
var groupCount = (instanceCountThisFrame + 31) >> 5; // ceil(instanceCount / 32) var groupCount = (instanceCountThisFrame + 31) >> 5; // ceil(instanceCount / 32)
@ -125,7 +126,7 @@ public class IndirectCullingGroup<T extends InstancedPart> {
return; return;
} }
draw.bind(); UniformBuffer.syncAndBind(draw);
glBindVertexArray(vertexArray); glBindVertexArray(vertexArray);
buffers.bindForDraw(); buffers.bindForDraw();

View file

@ -2,10 +2,10 @@ package com.jozufozu.flywheel.backend.engine.indirect;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
public final class IndirectDraw<T extends InstancedPart> { public final class IndirectDraw<T extends InstancedPart> {
private final IndirectInstancer<T> instancer; private final IndirectInstancer<T> instancer;
@ -25,8 +25,8 @@ public final class IndirectDraw<T extends InstancedPart> {
this.stage = stage; this.stage = stage;
this.mesh = mesh; this.mesh = mesh;
this.vertexMaterialID = ComponentRegistry.materials.getVertexID(material); this.vertexMaterialID = MaterialIndicies.getVertexShaderIndex(material.vertexShader());
this.fragmentMaterialID = ComponentRegistry.materials.getFragmentID(material); this.fragmentMaterialID = MaterialIndicies.getFragmentShaderIndex(material.fragmentShader());
} }
public void prepare(int baseInstance) { public void prepare(int baseInstance) {

View file

@ -10,10 +10,10 @@ import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
import com.jozufozu.flywheel.util.Textures; import com.jozufozu.flywheel.util.Textures;
public class IndirectDrawSet<T extends InstancedPart> { public class IndirectDrawSet<T extends InstancedPart> {
@ -50,7 +50,7 @@ public class IndirectDrawSet<T extends InstancedPart> {
multiDraws.clear(); multiDraws.clear();
// sort by stage, then material // sort by stage, then material
indirectDraws.sort(Comparator.comparing(IndirectDraw<T>::stage) indirectDraws.sort(Comparator.comparing(IndirectDraw<T>::stage)
.thenComparing(draw -> ComponentRegistry.materials.getMaterialID(draw.material()))); .thenComparing(draw -> MaterialIndicies.getMaterialIndex(draw.material())));
for (int start = 0, i = 0; i < indirectDraws.size(); i++) { for (int start = 0, i = 0; i < indirectDraws.size(); i++) {
var draw = indirectDraws.get(i); var draw = indirectDraws.get(i);

View file

@ -48,7 +48,7 @@ public class IndirectEngine implements Engine {
} }
@Override @Override
public <D extends InstancedPart> Instancer<D> instancer(StructType<D> type, Model model, RenderStage stage) { public <D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model, RenderStage stage) {
return drawManager.getInstancer(type, model, stage); return drawManager.getInstancer(type, model, stage);
} }

View file

@ -5,13 +5,13 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.layout.LayoutItem;
import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.pipeline.SourceComponent; import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.generate.FnSignature; import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock; import com.jozufozu.flywheel.glsl.generate.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder; import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.layout.LayoutItem;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;

View file

@ -15,6 +15,7 @@ import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.gl.GlPrimitive; import com.jozufozu.flywheel.gl.GlPrimitive;
import com.jozufozu.flywheel.gl.array.GlVertexArray; import com.jozufozu.flywheel.gl.array.GlVertexArray;
import com.jozufozu.flywheel.gl.buffer.ElementBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBuffer; import com.jozufozu.flywheel.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferType; import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.gl.buffer.MappedBuffer; import com.jozufozu.flywheel.gl.buffer.MappedBuffer;
@ -234,9 +235,9 @@ public class InstancedMeshPool {
private void draw(int instanceCount) { private void draw(int instanceCount) {
if (instanceCount > 1) { if (instanceCount > 1) {
GL32.glDrawElementsInstanced(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0, instanceCount); GL32.glDrawElementsInstanced(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, instanceCount);
} else { } else {
GL32.glDrawElements(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0); GL32.glDrawElements(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0);
} }
} }

View file

@ -7,7 +7,6 @@ import java.util.Set;
import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
@ -18,8 +17,10 @@ import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.backend.compile.FlwCompiler; import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.uniform.UniformBuffer;
import com.jozufozu.flywheel.gl.GlStateTracker; import com.jozufozu.flywheel.gl.GlStateTracker;
import com.jozufozu.flywheel.gl.GlTextureUnit; import com.jozufozu.flywheel.gl.GlTextureUnit;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.FlwUtil;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
@ -51,7 +52,7 @@ public class InstancingEngine implements Engine {
} }
@Override @Override
public <D extends InstancedPart> Instancer<D> instancer(StructType<D> type, Model model, RenderStage stage) { public <D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model, RenderStage stage) {
return drawManager.getInstancer(type, model, stage); return drawManager.getInstancer(type, model, stage);
} }
@ -117,11 +118,11 @@ public class InstancingEngine implements Engine {
var material = desc.material(); var material = desc.material();
var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, context, Pipelines.INSTANCED_ARRAYS); var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, context, Pipelines.INSTANCED_ARRAYS);
program.bind(); UniformBuffer.syncAndBind(program);
var uniformLocation = program.getUniformLocation("_flw_materialID_instancing"); var uniformLocation = program.getUniformLocation("_flw_materialID_instancing");
var vertexID = ComponentRegistry.materials.getVertexID(material); var vertexID = MaterialIndicies.getVertexShaderIndex(material.vertexShader());
var fragmentID = ComponentRegistry.materials.getFragmentID(material); var fragmentID = MaterialIndicies.getFragmentShaderIndex(material.fragmentShader());
GL32.glUniform2ui(uniformLocation, vertexID, fragmentID); GL32.glUniform2ui(uniformLocation, vertexID, fragmentID);
} }

View file

@ -7,7 +7,7 @@ import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.FlatLit; import com.jozufozu.flywheel.api.instancer.FlatLit;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
import com.jozufozu.flywheel.lib.light.LightListener; import com.jozufozu.flywheel.lib.light.LightListener;
@ -22,11 +22,11 @@ import net.minecraft.world.level.LightLayer;
*/ */
public abstract class AbstractInstance implements Instance, LightListener { public abstract class AbstractInstance implements Instance, LightListener {
protected final InstancerManager instancerManager; protected final InstancerProvider instancerManager;
public final Level level; public final Level level;
protected boolean removed = false; protected boolean removed = false;
public AbstractInstance(InstancerManager instancerManager, Level level) { public AbstractInstance(InstancerProvider instancerManager, Level level) {
this.instancerManager = instancerManager; this.instancerManager = instancerManager;
this.level = level; this.level = level;
} }

View file

@ -9,11 +9,11 @@ import java.util.function.Consumer;
import org.joml.FrustumIntersection; import org.joml.FrustumIntersection;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.ratelimit.BandedPrimeLimiter; import com.jozufozu.flywheel.backend.instancing.ratelimit.BandedPrimeLimiter;
import com.jozufozu.flywheel.backend.instancing.ratelimit.DistanceUpdateLimiter; import com.jozufozu.flywheel.backend.instancing.ratelimit.DistanceUpdateLimiter;
import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter; import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter;
@ -164,7 +164,7 @@ public abstract class InstanceManager<T> {
} }
public void add(T obj) { public void add(T obj) {
if (!Backend.isOn()) return; if (!BackendManager.isOn()) return;
if (canCreateInstance(obj)) { if (canCreateInstance(obj)) {
getStorage().add(obj); getStorage().add(obj);
@ -172,7 +172,7 @@ public abstract class InstanceManager<T> {
} }
public void queueAdd(T obj) { public void queueAdd(T obj) {
if (!Backend.isOn()) { if (!BackendManager.isOn()) {
return; return;
} }
@ -186,7 +186,7 @@ public abstract class InstanceManager<T> {
} }
public void queueUpdate(T obj) { public void queueUpdate(T obj) {
if (!Backend.isOn()) return; if (!BackendManager.isOn()) return;
if (!canCreateInstance(obj)) { if (!canCreateInstance(obj)) {
return; return;
@ -209,7 +209,7 @@ public abstract class InstanceManager<T> {
* @param obj the object to update. * @param obj the object to update.
*/ */
public void update(T obj) { public void update(T obj) {
if (!Backend.isOn()) return; if (!BackendManager.isOn()) return;
if (canCreateInstance(obj)) { if (canCreateInstance(obj)) {
getStorage().update(obj); getStorage().update(obj);
@ -217,7 +217,7 @@ public abstract class InstanceManager<T> {
} }
public void remove(T obj) { public void remove(T obj) {
if (!Backend.isOn()) return; if (!BackendManager.isOn()) return;
getStorage().remove(obj); getStorage().remove(obj);
} }
@ -267,7 +267,7 @@ public abstract class InstanceManager<T> {
} }
public void queueAddAll(Collection<? extends T> objects) { public void queueAddAll(Collection<? extends T> objects) {
if (!Backend.isOn() || objects.isEmpty()) { if (!BackendManager.isOn() || objects.isEmpty()) {
return; return;
} }

View file

@ -1,12 +1,13 @@
package com.jozufozu.flywheel.backend.instancing; package com.jozufozu.flywheel.backend.instancing;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.event.BeginFrameEvent; import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
import com.jozufozu.flywheel.backend.instancing.effect.Effect; import com.jozufozu.flywheel.backend.instancing.effect.Effect;
import com.jozufozu.flywheel.backend.instancing.effect.EffectInstanceManager; import com.jozufozu.flywheel.backend.instancing.effect.EffectInstanceManager;
@ -35,7 +36,7 @@ public class InstanceWorld implements AutoCloseable {
private final InstanceManager<Effect> effects; private final InstanceManager<Effect> effects;
public static InstanceWorld create(LevelAccessor level) { public static InstanceWorld create(LevelAccessor level) {
var engine = Backend.getBackendType() var engine = BackendManager.getBackend()
.createEngine(); .createEngine();
var entities = new EntityInstanceManager(engine); var entities = new EntityInstanceManager(engine);
@ -53,7 +54,7 @@ public class InstanceWorld implements AutoCloseable {
this.entities = entities; this.entities = entities;
this.blockEntities = blockEntities; this.blockEntities = blockEntities;
this.effects = effects; this.effects = effects;
this.taskExecutor = Backend.getTaskExecutor(); this.taskExecutor = BackendUtil.getTaskExecutor();
} }
public InstanceManager<Entity> getEntities() { public InstanceManager<Entity> getEntities() {

View file

@ -2,10 +2,11 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.api.event.BeginFrameEvent; import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.api.event.RenderStageEvent; import com.jozufozu.flywheel.api.event.RenderStageEvent;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.instancing.effect.Effect; import com.jozufozu.flywheel.backend.instancing.effect.Effect;
import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
@ -29,7 +30,7 @@ public class InstancedRenderDispatcher {
* @param blockEntity The block entity whose instance you want to update. * @param blockEntity The block entity whose instance you want to update.
*/ */
public static void enqueueUpdate(BlockEntity blockEntity) { public static void enqueueUpdate(BlockEntity blockEntity) {
if (Backend.isOn() && blockEntity.hasLevel() && blockEntity.getLevel() instanceof ClientLevel) { if (BackendManager.isOn() && blockEntity.hasLevel() && blockEntity.getLevel() instanceof ClientLevel) {
instanceWorlds.get(blockEntity.getLevel()) instanceWorlds.get(blockEntity.getLevel())
.getBlockEntities() .getBlockEntities()
.queueUpdate(blockEntity); .queueUpdate(blockEntity);
@ -41,7 +42,7 @@ public class InstancedRenderDispatcher {
* @param entity The entity whose instance you want to update. * @param entity The entity whose instance you want to update.
*/ */
public static void enqueueUpdate(Entity entity) { public static void enqueueUpdate(Entity entity) {
if (Backend.isOn()) { if (BackendManager.isOn()) {
instanceWorlds.get(entity.level) instanceWorlds.get(entity.level)
.getEntities() .getEntities()
.queueUpdate(entity); .queueUpdate(entity);
@ -65,7 +66,7 @@ public class InstancedRenderDispatcher {
* @throws NullPointerException if the backend is off * @throws NullPointerException if the backend is off
*/ */
public static InstanceWorld getInstanceWorld(LevelAccessor world) { public static InstanceWorld getInstanceWorld(LevelAccessor world) {
if (Backend.isOn()) { if (BackendManager.isOn()) {
return instanceWorlds.get(world); return instanceWorlds.get(world);
} else { } else {
throw new NullPointerException("Backend is off, cannot retrieve instance world."); throw new NullPointerException("Backend is off, cannot retrieve instance world.");
@ -73,21 +74,21 @@ public class InstancedRenderDispatcher {
} }
public static void tick(TickEvent.ClientTickEvent event) { public static void tick(TickEvent.ClientTickEvent event) {
if (!Backend.isGameActive() || event.phase == TickEvent.Phase.START) { if (!BackendUtil.isGameActive() || event.phase == TickEvent.Phase.START) {
return; return;
} }
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
ClientLevel level = mc.level; ClientLevel level = mc.level;
AnimationTickHolder.tick(); AnimationTickHolder.tick();
if (Backend.isOn()) { if (BackendManager.isOn()) {
instanceWorlds.get(level) instanceWorlds.get(level)
.tick(); .tick();
} }
} }
public static void onBeginFrame(BeginFrameEvent event) { public static void onBeginFrame(BeginFrameEvent event) {
if (Backend.isGameActive() && Backend.isOn()) { if (BackendUtil.isGameActive() && BackendManager.isOn()) {
instanceWorlds.get(event.getContext().level()) instanceWorlds.get(event.getContext().level())
.beginFrame(event); .beginFrame(event);
} }
@ -95,14 +96,14 @@ public class InstancedRenderDispatcher {
public static void onRenderStage(RenderStageEvent event) { public static void onRenderStage(RenderStageEvent event) {
ClientLevel level = event.getContext().level(); ClientLevel level = event.getContext().level();
if (!Backend.canUseInstancing(level)) return; if (!BackendUtil.canUseInstancing(level)) return;
instanceWorlds.get(level).renderStage(event.getContext(), event.getStage()); instanceWorlds.get(level).renderStage(event.getContext(), event.getStage());
} }
public static void onReloadRenderers(ReloadRenderersEvent event) { public static void onReloadRenderers(ReloadRenderersEvent event) {
ClientLevel level = event.getLevel(); ClientLevel level = event.getLevel();
if (Backend.isOn() && level != null) { if (BackendManager.isOn() && level != null) {
resetInstanceLevel(level); resetInstanceLevel(level);
} }
} }
@ -113,7 +114,7 @@ public class InstancedRenderDispatcher {
} }
public static void getDebugString(List<String> debug) { public static void getDebugString(List<String> debug) {
if (Backend.isOn()) { if (BackendManager.isOn()) {
InstanceWorld instanceWorld = instanceWorlds.get(Minecraft.getInstance().level); InstanceWorld instanceWorld = instanceWorlds.get(Minecraft.getInstance().level);
debug.add("Update limiting: " + FlwCommands.boolToText(FlwConfig.get().limitUpdates()).getString()); debug.add("Update limiting: " + FlwCommands.boolToText(FlwConfig.get().limitUpdates()).getString());

View file

@ -8,7 +8,7 @@ import org.joml.FrustumIntersection;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.lib.box.ImmutableBox; import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.box.MutableBox; import com.jozufozu.flywheel.lib.box.MutableBox;
@ -41,7 +41,7 @@ public abstract class BlockEntityInstance<T extends BlockEntity> extends Abstrac
protected final BlockPos instancePos; protected final BlockPos instancePos;
protected final BlockState blockState; protected final BlockState blockState;
public BlockEntityInstance(InstancerManager instancerManager, T blockEntity) { public BlockEntityInstance(InstancerProvider instancerManager, T blockEntity) {
super(instancerManager, blockEntity.getLevel()); super(instancerManager, blockEntity.getLevel());
this.blockEntity = blockEntity; this.blockEntity = blockEntity;
this.pos = blockEntity.getBlockPos(); this.pos = blockEntity.getBlockPos();

View file

@ -2,11 +2,11 @@ package com.jozufozu.flywheel.backend.instancing.blockentity;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage; import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
import com.jozufozu.flywheel.backend.instancing.storage.Storage; import com.jozufozu.flywheel.backend.instancing.storage.Storage;
@ -21,7 +21,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
private final BlockEntityStorage storage; private final BlockEntityStorage storage;
public BlockEntityInstanceManager(InstancerManager instancerManager) { public BlockEntityInstanceManager(InstancerProvider instancerManager) {
storage = new BlockEntityStorage(instancerManager); storage = new BlockEntityStorage(instancerManager);
} }
@ -57,7 +57,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
return false; return false;
} }
if (Backend.isFlywheelLevel(level)) { if (BackendUtil.isFlywheelLevel(level)) {
BlockPos pos = blockEntity.getBlockPos(); BlockPos pos = blockEntity.getBlockPos();
BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4);
@ -73,7 +73,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
final Long2ObjectMap<BlockEntityInstance<?>> posLookup = new Long2ObjectOpenHashMap<>(); final Long2ObjectMap<BlockEntityInstance<?>> posLookup = new Long2ObjectOpenHashMap<>();
public BlockEntityStorage(InstancerManager manager) { public BlockEntityStorage(InstancerProvider manager) {
super(manager); super(manager);
} }

View file

@ -1,28 +0,0 @@
package com.jozufozu.flywheel.backend.instancing.blockentity;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import net.minecraft.world.level.block.entity.BlockEntity;
public class SimpleBlockEntityInstancingController<T extends BlockEntity> implements BlockEntityInstancingController<T> {
protected BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public SimpleBlockEntityInstancingController(BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) {
this.instanceFactory = instanceFactory;
this.skipRender = skipRender;
}
@Override
public BlockEntityInstance<? super T> createInstance(InstancerManager instancerManager, T blockEntity) {
return instanceFactory.apply(instancerManager, blockEntity);
}
@Override
public boolean shouldSkipRender(T blockEntity) {
return skipRender.test(blockEntity);
}
}

View file

@ -2,10 +2,10 @@ package com.jozufozu.flywheel.backend.instancing.effect;
import java.util.Collection; import java.util.Collection;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
public interface Effect { public interface Effect {
Collection<AbstractInstance> createInstances(InstancerManager instancerManager); Collection<AbstractInstance> createInstances(InstancerProvider instancerManager);
} }

View file

@ -4,7 +4,7 @@ import java.util.ArrayList;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.storage.AbstractStorage; import com.jozufozu.flywheel.backend.instancing.storage.AbstractStorage;
@ -15,7 +15,7 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
private final EffectStorage<Effect> storage; private final EffectStorage<Effect> storage;
public EffectInstanceManager(InstancerManager instancerManager) { public EffectInstanceManager(InstancerProvider instancerManager) {
storage = new EffectStorage<>(instancerManager); storage = new EffectStorage<>(instancerManager);
} }
@ -33,7 +33,7 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
private final Multimap<T, AbstractInstance> instances; private final Multimap<T, AbstractInstance> instances;
public EffectStorage(InstancerManager manager) { public EffectStorage(InstancerProvider manager) {
super(manager); super(manager);
this.instances = HashMultimap.create(); this.instances = HashMultimap.create();
} }

View file

@ -4,7 +4,7 @@ import org.joml.FrustumIntersection;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
import com.jozufozu.flywheel.lib.box.MutableBox; import com.jozufozu.flywheel.lib.box.MutableBox;
@ -40,7 +40,7 @@ public abstract class EntityInstance<E extends Entity> extends AbstractInstance
protected final E entity; protected final E entity;
protected final MutableBox bounds; protected final MutableBox bounds;
public EntityInstance(InstancerManager instancerManager, E entity) { public EntityInstance(InstancerProvider instancerManager, E entity) {
super(instancerManager, entity.level); super(instancerManager, entity.level);
this.entity = entity; this.entity = entity;
bounds = MutableBox.from(entity.getBoundingBox()); bounds = MutableBox.from(entity.getBoundingBox());

View file

@ -2,11 +2,11 @@ package com.jozufozu.flywheel.backend.instancing.entity;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage; import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -16,7 +16,7 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
private final One2OneStorage<Entity> storage; private final One2OneStorage<Entity> storage;
public EntityInstanceManager(InstancerManager instancerManager) { public EntityInstanceManager(InstancerProvider instancerManager) {
storage = new One2OneStorage<>(instancerManager) { storage = new One2OneStorage<>(instancerManager) {
@Override @Override
protected @Nullable AbstractInstance createRaw(Entity obj) { protected @Nullable AbstractInstance createRaw(Entity obj) {
@ -42,6 +42,6 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
Level level = entity.level; Level level = entity.level;
return Backend.isFlywheelLevel(level); return BackendUtil.isFlywheelLevel(level);
} }
} }

View file

@ -1,28 +0,0 @@
package com.jozufozu.flywheel.backend.instancing.entity;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import net.minecraft.world.entity.Entity;
public class SimpleEntityInstancingController<T extends Entity> implements EntityInstancingController<T> {
protected BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public SimpleEntityInstancingController(BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) {
this.instanceFactory = instanceFactory;
this.skipRender = skipRender;
}
@Override
public EntityInstance<? super T> createInstance(InstancerManager instancerManager, T entity) {
return instanceFactory.apply(instancerManager, entity);
}
@Override
public boolean shouldSkipRender(T entity) {
return skipRender.test(entity);
}
}

View file

@ -5,16 +5,16 @@ import java.util.List;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.lib.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
public abstract class AbstractStorage<T> implements Storage<T> { public abstract class AbstractStorage<T> implements Storage<T> {
protected final List<TickableInstance> tickableInstances; protected final List<TickableInstance> tickableInstances;
protected final List<DynamicInstance> dynamicInstances; protected final List<DynamicInstance> dynamicInstances;
protected final InstancerManager instancerManager; protected final InstancerProvider instancerManager;
protected AbstractStorage(InstancerManager instancerManager) { protected AbstractStorage(InstancerProvider instancerManager) {
this.instancerManager = instancerManager; this.instancerManager = instancerManager;
this.dynamicInstances = new ArrayList<>(); this.dynamicInstances = new ArrayList<>();

View file

@ -5,14 +5,14 @@ import java.util.Map;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.lib.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
public abstract class One2OneStorage<T> extends AbstractStorage<T> { public abstract class One2OneStorage<T> extends AbstractStorage<T> {
private final Map<T, AbstractInstance> instances; private final Map<T, AbstractInstance> instances;
public One2OneStorage(InstancerManager instancerManager) { public One2OneStorage(InstancerProvider instancerManager) {
super(instancerManager); super(instancerManager);
this.instances = new HashMap<>(); this.instances = new HashMap<>();
} }

View file

@ -1,15 +1,15 @@
package com.jozufozu.flywheel.backend.uniform; package com.jozufozu.flywheel.backend.uniform;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set;
import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL32;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.gl.buffer.GlBuffer; import com.jozufozu.flywheel.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferType; import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.RenderMath; import com.jozufozu.flywheel.util.RenderMath;
@ -35,7 +35,12 @@ public class UniformBuffer {
private UniformBuffer() { private UniformBuffer() {
buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER); buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER);
providerSet = new ProviderSet(ComponentRegistry.getAllUniformProviders()); providerSet = new ProviderSet(ShaderUniforms.REGISTRY.getAll());
}
public static void syncAndBind(GlProgram program) {
getInstance().sync();
program.bind();
} }
public void sync() { public void sync() {
@ -84,7 +89,7 @@ public class UniformBuffer {
private final MemoryBlock data; private final MemoryBlock data;
private ProviderSet(final Collection<ShaderUniforms> providers) { private ProviderSet(final Set<ShaderUniforms> providers) {
var builder = ImmutableList.<LiveProvider>builder(); var builder = ImmutableList.<LiveProvider>builder();
int totalBytes = 0; int totalBytes = 0;
for (ShaderUniforms provider : providers) { for (ShaderUniforms provider : providers) {

View file

@ -1,10 +1,10 @@
package com.jozufozu.flywheel.config; package com.jozufozu.flywheel.config;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import com.jozufozu.flywheel.api.backend.BackendType; import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.lib.backend.BackendTypes;
import com.mojang.brigadier.StringReader; import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
@ -15,38 +15,41 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
public enum BackendTypeArgument implements ArgumentType<BackendType> { public enum BackendArgument implements ArgumentType<Backend> {
INSTANCE; INSTANCE;
private static final List<String> STRING_IDS = Backend.REGISTRY.getAllIds().stream().map(ResourceLocation::toString).toList();
private static final Dynamic2CommandExceptionType INVALID = new Dynamic2CommandExceptionType((found, constants) -> { private static final Dynamic2CommandExceptionType INVALID = new Dynamic2CommandExceptionType((found, constants) -> {
// TODO: don't steal lang // TODO: don't steal lang
return new TranslatableComponent("commands.forge.arguments.enum.invalid", constants, found); return new TranslatableComponent("commands.forge.arguments.enum.invalid", constants, found);
}); });
public static BackendArgument getInstance() {
return INSTANCE;
}
@Override @Override
public BackendType parse(StringReader reader) throws CommandSyntaxException { public Backend parse(StringReader reader) throws CommandSyntaxException {
String string = reader.readUnquotedString(); ResourceLocation id = ResourceLocation.read(reader);
Backend backend = Backend.REGISTRY.get(id);
BackendType engine = BackendTypes.getBackendType(string); if (backend == null) {
throw INVALID.createWithContext(reader, id.toString(), STRING_IDS);
if (engine == null) {
throw INVALID.createWithContext(reader, string, BackendTypes.validNames());
} }
return engine; return backend;
} }
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) { public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return SharedSuggestionProvider.suggest(BackendTypes.validNames(), builder); return SharedSuggestionProvider.suggest(STRING_IDS, builder);
} }
@Override @Override
public Collection<String> getExamples() { public Collection<String> getExamples() {
return BackendTypes.validNames(); return STRING_IDS;
}
public static BackendTypeArgument getInstance() {
return INSTANCE;
} }
} }

View file

@ -2,12 +2,8 @@ package com.jozufozu.flywheel.config;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import org.jetbrains.annotations.NotNull; import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.api.backend.BackendType;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.lib.backend.BackendTypes;
import com.jozufozu.flywheel.lib.backend.SimpleBackendType;
import com.jozufozu.flywheel.lib.uniform.FlwShaderUniforms; import com.jozufozu.flywheel.lib.uniform.FlwShaderUniforms;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
@ -15,6 +11,7 @@ import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.ResourceLocationException;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
@ -24,6 +21,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraftforge.client.event.RegisterClientCommandsEvent; import net.minecraftforge.client.event.RegisterClientCommandsEvent;
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue; import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
@ -39,22 +37,38 @@ public class FlwCommands {
.executes(context -> { .executes(context -> {
LocalPlayer player = Minecraft.getInstance().player; LocalPlayer player = Minecraft.getInstance().player;
if (player != null) { if (player != null) {
player.displayClientMessage(BackendTypes.getBackendType(value.get()) String backendIdStr = value.get();
.getEngineMessage(), false);
ResourceLocation backendId;
try {
backendId = new ResourceLocation(backendIdStr);
} catch (ResourceLocationException e) {
player.displayClientMessage(new TextComponent("Config contains invalid backend ID '" + backendIdStr + "'!"), false);
return 0;
}
Backend backend = Backend.REGISTRY.get(backendId);
if (backend == null) {
player.displayClientMessage(new TextComponent("Config contains non-existent backend with ID '" + backendId + "'!"), false);
return 0;
}
Component message = backend.getEngineMessage();
player.displayClientMessage(message, false);
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
}) })
.then(Commands.argument("type", BackendTypeArgument.INSTANCE) .then(Commands.argument("id", BackendArgument.INSTANCE)
.executes(context -> { .executes(context -> {
LocalPlayer player = Minecraft.getInstance().player; LocalPlayer player = Minecraft.getInstance().player;
if (player != null) { if (player != null) {
BackendType type = context.getArgument("type", SimpleBackendType.class); Backend backend = context.getArgument("id", Backend.class);
value.set(type.getShortName()); value.set(Backend.REGISTRY.getId(backend).toString());
Component message = getEngineMessage(type); Component message = backend.getEngineMessage();
player.displayClientMessage(message, false); player.displayClientMessage(message, false);
Backend.reloadWorldRenderers(); BackendUtil.reloadWorldRenderers();
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
}))); })));
@ -74,7 +88,7 @@ public class FlwCommands {
Component text = boolToText(bool).append(new TextComponent(" update limiting.").withStyle(ChatFormatting.WHITE)); Component text = boolToText(bool).append(new TextComponent(" update limiting.").withStyle(ChatFormatting.WHITE));
player.displayClientMessage(text, false); player.displayClientMessage(text, false);
Backend.reloadWorldRenderers(); BackendUtil.reloadWorldRenderers();
} }
)); ));
@ -152,10 +166,6 @@ public class FlwCommands {
return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN) : new TextComponent("disabled").withStyle(ChatFormatting.RED); return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN) : new TextComponent("disabled").withStyle(ChatFormatting.RED);
} }
public static Component getEngineMessage(@NotNull BackendType type) {
return type.getEngineMessage();
}
public static class ConfigCommandBuilder { public static class ConfigCommandBuilder {
protected LiteralArgumentBuilder<CommandSourceStack> command; protected LiteralArgumentBuilder<CommandSourceStack> command;

View file

@ -2,54 +2,82 @@ package com.jozufozu.flywheel.config;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import com.jozufozu.flywheel.api.backend.BackendType; import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.lib.backend.BackendTypes; import com.jozufozu.flywheel.api.backend.BackendManager;
import com.mojang.logging.LogUtils;
import net.minecraft.ResourceLocationException;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.common.ForgeConfigSpec.BooleanValue; import net.minecraftforge.common.ForgeConfigSpec.BooleanValue;
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.config.ModConfig;
public class FlwConfig { public class FlwConfig {
private static final Logger LOGGER = LogUtils.getLogger();
private static final FlwConfig INSTANCE = new FlwConfig(); private static final FlwConfig INSTANCE = new FlwConfig();
public final ClientConfig client; public final ClientConfig client;
private final ForgeConfigSpec clientSpec;
public FlwConfig() { public FlwConfig() {
Pair<ClientConfig, ForgeConfigSpec> client = new ForgeConfigSpec.Builder().configure(ClientConfig::new); Pair<ClientConfig, ForgeConfigSpec> client = new ForgeConfigSpec.Builder().configure(ClientConfig::new);
this.client = client.getLeft(); this.client = client.getLeft();
clientSpec = client.getRight();
ModLoadingContext.get()
.registerConfig(ModConfig.Type.CLIENT, client.getRight());
} }
public static FlwConfig get() { public static FlwConfig get() {
return INSTANCE; return INSTANCE;
} }
public Backend getBackend() {
Backend backend = parseBackend(client.backend.get());
if (backend == null) {
backend = BackendManager.getDefaultBackend();
client.backend.set(Backend.REGISTRY.getId(backend).toString());
}
return backend;
}
@Nullable @Nullable
public BackendType getBackendType() { private static Backend parseBackend(String idStr) {
return BackendTypes.getBackendType(client.backend.get()); ResourceLocation backendId;
try {
backendId = new ResourceLocation(idStr);
} catch (ResourceLocationException e) {
LOGGER.warn("Config contains invalid backend ID '" + idStr + "'!");
return null;
}
Backend backend = Backend.REGISTRY.get(backendId);
if (backend == null) {
LOGGER.warn("Config contains non-existent backend with ID '" + backendId + "'!");
return null;
}
return backend;
} }
public boolean limitUpdates() { public boolean limitUpdates() {
return client.limitUpdates.get(); return client.limitUpdates.get();
} }
public static void init() { public void registerSpecs(ModLoadingContext context) {
context.registerConfig(ModConfig.Type.CLIENT, clientSpec);
} }
public static class ClientConfig { public static class ClientConfig {
public final ForgeConfigSpec.ConfigValue<String> backend; public final ConfigValue<String> backend;
public final BooleanValue limitUpdates; public final BooleanValue limitUpdates;
public ClientConfig(ForgeConfigSpec.Builder builder) { public ClientConfig(ForgeConfigSpec.Builder builder) {
backend = builder.comment("Select the backend to use.") backend = builder.comment("Select the backend to use.")
.define("backend", BackendTypes.defaultForCurrentPC() .define("backend", Backend.REGISTRY.getId(BackendManager.getDefaultBackend()).toString());
.getShortName());
limitUpdates = builder.comment("Enable or disable instance update limiting with distance.") limitUpdates = builder.comment("Enable or disable instance update limiting with distance.")
.define("limitUpdates", true); .define("limitUpdates", true);

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.extension;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstancingController; import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.extension;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstancingController; import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;

View file

@ -1,6 +1,5 @@
package com.jozufozu.flywheel.backend.engine.instancing; package com.jozufozu.flywheel.gl.buffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
public class ElementBuffer { public class ElementBuffer {

View file

@ -4,21 +4,20 @@ import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glGetUniformLocation; import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glUniform1i; import static org.lwjgl.opengl.GL20.glUniform1i;
import com.jozufozu.flywheel.backend.Backend; import org.slf4j.Logger;
import com.jozufozu.flywheel.backend.uniform.UniformBuffer;
import com.jozufozu.flywheel.gl.GlObject; import com.jozufozu.flywheel.gl.GlObject;
import com.mojang.blaze3d.shaders.ProgramManager; import com.mojang.blaze3d.shaders.ProgramManager;
import com.mojang.logging.LogUtils;
public class GlProgram extends GlObject { public class GlProgram extends GlObject {
private static final Logger LOGGER = LogUtils.getLogger();
public GlProgram(int handle) { public GlProgram(int handle) {
setHandle(handle); setHandle(handle);
} }
public void bind() { public void bind() {
// TODO: bind textures?
UniformBuffer.getInstance()
.sync();
ProgramManager.glUseProgram(handle()); ProgramManager.glUseProgram(handle());
} }
@ -36,7 +35,7 @@ public class GlProgram extends GlObject {
int index = glGetUniformLocation(this.handle(), uniform); int index = glGetUniformLocation(this.handle(), uniform);
if (index < 0) { if (index < 0) {
Backend.LOGGER.debug("No active uniform '{}' exists. Could be unused.", uniform); LOGGER.debug("No active uniform '{}' exists. Could be unused.", uniform);
} }
return index; return index;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.api.pipeline; package com.jozufozu.flywheel.glsl;
import java.util.Collection; import java.util.Collection;

View file

@ -9,7 +9,6 @@ import java.util.regex.Matcher;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.glsl.parse.Import; import com.jozufozu.flywheel.glsl.parse.Import;
import com.jozufozu.flywheel.glsl.parse.ShaderField; import com.jozufozu.flywheel.glsl.parse.ShaderField;
import com.jozufozu.flywheel.glsl.parse.ShaderFunction; import com.jozufozu.flywheel.glsl.parse.ShaderFunction;

View file

@ -4,14 +4,17 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.jozufozu.flywheel.Flywheel; import org.slf4j.Logger;
import com.jozufozu.flywheel.glsl.ShaderLoadingException; import com.jozufozu.flywheel.glsl.ShaderLoadingException;
import com.jozufozu.flywheel.glsl.SourceFile; import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.glsl.span.Span; import com.jozufozu.flywheel.glsl.span.Span;
import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.StringUtil; import com.jozufozu.flywheel.util.StringUtil;
import com.mojang.logging.LogUtils;
public class ErrorReporter { public class ErrorReporter {
private static final Logger LOGGER = LogUtils.getLogger();
private final List<ErrorBuilder> reportedErrors = new ArrayList<>(); private final List<ErrorBuilder> reportedErrors = new ArrayList<>();
@ -107,7 +110,7 @@ public class ErrorReporter {
.append('\n'); .append('\n');
} }
Flywheel.LOGGER.error(builder.toString()); LOGGER.error(builder.toString());
} }
} }

View file

@ -1,6 +0,0 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.glsl.error;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;

View file

@ -1,20 +1,19 @@
package com.jozufozu.flywheel.handler; package com.jozufozu.flywheel.handler;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.EntityLeaveWorldEvent; import net.minecraftforge.event.entity.EntityLeaveWorldEvent;
public class EntityWorldHandler { public class EntityWorldHandler {
public static void onEntityJoinWorld(EntityJoinWorldEvent event) { public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
if (event.getWorld().isClientSide && Backend.isOn()) InstancedRenderDispatcher.getEntities(event.getWorld()) if (event.getWorld().isClientSide && BackendManager.isOn()) InstancedRenderDispatcher.getEntities(event.getWorld())
.queueAdd(event.getEntity()); .queueAdd(event.getEntity());
} }
public static void onEntityLeaveWorld(EntityLeaveWorldEvent event) { public static void onEntityLeaveWorld(EntityLeaveWorldEvent event) {
if (event.getWorld().isClientSide && Backend.isOn()) InstancedRenderDispatcher.getEntities(event.getWorld()) if (event.getWorld().isClientSide && BackendManager.isOn()) InstancedRenderDispatcher.getEntities(event.getWorld())
.remove(event.getEntity()); .remove(event.getEntity());
} }
} }

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.handler;
import java.util.ArrayList; import java.util.ArrayList;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.lib.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker; import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
@ -34,7 +34,7 @@ public class ForgeEvents {
} }
public static void tickLight(TickEvent.ClientTickEvent event) { public static void tickLight(TickEvent.ClientTickEvent event) {
if (event.phase == TickEvent.Phase.END && Backend.isGameActive()) { if (event.phase == TickEvent.Phase.END && BackendUtil.isGameActive()) {
LightUpdater.get(Minecraft.getInstance().level) LightUpdater.get(Minecraft.getInstance().level)
.tick(); .tick();
} }

View file

@ -0,0 +1,56 @@
package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.lib.backend.Backends;
import com.mojang.logging.LogUtils;
public final class BackendManagerImpl {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Backend DEFAULT_BACKEND = findDefaultBackend();
private static Backend backend;
@Nullable
public static Backend getBackend() {
return backend;
}
public static String getBackendDescriptor() {
return backend == null ? "Uninitialized" : backend.getProperName();
}
public static boolean isOn() {
return backend != null && backend != Backends.OFF;
}
public static void refresh() {
backend = chooseBackend();
}
public static Backend getDefaultBackend() {
return DEFAULT_BACKEND;
}
private static Backend chooseBackend() {
var preferred = FlwConfig.get().getBackend();
var actual = preferred.findFallback();
if (preferred != actual) {
LOGGER.warn("Flywheel backend fell back from '{}' to '{}'", Backend.REGISTRY.getId(preferred), Backend.REGISTRY.getId(actual));
}
return actual;
}
private static Backend findDefaultBackend() {
// TODO: Automatically select the best default config based on the user's driver
// TODO: Figure out how this will work if custom backends are registered
return Backends.INDIRECT;
}
private BackendManagerImpl() {
}
}

View file

@ -0,0 +1,117 @@
package com.jozufozu.flywheel.impl;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import com.jozufozu.flywheel.api.registry.IdRegistry;
import it.unimi.dsi.fastutil.objects.Object2ReferenceMap;
import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import it.unimi.dsi.fastutil.objects.ObjectSets;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceCollection;
import it.unimi.dsi.fastutil.objects.ReferenceCollections;
import net.minecraft.resources.ResourceLocation;
public class IdRegistryImpl<T> implements IdRegistry<T> {
private static final ObjectList<IdRegistryImpl<?>> ALL = new ObjectArrayList<>();
private final Object2ReferenceMap<ResourceLocation, T> map = new Object2ReferenceOpenHashMap<>();
private final Reference2ObjectMap<T, ResourceLocation> reverseMap = new Reference2ObjectOpenHashMap<>();
private final ObjectSet<ResourceLocation> keysView = ObjectSets.unmodifiable(map.keySet());
private final ReferenceCollection<T> valuesView = ReferenceCollections.unmodifiable(map.values());
private final ObjectList<Runnable> freezeCallbacks = new ObjectArrayList<>();
private boolean frozen;
private IdRegistryImpl() {
ALL.add(this);
}
public static <T> IdRegistry<T> create() {
return new IdRegistryImpl<>();
}
@Override
public void register(ResourceLocation id, T object) {
if (frozen) {
throw new IllegalStateException("Cannot register to frozen registry!");
}
T oldValue = map.put(id, object);
if (oldValue != null) {
throw new IllegalArgumentException("Cannot override registration for ID '" + id + "'!");
}
ResourceLocation oldId = reverseMap.put(object, id);
if (oldId != null) {
throw new IllegalArgumentException("Cannot override ID '" + id + "' with registration for ID '" + oldId + "'!");
}
}
@Override
public <S extends T> S registerAndGet(ResourceLocation id, S object) {
register(id, object);
return object;
}
@Override
@Nullable
public T get(ResourceLocation id) {
return map.get(id);
}
@Override
@Nullable
public ResourceLocation getId(T object) {
return reverseMap.get(object);
}
@Override
@Unmodifiable
public Set<ResourceLocation> getAllIds() {
return keysView;
}
@Override
@Unmodifiable
public Collection<T> getAll() {
return valuesView;
}
@Override
public void addFreezeCallback(Runnable callback) {
if (frozen) {
throw new IllegalStateException("Cannot add freeze callback to frozen registry!");
}
freezeCallbacks.add(callback);
}
@Override
public boolean isFrozen() {
return frozen;
}
@Override
public Iterator<T> iterator() {
return getAll().iterator();
}
public void freeze() {
frozen = true;
for (Runnable runnable : freezeCallbacks) {
runnable.run();
}
}
public static void freezeAll() {
for (IdRegistryImpl<?> registry : ALL) {
registry.freeze();
}
}
}

View file

@ -0,0 +1,101 @@
package com.jozufozu.flywheel.impl;
import java.util.Iterator;
import java.util.Set;
import org.jetbrains.annotations.Unmodifiable;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import it.unimi.dsi.fastutil.objects.ObjectSets;
import net.minecraft.resources.ResourceLocation;
public class RegistryImpl<T> implements Registry<T> {
private static final ObjectList<RegistryImpl<?>> ALL = new ObjectArrayList<>();
private final ObjectSet<T> set = new ObjectOpenHashSet<>();
private final ObjectSet<T> setView = ObjectSets.unmodifiable(set);
private final ObjectList<Runnable> freezeCallbacks = new ObjectArrayList<>();
private boolean frozen;
private RegistryImpl() {
ALL.add(this);
}
public static <T> Registry<T> create() {
return new RegistryImpl<>();
}
public static <T extends ShaderUniforms> Registry<T> createForShaderUniforms() {
return new RegistryImpl<>() {
private final ObjectSet<ResourceLocation> files = new ObjectOpenHashSet<>();
@Override
public void register(T object) {
if (!files.add(object.uniformShader())) {
throw new IllegalArgumentException();
}
super.register(object);
}
};
}
@Override
public void register(T object) {
if (frozen) {
throw new IllegalStateException("Cannot register to frozen registry!");
}
boolean added = set.add(object);
if (!added) {
throw new IllegalArgumentException("Cannot override registration!");
}
}
@Override
public <S extends T> S registerAndGet(S object) {
register(object);
return object;
}
@Override
@Unmodifiable
public Set<T> getAll() {
return setView;
}
@Override
public void addFreezeCallback(Runnable callback) {
if (frozen) {
throw new IllegalStateException("Cannot add freeze callback to frozen registry!");
}
freezeCallbacks.add(callback);
}
@Override
public boolean isFrozen() {
return frozen;
}
@Override
public Iterator<T> iterator() {
return getAll().iterator();
}
public void freeze() {
frozen = true;
for (Runnable runnable : freezeCallbacks) {
runnable.run();
}
}
public static void freezeAll() {
for (RegistryImpl<?> registry : ALL) {
registry.freeze();
}
}
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.backend.vertex; package com.jozufozu.flywheel.impl.vertex;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.backend.vertex; package com.jozufozu.flywheel.impl.vertex;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.backend.vertex; package com.jozufozu.flywheel.impl.vertex;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexListProvider; import com.jozufozu.flywheel.api.vertex.VertexListProvider;

View file

@ -1,16 +1,7 @@
package com.jozufozu.flywheel.lib.backend; package com.jozufozu.flywheel.lib.backend;
import java.util.Collection; import com.jozufozu.flywheel.Flywheel;
import java.util.HashMap; import com.jozufozu.flywheel.api.backend.Backend;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.BackendType;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.backend.engine.batching.BatchingEngine; import com.jozufozu.flywheel.backend.engine.batching.BatchingEngine;
import com.jozufozu.flywheel.backend.engine.indirect.IndirectEngine; import com.jozufozu.flywheel.backend.engine.indirect.IndirectEngine;
import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine; import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine;
@ -22,90 +13,54 @@ import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
public class BackendTypes { public class Backends {
public static final Map<String, BackendType> BACKEND_TYPES = new HashMap<>(); public static final Backend OFF = SimpleBackend.builder()
public static final BackendType OFF = SimpleBackendType.builder()
.properName("Off") .properName("Off")
.shortName("off")
.engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED)) .engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED))
.engineSupplier(() -> { .engineSupplier(() -> {
throw new IllegalStateException("Cannot create engine when backend is off."); throw new IllegalStateException("Cannot create engine when backend is off.");
}) })
.fallback(() -> BackendTypes.OFF) .fallback(() -> Backends.OFF)
.supported(() -> true) .supported(() -> true)
.register(); .register(Flywheel.rl("off"));
/** /**
* Use a thread pool to buffer instances in parallel on the CPU. * Use a thread pool to buffer instances in parallel on the CPU.
*/ */
public static final BackendType BATCHING = SimpleBackendType.builder() public static final Backend BATCHING = SimpleBackend.builder()
.properName("Parallel Batching") .properName("Parallel Batching")
.shortName("batching")
.engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(BatchingEngine::new) .engineSupplier(BatchingEngine::new)
.fallback(() -> BackendTypes.OFF) .fallback(() -> Backends.OFF)
.supported(() -> !ShadersModHandler.isShaderPackInUse()) .supported(() -> !ShadersModHandler.isShaderPackInUse())
.register(); .register(Flywheel.rl("batching"));
/** /**
* Use GPU instancing to render everything. * Use GPU instancing to render everything.
*/ */
public static final BackendType INSTANCING = SimpleBackendType.builder() public static final Backend INSTANCING = SimpleBackend.builder()
.properName("GL33 Instanced Arrays") .properName("GL33 Instanced Arrays")
.shortName("instancing")
.engineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(() -> new InstancingEngine(Contexts.WORLD, 100 * 100)) .engineSupplier(() -> new InstancingEngine(Contexts.WORLD, 100 * 100))
.fallback(() -> BackendTypes.BATCHING) .fallback(() -> Backends.BATCHING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance() .supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
.instancedArraysSupported()) .instancedArraysSupported())
.pipelineShader(Pipelines.INSTANCED_ARRAYS) .pipelineShader(Pipelines.INSTANCED_ARRAYS)
.register(); .register(Flywheel.rl("instancing"));
/** /**
* Use Compute shaders to cull instances. * Use Compute shaders to cull instances.
*/ */
public static final BackendType INDIRECT = SimpleBackendType.builder() public static final Backend INDIRECT = SimpleBackend.builder()
.properName("GL46 Compute Culling") .properName("GL46 Compute Culling")
.shortName("indirect")
.engineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(() -> new IndirectEngine(Contexts.WORLD, 100 * 100)) .engineSupplier(() -> new IndirectEngine(Contexts.WORLD, 100 * 100))
.fallback(() -> BackendTypes.INSTANCING) .fallback(() -> Backends.INSTANCING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance() .supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
.supportsIndirect()) .supportsIndirect())
.pipelineShader(Pipelines.INDIRECT) .pipelineShader(Pipelines.INDIRECT)
.register(); .register(Flywheel.rl("indirect"));
public static BackendType register(BackendType type) {
BACKEND_TYPES.put(type.getShortName(), type);
return type;
}
public static BackendType defaultForCurrentPC() {
// TODO: Automatically select the best default config based on the user's driver
return INDIRECT;
}
@Nullable
public static BackendType getBackendType(String name) {
return BACKEND_TYPES.get(name.toLowerCase(Locale.ROOT));
}
public static Collection<String> validNames() {
return BACKEND_TYPES.keySet();
}
public static void init() { public static void init() {
// noop
}
public static Collection<Pipeline> availablePipelineShaders() {
return BACKEND_TYPES.values()
.stream()
.filter(BackendType::supported)
.map(BackendType::pipelineShader)
.filter(Objects::nonNull)
.collect(Collectors.toList());
} }
} }

View file

@ -5,26 +5,23 @@ import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.BackendType; import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.pipeline.Pipeline;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
public class SimpleBackendType implements BackendType { public class SimpleBackend implements Backend {
private final String properName; private final String properName;
private final String shortName;
private final Component engineMessage; private final Component engineMessage;
private final Supplier<Engine> engineSupplier; private final Supplier<Engine> engineSupplier;
private final Supplier<BackendType> fallback; private final Supplier<Backend> fallback;
private final BooleanSupplier isSupported; private final BooleanSupplier isSupported;
private final Pipeline pipelineShader; private final Pipeline pipelineShader;
public SimpleBackendType(String properName, String shortName, Component engineMessage, Supplier<Engine> engineSupplier, Supplier<BackendType> fallback, BooleanSupplier isSupported, @Nullable Pipeline pipelineShader) { public SimpleBackend(String properName, Component engineMessage, Supplier<Engine> engineSupplier, Supplier<Backend> fallback, BooleanSupplier isSupported, @Nullable Pipeline pipelineShader) {
this.properName = properName; this.properName = properName;
this.shortName = shortName;
this.engineMessage = engineMessage; this.engineMessage = engineMessage;
this.engineSupplier = engineSupplier; this.engineSupplier = engineSupplier;
this.fallback = fallback; this.fallback = fallback;
@ -41,11 +38,6 @@ public class SimpleBackendType implements BackendType {
return properName; return properName;
} }
@Override
public String getShortName() {
return shortName;
}
@Override @Override
public Component getEngineMessage() { public Component getEngineMessage() {
return engineMessage; return engineMessage;
@ -57,8 +49,8 @@ public class SimpleBackendType implements BackendType {
} }
@Override @Override
public BackendType findFallback() { public Backend findFallback() {
if (this.supported()) { if (this.isSupported()) {
return this; return this;
} else { } else {
return fallback.get() return fallback.get()
@ -67,7 +59,7 @@ public class SimpleBackendType implements BackendType {
} }
@Override @Override
public boolean supported() { public boolean isSupported() {
return isSupported.getAsBoolean(); return isSupported.getAsBoolean();
} }
@ -78,10 +70,9 @@ public class SimpleBackendType implements BackendType {
public static class Builder { public static class Builder {
private String properName; private String properName;
private String shortName;
private Component engineMessage; private Component engineMessage;
private Supplier<Engine> engineSupplier; private Supplier<Engine> engineSupplier;
private Supplier<BackendType> fallback; private Supplier<Backend> fallback;
private BooleanSupplier isSupported; private BooleanSupplier isSupported;
private Pipeline pipelineShader; private Pipeline pipelineShader;
@ -90,11 +81,6 @@ public class SimpleBackendType implements BackendType {
return this; return this;
} }
public Builder shortName(String shortName) {
this.shortName = shortName;
return this;
}
public Builder engineMessage(Component engineMessage) { public Builder engineMessage(Component engineMessage) {
this.engineMessage = engineMessage; this.engineMessage = engineMessage;
return this; return this;
@ -105,7 +91,7 @@ public class SimpleBackendType implements BackendType {
return this; return this;
} }
public Builder fallback(Supplier<BackendType> fallback) { public Builder fallback(Supplier<Backend> fallback) {
this.fallback = fallback; this.fallback = fallback;
return this; return this;
} }
@ -120,8 +106,8 @@ public class SimpleBackendType implements BackendType {
return this; return this;
} }
public BackendType register() { public Backend register(ResourceLocation id) {
return BackendTypes.register(new SimpleBackendType(properName, shortName, engineMessage, engineSupplier, fallback, isSupported, pipelineShader)); return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(properName, engineMessage, engineSupplier, fallback, isSupported, pipelineShader));
} }
} }
} }

View file

@ -1,14 +1,14 @@
package com.jozufozu.flywheel.lib.context; package com.jozufozu.flywheel.lib.context;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.component.ComponentRegistry; import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.util.ResourceUtil; import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public class Contexts { public class Contexts {
public static final SimpleContext WORLD = ComponentRegistry.register(new SimpleContext(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT)); public static final SimpleContext WORLD = Context.REGISTRY.registerAndGet(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 final SimpleContext CRUMBLING = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
public static void init() { public static void init() {
// noop // noop

View file

@ -1,14 +1,14 @@
package com.jozufozu.flywheel.lib.format; package com.jozufozu.flywheel.lib.format;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.component.ComponentRegistry; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.util.ResourceUtil; import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public class Formats { public class Formats {
public static final BlockVertex BLOCK = ComponentRegistry.register(new BlockVertex()); public static final BlockVertex BLOCK = VertexType.REGISTRY.registerAndGet(new BlockVertex());
public static final PosTexNormalVertex POS_TEX_NORMAL = ComponentRegistry.register(new PosTexNormalVertex()); public static final PosTexNormalVertex POS_TEX_NORMAL = VertexType.REGISTRY.registerAndGet(new PosTexNormalVertex());
public static void init() { public static void init() {
// noop // noop

View file

@ -0,0 +1,100 @@
package com.jozufozu.flywheel.lib.instance;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
public class SimpleBlockEntityInstancingController<T extends BlockEntity> implements BlockEntityInstancingController<T> {
protected BiFunction<InstancerProvider, T, BlockEntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public SimpleBlockEntityInstancingController(BiFunction<InstancerProvider, T, BlockEntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) {
this.instanceFactory = instanceFactory;
this.skipRender = skipRender;
}
@Override
public BlockEntityInstance<? super T> createInstance(InstancerProvider instancerManager, T blockEntity) {
return instanceFactory.apply(instancerManager, blockEntity);
}
@Override
public boolean shouldSkipRender(T blockEntity) {
return skipRender.test(blockEntity);
}
/**
* Get an object to configure the instancing controller for the given block entity type.
* @param type The block entity type to configure.
* @param <T> The type of the block entity.
* @return The configuration object.
*/
public static <T extends BlockEntity> BlockEntityConfig<T> configure(BlockEntityType<T> type) {
return new BlockEntityConfig<>(type);
}
/**
* An object to configure the instancing controller for a block entity.
* @param <T> The type of the block entity.
*/
public static class BlockEntityConfig<T extends BlockEntity> {
protected BlockEntityType<T> type;
protected BiFunction<InstancerProvider, T, BlockEntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public BlockEntityConfig(BlockEntityType<T> type) {
this.type = type;
}
/**
* Sets the instance factory for the block entity.
* @param instanceFactory The instance factory.
* @return {@code this}
*/
public BlockEntityConfig<T> factory(BiFunction<InstancerProvider, T, BlockEntityInstance<? super T>> instanceFactory) {
this.instanceFactory = instanceFactory;
return this;
}
/**
* Sets a predicate to determine whether to skip rendering a block entity.
* @param skipRender The predicate.
* @return {@code this}
*/
public BlockEntityConfig<T> skipRender(Predicate<T> skipRender) {
this.skipRender = skipRender;
return this;
}
/**
* Sets a predicate to always skip rendering for block entities of this type.
* @return {@code this}
*/
public BlockEntityConfig<T> alwaysSkipRender() {
this.skipRender = be -> true;
return this;
}
/**
* Constructs the block entity instancing controller, and sets it for the block entity type.
* @return The block entity instancing controller.
*/
public SimpleBlockEntityInstancingController<T> apply() {
Objects.requireNonNull(instanceFactory, "Instance factory cannot be null!");
if (skipRender == null) {
skipRender = be -> false;
}
SimpleBlockEntityInstancingController<T> controller = new SimpleBlockEntityInstancingController<>(instanceFactory, skipRender);
InstancedRenderRegistry.setController(type, controller);
return controller;
}
}
}

View file

@ -0,0 +1,100 @@
package com.jozufozu.flywheel.lib.instance;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
public class SimpleEntityInstancingController<T extends Entity> implements EntityInstancingController<T> {
protected BiFunction<InstancerProvider, T, EntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public SimpleEntityInstancingController(BiFunction<InstancerProvider, T, EntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) {
this.instanceFactory = instanceFactory;
this.skipRender = skipRender;
}
@Override
public EntityInstance<? super T> createInstance(InstancerProvider instancerManager, T entity) {
return instanceFactory.apply(instancerManager, entity);
}
@Override
public boolean shouldSkipRender(T entity) {
return skipRender.test(entity);
}
/**
* Get an object to configure the instancing controller for the given entity type.
* @param type The entity type to configure.
* @param <T> The type of the entity.
* @return The configuration object.
*/
public static <T extends Entity> EntityConfig<T> configure(EntityType<T> type) {
return new EntityConfig<>(type);
}
/**
* An object to configure the instancing controller for an entity.
* @param <T> The type of the entity.
*/
public static class EntityConfig<T extends Entity> {
protected EntityType<T> type;
protected BiFunction<InstancerProvider, T, EntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public EntityConfig(EntityType<T> type) {
this.type = type;
}
/**
* Sets the instance factory for the entity.
* @param instanceFactory The instance factory.
* @return {@code this}
*/
public EntityConfig<T> factory(BiFunction<InstancerProvider, T, EntityInstance<? super T>> instanceFactory) {
this.instanceFactory = instanceFactory;
return this;
}
/**
* Sets a predicate to determine whether to skip rendering an entity.
* @param skipRender The predicate.
* @return {@code this}
*/
public EntityConfig<T> skipRender(Predicate<T> skipRender) {
this.skipRender = skipRender;
return this;
}
/**
* Sets a predicate to always skip rendering for entities of this type.
* @return {@code this}
*/
public EntityConfig<T> alwaysSkipRender() {
this.skipRender = entity -> true;
return this;
}
/**
* Constructs the entity instancing controller, and sets it for the entity type.
* @return The entity instancing controller.
*/
public SimpleEntityInstancingController<T> apply() {
Objects.requireNonNull(instanceFactory, "Instance factory cannot be null!");
if (skipRender == null) {
skipRender = entity -> false;
}
SimpleEntityInstancingController<T> controller = new SimpleEntityInstancingController<>(instanceFactory, skipRender);
InstancedRenderRegistry.setController(type, controller);
return controller;
}
}
}

View file

@ -5,9 +5,9 @@ import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.task.WorkGroup;
import com.jozufozu.flywheel.lib.box.ImmutableBox; import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.task.WorkGroup;
import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.WorldAttached;
@ -68,7 +68,7 @@ public class LightUpdater {
} }
}) })
.onComplete(() -> listeners.forEach(this::addListener)) .onComplete(() -> listeners.forEach(this::addListener))
.execute(Backend.getTaskExecutor()); .execute(BackendUtil.getTaskExecutor());
} }
/** /**

View file

@ -0,0 +1,147 @@
package com.jozufozu.flywheel.lib.material;
import java.util.List;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Unmodifiable;
import com.jozufozu.flywheel.api.material.Material;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import it.unimi.dsi.fastutil.objects.ObjectLists;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMaps;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import net.minecraft.resources.ResourceLocation;
// TODO: add messages to exceptions
public class MaterialIndicies {
private static Reference2IntMap<Material> materialIndicies;
private static Object2IntMap<ResourceLocation> vertexShaderIndicies;
private static Object2IntMap<ResourceLocation> fragmentShaderIndicies;
private static ObjectList<Material> materialsByIndex;
private static ObjectList<ResourceLocation> vertexShadersByIndex;
private static ObjectList<ResourceLocation> fragmentShadersByIndex;
private static boolean initialized;
public static int getMaterialIndex(Material material) {
if (!initialized) {
throw new IllegalStateException();
}
return materialIndicies.getInt(material);
}
public static int getVertexShaderIndex(ResourceLocation vertexShader) {
if (!initialized) {
throw new IllegalStateException();
}
return vertexShaderIndicies.getInt(vertexShader);
}
public static int getFragmentShaderIndex(ResourceLocation fragmentShader) {
if (!initialized) {
throw new IllegalStateException();
}
return fragmentShaderIndicies.getInt(fragmentShader);
}
public static Material getMaterial(int index) {
if (!initialized) {
throw new IllegalStateException();
}
return materialsByIndex.get(index);
}
public static ResourceLocation getVertexShader(int index) {
if (!initialized) {
throw new IllegalStateException();
}
return vertexShadersByIndex.get(index);
}
public static ResourceLocation getFragmentShader(int index) {
if (!initialized) {
throw new IllegalStateException();
}
return fragmentShadersByIndex.get(index);
}
@Unmodifiable
public static List<Material> getAllMaterials() {
if (!initialized) {
throw new IllegalStateException();
}
return materialsByIndex;
}
@Unmodifiable
public static List<ResourceLocation> getAllVertexShaders() {
if (!initialized) {
throw new IllegalStateException();
}
return vertexShadersByIndex;
}
@Unmodifiable
public static List<ResourceLocation> getAllFragmentShaders() {
if (!initialized) {
throw new IllegalStateException();
}
return fragmentShadersByIndex;
}
private static void initInner() {
int amount = Material.REGISTRY.getAll().size();
Reference2IntMap<Material> materialIndicies = new Reference2IntOpenHashMap<>();
Object2IntMap<ResourceLocation> vertexShaderIndicies = new Object2IntOpenHashMap<>();
Object2IntMap<ResourceLocation> fragmentShaderIndicies = new Object2IntOpenHashMap<>();
ObjectList<Material> materialsByIndex = new ObjectArrayList<>(amount);
ObjectList<ResourceLocation> vertexShadersByIndex = new ObjectArrayList<>(amount);
ObjectList<ResourceLocation> fragmentShadersByIndex = new ObjectArrayList<>(amount);
ObjectSet<ResourceLocation> allVertexShaders = new ObjectOpenHashSet<>();
ObjectSet<ResourceLocation> allFragmentShaders = new ObjectOpenHashSet<>();
int materialIndex = 0;
int vertexShaderIndex = 0;
int fragmentShaderIndex = 0;
for (Material material : Material.REGISTRY) {
materialIndicies.put(material, materialIndex);
materialsByIndex.add(material);
materialIndex++;
ResourceLocation vertexShader = material.vertexShader();
if (allVertexShaders.add(vertexShader)) {
vertexShaderIndicies.put(vertexShader, vertexShaderIndex);
vertexShadersByIndex.add(vertexShader);
vertexShaderIndex++;
}
ResourceLocation fragmentShader = material.fragmentShader();
if (allFragmentShaders.add(fragmentShader)) {
fragmentShaderIndicies.put(fragmentShader, fragmentShaderIndex);
fragmentShadersByIndex.add(fragmentShader);
fragmentShaderIndex++;
}
}
MaterialIndicies.materialIndicies = Reference2IntMaps.unmodifiable(materialIndicies);
MaterialIndicies.vertexShaderIndicies = Object2IntMaps.unmodifiable(vertexShaderIndicies);
MaterialIndicies.fragmentShaderIndicies = Object2IntMaps.unmodifiable(fragmentShaderIndicies);
MaterialIndicies.materialsByIndex = ObjectLists.unmodifiable(materialsByIndex);
MaterialIndicies.vertexShadersByIndex = ObjectLists.unmodifiable(vertexShadersByIndex);
MaterialIndicies.fragmentShadersByIndex = ObjectLists.unmodifiable(fragmentShadersByIndex);
initialized = true;
}
@ApiStatus.Internal
public static void init() {
Material.REGISTRY.addFreezeCallback(MaterialIndicies::initInner);
}
}

View file

@ -1,6 +1,5 @@
package com.jozufozu.flywheel.lib.material; package com.jozufozu.flywheel.lib.material;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderStateShard;
@ -107,7 +106,7 @@ public class SimpleMaterial implements Material {
} }
public SimpleMaterial register() { public SimpleMaterial register() {
return ComponentRegistry.register(new SimpleMaterial(vertexShader, fragmentShader, setup, clear, batchingRenderType, vertexTransformer)); return Material.REGISTRY.registerAndGet(new SimpleMaterial(vertexShader, fragmentShader, setup, clear, batchingRenderType, vertexTransformer));
} }
private static Runnable chain(Runnable runnable1, Runnable runnable2) { private static Runnable chain(Runnable runnable1, Runnable runnable2) {

View file

@ -1,9 +1,9 @@
package com.jozufozu.flywheel.lib.pipeline; package com.jozufozu.flywheel.lib.pipeline;
import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.glsl.SourceComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;

View file

@ -1,15 +1,14 @@
package com.jozufozu.flywheel.lib.struct; package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.util.ResourceUtil; import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public class StructTypes { public class StructTypes {
public static final StructType<TransformedPart> TRANSFORMED = ComponentRegistry.register(new TransformedType()); public static final StructType<TransformedPart> TRANSFORMED = StructType.REGISTRY.registerAndGet(new TransformedType());
public static final StructType<OrientedPart> ORIENTED = ComponentRegistry.register(new OrientedType()); public static final StructType<OrientedPart> ORIENTED = StructType.REGISTRY.registerAndGet(new OrientedType());
public static void init() { public static void init() {
// noop // noop

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.backend.task; package com.jozufozu.flywheel.lib.task;
import java.util.Iterator; import java.util.Iterator;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;

View file

@ -5,7 +5,6 @@ import java.util.function.Consumer;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.event.BeginFrameEvent; import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
@ -20,7 +19,7 @@ import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
public class FlwShaderUniforms implements ShaderUniforms { public class FlwShaderUniforms implements ShaderUniforms {
public static final FlwShaderUniforms INSTANCE = ComponentRegistry.register(new FlwShaderUniforms()); public static final FlwShaderUniforms INSTANCE = ShaderUniforms.REGISTRY.registerAndGet(new FlwShaderUniforms());
public static final ResourceLocation FILE = Flywheel.rl("uniform/flywheel.glsl"); public static final ResourceLocation FILE = Flywheel.rl("uniform/flywheel.glsl");
public static final int SIZE = 224; public static final int SIZE = 224;

View file

@ -7,8 +7,8 @@ import org.lwjgl.opengl.GL32C;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.backend.engine.instancing.ElementBuffer;
import com.jozufozu.flywheel.gl.GlNumericType; import com.jozufozu.flywheel.gl.GlNumericType;
import com.jozufozu.flywheel.gl.buffer.ElementBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferType; import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.gl.buffer.GlBufferUsage; import com.jozufozu.flywheel.gl.buffer.GlBufferUsage;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;

View file

@ -6,7 +6,9 @@ import java.util.function.BooleanSupplier;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend; import org.slf4j.Logger;
import com.mojang.logging.LogUtils;
import net.irisshaders.iris.api.v0.IrisApi; import net.irisshaders.iris.api.v0.IrisApi;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
@ -14,6 +16,8 @@ import net.minecraft.client.renderer.culling.Frustum;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
public final class ShadersModHandler { public final class ShadersModHandler {
private static final Logger LOGGER = LogUtils.getLogger();
public static final String OPTIFINE_ROOT_PACKAGE = "net.optifine"; public static final String OPTIFINE_ROOT_PACKAGE = "net.optifine";
public static final String SHADER_PACKAGE = "net.optifine.shaders"; public static final String SHADER_PACKAGE = "net.optifine.shaders";
@ -30,13 +34,13 @@ public final class ShadersModHandler {
// optfine and oculus are assumed to be mutually exclusive // optfine and oculus are assumed to be mutually exclusive
if (isOptifineInstalled) { if (isOptifineInstalled) {
Backend.LOGGER.info("Optifine detected."); LOGGER.info("Optifine detected.");
internalHandler = new Optifine(); internalHandler = new Optifine();
} else if (isOculusLoaded) { } else if (isOculusLoaded) {
Backend.LOGGER.info("Oculus detected."); LOGGER.info("Oculus detected.");
internalHandler = new Oculus(); internalHandler = new Oculus();
} else { } else {
Backend.LOGGER.info("No shaders mod detected."); LOGGER.info("No shaders mod detected.");
internalHandler = new InternalHandler() {}; internalHandler = new InternalHandler() {};
} }
} }

View file

@ -4,7 +4,7 @@ import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstancingController; import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
import com.jozufozu.flywheel.extension.BlockEntityTypeExtension; import com.jozufozu.flywheel.extension.BlockEntityTypeExtension;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;

View file

@ -9,8 +9,8 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
import com.jozufozu.flywheel.extension.ClientLevelExtension; import com.jozufozu.flywheel.extension.ClientLevelExtension;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@ -29,7 +29,7 @@ public abstract class ClientLevelMixin implements ClientLevelExtension {
@Inject(method = "entitiesForRendering", at = @At("RETURN"), cancellable = true) @Inject(method = "entitiesForRendering", at = @At("RETURN"), cancellable = true)
private void flywheel$filterEntities(CallbackInfoReturnable<Iterable<Entity>> cir) { private void flywheel$filterEntities(CallbackInfoReturnable<Iterable<Entity>> cir) {
if (Backend.isOn()) { if (BackendManager.isOn()) {
Iterable<Entity> entities = cir.getReturnValue(); Iterable<Entity> entities = cir.getReturnValue();
ArrayList<Entity> filtered = Lists.newArrayList(entities); ArrayList<Entity> filtered = Lists.newArrayList(entities);

View file

@ -4,7 +4,7 @@ import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstancingController; import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
import com.jozufozu.flywheel.extension.EntityTypeExtension; import com.jozufozu.flywheel.extension.EntityTypeExtension;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;

Some files were not shown because too many files have changed in this diff Show more