Handle arbitrary numbers of GameStateProviders

- Use bitset instead of long.
 - We only ever iterate over the GameStateProviders, so use a list instead of a map.
 - GameStateProviders don't need IDs.
This commit is contained in:
Jozufozu 2022-01-13 15:58:51 -08:00
parent 298ca3e9f1
commit b351baa824
6 changed files with 54 additions and 62 deletions

View file

@ -1,61 +1,58 @@
package com.jozufozu.flywheel.core; package com.jozufozu.flywheel.core;
import java.util.HashMap; import java.util.ArrayList;
import java.util.Map; import java.util.BitSet;
import java.util.List;
import com.jozufozu.flywheel.core.shader.GameStateProvider; import com.jozufozu.flywheel.core.shader.GameStateProvider;
import com.jozufozu.flywheel.core.shader.ShaderConstants; import com.jozufozu.flywheel.core.shader.ShaderConstants;
import com.jozufozu.flywheel.core.shader.StateSnapshot; import com.jozufozu.flywheel.core.shader.StateSnapshot;
import net.minecraft.resources.ResourceLocation;
public class GameStateRegistry { public class GameStateRegistry {
private static final Map<ResourceLocation, GameStateProvider> registeredStateProviders = new HashMap<>(); private static final List<GameStateProvider> PROVIDERS = new ArrayList<>();
public static void _clear() { /**
registeredStateProviders.clear(); * Registers a game state provider.
} * @param provider The provider to register.
*/
public static GameStateProvider getStateProvider(ResourceLocation location) { public static void register(GameStateProvider provider) {
GameStateProvider out = registeredStateProviders.get(location); PROVIDERS.add(provider);
if (out == null) {
throw new IllegalArgumentException("State provider '" + location + "' does not exist.");
}
return out;
}
public static void register(GameStateProvider context) {
if (registeredStateProviders.containsKey(context.getID())) {
throw new IllegalStateException("Duplicate game state provider: " + context.getID());
}
registeredStateProviders.put(context.getID(), context);
} }
/**
* Takes a snapshot of the current game state, storing it in a bit set.
* @return An object that represents the current game state.
*/
public static StateSnapshot takeSnapshot() { public static StateSnapshot takeSnapshot() {
long ctx = 0; BitSet bitSet = new BitSet(PROVIDERS.size());
for (GameStateProvider state : registeredStateProviders.values()) {
if (state.isTrue()) { for (int i = 0, listSize = PROVIDERS.size(); i < listSize; i++) {
ctx |= 1; if (PROVIDERS.get(i).isTrue()) {
bitSet.set(i);
} }
ctx <<= 1;
} }
return new StateSnapshot(ctx); return new StateSnapshot(bitSet);
} }
public static ShaderConstants getDefines(long ctx) { /**
long stateID = ctx; * Based on the given snapshot, gathers shader constants to be injected during shader compilation.
* @param snapshot The snapshot to use.
* @return A list of shader constants.
*/
public static ShaderConstants getShaderConstants(StateSnapshot snapshot) {
BitSet ctx = snapshot.ctx();
ShaderConstants shaderConstants = new ShaderConstants(); ShaderConstants shaderConstants = new ShaderConstants();
for (GameStateProvider state : registeredStateProviders.values()) { for (int i = 0, listSize = PROVIDERS.size(); i < listSize; i++) {
if ((stateID & 1) == 1) { if (ctx.get(i)) {
state.alterConstants(shaderConstants); PROVIDERS.get(i).alterConstants(shaderConstants);
} }
stateID >>= 1;
} }
return shaderConstants; return shaderConstants;
} }
public static void _clear() {
PROVIDERS.clear();
}
} }

View file

@ -71,7 +71,7 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
} }
public ShaderConstants getShaderConstants() { public ShaderConstants getShaderConstants() {
ShaderConstants shaderConstants = ctx.getDefines(); ShaderConstants shaderConstants = ctx.getShaderConstants();
if (alphaDiscard > 0) { if (alphaDiscard > 0) {
shaderConstants.define("ALPHA_DISCARD", alphaDiscard); shaderConstants.define("ALPHA_DISCARD", alphaDiscard);

View file

@ -25,7 +25,7 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
finalSource.append(CompileUtil.generateHeader(template.getVersion(), ShaderType.VERTEX)); finalSource.append(CompileUtil.generateHeader(template.getVersion(), ShaderType.VERTEX));
key.ctx.getDefines().writeInto(finalSource); key.ctx.getShaderConstants().writeInto(finalSource);
finalSource.append(""" finalSource.append("""
struct Vertex { struct Vertex {

View file

@ -1,12 +1,19 @@
package com.jozufozu.flywheel.core.shader; package com.jozufozu.flywheel.core.shader;
import net.minecraft.resources.ResourceLocation; /**
* An object that provides a view of the current game state for shader compilation.
*/
public interface GameStateProvider { public interface GameStateProvider {
ResourceLocation getID(); /**
* Get the status of this game state provider.
* @return Returning {@code true} will cause #alterConstants to be called before compiling a shader.
*/
boolean isTrue(); boolean isTrue();
/**
* Alter the constants for shader compilation.
* @param constants The shader constants.
*/
void alterConstants(ShaderConstants constants); void alterConstants(ShaderConstants constants);
} }

View file

@ -1,18 +1,9 @@
package com.jozufozu.flywheel.core.shader; package com.jozufozu.flywheel.core.shader;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import net.minecraft.resources.ResourceLocation; public enum NormalDebugStateProvider implements GameStateProvider {
INSTANCE;
public class NormalDebugStateProvider implements GameStateProvider {
public static final NormalDebugStateProvider INSTANCE = new NormalDebugStateProvider();
public static final ResourceLocation NAME = Flywheel.rl("normal_debug");
protected NormalDebugStateProvider() {
}
@Override @Override
public boolean isTrue() { public boolean isTrue() {
@ -20,11 +11,6 @@ public class NormalDebugStateProvider implements GameStateProvider {
.debugNormals(); .debugNormals();
} }
@Override
public ResourceLocation getID() {
return NAME;
}
@Override @Override
public void alterConstants(ShaderConstants constants) { public void alterConstants(ShaderConstants constants) {
constants.define("DEBUG_NORMAL"); constants.define("DEBUG_NORMAL");

View file

@ -1,11 +1,13 @@
package com.jozufozu.flywheel.core.shader; package com.jozufozu.flywheel.core.shader;
import java.util.BitSet;
import com.jozufozu.flywheel.core.GameStateRegistry; import com.jozufozu.flywheel.core.GameStateRegistry;
public record StateSnapshot(long ctx) { public record StateSnapshot(BitSet ctx) {
// TODO: is this needed? // TODO: is this needed?
public ShaderConstants getDefines() { public ShaderConstants getShaderConstants() {
return GameStateRegistry.getDefines(ctx); return GameStateRegistry.getShaderConstants(this);
} }
} }