Post-post-pre-refactor-refactor actual refactor

- Mark backends as unavailable if their shader compilation failed
- Update command output to notify when a fallback occurs
This commit is contained in:
Jozufozu 2023-04-18 21:28:28 -07:00
parent 4c8e174712
commit 296aa7ca08
9 changed files with 71 additions and 23 deletions

View file

@ -2,6 +2,8 @@ package com.jozufozu.flywheel.backend;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.backend.compile.IndirectPrograms;
import com.jozufozu.flywheel.backend.compile.InstancingPrograms;
import com.jozufozu.flywheel.backend.engine.batching.BatchingEngine;
import com.jozufozu.flywheel.backend.engine.indirect.IndirectEngine;
import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine;
@ -31,7 +33,7 @@ public class Backends {
.engineFactory(level -> new InstancingEngine(256, Contexts.WORLD))
.fallback(() -> Backends.BATCHING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
.instancedArraysSupported())
.instancedArraysSupported() && InstancingPrograms.allLoaded())
.register(Flywheel.rl("instancing"));
/**
@ -42,7 +44,7 @@ public class Backends {
.engineFactory(level -> new IndirectEngine(256))
.fallback(() -> Backends.INSTANCING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
.supportsIndirect())
.supportsIndirect() && IndirectPrograms.allLoaded())
.register(Flywheel.rl("indirect"));
public static void init() {

View file

@ -6,6 +6,7 @@ import java.util.Map;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.glsl.ShaderSources;
@ -28,7 +29,8 @@ public abstract class AbstractCompiler<K> {
@Nullable
protected abstract GlProgram compile(K key);
public Map<K, GlProgram> compile() {
@Nullable
public Map<K, GlProgram> compileAndReportErrors() {
stats.start();
Map<K, GlProgram> out = new HashMap<>();
for (var key : keys) {
@ -38,6 +40,12 @@ public abstract class AbstractCompiler<K> {
}
}
stats.finish();
if (stats.errored()) {
Flywheel.LOGGER.error(stats.generateErrorLog());
return null;
}
return out;
}

View file

@ -25,15 +25,13 @@ public class CompilerStats {
var elapsed = StringUtil.formatTime(compileEnd - compileStart);
Flywheel.LOGGER.info("Compiled " + shaderCount + " shaders (with " + shaderErrors.size() + " compile errors) " + "and " + programCount + " programs (with " + programErrors.size() + " link errors) in " + elapsed);
}
// TODO: use this to turn off backends
public boolean errored() {
return errored;
}
private String generateLog() {
public String generateErrorLog() {
return String.join("\n", programErrors) + '\n' + shaderErrors.stream()
.map(FailedCompilation::getMessage)
.collect(Collectors.joining("\n"));

View file

@ -25,11 +25,18 @@ public class IndirectPrograms {
public static void reload(ShaderSources sources, ImmutableList<PipelineProgramKey> pipelineKeys, UniformComponent uniformComponent) {
if (instance != null) {
instance.delete();
instance = null;
}
var indirectCompiler = new PipelineCompiler(sources, pipelineKeys, Pipelines.INDIRECT, uniformComponent);
var pipelineCompiler = new PipelineCompiler(sources, pipelineKeys, Pipelines.INDIRECT, uniformComponent);
var cullingCompiler = new CullingCompiler(sources, createCullingKeys(), uniformComponent);
instance = new IndirectPrograms(indirectCompiler.compile(), cullingCompiler.compile());
indirectCompiler.delete();
var pipelineResult = pipelineCompiler.compileAndReportErrors();
var cullingResult = cullingCompiler.compileAndReportErrors();
if (pipelineResult != null && cullingResult != null) {
instance = new IndirectPrograms(pipelineResult, cullingResult);
}
pipelineCompiler.delete();
cullingCompiler.delete();
}
@ -46,6 +53,10 @@ public class IndirectPrograms {
return instance;
}
public static boolean allLoaded() {
return instance != null;
}
public GlProgram getIndirectProgram(VertexType vertexType, InstanceType<?> instanceType, Context contextShader) {
return pipeline.get(new PipelineProgramKey(vertexType, instanceType, contextShader));
}

View file

@ -23,9 +23,15 @@ public class InstancingPrograms {
public static void reload(ShaderSources sources, ImmutableList<PipelineProgramKey> pipelineKeys, UniformComponent uniformComponent) {
if (instance != null) {
instance.delete();
instance = null;
}
var instancingCompiler = new PipelineCompiler(sources, pipelineKeys, Pipelines.INSTANCED_ARRAYS, uniformComponent);
instance = new InstancingPrograms(instancingCompiler.compile());
var result = instancingCompiler.compileAndReportErrors();
if (result != null) {
instance = new InstancingPrograms(result);
}
instancingCompiler.delete();
}
@ -34,6 +40,10 @@ public class InstancingPrograms {
return instance;
}
public static boolean allLoaded() {
return instance != null;
}
public GlProgram get(VertexType vertexType, InstanceType<?> instanceType, Context contextShader) {
return pipeline.get(new PipelineProgramKey(vertexType, instanceType, contextShader));
}

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend.compile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.gl.shader.GlProgram;
@ -8,13 +9,15 @@ public sealed interface LinkResult {
@Nullable
default GlProgram unwrap() {
if (this instanceof Success s) {
return s.program();
}
return null;
}
record Success(GlProgram program, String log) implements LinkResult {
@Override
@NotNull
public GlProgram unwrap() {
return program;
}
}
record Failure(String failure) implements LinkResult {

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend.compile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.gl.shader.GlShader;
@ -7,13 +8,15 @@ import com.jozufozu.flywheel.gl.shader.GlShader;
public sealed interface ShaderResult {
@Nullable
default GlShader unwrap() {
if (this instanceof Success s) {
return s.shader();
}
return null;
}
record Success(GlShader shader, String infoLog) implements ShaderResult {
@Override
@NotNull
public GlShader unwrap() {
return shader;
}
}
record Failure(FailedCompilation failure) implements ShaderResult {

View file

@ -3,6 +3,7 @@ package com.jozufozu.flywheel.config;
import java.util.function.BiConsumer;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.lib.uniform.FlwShaderUniforms;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.IntegerArgumentType;
@ -60,13 +61,25 @@ public class FlwCommands {
.executes(context -> {
LocalPlayer player = Minecraft.getInstance().player;
if (player != null) {
Backend backend = context.getArgument("id", Backend.class);
value.set(Backend.REGISTRY.getIdOrThrow(backend).toString());
Component message = backend.engineMessage();
player.displayClientMessage(message, false);
Backend requestedBackend = context.getArgument("id", Backend.class);
var requestedId = Backend.REGISTRY.getIdOrThrow(requestedBackend)
.toString();
value.set(requestedId);
// Reload renderers so we can report the backend that we fell back to.
Minecraft.getInstance().levelRenderer.allChanged();
var actualBackend = BackendManager.getBackend();
if (actualBackend == null) {
player.displayClientMessage(new TextComponent("Error switching backends, flywheel disabled"), false);
} else if (actualBackend != requestedBackend) {
player.displayClientMessage(new TextComponent("'" + requestedId + "' not available").withStyle(ChatFormatting.RED), false);
var component = actualBackend.engineMessage();
player.displayClientMessage(component, false);
} else {
Component message = requestedBackend.engineMessage();
player.displayClientMessage(message, false);
}
}
return Command.SINGLE_SUCCESS;
})));

View file

@ -80,10 +80,10 @@ public class ShaderSources {
if (findStack.contains(location)) {
generateRecursiveImportException(location);
}
findStack.add(location);
findStack.addLast(location);
}
private void popFindStack() {
findStack.pop();
findStack.removeLast();
}
}