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.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.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.FlwConfig;
import com.jozufozu.flywheel.handler.EntityWorldHandler;
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.format.Formats;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.Models;
import com.jozufozu.flywheel.lib.model.PartialModel;
@ -61,7 +65,7 @@ public class Flywheel {
.getModEventBus();
modEventBus.addListener(Flywheel::setup);
FlwConfig.init();
FlwConfig.get().registerSpecs(modLoadingContext);
modLoadingContext.registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(
() -> NetworkConstants.IGNORESERVERONLY,
@ -72,12 +76,6 @@ public class Flywheel {
}
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(EventPriority.HIGHEST, QuadConverter::onReloadRenderers);
@ -102,14 +100,23 @@ public class Flywheel {
// forgeEventBus.addListener(ExampleEffect::tick);
// forgeEventBus.addListener(ExampleEffect::onReload);
ShadersModHandler.init();
Backends.init();
Loader.init();
Formats.init();
StructTypes.init();
Materials.init();
Contexts.init();
Pipelines.init();
MaterialIndicies.init();
VanillaInstances.init();
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManager::getBackendDescriptor);
// https://github.com/Jozufozu/Flywheel/issues/69
// 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.
@ -119,7 +126,10 @@ public class Flywheel {
}
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() {

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 com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
public interface Engine extends RenderDispatcher, InstancerManager {
public interface Engine extends RenderDispatcher, InstancerProvider {
void attachManagers(InstanceManager<?>... listener);
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;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation;
public interface Context {
static Registry<Context> REGISTRY = RegistryImpl.create();
void onProgramLink(GlProgram program);
ResourceLocation vertexShader();

View file

@ -1,18 +1,12 @@
package com.jozufozu.flywheel.backend.instancing;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Predicate;
package com.jozufozu.flywheel.api.instance;
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.BlockEntityInstancingController;
import com.jozufozu.flywheel.backend.instancing.blockentity.SimpleBlockEntityInstancingController;
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.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.
*/
@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));
if (controller == 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.
*/
@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));
if (controller == null) {
return null;
@ -106,26 +100,6 @@ public class InstancedRenderRegistry {
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.
* @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) {
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;
/**
* 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> {
/**
@ -15,7 +16,7 @@ public interface BlockEntityInstancingController<T extends BlockEntity> {
* @param blockEntity The block entity to construct an instance for.
* @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.

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;
@ -15,7 +16,7 @@ public interface EntityInstancingController<T extends Entity> {
* @param entity The entity to construct an instance for.
* @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.

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.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.gl.array.VertexAttribute;
import com.jozufozu.flywheel.lib.layout.LayoutItem;
/**
* 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.GlslStruct;

View file

@ -1,12 +1,16 @@
package com.jozufozu.flywheel.api.material;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
public interface Material {
static Registry<Material> REGISTRY = RegistryImpl.create();
ResourceLocation vertexShader();
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.VertexType;
import com.jozufozu.flywheel.backend.engine.instancing.ElementBuffer;
import com.jozufozu.flywheel.gl.buffer.ElementBuffer;
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.gl.GLSLVersion;
import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
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.layout.BufferLayout;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.ResourceLocation;
@ -12,6 +14,7 @@ import net.minecraft.resources.ResourceLocation;
* @param <S> The java representation of the instance struct.
*/
public interface StructType<S extends InstancedPart> {
static Registry<StructType<?>> REGISTRY = RegistryImpl.create();
/**
* @return A new, zeroed instance of S.

View file

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

View file

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

View file

@ -1,6 +1,8 @@
package com.jozufozu.flywheel.api.vertex;
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;
@ -8,6 +10,7 @@ import net.minecraft.resources.ResourceLocation;
* A vertex type containing metadata about a specific vertex layout.
*/
public interface VertexType extends VertexListProvider {
static Registry<VertexType> REGISTRY = RegistryImpl.create();
/**
* 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;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.glsl.ShaderSources;
@ -19,22 +20,14 @@ import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
* </p>
*/
public class Loader implements ResourceManagerReloadListener {
public static final Loader INSTANCE = new Loader();
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);
}
private Loader() {
}
@Override
public void onResourceManagerReload(ResourceManager manager) {
Backend.refresh();
BackendManager.refresh();
var errorReporter = new ErrorReporter();
ShaderSources sources = new ShaderSources(errorReporter, manager);
@ -46,9 +39,20 @@ public class Loader implements ResourceManagerReloadListener {
FlwCompiler.INSTANCE = new FlwCompiler(sources);
ClientLevel level = Minecraft.getInstance().level;
if (Backend.canUseInstancing(level)) {
if (BackendUtil.canUseInstancing(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.lwjgl.opengl.GL20;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlShader;
import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.gl.versioned.GlCompat;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.util.StringUtil;
@ -130,7 +131,7 @@ public class Compilation {
}
private static void dumpSource(String source, String fileName) {
if (!Backend.DUMP_SHADER_SOURCE) {
if (!BackendUtil.DUMP_SHADER_SOURCE) {
return;
}
@ -140,7 +141,7 @@ public class Compilation {
try (FileWriter writer = new FileWriter(file)) {
writer.write(source);
} 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 com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.glsl.SourceFile;
@ -76,7 +76,7 @@ public class CompileUtil {
String log = glGetProgramInfoLog(handle);
if (!log.isEmpty()) {
Backend.LOGGER.debug("Program link log: " + log);
Flywheel.LOGGER.debug("Program link log: " + log);
}
int result = glGetProgrami(handle, GL_LINK_STATUS);

View file

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

View file

@ -12,22 +12,21 @@ import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.context.Context;
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.uniform.ShaderUniforms;
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.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.glsl.ShaderLoadingException;
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.GlslExpr;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.util.StringUtil;
@ -56,12 +55,12 @@ public class FlwCompiler {
this.sources = sources;
this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
.materialSources(ComponentRegistry.materials.vertexSources())
.materialSources(MaterialIndicies.getAllVertexShaders())
.adapt(FnSignature.ofVoid("flw_materialVertex"))
.switchOn(GlslExpr.variable("flw_materialVertexID"))
.build(sources);
this.fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter"))
.materialSources(ComponentRegistry.materials.fragmentSources())
.materialSources(MaterialIndicies.getAllFragmentShaders())
.adapt(FnSignature.ofVoid("flw_materialFragment"))
.adapt(FnSignature.create()
.returnType("bool")
@ -76,7 +75,7 @@ public class FlwCompiler {
.switchOn(GlslExpr.variable("flw_materialFragmentID"))
.build(sources);
this.uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms"))
.sources(ComponentRegistry.getAllUniformProviders()
.sources(ShaderUniforms.REGISTRY.getAll()
.stream()
.map(ShaderUniforms::uniformShader)
.toList())
@ -102,12 +101,12 @@ public class FlwCompiler {
private void finish() {
long compileEnd = System.nanoTime();
int programCount = pipelineContexts.size() + ComponentRegistry.structTypes.size();
int programCount = pipelineContexts.size() + StructType.REGISTRY.getAll().size();
int shaderCount = shaderCompiler.shaderCount();
int errorCount = errors.size();
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) {
var details = errors.stream()

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.backend.compile;
import java.util.function.Consumer;
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.

View file

@ -11,8 +11,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
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.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,7 +25,7 @@ public class BatchingEngine implements Engine {
protected final BatchingDrawTracker drawTracker = new BatchingDrawTracker();
@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);
}

View file

@ -5,16 +5,16 @@ import java.util.List;
import com.google.common.collect.ImmutableList;
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.SourceComponent;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.layout.LayoutItem;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
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.vertex.VertexType;
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.lib.context.Contexts;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
@ -112,7 +113,7 @@ public class IndirectCullingGroup<T extends InstancedPart> {
uploadInstanceData();
uploadIndirectCommands();
compute.bind();
UniformBuffer.syncAndBind(compute);
buffers.bindForCompute();
var groupCount = (instanceCountThisFrame + 31) >> 5; // ceil(instanceCount / 32)
@ -125,7 +126,7 @@ public class IndirectCullingGroup<T extends InstancedPart> {
return;
}
draw.bind();
UniformBuffer.syncAndBind(draw);
glBindVertexArray(vertexArray);
buffers.bindForDraw();

View file

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

View file

@ -10,10 +10,10 @@ import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
import com.jozufozu.flywheel.util.Textures;
public class IndirectDrawSet<T extends InstancedPart> {
@ -50,7 +50,7 @@ public class IndirectDrawSet<T extends InstancedPart> {
multiDraws.clear();
// sort by stage, then material
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++) {
var draw = indirectDraws.get(i);

View file

@ -48,7 +48,7 @@ public class IndirectEngine implements Engine {
}
@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);
}

View file

@ -5,13 +5,13 @@ import java.util.Collections;
import java.util.List;
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.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.layout.LayoutItem;
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.gl.GlPrimitive;
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.GlBufferType;
import com.jozufozu.flywheel.gl.buffer.MappedBuffer;
@ -234,9 +235,9 @@ public class InstancedMeshPool {
private void draw(int instanceCount) {
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 {
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 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.event.RenderContext;
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.backend.compile.FlwCompiler;
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.GlTextureUnit;
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.util.FlwUtil;
import com.mojang.blaze3d.systems.RenderSystem;
@ -51,7 +52,7 @@ public class InstancingEngine implements Engine {
}
@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);
}
@ -117,11 +118,11 @@ public class InstancingEngine implements Engine {
var material = desc.material();
var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, context, Pipelines.INSTANCED_ARRAYS);
program.bind();
UniformBuffer.syncAndBind(program);
var uniformLocation = program.getUniformLocation("_flw_materialID_instancing");
var vertexID = ComponentRegistry.materials.getVertexID(material);
var fragmentID = ComponentRegistry.materials.getFragmentID(material);
var vertexID = MaterialIndicies.getVertexShaderIndex(material.vertexShader());
var fragmentID = MaterialIndicies.getFragmentShaderIndex(material.fragmentShader());
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.TickableInstance;
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.lib.light.LightListener;
@ -22,11 +22,11 @@ import net.minecraft.world.level.LightLayer;
*/
public abstract class AbstractInstance implements Instance, LightListener {
protected final InstancerManager instancerManager;
protected final InstancerProvider instancerManager;
public final Level level;
protected boolean removed = false;
public AbstractInstance(InstancerManager instancerManager, Level level) {
public AbstractInstance(InstancerProvider instancerManager, Level level) {
this.instancerManager = instancerManager;
this.level = level;
}

View file

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

View file

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

View file

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

View file

@ -2,11 +2,11 @@ package com.jozufozu.flywheel.backend.instancing.blockentity;
import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
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.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
@ -21,7 +21,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
private final BlockEntityStorage storage;
public BlockEntityInstanceManager(InstancerManager instancerManager) {
public BlockEntityInstanceManager(InstancerProvider instancerManager) {
storage = new BlockEntityStorage(instancerManager);
}
@ -57,7 +57,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
return false;
}
if (Backend.isFlywheelLevel(level)) {
if (BackendUtil.isFlywheelLevel(level)) {
BlockPos pos = blockEntity.getBlockPos();
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<>();
public BlockEntityStorage(InstancerManager manager) {
public BlockEntityStorage(InstancerProvider 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 com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
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.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.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.storage.AbstractStorage;
@ -15,7 +15,7 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
private final EffectStorage<Effect> storage;
public EffectInstanceManager(InstancerManager instancerManager) {
public EffectInstanceManager(InstancerProvider instancerManager) {
storage = new EffectStorage<>(instancerManager);
}
@ -33,7 +33,7 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
private final Multimap<T, AbstractInstance> instances;
public EffectStorage(InstancerManager manager) {
public EffectStorage(InstancerProvider manager) {
super(manager);
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.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.blockentity.BlockEntityInstanceManager;
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 MutableBox bounds;
public EntityInstance(InstancerManager instancerManager, E entity) {
public EntityInstance(InstancerProvider instancerManager, E entity) {
super(instancerManager, entity.level);
this.entity = entity;
bounds = MutableBox.from(entity.getBoundingBox());

View file

@ -2,11 +2,11 @@ package com.jozufozu.flywheel.backend.instancing.entity;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
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.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
import net.minecraft.world.entity.Entity;
@ -16,7 +16,7 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
private final One2OneStorage<Entity> storage;
public EntityInstanceManager(InstancerManager instancerManager) {
public EntityInstanceManager(InstancerProvider instancerManager) {
storage = new One2OneStorage<>(instancerManager) {
@Override
protected @Nullable AbstractInstance createRaw(Entity obj) {
@ -42,6 +42,6 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
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.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.lib.light.LightUpdater;
public abstract class AbstractStorage<T> implements Storage<T> {
protected final List<TickableInstance> tickableInstances;
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.dynamicInstances = new ArrayList<>();

View file

@ -5,14 +5,14 @@ import java.util.Map;
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.lib.light.LightUpdater;
public abstract class One2OneStorage<T> extends AbstractStorage<T> {
private final Map<T, AbstractInstance> instances;
public One2OneStorage(InstancerManager instancerManager) {
public One2OneStorage(InstancerProvider instancerManager) {
super(instancerManager);
this.instances = new HashMap<>();
}

View file

@ -1,15 +1,15 @@
package com.jozufozu.flywheel.backend.uniform;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.lwjgl.opengl.GL32;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.gl.buffer.GlBuffer;
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.util.FlwUtil;
import com.jozufozu.flywheel.util.RenderMath;
@ -35,7 +35,12 @@ public class UniformBuffer {
private UniformBuffer() {
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() {
@ -84,7 +89,7 @@ public class UniformBuffer {
private final MemoryBlock data;
private ProviderSet(final Collection<ShaderUniforms> providers) {
private ProviderSet(final Set<ShaderUniforms> providers) {
var builder = ImmutableList.<LiveProvider>builder();
int totalBytes = 0;
for (ShaderUniforms provider : providers) {

View file

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

View file

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

View file

@ -2,54 +2,82 @@ package com.jozufozu.flywheel.config;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import com.jozufozu.flywheel.api.backend.BackendType;
import com.jozufozu.flywheel.lib.backend.BackendTypes;
import com.jozufozu.flywheel.api.backend.Backend;
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.BooleanValue;
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig;
public class FlwConfig {
private static final Logger LOGGER = LogUtils.getLogger();
private static final FlwConfig INSTANCE = new FlwConfig();
public final ClientConfig client;
private final ForgeConfigSpec clientSpec;
public FlwConfig() {
Pair<ClientConfig, ForgeConfigSpec> client = new ForgeConfigSpec.Builder().configure(ClientConfig::new);
this.client = client.getLeft();
ModLoadingContext.get()
.registerConfig(ModConfig.Type.CLIENT, client.getRight());
clientSpec = client.getRight();
}
public static FlwConfig get() {
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
public BackendType getBackendType() {
return BackendTypes.getBackendType(client.backend.get());
private static Backend parseBackend(String idStr) {
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() {
return client.limitUpdates.get();
}
public static void init() {
public void registerSpecs(ModLoadingContext context) {
context.registerConfig(ModConfig.Type.CLIENT, clientSpec);
}
public static class ClientConfig {
public final ForgeConfigSpec.ConfigValue<String> backend;
public final ConfigValue<String> backend;
public final BooleanValue limitUpdates;
public ClientConfig(ForgeConfigSpec.Builder builder) {
backend = builder.comment("Select the backend to use.")
.define("backend", BackendTypes.defaultForCurrentPC()
.getShortName());
.define("backend", Backend.REGISTRY.getId(BackendManager.getDefaultBackend()).toString());
limitUpdates = builder.comment("Enable or disable instance update limiting with distance.")
.define("limitUpdates", true);

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.extension;
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;

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.extension;
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;

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;
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.glUniform1i;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.uniform.UniformBuffer;
import org.slf4j.Logger;
import com.jozufozu.flywheel.gl.GlObject;
import com.mojang.blaze3d.shaders.ProgramManager;
import com.mojang.logging.LogUtils;
public class GlProgram extends GlObject {
private static final Logger LOGGER = LogUtils.getLogger();
public GlProgram(int handle) {
setHandle(handle);
}
public void bind() {
// TODO: bind textures?
UniformBuffer.getInstance()
.sync();
ProgramManager.glUseProgram(handle());
}
@ -36,7 +35,7 @@ public class GlProgram extends GlObject {
int index = glGetUniformLocation(this.handle(), uniform);
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;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.api.pipeline;
package com.jozufozu.flywheel.glsl;
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.ImmutableMap;
import com.jozufozu.flywheel.api.pipeline.SourceComponent;
import com.jozufozu.flywheel.glsl.parse.Import;
import com.jozufozu.flywheel.glsl.parse.ShaderField;
import com.jozufozu.flywheel.glsl.parse.ShaderFunction;

View file

@ -4,14 +4,17 @@ import java.util.ArrayList;
import java.util.List;
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.SourceFile;
import com.jozufozu.flywheel.glsl.span.Span;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.StringUtil;
import com.mojang.logging.LogUtils;
public class ErrorReporter {
private static final Logger LOGGER = LogUtils.getLogger();
private final List<ErrorBuilder> reportedErrors = new ArrayList<>();
@ -107,7 +110,7 @@ public class ErrorReporter {
.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;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.EntityLeaveWorldEvent;
public class EntityWorldHandler {
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());
}
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());
}
}

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.handler;
import java.util.ArrayList;
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.lib.light.LightUpdater;
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
@ -34,7 +34,7 @@ public class ForgeEvents {
}
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)
.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.VertexFormat;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.backend.vertex;
package com.jozufozu.flywheel.impl.vertex;
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.VertexListProvider;

View file

@ -1,16 +1,7 @@
package com.jozufozu.flywheel.lib.backend;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.BackendType;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.backend.engine.batching.BatchingEngine;
import com.jozufozu.flywheel.backend.engine.indirect.IndirectEngine;
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.network.chat.TextComponent;
public class BackendTypes {
public static final Map<String, BackendType> BACKEND_TYPES = new HashMap<>();
public static final BackendType OFF = SimpleBackendType.builder()
public class Backends {
public static final Backend OFF = SimpleBackend.builder()
.properName("Off")
.shortName("off")
.engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED))
.engineSupplier(() -> {
throw new IllegalStateException("Cannot create engine when backend is off.");
})
.fallback(() -> BackendTypes.OFF)
.fallback(() -> Backends.OFF)
.supported(() -> true)
.register();
.register(Flywheel.rl("off"));
/**
* 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")
.shortName("batching")
.engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(BatchingEngine::new)
.fallback(() -> BackendTypes.OFF)
.fallback(() -> Backends.OFF)
.supported(() -> !ShadersModHandler.isShaderPackInUse())
.register();
.register(Flywheel.rl("batching"));
/**
* Use GPU instancing to render everything.
*/
public static final BackendType INSTANCING = SimpleBackendType.builder()
public static final Backend INSTANCING = SimpleBackend.builder()
.properName("GL33 Instanced Arrays")
.shortName("instancing")
.engineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(() -> new InstancingEngine(Contexts.WORLD, 100 * 100))
.fallback(() -> BackendTypes.BATCHING)
.fallback(() -> Backends.BATCHING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
.instancedArraysSupported())
.pipelineShader(Pipelines.INSTANCED_ARRAYS)
.register();
.register(Flywheel.rl("instancing"));
/**
* Use Compute shaders to cull instances.
*/
public static final BackendType INDIRECT = SimpleBackendType.builder()
public static final Backend INDIRECT = SimpleBackend.builder()
.properName("GL46 Compute Culling")
.shortName("indirect")
.engineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN))
.engineSupplier(() -> new IndirectEngine(Contexts.WORLD, 100 * 100))
.fallback(() -> BackendTypes.INSTANCING)
.fallback(() -> Backends.INSTANCING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
.supportsIndirect())
.pipelineShader(Pipelines.INDIRECT)
.register();
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();
}
.register(Flywheel.rl("indirect"));
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 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.pipeline.Pipeline;
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 shortName;
private final Component engineMessage;
private final Supplier<Engine> engineSupplier;
private final Supplier<BackendType> fallback;
private final Supplier<Backend> fallback;
private final BooleanSupplier isSupported;
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.shortName = shortName;
this.engineMessage = engineMessage;
this.engineSupplier = engineSupplier;
this.fallback = fallback;
@ -41,11 +38,6 @@ public class SimpleBackendType implements BackendType {
return properName;
}
@Override
public String getShortName() {
return shortName;
}
@Override
public Component getEngineMessage() {
return engineMessage;
@ -57,8 +49,8 @@ public class SimpleBackendType implements BackendType {
}
@Override
public BackendType findFallback() {
if (this.supported()) {
public Backend findFallback() {
if (this.isSupported()) {
return this;
} else {
return fallback.get()
@ -67,7 +59,7 @@ public class SimpleBackendType implements BackendType {
}
@Override
public boolean supported() {
public boolean isSupported() {
return isSupported.getAsBoolean();
}
@ -78,10 +70,9 @@ public class SimpleBackendType implements BackendType {
public static class Builder {
private String properName;
private String shortName;
private Component engineMessage;
private Supplier<Engine> engineSupplier;
private Supplier<BackendType> fallback;
private Supplier<Backend> fallback;
private BooleanSupplier isSupported;
private Pipeline pipelineShader;
@ -90,11 +81,6 @@ public class SimpleBackendType implements BackendType {
return this;
}
public Builder shortName(String shortName) {
this.shortName = shortName;
return this;
}
public Builder engineMessage(Component engineMessage) {
this.engineMessage = engineMessage;
return this;
@ -105,7 +91,7 @@ public class SimpleBackendType implements BackendType {
return this;
}
public Builder fallback(Supplier<BackendType> fallback) {
public Builder fallback(Supplier<Backend> fallback) {
this.fallback = fallback;
return this;
}
@ -120,8 +106,8 @@ public class SimpleBackendType implements BackendType {
return this;
}
public BackendType register() {
return BackendTypes.register(new SimpleBackendType(properName, shortName, engineMessage, engineSupplier, fallback, isSupported, pipelineShader));
public Backend register(ResourceLocation id) {
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;
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 net.minecraft.resources.ResourceLocation;
public class Contexts {
public static final SimpleContext WORLD = ComponentRegistry.register(new SimpleContext(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
public static final SimpleContext CRUMBLING = ComponentRegistry.register(new SimpleContext(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
public static final SimpleContext WORLD = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
public static final SimpleContext CRUMBLING = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
public static void init() {
// noop

View file

@ -1,14 +1,14 @@
package com.jozufozu.flywheel.lib.format;
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 net.minecraft.resources.ResourceLocation;
public class Formats {
public static final BlockVertex BLOCK = ComponentRegistry.register(new BlockVertex());
public static final PosTexNormalVertex POS_TEX_NORMAL = ComponentRegistry.register(new PosTexNormalVertex());
public static final BlockVertex BLOCK = VertexType.REGISTRY.registerAndGet(new BlockVertex());
public static final PosTexNormalVertex POS_TEX_NORMAL = VertexType.REGISTRY.registerAndGet(new PosTexNormalVertex());
public static void init() {
// 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.stream.Stream;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.task.WorkGroup;
import com.jozufozu.flywheel.backend.BackendUtil;
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.WorldAttached;
@ -68,7 +68,7 @@ public class LightUpdater {
}
})
.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;
import com.jozufozu.flywheel.api.component.ComponentRegistry;
import com.jozufozu.flywheel.api.material.Material;
import net.minecraft.client.renderer.RenderStateShard;
@ -107,7 +106,7 @@ public class SimpleMaterial implements Material {
}
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) {

View file

@ -1,9 +1,9 @@
package com.jozufozu.flywheel.lib.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.gl.GLSLVersion;
import com.jozufozu.flywheel.glsl.SourceComponent;
import net.minecraft.resources.ResourceLocation;

View file

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

View file

@ -5,7 +5,6 @@ import java.util.function.Consumer;
import org.lwjgl.system.MemoryUtil;
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.RenderContext;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
@ -20,7 +19,7 @@ import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.MinecraftForge;
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 int SIZE = 224;

View file

@ -7,8 +7,8 @@ import org.lwjgl.opengl.GL32C;
import org.lwjgl.system.MemoryUtil;
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.buffer.ElementBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.gl.buffer.GlBufferUsage;
import com.mojang.blaze3d.vertex.VertexFormat;

View file

@ -6,7 +6,9 @@ import java.util.function.BooleanSupplier;
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.minecraft.client.Camera;
@ -14,6 +16,8 @@ import net.minecraft.client.renderer.culling.Frustum;
import net.minecraftforge.fml.ModList;
public final class ShadersModHandler {
private static final Logger LOGGER = LogUtils.getLogger();
public static final String OPTIFINE_ROOT_PACKAGE = "net.optifine";
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
if (isOptifineInstalled) {
Backend.LOGGER.info("Optifine detected.");
LOGGER.info("Optifine detected.");
internalHandler = new Optifine();
} else if (isOculusLoaded) {
Backend.LOGGER.info("Oculus detected.");
LOGGER.info("Oculus detected.");
internalHandler = new Oculus();
} else {
Backend.LOGGER.info("No shaders mod detected.");
LOGGER.info("No shaders mod detected.");
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.Unique;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstancingController;
import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
import com.jozufozu.flywheel.extension.BlockEntityTypeExtension;
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 com.google.common.collect.Lists;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
import com.jozufozu.flywheel.extension.ClientLevelExtension;
import net.minecraft.client.multiplayer.ClientLevel;
@ -29,7 +29,7 @@ public abstract class ClientLevelMixin implements ClientLevelExtension {
@Inject(method = "entitiesForRendering", at = @At("RETURN"), cancellable = true)
private void flywheel$filterEntities(CallbackInfoReturnable<Iterable<Entity>> cir) {
if (Backend.isOn()) {
if (BackendManager.isOn()) {
Iterable<Entity> entities = cir.getReturnValue();
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.Unique;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstancingController;
import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
import com.jozufozu.flywheel.extension.EntityTypeExtension;
import net.minecraft.world.entity.Entity;

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