Load a single file

- Use the new immutable sources system to load a single file
 - It doesn't compile it yet
 - Slightly less verbose name
This commit is contained in:
Jozufozu 2021-07-05 12:09:13 -07:00
parent fa5d586f0a
commit b10e4024c3
8 changed files with 142 additions and 18 deletions

View File

@ -11,6 +11,7 @@ import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
@ -25,11 +26,14 @@ import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.loading.Shader;
import com.jozufozu.flywheel.backend.loading.ShaderLoadingException;
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.jozufozu.flywheel.event.GatherContextEvent;
import com.mojang.blaze3d.systems.RenderSystem;
@ -86,6 +90,11 @@ public class ShaderSources implements ISelectiveResourceReloadListener {
loadProgramSpecs(manager);
loadShaderSources(manager);
WorldShaderPipeline<WorldProgram> pl = new WorldShaderPipeline<>(this);
SourceFile source = source(new ResourceLocation(Flywheel.ID, "model.glsl"));
pl.compile(source, Collections.emptyList());
for (IShaderContext<?> context : backend.allContexts()) {
context.load();
}

View File

@ -21,4 +21,14 @@ public class PipelineProgramBuilder {
sources.addAll(files);
return this;
}
public CharSequence build() {
StringBuilder builder = new StringBuilder();
for (SourceFile source : sources) {
builder.append(source.getElidedSource());
}
return builder;
}
}

View File

