mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-28 16:06:28 +01:00
Some decoupling
- New Loader class in charge of loading and compiling everything - ShaderSources now only loads sources - ShaderSources is immutable now - Resolver singleton in charge of managing name resolutions - ProgramSpecs go through Resolver - WorldShaderPipeline no longer needs reference to ShaderSources
This commit is contained in:
parent
b0c1ebc76f
commit
947c611bbc
17 changed files with 235 additions and 165 deletions
|
@ -37,6 +37,7 @@ public class Backend {
|
||||||
|
|
||||||
public final Minecraft minecraft;
|
public final Minecraft minecraft;
|
||||||
public ShaderSources sources;
|
public ShaderSources sources;
|
||||||
|
public Loader loader;
|
||||||
|
|
||||||
public GLCapabilities capabilities;
|
public GLCapabilities capabilities;
|
||||||
public GlCompat compat;
|
public GlCompat compat;
|
||||||
|
@ -55,7 +56,7 @@ public class Backend {
|
||||||
minecraft = Minecraft.getInstance();
|
minecraft = Minecraft.getInstance();
|
||||||
if (minecraft == null) return;
|
if (minecraft == null) return;
|
||||||
|
|
||||||
sources = new ShaderSources(this);
|
loader = new Loader(this);
|
||||||
|
|
||||||
OptifineHandler.init();
|
OptifineHandler.init();
|
||||||
}
|
}
|
||||||
|
|
125
src/main/java/com/jozufozu/flywheel/backend/Loader.java
Normal file
125
src/main/java/com/jozufozu/flywheel/backend/Loader.java
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
package com.jozufozu.flywheel.backend;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
|
import com.jozufozu.flywheel.backend.source.Resolver;
|
||||||
|
import com.jozufozu.flywheel.backend.source.ShaderLoadingException;
|
||||||
|
import com.jozufozu.flywheel.backend.source.ShaderSources;
|
||||||
|
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||||
|
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
|
||||||
|
import com.jozufozu.flywheel.event.GatherContextEvent;
|
||||||
|
import com.jozufozu.flywheel.util.ResourceUtil;
|
||||||
|
import com.jozufozu.flywheel.util.StreamUtil;
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
import com.mojang.serialization.DataResult;
|
||||||
|
import com.mojang.serialization.JsonOps;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.resources.IReloadableResourceManager;
|
||||||
|
import net.minecraft.resources.IResource;
|
||||||
|
import net.minecraft.resources.IResourceManager;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.fml.ModLoader;
|
||||||
|
import net.minecraftforge.resource.IResourceType;
|
||||||
|
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
||||||
|
import net.minecraftforge.resource.VanillaResourceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main entity for loading shaders.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This class is responsible for invoking the loading, parsing, and compilation stages.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class Loader implements ISelectiveResourceReloadListener {
|
||||||
|
public static final String PROGRAM_DIR = "flywheel/programs/";
|
||||||
|
private static final Gson GSON = new GsonBuilder().create();
|
||||||
|
|
||||||
|
private final Backend backend;
|
||||||
|
public boolean shouldCrash;
|
||||||
|
|
||||||
|
|
||||||
|
public Loader(Backend backend) {
|
||||||
|
this.backend = backend;
|
||||||
|
|
||||||
|
IResourceManager manager = backend.minecraft.getResourceManager();
|
||||||
|
if (manager instanceof IReloadableResourceManager) {
|
||||||
|
((IReloadableResourceManager) manager).registerReloadListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyError() {
|
||||||
|
shouldCrash = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
||||||
|
if (predicate.test(VanillaResourceType.SHADERS)) {
|
||||||
|
backend.refresh();
|
||||||
|
|
||||||
|
if (backend.gl20()) {
|
||||||
|
shouldCrash = false;
|
||||||
|
backend._clearContexts();
|
||||||
|
|
||||||
|
Resolver.INSTANCE.invalidate();
|
||||||
|
ModLoader.get()
|
||||||
|
.postEvent(new GatherContextEvent(backend));
|
||||||
|
|
||||||
|
backend.sources = new ShaderSources(manager);
|
||||||
|
|
||||||
|
loadProgramSpecs(manager);
|
||||||
|
|
||||||
|
Resolver.INSTANCE.resolve(backend.sources);
|
||||||
|
|
||||||
|
for (IShaderContext<?> context : backend.allContexts()) {
|
||||||
|
context.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldCrash) {
|
||||||
|
throw new ShaderLoadingException("Could not load all shaders, see log for details");
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend.log.info("Loaded all shader programs.");
|
||||||
|
|
||||||
|
ClientWorld world = Minecraft.getInstance().level;
|
||||||
|
if (Backend.isFlywheelWorld(world)) {
|
||||||
|
// TODO: looks like it might be good to have another event here
|
||||||
|
InstancedRenderDispatcher.loadAllInWorld(world);
|
||||||
|
CrumblingRenderer.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadProgramSpecs(IResourceManager manager) {
|
||||||
|
Collection<ResourceLocation> programSpecs = manager.listResources(PROGRAM_DIR, s -> s.endsWith(".json"));
|
||||||
|
|
||||||
|
for (ResourceLocation location : programSpecs) {
|
||||||
|
try {
|
||||||
|
IResource file = manager.getResource(location);
|
||||||
|
|
||||||
|
String s = StreamUtil.readToString(file.getInputStream());
|
||||||
|
|
||||||
|
ResourceLocation specName = ResourceUtil.trim(location, PROGRAM_DIR, ".json");
|
||||||
|
|
||||||
|
DataResult<Pair<ProgramSpec, JsonElement>> result = ProgramSpec.CODEC.decode(JsonOps.INSTANCE, GSON.fromJson(s, JsonElement.class));
|
||||||
|
|
||||||
|
ProgramSpec spec = result.get()
|
||||||
|
.orThrow()
|
||||||
|
.getFirst();
|
||||||
|
|
||||||
|
spec.setName(specName);
|
||||||
|
|
||||||
|
backend.register(spec);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Backend.log.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package com.jozufozu.flywheel.backend.pipeline;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.jozufozu.flywheel.backend.source.ShaderLoadingException;
|
||||||
import com.jozufozu.flywheel.backend.source.SourceFile;
|
import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
import com.jozufozu.flywheel.backend.source.error.ErrorReporter;
|
import com.jozufozu.flywheel.backend.source.error.ErrorReporter;
|
||||||
import com.jozufozu.flywheel.backend.source.parse.ShaderFunction;
|
import com.jozufozu.flywheel.backend.source.parse.ShaderFunction;
|
||||||
|
@ -36,7 +37,7 @@ public class InstancingProgramMetaData {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fragmentFunc.isPresent() || !vertexFunc.isPresent()) {
|
if (!fragmentFunc.isPresent() || !vertexFunc.isPresent()) {
|
||||||
throw new RuntimeException();
|
throw new ShaderLoadingException();
|
||||||
}
|
}
|
||||||
|
|
||||||
fragmentMain = fragmentFunc.get();
|
fragmentMain = fragmentFunc.get();
|
||||||
|
@ -50,7 +51,7 @@ public class InstancingProgramMetaData {
|
||||||
|
|
||||||
if (vertexParams.size() != 2) {
|
if (vertexParams.size() != 2) {
|
||||||
ErrorReporter.generateSpanError(vertexMain.getArgs(), "instancing requires vertex function to have 2 arguments");
|
ErrorReporter.generateSpanError(vertexMain.getArgs(), "instancing requires vertex function to have 2 arguments");
|
||||||
throw new RuntimeException();
|
throw new ShaderLoadingException();
|
||||||
}
|
}
|
||||||
|
|
||||||
interpolantName = vertexMain.getType();
|
interpolantName = vertexMain.getType();
|
||||||
|
@ -76,7 +77,7 @@ public class InstancingProgramMetaData {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!maybeVertex.isPresent() || !maybeInterpolant.isPresent() || !maybeInstance.isPresent()) {
|
if (!maybeVertex.isPresent() || !maybeInterpolant.isPresent() || !maybeInstance.isPresent()) {
|
||||||
throw new RuntimeException();
|
throw new ShaderLoadingException();
|
||||||
}
|
}
|
||||||
|
|
||||||
interpolant = maybeInterpolant.get();
|
interpolant = maybeInterpolant.get();
|
||||||
|
|
|
@ -7,7 +7,6 @@ import java.util.List;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.source.FileResolution;
|
import com.jozufozu.flywheel.backend.source.FileResolution;
|
||||||
import com.jozufozu.flywheel.backend.source.ShaderSources;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
import com.jozufozu.flywheel.backend.source.SourceFile;
|
import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram;
|
import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram;
|
||||||
|
@ -21,15 +20,12 @@ import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
public class WorldShaderPipeline<P extends WorldProgram> implements IShaderPipeline<P> {
|
public class WorldShaderPipeline<P extends WorldProgram> implements IShaderPipeline<P> {
|
||||||
|
|
||||||
private final ShaderSources sources;
|
|
||||||
|
|
||||||
private final ExtensibleGlProgram.Factory<P> factory;
|
private final ExtensibleGlProgram.Factory<P> factory;
|
||||||
|
|
||||||
private final Template<?> template;
|
private final Template<?> template;
|
||||||
private final FileResolution header;
|
private final FileResolution header;
|
||||||
|
|
||||||
public WorldShaderPipeline(ShaderSources sources, ExtensibleGlProgram.Factory<P> factory, Template<?> template, FileResolution header) {
|
public WorldShaderPipeline(ExtensibleGlProgram.Factory<P> factory, Template<?> template, FileResolution header) {
|
||||||
this.sources = sources;
|
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.header = header;
|
this.header = header;
|
||||||
|
@ -37,7 +33,7 @@ public class WorldShaderPipeline<P extends WorldProgram> implements IShaderPipel
|
||||||
|
|
||||||
public IMultiProgram<P> compile(ProgramSpec spec) {
|
public IMultiProgram<P> compile(ProgramSpec spec) {
|
||||||
|
|
||||||
SourceFile file = sources.source(spec.source);
|
SourceFile file = spec.getSource().getFile();
|
||||||
|
|
||||||
return compile(spec.name, file, spec.getStates());
|
return compile(spec.name, file, spec.getStates());
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,10 @@ public class FileResolution {
|
||||||
* Spans that have references that resolved to this.
|
* Spans that have references that resolved to this.
|
||||||
*/
|
*/
|
||||||
private final List<Span> foundSpans = new ArrayList<>();
|
private final List<Span> foundSpans = new ArrayList<>();
|
||||||
private final ShaderSources parent;
|
|
||||||
private final ResourceLocation fileLoc;
|
private final ResourceLocation fileLoc;
|
||||||
private SourceFile file;
|
private SourceFile file;
|
||||||
|
|
||||||
public FileResolution(ShaderSources parent, ResourceLocation fileLoc) {
|
public FileResolution(ResourceLocation fileLoc) {
|
||||||
this.parent = parent;
|
|
||||||
this.fileLoc = fileLoc;
|
this.fileLoc = fileLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +50,9 @@ public class FileResolution {
|
||||||
* </p>
|
* </p>
|
||||||
* @param span A span where this file is referenced.
|
* @param span A span where this file is referenced.
|
||||||
*/
|
*/
|
||||||
public void addSpan(Span span) {
|
public FileResolution addSpan(Span span) {
|
||||||
foundSpans.add(span);
|
foundSpans.add(span);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,10 +62,10 @@ public class FileResolution {
|
||||||
* Called after all files are loaded. If we can't find the file here, it doesn't exist.
|
* Called after all files are loaded. If we can't find the file here, it doesn't exist.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
void resolve() {
|
void resolve(ISourceHolder sources) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
file = this.parent.source(fileLoc);
|
file = sources.findSource(fileLoc);
|
||||||
} catch (RuntimeException error) {
|
} catch (RuntimeException error) {
|
||||||
ErrorBuilder builder = new ErrorBuilder();
|
ErrorBuilder builder = new ErrorBuilder();
|
||||||
builder.error(String.format("could not find source for file %s", fileLoc));
|
builder.error(String.format("could not find source for file %s", fileLoc));
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.jozufozu.flywheel.backend.source;
|
||||||
|
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A minimal source file lookup function.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ISourceHolder {
|
||||||
|
|
||||||
|
SourceFile findSource(ResourceLocation name);
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.jozufozu.flywheel.backend.source;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages deferred file resolution.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Interns all referenced files in all sources, duplicating the final lookups and allowing for more dev-friendly
|
||||||
|
* error reporting.
|
||||||
|
* </p><p>
|
||||||
|
* See {@link FileResolution} for more information.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class Resolver {
|
||||||
|
|
||||||
|
public static final Resolver INSTANCE = new Resolver();
|
||||||
|
|
||||||
|
private final Map<ResourceLocation, FileResolution> resolutions = new HashMap<>();
|
||||||
|
|
||||||
|
public FileResolution findShader(ResourceLocation fileLoc) {
|
||||||
|
return resolutions.computeIfAbsent(fileLoc, FileResolution::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try and resolve all referenced source files, printing errors if any aren't found.
|
||||||
|
*/
|
||||||
|
public void resolve(ISourceHolder sources) {
|
||||||
|
for (FileResolution resolution : resolutions.values()) {
|
||||||
|
resolution.resolve(sources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates all FileResolutions.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Called on resource reload.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public void invalidate() {
|
||||||
|
resolutions.values().forEach(FileResolution::invalidate);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,126 +5,27 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.gson.Gson;
|
import com.jozufozu.flywheel.util.ResourceUtil;
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.IShaderContext;
|
|
||||||
import com.jozufozu.flywheel.backend.ResourceUtil;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
|
||||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
|
||||||
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
|
|
||||||
import com.jozufozu.flywheel.event.GatherContextEvent;
|
|
||||||
import com.jozufozu.flywheel.util.StreamUtil;
|
import com.jozufozu.flywheel.util.StreamUtil;
|
||||||
import com.mojang.datafixers.util.Pair;
|
|
||||||
import com.mojang.serialization.DataResult;
|
|
||||||
import com.mojang.serialization.JsonOps;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.world.ClientWorld;
|
|
||||||
import net.minecraft.resources.IReloadableResourceManager;
|
|
||||||
import net.minecraft.resources.IResource;
|
import net.minecraft.resources.IResource;
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.fml.ModLoader;
|
|
||||||
import net.minecraftforge.resource.IResourceType;
|
|
||||||
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
|
||||||
import net.minecraftforge.resource.VanillaResourceType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main entity for loading shaders.
|
* The main object for loading and parsing source files.
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This class is responsible for invoking the loading, parsing, and compilation stages.
|
|
||||||
* </p>
|
|
||||||
*/
|
*/
|
||||||
public class ShaderSources implements ISelectiveResourceReloadListener {
|
public class ShaderSources implements ISourceHolder {
|
||||||
public static final String SHADER_DIR = "flywheel/shaders/";
|
public static final String SHADER_DIR = "flywheel/shaders/";
|
||||||
public static final String PROGRAM_DIR = "flywheel/programs/";
|
|
||||||
public static final ArrayList<String> EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl");
|
public static final ArrayList<String> EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl");
|
||||||
private static final Gson GSON = new GsonBuilder().create();
|
|
||||||
|
|
||||||
private final Map<ResourceLocation, SourceFile> shaderSources = new HashMap<>();
|
private final Map<ResourceLocation, SourceFile> shaderSources = new HashMap<>();
|
||||||
|
|
||||||
private final Map<ResourceLocation, FileResolution> resolutions = new HashMap<>();
|
public final Index index;
|
||||||
|
|
||||||
private boolean shouldCrash;
|
public ShaderSources(IResourceManager manager) {
|
||||||
private final Backend backend;
|
|
||||||
|
|
||||||
public Index index;
|
|
||||||
|
|
||||||
public ShaderSources(Backend backend) {
|
|
||||||
this.backend = backend;
|
|
||||||
IResourceManager manager = backend.minecraft.getResourceManager();
|
|
||||||
if (manager instanceof IReloadableResourceManager) {
|
|
||||||
((IReloadableResourceManager) manager).registerReloadListener(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceFile source(ResourceLocation name) {
|
|
||||||
SourceFile source = shaderSources.get(name);
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
throw new ShaderLoadingException(String.format("shader '%s' does not exist", name));
|
|
||||||
}
|
|
||||||
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileResolution resolveFile(ResourceLocation fileLoc) {
|
|
||||||
return resolutions.computeIfAbsent(fileLoc, l -> new FileResolution(this, l));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public void notifyError() {
|
|
||||||
shouldCrash = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
|
||||||
if (predicate.test(VanillaResourceType.SHADERS)) {
|
|
||||||
backend.refresh();
|
|
||||||
|
|
||||||
if (backend.gl20()) {
|
|
||||||
shouldCrash = false;
|
|
||||||
|
|
||||||
backend._clearContexts();
|
|
||||||
resolutions.values().forEach(FileResolution::invalidate);
|
|
||||||
shaderSources.clear();
|
|
||||||
ModLoader.get()
|
|
||||||
.postEvent(new GatherContextEvent(backend));
|
|
||||||
|
|
||||||
loadProgramSpecs(manager);
|
|
||||||
loadShaderSources(manager);
|
|
||||||
|
|
||||||
for (FileResolution resolution : resolutions.values()) {
|
|
||||||
resolution.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IShaderContext<?> context : backend.allContexts()) {
|
|
||||||
context.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldCrash) {
|
|
||||||
throw new ShaderLoadingException("Could not load all shaders, see log for details");
|
|
||||||
}
|
|
||||||
|
|
||||||
Backend.log.info("Loaded all shader programs.");
|
|
||||||
|
|
||||||
ClientWorld world = Minecraft.getInstance().level;
|
|
||||||
if (Backend.isFlywheelWorld(world)) {
|
|
||||||
// TODO: looks like it might be good to have another event here
|
|
||||||
InstancedRenderDispatcher.loadAllInWorld(world);
|
|
||||||
CrumblingRenderer.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadShaderSources(IResourceManager manager) {
|
|
||||||
Collection<ResourceLocation> allShaders = manager.listResources(SHADER_DIR, s -> {
|
Collection<ResourceLocation> allShaders = manager.listResources(SHADER_DIR, s -> {
|
||||||
for (String ext : EXTENSIONS) {
|
for (String ext : EXTENSIONS) {
|
||||||
if (s.endsWith(ext)) return true;
|
if (s.endsWith(ext)) return true;
|
||||||
|
@ -149,30 +50,14 @@ public class ShaderSources implements ISelectiveResourceReloadListener {
|
||||||
index = new Index(shaderSources);
|
index = new Index(shaderSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceFile findSource(ResourceLocation name) {
|
||||||
|
SourceFile source = shaderSources.get(name);
|
||||||
|
|
||||||
private void loadProgramSpecs(IResourceManager manager) {
|
if (source == null) {
|
||||||
Collection<ResourceLocation> programSpecs = manager.listResources(PROGRAM_DIR, s -> s.endsWith(".json"));
|
throw new ShaderLoadingException(String.format("shader '%s' does not exist", name));
|
||||||
|
|
||||||
for (ResourceLocation location : programSpecs) {
|
|
||||||
try {
|
|
||||||
IResource file = manager.getResource(location);
|
|
||||||
|
|
||||||
String s = StreamUtil.readToString(file.getInputStream());
|
|
||||||
|
|
||||||
ResourceLocation specName = ResourceUtil.trim(location, PROGRAM_DIR, ".json");
|
|
||||||
|
|
||||||
DataResult<Pair<ProgramSpec, JsonElement>> result = ProgramSpec.CODEC.decode(JsonOps.INSTANCE, GSON.fromJson(s, JsonElement.class));
|
|
||||||
|
|
||||||
ProgramSpec spec = result.get()
|
|
||||||
.orThrow()
|
|
||||||
.getFirst();
|
|
||||||
|
|
||||||
spec.setName(specName);
|
|
||||||
|
|
||||||
backend.register(spec);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Backend.log.error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,7 +294,7 @@ public class SourceFile {
|
||||||
Span use = Span.fromMatcher(this, uses);
|
Span use = Span.fromMatcher(this, uses);
|
||||||
Span file = Span.fromMatcher(this, uses, 1);
|
Span file = Span.fromMatcher(this, uses, 1);
|
||||||
|
|
||||||
imports.add(new Import(parent, use, file));
|
imports.add(new Import(Resolver.INSTANCE, use, file));
|
||||||
|
|
||||||
elisions.add(use); // we have to trim that later
|
elisions.add(use); // we have to trim that later
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.jozufozu.flywheel.backend.source.error;
|
package com.jozufozu.flywheel.backend.source.error;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.source.SourceFile;
|
import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
import com.jozufozu.flywheel.backend.source.span.Span;
|
import com.jozufozu.flywheel.backend.source.span.Span;
|
||||||
import com.jozufozu.flywheel.util.FlwUtil;
|
import com.jozufozu.flywheel.util.FlwUtil;
|
||||||
|
@ -55,7 +57,7 @@ public class ErrorBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErrorBuilder hintIncludeFor(Span span, CharSequence msg) {
|
public ErrorBuilder hintIncludeFor(@Nullable Span span, CharSequence msg) {
|
||||||
if (span == null) return this;
|
if (span == null) return this;
|
||||||
|
|
||||||
hint("add " + span.getSourceFile().importStatement() + " " + msg)
|
hint("add " + span.getSourceFile().importStatement() + " " + msg)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import java.util.Optional;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.source.FileResolution;
|
import com.jozufozu.flywheel.backend.source.FileResolution;
|
||||||
import com.jozufozu.flywheel.backend.source.ShaderSources;
|
import com.jozufozu.flywheel.backend.source.Resolver;
|
||||||
import com.jozufozu.flywheel.backend.source.error.ErrorReporter;
|
import com.jozufozu.flywheel.backend.source.error.ErrorReporter;
|
||||||
import com.jozufozu.flywheel.backend.source.SourceFile;
|
import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
import com.jozufozu.flywheel.backend.source.span.Span;
|
import com.jozufozu.flywheel.backend.source.span.Span;
|
||||||
|
@ -21,15 +21,13 @@ public class Import extends AbstractShaderElement {
|
||||||
private final Span file;
|
private final Span file;
|
||||||
|
|
||||||
private final FileResolution resolution;
|
private final FileResolution resolution;
|
||||||
private final ResourceLocation fileLoc;
|
|
||||||
|
|
||||||
public Import(ShaderSources parent, Span self, Span file) {
|
public Import(Resolver resolver, Span self, Span file) {
|
||||||
super(self);
|
super(self);
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
fileLoc = toRL(file);
|
resolution = resolver.findShader(toRL(file))
|
||||||
resolution = parent.resolveFile(fileLoc);
|
.addSpan(file);
|
||||||
resolution.addSpan(file);
|
|
||||||
|
|
||||||
IMPORTS.add(this);
|
IMPORTS.add(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,12 @@ package com.jozufozu.flywheel.core;
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.source.FileResolution;
|
import com.jozufozu.flywheel.backend.source.FileResolution;
|
||||||
import com.jozufozu.flywheel.backend.ResourceUtil;
|
import com.jozufozu.flywheel.util.ResourceUtil;
|
||||||
import com.jozufozu.flywheel.backend.SpecMetaRegistry;
|
import com.jozufozu.flywheel.backend.SpecMetaRegistry;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.IShaderPipeline;
|
import com.jozufozu.flywheel.backend.pipeline.IShaderPipeline;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.InstancingTemplate;
|
import com.jozufozu.flywheel.backend.pipeline.InstancingTemplate;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline;
|
import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline;
|
||||||
|
import com.jozufozu.flywheel.backend.source.Resolver;
|
||||||
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
||||||
import com.jozufozu.flywheel.core.shader.WorldFog;
|
import com.jozufozu.flywheel.core.shader.WorldFog;
|
||||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||||
|
@ -34,11 +35,11 @@ public class Contexts {
|
||||||
SpecMetaRegistry.register(WorldFog.LINEAR);
|
SpecMetaRegistry.register(WorldFog.LINEAR);
|
||||||
SpecMetaRegistry.register(WorldFog.EXP2);
|
SpecMetaRegistry.register(WorldFog.EXP2);
|
||||||
|
|
||||||
FileResolution crumblingBuiltins = backend.sources.resolveFile(ResourceUtil.subPath(Names.CRUMBLING, ".glsl"));
|
FileResolution crumblingBuiltins = Resolver.INSTANCE.findShader(ResourceUtil.subPath(Names.CRUMBLING, ".glsl"));
|
||||||
FileResolution worldBuiltins = backend.sources.resolveFile(ResourceUtil.subPath(Names.WORLD, ".glsl"));
|
FileResolution worldBuiltins = Resolver.INSTANCE.findShader(ResourceUtil.subPath(Names.WORLD, ".glsl"));
|
||||||
|
|
||||||
IShaderPipeline<CrumblingProgram> crumblingPipeline = new WorldShaderPipeline<>(backend.sources, CrumblingProgram::new, InstancingTemplate.INSTANCE, crumblingBuiltins);
|
IShaderPipeline<CrumblingProgram> crumblingPipeline = new WorldShaderPipeline<>(CrumblingProgram::new, InstancingTemplate.INSTANCE, crumblingBuiltins);
|
||||||
IShaderPipeline<WorldProgram> worldPipeline = new WorldShaderPipeline<>(backend.sources, WorldProgram::new, InstancingTemplate.INSTANCE, worldBuiltins);
|
IShaderPipeline<WorldProgram> worldPipeline = new WorldShaderPipeline<>(WorldProgram::new, InstancingTemplate.INSTANCE, worldBuiltins);
|
||||||
|
|
||||||
CRUMBLING = backend.register(WorldContext.builder(backend, Names.CRUMBLING).build(crumblingPipeline));
|
CRUMBLING = backend.register(WorldContext.builder(backend, Names.CRUMBLING).build(crumblingPipeline));
|
||||||
WORLD = backend.register(WorldContext.builder(backend, Names.WORLD).build(worldPipeline));
|
WORLD = backend.register(WorldContext.builder(backend, Names.WORLD).build(worldPipeline));
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class WorldContext<P extends WorldProgram> implements IShaderContext<P> {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Backend.log.error("Error loading program {}", spec.name);
|
Backend.log.error("Error loading program {}", spec.name);
|
||||||
Backend.log.error("", e);
|
Backend.log.error("", e);
|
||||||
backend.sources.notifyError();
|
backend.loader.notifyError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ package com.jozufozu.flywheel.core.shader.spec;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.source.FileResolution;
|
||||||
|
import com.jozufozu.flywheel.backend.source.Resolver;
|
||||||
import com.jozufozu.flywheel.backend.source.SourceFile;
|
import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
@ -27,19 +29,19 @@ public class ProgramSpec {
|
||||||
// TODO: Block model style inheritance?
|
// TODO: Block model style inheritance?
|
||||||
public static final Codec<ProgramSpec> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
public static final Codec<ProgramSpec> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
ResourceLocation.CODEC.fieldOf("source")
|
ResourceLocation.CODEC.fieldOf("source")
|
||||||
.forGetter(ProgramSpec::getSource),
|
.forGetter(ProgramSpec::getSourceLoc),
|
||||||
ProgramState.CODEC.listOf()
|
ProgramState.CODEC.listOf()
|
||||||
.optionalFieldOf("states", Collections.emptyList())
|
.optionalFieldOf("states", Collections.emptyList())
|
||||||
.forGetter(ProgramSpec::getStates))
|
.forGetter(ProgramSpec::getStates))
|
||||||
.apply(instance, ProgramSpec::new));
|
.apply(instance, ProgramSpec::new));
|
||||||
|
|
||||||
public ResourceLocation name;
|
public ResourceLocation name;
|
||||||
public final ResourceLocation source;
|
public final FileResolution source;
|
||||||
|
|
||||||
public final List<ProgramState> states;
|
public final List<ProgramState> states;
|
||||||
|
|
||||||
public ProgramSpec(ResourceLocation source, List<ProgramState> states) {
|
public ProgramSpec(ResourceLocation source, List<ProgramState> states) {
|
||||||
this.source = source;
|
this.source = Resolver.INSTANCE.findShader(source);
|
||||||
this.states = states;
|
this.states = states;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +49,11 @@ public class ProgramSpec {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceLocation getSource() {
|
public ResourceLocation getSourceLoc() {
|
||||||
|
return source.getFileLoc();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileResolution getSource() {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.backend;
|
package com.jozufozu.flywheel.util;
|
||||||
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#use "flywheel:core/diffuse.glsl"
|
#use "flywheel:core/diffuse.glsl"
|
||||||
|
|
||||||
#use "flywheel:data/modelvertex.glsl"
|
#use "flywheel:data/modelvertex.glsl"
|
||||||
|
|
||||||
#use "flywheel:block.frag"
|
#use "flywheel:block.frag"
|
||||||
|
|
||||||
struct Instance {
|
struct Instance {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#use "flywheel:core/matutils.glsl"
|
|
||||||
#use "flywheel:core/quaternion.glsl"
|
#use "flywheel:core/quaternion.glsl"
|
||||||
#use "flywheel:core/diffuse.glsl"
|
#use "flywheel:core/diffuse.glsl"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue