mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-22 10:57:55 +01:00
Pre-processing Pre-refactor
- Move pipeline code to backend package - Store compiled programs in FlwPrograms instead of FlwCompiler - Rename PipelineContext to PipelineProgramKey and remove CullingContext - Remove PipelineContextSet and CullingContextSet - Improve quality of dumped sources - Rename pipeline directory to internal - Add underscores before more internal GLSL variables - Remove unnecessary GLSL files
This commit is contained in:
parent
5b84046c1d
commit
7afa2486ad
42 changed files with 369 additions and 596 deletions
|
@ -5,7 +5,7 @@ import org.slf4j.Logger;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backends;
|
import com.jozufozu.flywheel.backend.Backends;
|
||||||
import com.jozufozu.flywheel.backend.Loader;
|
import com.jozufozu.flywheel.backend.Loader;
|
||||||
import com.jozufozu.flywheel.backend.Pipelines;
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines;
|
||||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||||
import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer;
|
import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer;
|
||||||
import com.jozufozu.flywheel.config.BackendArgument;
|
import com.jozufozu.flywheel.config.BackendArgument;
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package com.jozufozu.flywheel.api.backend;
|
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.api.registry.IdRegistry;
|
||||||
import com.jozufozu.flywheel.impl.IdRegistryImpl;
|
import com.jozufozu.flywheel.impl.IdRegistryImpl;
|
||||||
|
|
||||||
|
@ -31,6 +28,4 @@ public interface Backend {
|
||||||
* Check if this backend is supported.
|
* Check if this backend is supported.
|
||||||
*/
|
*/
|
||||||
boolean isSupported();
|
boolean isSupported();
|
||||||
|
|
||||||
@Nullable Pipeline pipelineShader();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.jozufozu.flywheel.api.pipeline;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
|
||||||
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;
|
|
||||||
|
|
||||||
public interface Pipeline {
|
|
||||||
GLSLVersion glslVersion();
|
|
||||||
|
|
||||||
ResourceLocation vertexShader();
|
|
||||||
|
|
||||||
ResourceLocation fragmentShader();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the source component necessary to convert a packed {@link InstanceType} into its shader representation.
|
|
||||||
*
|
|
||||||
* @return A source component defining functions that unpack a representation of the given instance type.
|
|
||||||
*/
|
|
||||||
SourceComponent assemble(InstanceAssemblerContext context);
|
|
||||||
|
|
||||||
record InstanceAssemblerContext(ShaderSources sources, VertexType vertexType, InstanceType<?> instanceType) {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -32,7 +32,6 @@ public class Backends {
|
||||||
.fallback(() -> Backends.BATCHING)
|
.fallback(() -> Backends.BATCHING)
|
||||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
|
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
|
||||||
.instancedArraysSupported())
|
.instancedArraysSupported())
|
||||||
.pipelineShader(Pipelines.INSTANCED_ARRAYS)
|
|
||||||
.register(Flywheel.rl("instancing"));
|
.register(Flywheel.rl("instancing"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,7 +43,6 @@ public class Backends {
|
||||||
.fallback(() -> Backends.INSTANCING)
|
.fallback(() -> Backends.INSTANCING)
|
||||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
|
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
|
||||||
.supportsIndirect())
|
.supportsIndirect())
|
||||||
.pipelineShader(Pipelines.INDIRECT)
|
|
||||||
.register(Flywheel.rl("indirect"));
|
.register(Flywheel.rl("indirect"));
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package com.jozufozu.flywheel.backend;
|
package com.jozufozu.flywheel.backend;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
|
import com.jozufozu.flywheel.backend.compile.FlwPrograms;
|
||||||
import com.jozufozu.flywheel.glsl.ShaderSources;
|
|
||||||
import com.jozufozu.flywheel.glsl.error.ErrorReporter;
|
|
||||||
import com.jozufozu.flywheel.impl.BackendManagerImpl;
|
import com.jozufozu.flywheel.impl.BackendManagerImpl;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -25,14 +23,7 @@ public class Loader implements ResourceManagerReloadListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResourceManagerReload(ResourceManager manager) {
|
public void onResourceManagerReload(ResourceManager manager) {
|
||||||
var errorReporter = new ErrorReporter();
|
FlwPrograms.reload(manager);
|
||||||
ShaderSources sources = new ShaderSources(errorReporter, manager);
|
|
||||||
|
|
||||||
if (FlwCompiler.INSTANCE != null) {
|
|
||||||
FlwCompiler.INSTANCE.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
FlwCompiler.INSTANCE = new FlwCompiler(sources);
|
|
||||||
|
|
||||||
// TODO: Move this to the impl package
|
// TODO: Move this to the impl package
|
||||||
BackendManagerImpl.refresh(Minecraft.getInstance().level);
|
BackendManagerImpl.refresh(Minecraft.getInstance().level);
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class Compilation {
|
||||||
|
|
||||||
public Compilation(GLSLVersion glslVersion, ShaderType shaderType) {
|
public Compilation(GLSLVersion glslVersion, ShaderType shaderType) {
|
||||||
this.generatedSource = new StringBuilder();
|
this.generatedSource = new StringBuilder();
|
||||||
this.fullSource = new StringBuilder(CompileUtil.generateHeader(glslVersion, shaderType));
|
this.fullSource = new StringBuilder(CompileUtil.generateHeader(glslVersion, shaderType)).append('\n');
|
||||||
this.glslVersion = glslVersion;
|
this.glslVersion = glslVersion;
|
||||||
this.shaderType = shaderType;
|
this.shaderType = shaderType;
|
||||||
}
|
}
|
||||||
|
@ -71,10 +71,6 @@ public class Compilation {
|
||||||
.append(" : enable\n");
|
.append(" : enable\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addComponentName(ResourceLocation name) {
|
|
||||||
componentNames.add(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void appendComponent(SourceComponent component) {
|
public void appendComponent(SourceComponent component) {
|
||||||
var source = component.source();
|
var source = component.source();
|
||||||
|
|
||||||
|
@ -85,12 +81,12 @@ public class Compilation {
|
||||||
.toString()));
|
.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fullSource.append(source)
|
fullSource.append(source);
|
||||||
.append('\n');
|
componentNames.add(component.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String sourceHeader(SourceFile sourceFile) {
|
private String sourceHeader(SourceFile sourceFile) {
|
||||||
return "#line " + 0 + ' ' + getOrCreateFileID(sourceFile) + " // " + sourceFile.name + '\n';
|
return '\n' + "#line " + 0 + ' ' + getOrCreateFileID(sourceFile) + " // " + sourceFile.name + '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generatedHeader(String generatedCode, String comment) {
|
private String generatedHeader(String generatedCode, String comment) {
|
||||||
|
@ -98,7 +94,7 @@ public class Compilation {
|
||||||
int lines = StringUtil.countLines(generatedCode);
|
int lines = StringUtil.countLines(generatedCode);
|
||||||
|
|
||||||
// all generated code is put in file 0,
|
// all generated code is put in file 0,
|
||||||
var out = "#line " + generatedLines + ' ' + 0;
|
var out = '\n' + "#line " + generatedLines + ' ' + 0;
|
||||||
|
|
||||||
generatedLines += lines;
|
generatedLines += lines;
|
||||||
|
|
||||||
|
@ -123,12 +119,13 @@ public class Compilation {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String buildShaderName() {
|
private String buildShaderName() {
|
||||||
|
// TODO: This name is so long it fails to create the file. Use index and map indices to component sources in separate file?
|
||||||
var components = componentNames.stream()
|
var components = componentNames.stream()
|
||||||
.map(ResourceLocation::toString)
|
.map(ResourceLocation::toString)
|
||||||
.map(s -> s.replaceAll("/", "_")
|
.map(s -> s.replaceAll("/", "_")
|
||||||
.replaceAll(":", "\\$"))
|
.replaceAll(":", "\\$"))
|
||||||
.collect(Collectors.joining(";"));
|
.collect(Collectors.joining(";"));
|
||||||
return shaderType.name + glslVersion + ';' + components;
|
return shaderType.name + glslVersion + ';' /*+ components*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void dumpSource(String source, String fileName) {
|
private static void dumpSource(String source, String fileName) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class CompileUtil {
|
||||||
public static final Pattern matType = Pattern.compile("^mat([234])(?:x([234]))?$");
|
public static final Pattern matType = Pattern.compile("^mat([234])(?:x([234]))?$");
|
||||||
|
|
||||||
public static String generateHeader(GLSLVersion version, ShaderType type) {
|
public static String generateHeader(GLSLVersion version, ShaderType type) {
|
||||||
return version.getVersionLine() + type.getDefineStatement() + '\n';
|
return version.getVersionLine() + type.getDefineStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getElementCount(String type) {
|
public static int getElementCount(String type) {
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.compile;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
|
||||||
|
|
||||||
public record CullingContext(InstanceType<?> instanceType) {
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.compile;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
|
||||||
|
|
||||||
public class CullingContextSet {
|
|
||||||
static CullingContextSet create() {
|
|
||||||
var builder = new CullingContextSet();
|
|
||||||
for (InstanceType<?> instanceType : InstanceType.REGISTRY) {
|
|
||||||
builder.add(instanceType);
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<CullingContext> contexts = new ArrayList<>();
|
|
||||||
private final List<CullingContext> contextView = Collections.unmodifiableList(contexts);
|
|
||||||
|
|
||||||
CullingContextSet() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<CullingContext> all() {
|
|
||||||
return contextView;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return contexts.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void add(InstanceType<?> instanceType) {
|
|
||||||
var ctx = new CullingContext(instanceType);
|
|
||||||
|
|
||||||
contexts.add(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,14 +10,14 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.context.Context;
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||||
import com.jozufozu.flywheel.api.pipeline.Pipeline;
|
|
||||||
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
|
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.backend.compile.FlwPrograms.PipelineProgramKey;
|
||||||
import com.jozufozu.flywheel.backend.Pipelines;
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline;
|
||||||
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
|
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
|
||||||
import com.jozufozu.flywheel.gl.GLSLVersion;
|
import com.jozufozu.flywheel.gl.GLSLVersion;
|
||||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||||
|
@ -30,36 +30,42 @@ import com.jozufozu.flywheel.glsl.generate.GlslExpr;
|
||||||
import com.jozufozu.flywheel.lib.material.MaterialIndices;
|
import com.jozufozu.flywheel.lib.material.MaterialIndices;
|
||||||
import com.jozufozu.flywheel.util.StringUtil;
|
import com.jozufozu.flywheel.util.StringUtil;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class FlwCompiler {
|
public class FlwCompiler {
|
||||||
|
private final long compileStart = System.nanoTime();
|
||||||
|
|
||||||
public static FlwCompiler INSTANCE;
|
|
||||||
|
|
||||||
final long compileStart = System.nanoTime();
|
|
||||||
private final ShaderSources sources;
|
private final ShaderSources sources;
|
||||||
private final UniformComponent uniformComponent;
|
|
||||||
|
private final ImmutableList<PipelineProgramKey> pipelineKeys;
|
||||||
|
private final ImmutableList<InstanceType<?>> cullingKeys;
|
||||||
|
|
||||||
|
private final ShaderCompiler shaderCompiler;
|
||||||
|
private final List<FailedCompilation> errors = new ArrayList<>();
|
||||||
|
|
||||||
private final MaterialAdapterComponent vertexMaterialComponent;
|
private final MaterialAdapterComponent vertexMaterialComponent;
|
||||||
private final MaterialAdapterComponent fragmentMaterialComponent;
|
private final MaterialAdapterComponent fragmentMaterialComponent;
|
||||||
|
private final UniformComponent uniformComponent;
|
||||||
|
|
||||||
private final PipelineContextSet pipelineContexts;
|
private final Map<PipelineProgramKey, GlProgram> pipelinePrograms = new HashMap<>();
|
||||||
private final CullingContextSet cullingContexts;
|
private final Map<InstanceType<?>, GlProgram> cullingPrograms = new HashMap<>();
|
||||||
|
|
||||||
final ShaderCompiler shaderCompiler;
|
public FlwCompiler(ShaderSources sources, ImmutableList<PipelineProgramKey> pipelineKeys, ImmutableList<InstanceType<?>> cullingKeys) {
|
||||||
final Map<PipelineContext, GlProgram> pipelinePrograms = new HashMap<>();
|
this.sources = sources;
|
||||||
final Map<InstanceType<?>, GlProgram> cullingPrograms = new HashMap<>();
|
|
||||||
final List<FailedCompilation> errors = new ArrayList<>();
|
|
||||||
|
|
||||||
public FlwCompiler(ShaderSources sources) {
|
this.pipelineKeys = pipelineKeys;
|
||||||
this.shaderCompiler = ShaderCompiler.builder()
|
this.cullingKeys = cullingKeys;
|
||||||
|
|
||||||
|
shaderCompiler = ShaderCompiler.builder()
|
||||||
.errorConsumer(errors::add)
|
.errorConsumer(errors::add)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
this.sources = sources;
|
vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
|
||||||
this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
|
|
||||||
.materialSources(MaterialIndices.getAllVertexShaders())
|
.materialSources(MaterialIndices.getAllVertexShaders())
|
||||||
.adapt(FnSignature.ofVoid("flw_materialVertex"))
|
.adapt(FnSignature.ofVoid("flw_materialVertex"))
|
||||||
.switchOn(GlslExpr.variable("flw_materialVertexID"))
|
.switchOn(GlslExpr.variable("_flw_materialVertexID"))
|
||||||
.build(sources);
|
.build(sources);
|
||||||
this.fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter"))
|
fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter"))
|
||||||
.materialSources(MaterialIndices.getAllFragmentShaders())
|
.materialSources(MaterialIndices.getAllFragmentShaders())
|
||||||
.adapt(FnSignature.ofVoid("flw_materialFragment"))
|
.adapt(FnSignature.ofVoid("flw_materialFragment"))
|
||||||
.adapt(FnSignature.create()
|
.adapt(FnSignature.create()
|
||||||
|
@ -72,36 +78,116 @@ public class FlwCompiler {
|
||||||
.name("flw_fogFilter")
|
.name("flw_fogFilter")
|
||||||
.arg("vec4", "color")
|
.arg("vec4", "color")
|
||||||
.build(), GlslExpr.variable("color"))
|
.build(), GlslExpr.variable("color"))
|
||||||
.switchOn(GlslExpr.variable("flw_materialFragmentID"))
|
.switchOn(GlslExpr.variable("_flw_materialFragmentID"))
|
||||||
.build(sources);
|
.build(sources);
|
||||||
this.uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms"))
|
uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms"))
|
||||||
.sources(ShaderUniforms.REGISTRY.getAll()
|
.sources(ShaderUniforms.REGISTRY.getAll()
|
||||||
.stream()
|
.stream()
|
||||||
.map(ShaderUniforms::uniformShader)
|
.map(ShaderUniforms::uniformShader)
|
||||||
.toList())
|
.toList())
|
||||||
.build(sources);
|
.build(sources);
|
||||||
|
}
|
||||||
|
|
||||||
this.pipelineContexts = PipelineContextSet.create();
|
public FlwPrograms compile() {
|
||||||
this.cullingContexts = CullingContextSet.create();
|
|
||||||
|
|
||||||
doCompilation();
|
doCompilation();
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
|
|
||||||
|
return new FlwPrograms(pipelinePrograms, cullingPrograms);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doCompilation() {
|
private void doCompilation() {
|
||||||
for (var ctx : pipelineContexts.all()) {
|
for (var key : pipelineKeys) {
|
||||||
compilePipelineContext(ctx);
|
GlProgram glProgram = compilePipelineProgram(key);
|
||||||
|
if (glProgram != null) {
|
||||||
|
pipelinePrograms.put(key, glProgram);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var ctx : cullingContexts.all()) {
|
for (var key : cullingKeys) {
|
||||||
compileComputeCuller(ctx);
|
GlProgram glProgram = compileCullingProgram(key);
|
||||||
|
if (glProgram != null) {
|
||||||
|
cullingPrograms.put(key, glProgram);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GlProgram link(int... shaders) {
|
||||||
|
var handle = glCreateProgram();
|
||||||
|
for (var shader : shaders) {
|
||||||
|
glAttachShader(handle, shader);
|
||||||
|
}
|
||||||
|
glLinkProgram(handle);
|
||||||
|
CompileUtil.checkLinkLog(handle);
|
||||||
|
return new GlProgram(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private GlProgram compilePipelineProgram(PipelineProgramKey key) {
|
||||||
|
var glslVersion = key.pipelineShader()
|
||||||
|
.glslVersion();
|
||||||
|
|
||||||
|
var vertex = shaderCompiler.compile(glslVersion, ShaderType.VERTEX, getVertexComponents(key));
|
||||||
|
var fragment = shaderCompiler.compile(glslVersion, ShaderType.FRAGMENT, getFragmentComponents(key));
|
||||||
|
|
||||||
|
if (vertex == null || fragment == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var glProgram = link(vertex.handle(), fragment.handle());
|
||||||
|
key.contextShader()
|
||||||
|
.onProgramLink(glProgram);
|
||||||
|
return glProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableList<SourceComponent> getVertexComponents(PipelineProgramKey key) {
|
||||||
|
var instanceAssembly = key.pipelineShader()
|
||||||
|
.assembler()
|
||||||
|
.assemble(new Pipeline.InstanceAssemblerContext(sources, key.vertexType(), key.instanceType()));
|
||||||
|
|
||||||
|
var layout = sources.find(key.vertexType()
|
||||||
|
.layoutShader());
|
||||||
|
var instance = sources.find(key.instanceType()
|
||||||
|
.instanceShader());
|
||||||
|
var context = sources.find(key.contextShader()
|
||||||
|
.vertexShader());
|
||||||
|
var pipeline = sources.find(key.pipelineShader()
|
||||||
|
.vertexShader());
|
||||||
|
|
||||||
|
return ImmutableList.of(uniformComponent, vertexMaterialComponent, instanceAssembly, layout, instance, context, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableList<SourceComponent> getFragmentComponents(PipelineProgramKey key) {
|
||||||
|
var context = sources.find(key.contextShader()
|
||||||
|
.fragmentShader());
|
||||||
|
var pipeline = sources.find(key.pipelineShader()
|
||||||
|
.fragmentShader());
|
||||||
|
return ImmutableList.of(uniformComponent, fragmentMaterialComponent, context, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private GlProgram compileCullingProgram(InstanceType<?> key) {
|
||||||
|
var computeComponents = getComputeComponents(key);
|
||||||
|
var result = shaderCompiler.compile(GLSLVersion.V460, ShaderType.COMPUTE, computeComponents);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return link(result.handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableList<SourceComponent> getComputeComponents(InstanceType<?> instanceType) {
|
||||||
|
var instanceAssembly = new IndirectComponent(sources, instanceType);
|
||||||
|
var instance = sources.find(instanceType.instanceShader());
|
||||||
|
var pipeline = sources.find(Files.INDIRECT_CULL);
|
||||||
|
|
||||||
|
return ImmutableList.of(uniformComponent, instanceAssembly, instance, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
private void finish() {
|
private void finish() {
|
||||||
long compileEnd = System.nanoTime();
|
long compileEnd = System.nanoTime();
|
||||||
int programCount = pipelineContexts.size() + InstanceType.REGISTRY.getAll().size();
|
int programCount = pipelineKeys.size() + cullingKeys.size();
|
||||||
int shaderCount = shaderCompiler.shaderCount();
|
int shaderCount = shaderCompiler.shaderCount();
|
||||||
int errorCount = errors.size();
|
int errorCount = errors.size();
|
||||||
var elapsed = StringUtil.formatTime(compileEnd - compileStart);
|
var elapsed = StringUtil.formatTime(compileEnd - compileStart);
|
||||||
|
@ -112,94 +198,16 @@ public class FlwCompiler {
|
||||||
var details = errors.stream()
|
var details = errors.stream()
|
||||||
.map(FailedCompilation::getMessage)
|
.map(FailedCompilation::getMessage)
|
||||||
.collect(Collectors.joining("\n"));
|
.collect(Collectors.joining("\n"));
|
||||||
// throw new ShaderLoadingException("Compilation failed.\n" + details);
|
// TODO: disable backend instead of crashing if compilation fails
|
||||||
|
throw new ShaderLoadingException("Compilation failed.\n" + details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
pipelinePrograms.values()
|
|
||||||
.forEach(GlProgram::delete);
|
|
||||||
cullingPrograms.values()
|
|
||||||
.forEach(GlProgram::delete);
|
|
||||||
shaderCompiler.delete();
|
shaderCompiler.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlProgram getPipelineProgram(VertexType vertexType, InstanceType<?> instanceType, Context contextShader, Pipeline pipelineShader) {
|
private static final class Files {
|
||||||
return pipelinePrograms.get(new PipelineContext(vertexType, instanceType, contextShader, pipelineShader));
|
public static final ResourceLocation INDIRECT_CULL = Flywheel.rl("internal/indirect_cull.glsl");
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlProgram getCullingProgram(InstanceType<?> instanceType) {
|
|
||||||
return cullingPrograms.get(instanceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void compilePipelineContext(PipelineContext ctx) {
|
|
||||||
var glslVersion = ctx.pipelineShader()
|
|
||||||
.glslVersion();
|
|
||||||
|
|
||||||
var vertex = shaderCompiler.compile(glslVersion, ShaderType.VERTEX, getVertexComponents(ctx));
|
|
||||||
var fragment = shaderCompiler.compile(glslVersion, ShaderType.FRAGMENT, getFragmentComponents(ctx));
|
|
||||||
|
|
||||||
if (vertex == null || fragment == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var glProgram = link(vertex.handle(), fragment.handle());
|
|
||||||
ctx.contextShader()
|
|
||||||
.onProgramLink(glProgram);
|
|
||||||
pipelinePrograms.put(ctx, glProgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void compileComputeCuller(CullingContext ctx) {
|
|
||||||
var computeComponents = getComputeComponents(ctx.instanceType());
|
|
||||||
var result = shaderCompiler.compile(GLSLVersion.V460, ShaderType.COMPUTE, computeComponents);
|
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cullingPrograms.put(ctx.instanceType(), link(result.handle()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GlProgram link(int... shaders) {
|
|
||||||
var handle = glCreateProgram();
|
|
||||||
for (var shader : shaders) {
|
|
||||||
glAttachShader(handle, shader);
|
|
||||||
}
|
|
||||||
glLinkProgram(handle);
|
|
||||||
CompileUtil.checkLinkLog(handle);
|
|
||||||
return new GlProgram(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ImmutableList<SourceComponent> getVertexComponents(PipelineContext ctx) {
|
|
||||||
var instanceAssembly = ctx.pipelineShader()
|
|
||||||
.assemble(new Pipeline.InstanceAssemblerContext(sources, ctx.vertexType(), ctx.instanceType()));
|
|
||||||
|
|
||||||
var layout = sources.find(ctx.vertexType()
|
|
||||||
.layoutShader());
|
|
||||||
var instance = sources.find(ctx.instanceType()
|
|
||||||
.instanceShader());
|
|
||||||
var context = sources.find(ctx.contextShader()
|
|
||||||
.vertexShader());
|
|
||||||
var pipeline = sources.find(ctx.pipelineShader()
|
|
||||||
.vertexShader());
|
|
||||||
|
|
||||||
return ImmutableList.of(uniformComponent, vertexMaterialComponent, instanceAssembly, layout, instance, context, pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ImmutableList<SourceComponent> getFragmentComponents(PipelineContext ctx) {
|
|
||||||
var context = sources.find(ctx.contextShader()
|
|
||||||
.fragmentShader());
|
|
||||||
var pipeline = sources.find(ctx.pipelineShader()
|
|
||||||
.fragmentShader());
|
|
||||||
return ImmutableList.of(uniformComponent, fragmentMaterialComponent, context, pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ImmutableList<SourceComponent> getComputeComponents(InstanceType<?> instanceType) {
|
|
||||||
var instanceAssembly = new IndirectComponent(sources, instanceType);
|
|
||||||
var instance = sources.find(instanceType.instanceShader());
|
|
||||||
var pipeline = sources.find(Pipelines.Files.INDIRECT_CULL);
|
|
||||||
|
|
||||||
return ImmutableList.of(uniformComponent, instanceAssembly, instance, pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
package com.jozufozu.flywheel.backend.compile;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.jozufozu.flywheel.api.context.Context;
|
||||||
|
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline;
|
||||||
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines;
|
||||||
|
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||||
|
import com.jozufozu.flywheel.glsl.ShaderSources;
|
||||||
|
import com.jozufozu.flywheel.glsl.error.ErrorReporter;
|
||||||
|
import com.jozufozu.flywheel.lib.context.Contexts;
|
||||||
|
|
||||||
|
import net.minecraft.server.packs.resources.ResourceManager;
|
||||||
|
|
||||||
|
public class FlwPrograms {
|
||||||
|
private static FlwPrograms instance;
|
||||||
|
|
||||||
|
private final Map<PipelineProgramKey, GlProgram> pipelinePrograms;
|
||||||
|
private final Map<InstanceType<?>, GlProgram> cullingPrograms;
|
||||||
|
|
||||||
|
public FlwPrograms(Map<PipelineProgramKey, GlProgram> pipelinePrograms, Map<InstanceType<?>, GlProgram> cullingPrograms) {
|
||||||
|
this.pipelinePrograms = pipelinePrograms;
|
||||||
|
this.cullingPrograms = cullingPrograms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reload(ResourceManager resourceManager) {
|
||||||
|
if (instance != null) {
|
||||||
|
instance.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorReporter errorReporter = new ErrorReporter();
|
||||||
|
ShaderSources sources = new ShaderSources(errorReporter, resourceManager);
|
||||||
|
FlwCompiler compiler = new FlwCompiler(sources, createPipelineKeys(), createCullingKeys());
|
||||||
|
instance = compiler.compile();
|
||||||
|
compiler.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImmutableList<PipelineProgramKey> createPipelineKeys() {
|
||||||
|
ImmutableList.Builder<PipelineProgramKey> builder = ImmutableList.builder();
|
||||||
|
for (Pipeline pipelineShader : Pipelines.ALL) {
|
||||||
|
for (InstanceType<?> instanceType : InstanceType.REGISTRY) {
|
||||||
|
for (VertexType vertexType : VertexType.REGISTRY) {
|
||||||
|
builder.add(new PipelineProgramKey(vertexType, instanceType, Contexts.WORLD, pipelineShader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImmutableList<InstanceType<?>> createCullingKeys() {
|
||||||
|
ImmutableList.Builder<InstanceType<?>> builder = ImmutableList.builder();
|
||||||
|
for (InstanceType<?> instanceType : InstanceType.REGISTRY) {
|
||||||
|
builder.add(instanceType);
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static FlwPrograms get() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlProgram getPipelineProgram(VertexType vertexType, InstanceType<?> instanceType, Context contextShader, Pipeline pipelineShader) {
|
||||||
|
return pipelinePrograms.get(new PipelineProgramKey(vertexType, instanceType, contextShader, pipelineShader));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlProgram getCullingProgram(InstanceType<?> instanceType) {
|
||||||
|
return cullingPrograms.get(instanceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void delete() {
|
||||||
|
pipelinePrograms.values()
|
||||||
|
.forEach(GlProgram::delete);
|
||||||
|
cullingPrograms.values()
|
||||||
|
.forEach(GlProgram::delete);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the entire context of a program's usage.
|
||||||
|
*
|
||||||
|
* @param vertexType The vertex type the program should be adapted for.
|
||||||
|
* @param instanceType The instance shader to use.
|
||||||
|
* @param contextShader The context shader to use.
|
||||||
|
* @param pipelineShader The pipeline shader to use.
|
||||||
|
*/
|
||||||
|
public record PipelineProgramKey(VertexType vertexType, InstanceType<?> instanceType, Context contextShader,
|
||||||
|
Pipeline pipelineShader) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,6 +61,8 @@ public class MaterialAdapterComponent implements SourceComponent {
|
||||||
.body(body -> generateAdapter(body, adaptedFunction));
|
.body(body -> generateAdapter(body, adaptedFunction));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.blankLine();
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.compile;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.context.Context;
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
|
||||||
import com.jozufozu.flywheel.api.pipeline.Pipeline;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the entire context of a program's usage.
|
|
||||||
*
|
|
||||||
* @param vertexType The vertexType the program should be adapted for.
|
|
||||||
* @param instanceType The instance shader to use.
|
|
||||||
* @param contextShader The context shader to use.
|
|
||||||
*/
|
|
||||||
public record PipelineContext(VertexType vertexType, InstanceType<?> instanceType, Context contextShader,
|
|
||||||
Pipeline pipelineShader) {
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
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.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.api.context.Context;
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
|
||||||
import com.jozufozu.flywheel.api.pipeline.Pipeline;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
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 : availablePipelineShaders()) {
|
|
||||||
for (InstanceType<?> instanceType : InstanceType.REGISTRY) {
|
|
||||||
for (VertexType vertexType : VertexType.REGISTRY) {
|
|
||||||
builder.add(vertexType, instanceType, Contexts.WORLD, pipelineShader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
return contextView;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return contexts.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void add(VertexType vertexType, InstanceType<?> instanceType, Context world, Pipeline pipelineShader) {
|
|
||||||
var ctx = new PipelineContext(vertexType, instanceType, world, pipelineShader);
|
|
||||||
|
|
||||||
contexts.add(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -41,6 +41,8 @@ public class UniformComponent implements SourceComponent {
|
||||||
.name("FLWUniforms")
|
.name("FLWUniforms")
|
||||||
.member("flywheel_uniforms", "flywheel");
|
.member("flywheel_uniforms", "flywheel");
|
||||||
|
|
||||||
|
builder.blankLine();
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.jozufozu.flywheel.backend.compile.pipeline;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public record Pipeline(GLSLVersion glslVersion, ResourceLocation vertexShader, ResourceLocation fragmentShader, InstanceAssembler assembler) {
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface InstanceAssembler {
|
||||||
|
/**
|
||||||
|
* Generate the source component necessary to convert a packed {@link InstanceType} into its shader representation.
|
||||||
|
*
|
||||||
|
* @return A source component defining functions that unpack a representation of the given instance type.
|
||||||
|
*/
|
||||||
|
SourceComponent assemble(InstanceAssemblerContext context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record InstanceAssemblerContext(ShaderSources sources, VertexType vertexType, InstanceType<?> instanceType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private GLSLVersion glslVersion;
|
||||||
|
private ResourceLocation vertex;
|
||||||
|
private ResourceLocation fragment;
|
||||||
|
private InstanceAssembler assembler;
|
||||||
|
|
||||||
|
public Builder glslVersion(GLSLVersion glslVersion) {
|
||||||
|
this.glslVersion = glslVersion;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder vertex(ResourceLocation vertex) {
|
||||||
|
this.vertex = vertex;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder fragment(ResourceLocation fragment) {
|
||||||
|
this.fragment = fragment;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder assembler(InstanceAssembler assembler) {
|
||||||
|
this.assembler = assembler;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pipeline build() {
|
||||||
|
return new Pipeline(glslVersion, vertex, fragment, assembler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,35 +1,38 @@
|
||||||
package com.jozufozu.flywheel.backend;
|
package com.jozufozu.flywheel.backend.compile.pipeline;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
|
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
|
||||||
import com.jozufozu.flywheel.backend.engine.instancing.InstancedArraysComponent;
|
import com.jozufozu.flywheel.backend.engine.instancing.InstancedArraysComponent;
|
||||||
import com.jozufozu.flywheel.gl.GLSLVersion;
|
import com.jozufozu.flywheel.gl.GLSLVersion;
|
||||||
import com.jozufozu.flywheel.lib.pipeline.SimplePipeline;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class Pipelines {
|
public final class Pipelines {
|
||||||
public static final SimplePipeline INSTANCED_ARRAYS = SimplePipeline.builder()
|
public static final Pipeline INSTANCED_ARRAYS = Pipeline.builder()
|
||||||
.glslVersion(GLSLVersion.V420)
|
.glslVersion(GLSLVersion.V420)
|
||||||
.vertex(Files.INSTANCED_ARRAYS_DRAW)
|
.vertex(Files.INSTANCED_ARRAYS_DRAW)
|
||||||
.fragment(Files.DRAW_FRAGMENT)
|
.fragment(Files.DRAW_FRAGMENT)
|
||||||
.assemblerFactory(InstancedArraysComponent::new)
|
.assembler(InstancedArraysComponent::new)
|
||||||
.build();
|
.build();
|
||||||
public static final SimplePipeline INDIRECT = SimplePipeline.builder()
|
public static final Pipeline INDIRECT = Pipeline.builder()
|
||||||
.glslVersion(GLSLVersion.V460)
|
.glslVersion(GLSLVersion.V460)
|
||||||
.vertex(Files.INDIRECT_DRAW)
|
.vertex(Files.INDIRECT_DRAW)
|
||||||
.fragment(Files.DRAW_FRAGMENT)
|
.fragment(Files.DRAW_FRAGMENT)
|
||||||
.assemblerFactory(IndirectComponent::new)
|
.assembler(IndirectComponent::new)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static final List<Pipeline> ALL = List.of(INSTANCED_ARRAYS, INDIRECT);
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Files {
|
public static final class Files {
|
||||||
public static final ResourceLocation DRAW_FRAGMENT = Flywheel.rl("pipeline/draw.frag");
|
public static final ResourceLocation INSTANCED_ARRAYS_DRAW = Flywheel.rl("internal/instanced_arrays_draw.vert");
|
||||||
public static final ResourceLocation INSTANCED_ARRAYS_DRAW = Flywheel.rl("pipeline/instanced_arrays_draw.vert");
|
public static final ResourceLocation INDIRECT_DRAW = Flywheel.rl("internal/indirect_draw.vert");
|
||||||
public static final ResourceLocation INDIRECT_DRAW = Flywheel.rl("pipeline/indirect_draw.vert");
|
public static final ResourceLocation DRAW_FRAGMENT = Flywheel.rl("internal/draw.frag");
|
||||||
public static final ResourceLocation INDIRECT_CULL = Flywheel.rl("pipeline/indirect_cull.glsl");
|
|
||||||
public static final ResourceLocation UTIL_TYPES = Flywheel.rl("util/types.glsl");
|
public static final ResourceLocation UTIL_TYPES = Flywheel.rl("util/types.glsl");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,8 +7,8 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||||
import com.jozufozu.flywheel.api.layout.LayoutItem;
|
import com.jozufozu.flywheel.api.layout.LayoutItem;
|
||||||
import com.jozufozu.flywheel.api.pipeline.Pipeline;
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline;
|
||||||
import com.jozufozu.flywheel.backend.Pipelines;
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines;
|
||||||
import com.jozufozu.flywheel.glsl.ShaderSources;
|
import com.jozufozu.flywheel.glsl.ShaderSources;
|
||||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
import com.jozufozu.flywheel.glsl.SourceComponent;
|
||||||
import com.jozufozu.flywheel.glsl.SourceFile;
|
import com.jozufozu.flywheel.glsl.SourceFile;
|
||||||
|
@ -57,6 +57,7 @@ public class IndirectComponent implements SourceComponent {
|
||||||
var builder = new GlslBuilder();
|
var builder = new GlslBuilder();
|
||||||
builder.define("FlwInstance", STRUCT_NAME);
|
builder.define("FlwInstance", STRUCT_NAME);
|
||||||
builder.define("FlwPackedInstance", PACKED_STRUCT_NAME);
|
builder.define("FlwPackedInstance", PACKED_STRUCT_NAME);
|
||||||
|
builder.blankLine();
|
||||||
|
|
||||||
var packed = builder.struct();
|
var packed = builder.struct();
|
||||||
builder.blankLine();
|
builder.blankLine();
|
||||||
|
@ -74,11 +75,13 @@ public class IndirectComponent implements SourceComponent {
|
||||||
builder.function()
|
builder.function()
|
||||||
.signature(FnSignature.create()
|
.signature(FnSignature.create()
|
||||||
.returnType(STRUCT_NAME)
|
.returnType(STRUCT_NAME)
|
||||||
.name("flw_unpackInstance")
|
.name("_flw_unpackInstance")
|
||||||
.arg(PACKED_STRUCT_NAME, UNPACK_ARG)
|
.arg(PACKED_STRUCT_NAME, UNPACK_ARG)
|
||||||
.build())
|
.build())
|
||||||
.body(this::generateUnpackingBody);
|
.body(this::generateUnpackingBody);
|
||||||
|
|
||||||
|
builder.blankLine();
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ import com.jozufozu.flywheel.api.event.RenderStage;
|
||||||
import com.jozufozu.flywheel.api.instance.Instance;
|
import com.jozufozu.flywheel.api.instance.Instance;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.Pipelines;
|
import com.jozufozu.flywheel.backend.compile.FlwPrograms;
|
||||||
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines;
|
||||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.lib.context.Contexts;
|
import com.jozufozu.flywheel.lib.context.Contexts;
|
||||||
|
@ -62,8 +62,8 @@ public class IndirectCullingGroup<I extends Instance> {
|
||||||
.quads2Tris(2048).glBuffer;
|
.quads2Tris(2048).glBuffer;
|
||||||
setupVertexArray();
|
setupVertexArray();
|
||||||
|
|
||||||
compute = FlwCompiler.INSTANCE.getCullingProgram(instanceType);
|
compute = FlwPrograms.get().getCullingProgram(instanceType);
|
||||||
draw = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, instanceType, Contexts.WORLD, Pipelines.INDIRECT);
|
draw = FlwPrograms.get().getPipelineProgram(vertexType, instanceType, Contexts.WORLD, Pipelines.INDIRECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupVertexArray() {
|
private void setupVertexArray() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import java.util.List;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.layout.LayoutItem;
|
import com.jozufozu.flywheel.api.layout.LayoutItem;
|
||||||
import com.jozufozu.flywheel.api.pipeline.Pipeline;
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline;
|
||||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
import com.jozufozu.flywheel.glsl.SourceComponent;
|
||||||
import com.jozufozu.flywheel.glsl.generate.FnSignature;
|
import com.jozufozu.flywheel.glsl.generate.FnSignature;
|
||||||
import com.jozufozu.flywheel.glsl.generate.GlslBlock;
|
import com.jozufozu.flywheel.glsl.generate.GlslBlock;
|
||||||
|
@ -16,7 +16,7 @@ import com.jozufozu.flywheel.glsl.generate.GlslExpr;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class InstancedArraysComponent implements SourceComponent {
|
public class InstancedArraysComponent implements SourceComponent {
|
||||||
private static final String ATTRIBUTE_SUFFIX = "_vertex_in";
|
private static final String ATTRIBUTE_PREFIX = "_flw_i_";
|
||||||
private static final String STRUCT_NAME = "Instance";
|
private static final String STRUCT_NAME = "Instance";
|
||||||
|
|
||||||
private final List<LayoutItem> layoutItems;
|
private final List<LayoutItem> layoutItems;
|
||||||
|
@ -45,13 +45,15 @@ public class InstancedArraysComponent implements SourceComponent {
|
||||||
var builder = new GlslBuilder();
|
var builder = new GlslBuilder();
|
||||||
builder.define("FlwInstance", STRUCT_NAME);
|
builder.define("FlwInstance", STRUCT_NAME);
|
||||||
|
|
||||||
|
builder.blankLine();
|
||||||
|
|
||||||
int i = baseIndex;
|
int i = baseIndex;
|
||||||
for (var field : layoutItems) {
|
for (var field : layoutItems) {
|
||||||
builder.vertexInput()
|
builder.vertexInput()
|
||||||
.binding(i)
|
.binding(i)
|
||||||
.type(field.type()
|
.type(field.type()
|
||||||
.typeName())
|
.typeName())
|
||||||
.name(field.name() + ATTRIBUTE_SUFFIX);
|
.name(ATTRIBUTE_PREFIX + field.name());
|
||||||
|
|
||||||
i += field.type()
|
i += field.type()
|
||||||
.attributeCount();
|
.attributeCount();
|
||||||
|
@ -70,15 +72,17 @@ public class InstancedArraysComponent implements SourceComponent {
|
||||||
|
|
||||||
// unpacking function
|
// unpacking function
|
||||||
builder.function()
|
builder.function()
|
||||||
.signature(FnSignature.of(STRUCT_NAME, "flw_unpackInstance"))
|
.signature(FnSignature.of(STRUCT_NAME, "_flw_unpackInstance"))
|
||||||
.body(this::generateUnpackingBody);
|
.body(this::generateUnpackingBody);
|
||||||
|
|
||||||
|
builder.blankLine();
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateUnpackingBody(GlslBlock b) {
|
private void generateUnpackingBody(GlslBlock b) {
|
||||||
var fields = layoutItems.stream()
|
var fields = layoutItems.stream()
|
||||||
.map(it -> new GlslExpr.Variable(it.name() + ATTRIBUTE_SUFFIX))
|
.map(it -> new GlslExpr.Variable(ATTRIBUTE_PREFIX + it.name()))
|
||||||
.toList();
|
.toList();
|
||||||
b.ret(GlslExpr.call(STRUCT_NAME, fields));
|
b.ret(GlslExpr.call(STRUCT_NAME, fields));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ import com.jozufozu.flywheel.api.instance.Instancer;
|
||||||
import com.jozufozu.flywheel.api.model.Model;
|
import com.jozufozu.flywheel.api.model.Model;
|
||||||
import com.jozufozu.flywheel.api.task.Plan;
|
import com.jozufozu.flywheel.api.task.Plan;
|
||||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||||
import com.jozufozu.flywheel.backend.Pipelines;
|
import com.jozufozu.flywheel.backend.compile.FlwPrograms;
|
||||||
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
|
import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines;
|
||||||
import com.jozufozu.flywheel.backend.engine.AbstractEngine;
|
import com.jozufozu.flywheel.backend.engine.AbstractEngine;
|
||||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
import com.jozufozu.flywheel.gl.GlStateTracker;
|
||||||
|
@ -106,7 +106,7 @@ public class InstancingEngine extends AbstractEngine {
|
||||||
var vertexType = desc.vertexType();
|
var vertexType = desc.vertexType();
|
||||||
var instanceType = desc.instanceType();
|
var instanceType = desc.instanceType();
|
||||||
|
|
||||||
var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, instanceType, context, Pipelines.INSTANCED_ARRAYS);
|
var program = FlwPrograms.get().getPipelineProgram(vertexType, instanceType, context, Pipelines.INSTANCED_ARRAYS);
|
||||||
UniformBuffer.syncAndBind(program);
|
UniformBuffer.syncAndBind(program);
|
||||||
|
|
||||||
var uniformLocation = program.getUniformLocation("_flw_materialID_instancing");
|
var uniformLocation = program.getUniformLocation("_flw_materialID_instancing");
|
||||||
|
|
|
@ -93,7 +93,7 @@ public interface GlslExpr {
|
||||||
public String prettyPrint() {
|
public String prettyPrint() {
|
||||||
var args = this.args.stream()
|
var args = this.args.stream()
|
||||||
.map(GlslExpr::prettyPrint)
|
.map(GlslExpr::prettyPrint)
|
||||||
.collect(Collectors.joining(","));
|
.collect(Collectors.joining(", "));
|
||||||
return name + "(" + args + ")";
|
return name + "(" + args + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ public class GlslFn implements GlslBuilder.Declaration {
|
||||||
return """
|
return """
|
||||||
%s {
|
%s {
|
||||||
%s
|
%s
|
||||||
}
|
}""".formatted(signature.fullDeclaration(), StringUtil.indent(body.prettyPrint(), 4));
|
||||||
""".formatted(signature.fullDeclaration(), StringUtil.indent(body.prettyPrint(), 4));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.util.Pair;
|
import com.jozufozu.flywheel.util.Pair;
|
||||||
|
import com.jozufozu.flywheel.util.StringUtil;
|
||||||
|
|
||||||
public class GlslStruct implements GlslBuilder.Declaration {
|
public class GlslStruct implements GlslBuilder.Declaration {
|
||||||
|
|
||||||
|
@ -25,11 +26,11 @@ public class GlslStruct implements GlslBuilder.Declaration {
|
||||||
.collect(Collectors.joining("\n"));
|
.collect(Collectors.joining("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String prettyPrint() {
|
public String prettyPrint() {
|
||||||
return """
|
return """
|
||||||
struct %s {
|
struct %s {
|
||||||
%s
|
%s
|
||||||
};
|
};""".formatted(name, StringUtil.indent(buildFields(), 4));
|
||||||
""".formatted(name, buildFields().indent(4));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,7 @@ public class GlslUniformBlock implements GlslBuilder.Declaration {
|
||||||
return """
|
return """
|
||||||
layout(%s, binding = %d) uniform %s {
|
layout(%s, binding = %d) uniform %s {
|
||||||
%s
|
%s
|
||||||
};
|
};""".formatted(qualifier, binding, name, StringUtil.indent(formatMembers(), 4));
|
||||||
""".formatted(qualifier, binding, name, StringUtil.indent(formatMembers(), 4));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatMembers() {
|
private String formatMembers() {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.glsl.span.Span;
|
import com.jozufozu.flywheel.glsl.span.Span;
|
||||||
|
|
||||||
public class ShaderFunction {
|
public class ShaderFunction {
|
||||||
|
|
||||||
// https://regexr.com/60n3d
|
// https://regexr.com/60n3d
|
||||||
public static final Pattern PATTERN = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{");
|
public static final Pattern PATTERN = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{");
|
||||||
|
|
||||||
|
@ -86,11 +85,10 @@ public class ShaderFunction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
String p = parameters.stream()
|
String p = parameters.stream()
|
||||||
.map(variable -> variable.type)
|
.map(variable -> variable.type)
|
||||||
.map(Span::get)
|
.map(Span::get)
|
||||||
.collect(Collectors.joining(","));
|
.collect(Collectors.joining(", "));
|
||||||
|
|
||||||
return type + " " + name + "(" + p + ")";
|
return type + " " + name + "(" + p + ")";
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,9 @@ import java.util.function.BooleanSupplier;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.backend.Backend;
|
import com.jozufozu.flywheel.api.backend.Backend;
|
||||||
import com.jozufozu.flywheel.api.backend.BackendManager;
|
import com.jozufozu.flywheel.api.backend.BackendManager;
|
||||||
import com.jozufozu.flywheel.api.backend.Engine;
|
import com.jozufozu.flywheel.api.backend.Engine;
|
||||||
import com.jozufozu.flywheel.api.pipeline.Pipeline;
|
|
||||||
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
@ -20,14 +17,12 @@ public class SimpleBackend implements Backend {
|
||||||
private final Function<LevelAccessor, Engine> engineFactory;
|
private final Function<LevelAccessor, Engine> engineFactory;
|
||||||
private final Supplier<Backend> fallback;
|
private final Supplier<Backend> fallback;
|
||||||
private final BooleanSupplier isSupported;
|
private final BooleanSupplier isSupported;
|
||||||
private final Pipeline pipelineShader;
|
|
||||||
|
|
||||||
public SimpleBackend(Component engineMessage, Function<LevelAccessor, Engine> engineFactory, Supplier<Backend> fallback, BooleanSupplier isSupported, @Nullable Pipeline pipelineShader) {
|
public SimpleBackend(Component engineMessage, Function<LevelAccessor, Engine> engineFactory, Supplier<Backend> fallback, BooleanSupplier isSupported) {
|
||||||
this.engineMessage = engineMessage;
|
this.engineMessage = engineMessage;
|
||||||
this.engineFactory = engineFactory;
|
this.engineFactory = engineFactory;
|
||||||
this.fallback = fallback;
|
this.fallback = fallback;
|
||||||
this.isSupported = isSupported;
|
this.isSupported = isSupported;
|
||||||
this.pipelineShader = pipelineShader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
|
@ -59,17 +54,11 @@ public class SimpleBackend implements Backend {
|
||||||
return isSupported.getAsBoolean();
|
return isSupported.getAsBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Pipeline pipelineShader() {
|
|
||||||
return pipelineShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private Component engineMessage;
|
private Component engineMessage;
|
||||||
private Function<LevelAccessor, Engine> engineFactory;
|
private Function<LevelAccessor, Engine> engineFactory;
|
||||||
private Supplier<Backend> fallback = BackendManager::getOffBackend;
|
private Supplier<Backend> fallback = BackendManager::getOffBackend;
|
||||||
private BooleanSupplier isSupported;
|
private BooleanSupplier isSupported;
|
||||||
private Pipeline pipelineShader;
|
|
||||||
|
|
||||||
public Builder engineMessage(Component engineMessage) {
|
public Builder engineMessage(Component engineMessage) {
|
||||||
this.engineMessage = engineMessage;
|
this.engineMessage = engineMessage;
|
||||||
|
@ -91,13 +80,8 @@ public class SimpleBackend implements Backend {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder pipelineShader(Pipeline pipelineShader) {
|
|
||||||
this.pipelineShader = pipelineShader;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Backend register(ResourceLocation id) {
|
public Backend register(ResourceLocation id) {
|
||||||
return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(engineMessage, engineFactory, fallback, isSupported, pipelineShader));
|
return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(engineMessage, engineFactory, fallback, isSupported));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
package com.jozufozu.flywheel.lib.pipeline;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
|
||||||
import com.jozufozu.flywheel.api.pipeline.Pipeline;
|
|
||||||
import com.jozufozu.flywheel.gl.GLSLVersion;
|
|
||||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
public final class SimplePipeline implements Pipeline {
|
|
||||||
private final GLSLVersion glslVersion;
|
|
||||||
private final ResourceLocation vertex;
|
|
||||||
private final ResourceLocation fragment;
|
|
||||||
private final InstanceAssemblerFactory factory;
|
|
||||||
|
|
||||||
public SimplePipeline(GLSLVersion glslVersion, ResourceLocation vertex, ResourceLocation fragment, InstanceAssemblerFactory factory) {
|
|
||||||
this.glslVersion = glslVersion;
|
|
||||||
this.vertex = vertex;
|
|
||||||
this.fragment = fragment;
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the source component necessary to convert a packed {@link InstanceType} into its shader representation.
|
|
||||||
*
|
|
||||||
* @return A source component defining functions that unpack a representation of the given instance type.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public SourceComponent assemble(InstanceAssemblerContext context) {
|
|
||||||
return factory.apply(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GLSLVersion glslVersion() {
|
|
||||||
return glslVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceLocation vertexShader() {
|
|
||||||
return vertex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceLocation fragmentShader() {
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface InstanceAssemblerFactory {
|
|
||||||
SourceComponent apply(InstanceAssemblerContext context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Builder builder() {
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
|
||||||
private GLSLVersion glslVersion;
|
|
||||||
private ResourceLocation vertex;
|
|
||||||
private ResourceLocation fragment;
|
|
||||||
private InstanceAssemblerFactory factory;
|
|
||||||
|
|
||||||
public Builder glslVersion(GLSLVersion glslVersion) {
|
|
||||||
this.glslVersion = glslVersion;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder vertex(ResourceLocation vertex) {
|
|
||||||
this.vertex = vertex;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder fragment(ResourceLocation fragment) {
|
|
||||||
this.fragment = fragment;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder assemblerFactory(InstanceAssemblerFactory factory) {
|
|
||||||
this.factory = factory;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimplePipeline build() {
|
|
||||||
return new SimplePipeline(glslVersion, vertex, fragment, factory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,6 +24,7 @@ public class StringUtil {
|
||||||
|
|
||||||
private static final NumberFormat THREE_DECIMAL_PLACES = new DecimalFormat("#0.000");
|
private static final NumberFormat THREE_DECIMAL_PLACES = new DecimalFormat("#0.000");
|
||||||
|
|
||||||
|
// FIXME: this method should count trailing newlines
|
||||||
public static int countLines(String s) {
|
public static int countLines(String s) {
|
||||||
return (int) s.lines()
|
return (int) s.lines()
|
||||||
.count();
|
.count();
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
#ifdef COMPUTE_SHADER
|
|
||||||
uint flw_objectID;
|
|
||||||
uint flw_batchID;
|
|
||||||
#endif
|
|
|
@ -13,7 +13,7 @@ in vec4 flw_var1;
|
||||||
in vec4 flw_var2;
|
in vec4 flw_var2;
|
||||||
in vec4 flw_var3;
|
in vec4 flw_var3;
|
||||||
|
|
||||||
flat in uint flw_materialFragmentID;
|
flat in uint _flw_materialFragmentID;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifdef VERTEX_SHADER
|
#ifdef VERTEX_SHADER
|
||||||
uint flw_materialVertexID;
|
uint _flw_materialVertexID;
|
||||||
|
|
||||||
out vec4 flw_vertexPos;
|
out vec4 flw_vertexPos;
|
||||||
out vec4 flw_vertexColor;
|
out vec4 flw_vertexColor;
|
||||||
|
@ -14,5 +14,5 @@ out vec4 flw_var0;
|
||||||
out vec4 flw_var1;
|
out vec4 flw_var1;
|
||||||
out vec4 flw_var2;
|
out vec4 flw_var2;
|
||||||
out vec4 flw_var3;
|
out vec4 flw_var3;
|
||||||
flat out uint flw_materialFragmentID;
|
flat out uint _flw_materialFragmentID;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
This is what generated ubershaders should look like
|
|
||||||
|
|
||||||
uint flw_materialVertexID = 0;
|
|
||||||
uint flw_materialFragmentID = 0;
|
|
||||||
|
|
||||||
void flw_materialVertex() {
|
|
||||||
switch (flw_materialVertexID) {
|
|
||||||
case 0: flw_materialVertex_flywheel_cutout_vert(); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void flw_materialFragment() {
|
|
||||||
switch (flw_materialFragmentID) {
|
|
||||||
case 0: flw_materialFragment_flywheel_cutout_frag(); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool flw_discardPredicate(vec4 finalColor) {
|
|
||||||
switch (flw_materialFragmentID) {
|
|
||||||
case 0: return flw_discardPredicate_flywheel_cutout_frag(finalColor);
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 flw_fogFilter(vec4 color) {
|
|
||||||
switch (flw_materialFragmentID) {
|
|
||||||
case 0: return flw_fogFilter_flywheel_cutout_frag(color);
|
|
||||||
default: return color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void flw_materialVertex_flywheel_cutout_vert() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void flw_materialFragment_flywheel_cutout_frag() {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool flw_discardPredicate_flywheel_cutout_frag(vec4 finalColor) {
|
|
||||||
return finalColor.a < 0.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 flw_fogFilter_flywheel_cutout_frag(vec4 color) {
|
|
||||||
return linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
|
@ -1,72 +0,0 @@
|
||||||
#version 450
|
|
||||||
#define FLW_SUBGROUP_SIZE 32
|
|
||||||
|
|
||||||
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
|
||||||
|
|
||||||
|
|
||||||
// in uvec3 gl_NumWorkGroups;
|
|
||||||
// in uvec3 gl_WorkGroupID;
|
|
||||||
// in uvec3 gl_LocalInvocationID;
|
|
||||||
// in uvec3 gl_GlobalInvocationID;
|
|
||||||
// in uint gl_LocalInvocationIndex;
|
|
||||||
|
|
||||||
layout(std430, binding = 0) buffer Frustum1 {
|
|
||||||
vec4 a1; // vec4(nx.x, px.x, ny.x, py.x)
|
|
||||||
vec4 a2; // vec4(nx.y, px.y, ny.y, py.y)
|
|
||||||
vec4 a3; // vec4(nx.z, px.z, ny.z, py.z)
|
|
||||||
vec4 a4; // vec4(nx.w, px.w, ny.w, py.w)
|
|
||||||
vec2 b1; // vec2(nz.x, pz.x)
|
|
||||||
vec2 b2; // vec2(nz.y, pz.y)
|
|
||||||
vec2 b3; // vec2(nz.z, pz.z)
|
|
||||||
vec2 b4; // vec2(nz.w, pz.w)
|
|
||||||
} frustum1;
|
|
||||||
|
|
||||||
layout(binding = 1) buffer Frustum2 {
|
|
||||||
vec4 nx;
|
|
||||||
vec4 px;
|
|
||||||
vec4 ny;
|
|
||||||
vec4 py;
|
|
||||||
vec4 nz;
|
|
||||||
vec4 pz;
|
|
||||||
} frustum2;
|
|
||||||
|
|
||||||
layout(binding = 2) buffer Result {
|
|
||||||
bool res1;
|
|
||||||
bool res2;
|
|
||||||
bool res3;
|
|
||||||
} result;
|
|
||||||
|
|
||||||
// 83 - 27 = 56 spirv instruction results
|
|
||||||
bool testSphere1(vec4 sphere) {
|
|
||||||
return
|
|
||||||
all(lessThanEqual(fma(frustum1.a1, sphere.xxxx, fma(frustum1.a2, sphere.yyyy, fma(frustum1.a3, sphere.zzzz, frustum1.a4))), -sphere.wwww)) &&
|
|
||||||
all(lessThanEqual(fma(frustum1.b1, sphere.xx, fma(frustum1.b2, sphere.yy, fma(frustum1.b3, sphere.zz, frustum1.b4))), -sphere.ww));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 236 - 92 = 144 spirv instruction results
|
|
||||||
bool testSphere2(vec4 sphere) {
|
|
||||||
return
|
|
||||||
fma(frustum2.nx.x, sphere.x, fma(frustum2.nx.y, sphere.y, fma(frustum2.nx.z, sphere.z, frustum2.nx.w))) >= -sphere.w &&
|
|
||||||
fma(frustum2.px.x, sphere.x, fma(frustum2.px.y, sphere.y, fma(frustum2.px.z, sphere.z, frustum2.px.w))) >= -sphere.w &&
|
|
||||||
fma(frustum2.ny.x, sphere.x, fma(frustum2.ny.y, sphere.y, fma(frustum2.ny.z, sphere.z, frustum2.ny.w))) >= -sphere.w &&
|
|
||||||
fma(frustum2.py.x, sphere.x, fma(frustum2.py.y, sphere.y, fma(frustum2.py.z, sphere.z, frustum2.py.w))) >= -sphere.w &&
|
|
||||||
fma(frustum2.nz.x, sphere.x, fma(frustum2.nz.y, sphere.y, fma(frustum2.nz.z, sphere.z, frustum2.nz.w))) >= -sphere.w &&
|
|
||||||
fma(frustum2.pz.x, sphere.x, fma(frustum2.pz.y, sphere.y, fma(frustum2.pz.z, sphere.z, frustum2.pz.w))) >= -sphere.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 322 - 240 = 82 spirv instruction results
|
|
||||||
bool testSphere3(vec4 sphere) {
|
|
||||||
return
|
|
||||||
(dot(frustum2.nx.xyz, sphere.xyz) + frustum2.nx.w) >= -sphere.w &&
|
|
||||||
(dot(frustum2.px.xyz, sphere.xyz) + frustum2.px.w) >= -sphere.w &&
|
|
||||||
(dot(frustum2.ny.xyz, sphere.xyz) + frustum2.ny.w) >= -sphere.w &&
|
|
||||||
(dot(frustum2.py.xyz, sphere.xyz) + frustum2.py.w) >= -sphere.w &&
|
|
||||||
(dot(frustum2.nz.xyz, sphere.xyz) + frustum2.nz.w) >= -sphere.w &&
|
|
||||||
(dot(frustum2.pz.xyz, sphere.xyz) + frustum2.pz.w) >= -sphere.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
result.res1 = testSphere1(vec4(0., 1., 0., 1.));
|
|
||||||
result.res2 = testSphere2(vec4(0., 1., 0., 1.));
|
|
||||||
result.res3 = testSphere3(vec4(0., 1., 0., 1.));
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
fragColor = vec4(1.0, 1.0, 1.0, 0.2);
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
layout(location = 0) in vec3 worldPos;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = flywheel.viewProjection * vec4(worldPos, 1.0);
|
|
||||||
}
|
|
|
@ -1,8 +1,8 @@
|
||||||
#define FLW_SUBGROUP_SIZE 32
|
#define FLW_SUBGROUP_SIZE 32
|
||||||
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
||||||
#use "flywheel:api/cull.glsl"
|
|
||||||
#use "flywheel:util/types.glsl"
|
#use "flywheel:util/types.glsl"
|
||||||
#use "flywheel:pipeline/indirect_draw_command.glsl"
|
#use "flywheel:internal/indirect_draw_command.glsl"
|
||||||
|
|
||||||
// populated by instancers
|
// populated by instancers
|
||||||
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
|
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
|
||||||
|
@ -21,6 +21,9 @@ layout(std430, binding = 3) restrict buffer DrawCommands {
|
||||||
MeshDrawCommand drawCommands[];
|
MeshDrawCommand drawCommands[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint flw_objectID;
|
||||||
|
uint flw_batchID;
|
||||||
|
|
||||||
// 83 - 27 = 56 spirv instruction results
|
// 83 - 27 = 56 spirv instruction results
|
||||||
bool testSphere(vec3 center, float radius) {
|
bool testSphere(vec3 center, float radius) {
|
||||||
bvec4 xyInside = greaterThanEqual(fma(flywheel.planes.xyX, center.xxxx, fma(flywheel.planes.xyY, center.yyyy, fma(flywheel.planes.xyZ, center.zzzz, flywheel.planes.xyW))), -radius.xxxx);
|
bvec4 xyInside = greaterThanEqual(fma(flywheel.planes.xyX, center.xxxx, fma(flywheel.planes.xyY, center.yyyy, fma(flywheel.planes.xyZ, center.zzzz, flywheel.planes.xyW))), -radius.xxxx);
|
||||||
|
@ -36,7 +39,7 @@ bool isVisible() {
|
||||||
float radius;
|
float radius;
|
||||||
unpackBoundingSphere(sphere, center, radius);
|
unpackBoundingSphere(sphere, center, radius);
|
||||||
|
|
||||||
FlwInstance object = flw_unpackInstance(objects[flw_objectID]);
|
FlwInstance object = _flw_unpackInstance(objects[flw_objectID]);
|
||||||
flw_transformBoundingSphere(object, center, radius);
|
flw_transformBoundingSphere(object, center, radius);
|
||||||
|
|
||||||
return testSphere(center, radius);
|
return testSphere(center, radius);
|
|
@ -1,5 +1,5 @@
|
||||||
#use "flywheel:api/vertex.glsl"
|
#use "flywheel:api/vertex.glsl"
|
||||||
#use "flywheel:pipeline/indirect_draw_command.glsl"
|
#use "flywheel:internal/indirect_draw_command.glsl"
|
||||||
|
|
||||||
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
|
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
|
||||||
FlwPackedInstance objects[];
|
FlwPackedInstance objects[];
|
||||||
|
@ -20,10 +20,10 @@ layout(std430, binding = 3) restrict readonly buffer DrawCommands {
|
||||||
void main() {
|
void main() {
|
||||||
uint instanceIndex = objectIDs[gl_BaseInstance + gl_InstanceID];
|
uint instanceIndex = objectIDs[gl_BaseInstance + gl_InstanceID];
|
||||||
uint batchID = batchIDs[instanceIndex];
|
uint batchID = batchIDs[instanceIndex];
|
||||||
FlwInstance i = flw_unpackInstance(objects[instanceIndex]);
|
FlwInstance i = _flw_unpackInstance(objects[instanceIndex]);
|
||||||
|
|
||||||
flw_materialVertexID = drawCommands[batchID].vertexMaterialID;
|
_flw_materialVertexID = drawCommands[batchID].vertexMaterialID;
|
||||||
flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID;
|
_flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID;
|
||||||
|
|
||||||
flw_layoutVertex();
|
flw_layoutVertex();
|
||||||
flw_instanceVertex(i);
|
flw_instanceVertex(i);
|
|
@ -5,10 +5,10 @@ uniform uvec2 _flw_materialID_instancing;
|
||||||
void main() {
|
void main() {
|
||||||
flw_layoutVertex();
|
flw_layoutVertex();
|
||||||
|
|
||||||
flw_materialVertexID = _flw_materialID_instancing.x;
|
_flw_materialVertexID = _flw_materialID_instancing.x;
|
||||||
flw_materialFragmentID = _flw_materialID_instancing.y;
|
_flw_materialFragmentID = _flw_materialID_instancing.y;
|
||||||
|
|
||||||
FlwInstance i = flw_unpackInstance();
|
FlwInstance i = _flw_unpackInstance();
|
||||||
flw_instanceVertex(i);
|
flw_instanceVertex(i);
|
||||||
flw_materialVertex();
|
flw_materialVertex();
|
||||||
flw_contextVertex();
|
flw_contextVertex();
|
|
@ -1,12 +1,12 @@
|
||||||
struct FLWPackedPlanes {
|
struct FLWPackedPlanes {
|
||||||
vec4 xyX;// <nx.x, px.x, ny.x, py.x>
|
vec4 xyX; // <nx.x, px.x, ny.x, py.x>
|
||||||
vec4 xyY;// <nx.y, px.y, ny.y, py.y>
|
vec4 xyY; // <nx.y, px.y, ny.y, py.y>
|
||||||
vec4 xyZ;// <nx.z, px.z, ny.z, py.z>
|
vec4 xyZ; // <nx.z, px.z, ny.z, py.z>
|
||||||
vec4 xyW;// <nx.w, px.w, ny.w, py.w>
|
vec4 xyW; // <nx.w, px.w, ny.w, py.w>
|
||||||
vec2 zX;// <nz.x, pz.x>
|
vec2 zX; // <nz.x, pz.x>
|
||||||
vec2 zY;// <nz.y, pz.y>
|
vec2 zY; // <nz.y, pz.y>
|
||||||
vec2 zZ;// <nz.z, pz.z>
|
vec2 zZ; // <nz.z, pz.z>
|
||||||
vec2 zW;// <nz.w, pz.w>
|
vec2 zW; // <nz.w, pz.w>
|
||||||
};
|
};
|
||||||
|
|
||||||
struct flywheel_uniforms {
|
struct flywheel_uniforms {
|
||||||
|
|
Loading…
Reference in a new issue