@ -28,8 +28,6 @@ public class SourceFile {
// https://regexr.com/60n3d
public static final Pattern functionDeclaration = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{");
public static final Pattern versionDetector = Pattern.compile("#version[^\\n]*");
public final ResourceLocation name;
private final String source;
private final ShaderSources parent;
@ -150,7 +148,24 @@ public class SourceFile {
return builder.toString();
}
public static Stream<String> lines(String s) {
return new BufferedReader(new StringReader(s)).lines();
private CharSequence elided = null;
public CharSequence getElidedSource() {
if (elided == null) {
StringBuilder out = new StringBuilder();
int lastEnd = 0;
for (Span elision : elisions) {
out.append(source, lastEnd, elision.getStart());
lastEnd = elision.getEnd();
}
out.append(source, lastEnd, source.length());
elided = out.toString();
}
return elided;
}
}

View File

@ -4,20 +4,37 @@ import java.util.List;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.ShaderSources;
import com.jozufozu.flywheel.core.shader.IMultiProgram;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.jozufozu.flywheel.core.shader.spec.ProgramState;
public class WorldShaderPipeline<P extends WorldProgram> {
@Nullable // TODO: temporary null return
public P compile(SourceFile file) {
private final ShaderSources sources;
public WorldShaderPipeline(ShaderSources sources) {
this.sources = sources;
}
@Nullable // TODO: temporary null return
public IMultiProgram<P> compile(ProgramSpec spec) {
SourceFile file = sources.source(spec.vert);
return compile(file, spec.getStates());
}
@Nullable
public IMultiProgram<P> compile(SourceFile file, List<ProgramState> variants) {
PipelineProgramBuilder builder = new PipelineProgramBuilder();
builder.includeAll(Includer.recurseIncludes(file));
builder.include(file);
builder.build();
return null;
}

View File

@ -7,6 +7,8 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.ResourceUtil;
import com.jozufozu.flywheel.backend.ShaderContext;
@ -21,7 +23,7 @@ import com.jozufozu.flywheel.backend.loading.Shader;
import com.jozufozu.flywheel.backend.loading.ShaderLoadingException;
import com.jozufozu.flywheel.backend.loading.ShaderTransformer;
import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram;
import com.jozufozu.flywheel.core.shader.StateSensitiveMultiProgram;
import com.jozufozu.flywheel.core.shader.GameStateProgram;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.jozufozu.flywheel.core.shader.spec.ProgramState;
@ -149,12 +151,11 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
private void loadSpec(ProgramSpec spec) {
try {
StateSensitiveMultiProgram.Builder<P> builder = new StateSensitiveMultiProgram.Builder<>(factory.create(loadAndLink(spec, null)));
GameStateProgram.Builder<P> builder = GameStateProgram.builder(compile(spec, null));
for (ProgramState state : spec.states) {
Program variant = loadAndLink(spec, state);
builder.withVariant(state.getContext(), factory.create(variant, state.getExtensions()));
builder.withVariant(state.getContext(), compile(spec, state));
}
programs.put(spec.name, builder.build());
@ -166,6 +167,13 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
}
}
private P compile(ProgramSpec spec, @Nullable ProgramState state) {
if (state != null)
return factory.create(loadAndLink(spec, state), state.getExtensions());
else
return factory.create(loadAndLink(spec, null));
}
public interface TemplateFactory {
ProgramTemplate create(ShaderSources loader);
}

View File

@ -8,12 +8,12 @@ import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.core.shader.spec.IGameStateCondition;
import com.jozufozu.flywheel.util.Pair;
public class StateSensitiveMultiProgram<P extends GlProgram> implements IMultiProgram<P> {
public class GameStateProgram<P extends GlProgram> implements IMultiProgram<P> {
private final List<Pair<IGameStateCondition, P>> variants;
private final P fallback;
protected StateSensitiveMultiProgram(List<Pair<IGameStateCondition, P>> variants, P fallback) {
protected GameStateProgram(List<Pair<IGameStateCondition, P>> variants, P fallback) {
this.variants = variants;
this.fallback = fallback;
}
@ -38,6 +38,10 @@ public class StateSensitiveMultiProgram<P extends GlProgram> implements IMultiPr
fallback.delete();
}
public static <P extends GlProgram> Builder<P> builder(P fallback) {
return new Builder<>(fallback);
}
public static class Builder<P extends GlProgram> {
private final P fallback;
private final List<Pair<IGameStateCondition, P>> variants = new ArrayList<>();
@ -52,7 +56,7 @@ public class StateSensitiveMultiProgram<P extends GlProgram> implements IMultiPr
}
public IMultiProgram<P> build() {
return new StateSensitiveMultiProgram<>(ImmutableList.copyOf(variants), fallback);
return new GameStateProgram<>(ImmutableList.copyOf(variants), fallback);
}
}
}

View File

@ -12,11 +12,14 @@ import net.minecraft.util.ResourceLocation;
public class ProgramSpec {
// TODO: Block model style inheritance?
public static final Codec<ProgramSpec> CODEC = RecordCodecBuilder.create(instance -> instance.group(ResourceLocation.CODEC.fieldOf("vert")
.forGetter(ProgramSpec::getVert), ResourceLocation.CODEC.fieldOf("frag")
.forGetter(ProgramSpec::getFrag), ProgramState.CODEC.listOf()
.optionalFieldOf("states", Collections.emptyList())
.forGetter(ProgramSpec::getStates))
public static final Codec<ProgramSpec> CODEC = RecordCodecBuilder.create(instance -> instance.group(
ResourceLocation.CODEC.fieldOf("vert")
.forGetter(ProgramSpec::getVert),
ResourceLocation.CODEC.fieldOf("frag")
.forGetter(ProgramSpec::getFrag),
ProgramState.CODEC.listOf()
.optionalFieldOf("states", Collections.emptyList())
.forGetter(ProgramSpec::getStates))
.apply(instance, ProgramSpec::new));
public ResourceLocation name;

View File

@ -0,0 +1,58 @@
#use "flywheel:core/diffuse.glsl"
struct Instance {
vec2 light;
vec4 color;
mat4 transform;
mat3 normalMat;
};
struct Vertex {
vec3 pos;
vec3 normal;
vec2 texCoords;
};
struct BlockFrag {
vec2 texCoords;
vec4 color;
float diffuse;
vec2 light;
};
BlockFrag vertex(Vertex v, Instance i) {
vec4 worldPos = i.transform * vec4(v.pos, 1.);
vec3 norm = i.normalMat * v.normal;
FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm);
norm = normalize(norm);
BlockFrag b;
b.diffuse = diffuse(norm);
b.texCoords = v.texCoords;
b.light = i.light;
#if defined(DEBUG_NORMAL)
b.color = vec4(norm, 1.);
#else
b.color = i.color;
#endif
return b;
}
void fragment(BlockFrag r) {
vec4 tex = FLWBlockTexture(r.texCoords);
vec4 color = vec4(tex.rgb * FLWLight(r.light).rgb * r.diffuse, tex.a) * r.color;
// flw_WorldPos = ;
// flw_Normal = ;
// flw_Albedo = tex.rgb;
// flw_Alpha = tex.a;
// flw_LightMap = r.light;
// flw_Tint = r.color;
FLWFinalizeColor(color);
}