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:
PepperCode1 2023-04-16 22:09:28 -07:00
parent 5b84046c1d
commit 7afa2486ad
42 changed files with 369 additions and 596 deletions

View file

@ -5,7 +5,7 @@ import org.slf4j.Logger;
import com.jozufozu.flywheel.backend.Backends;
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.batching.DrawBuffer;
import com.jozufozu.flywheel.config.BackendArgument;

View file

@ -1,8 +1,5 @@
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.impl.IdRegistryImpl;
@ -31,6 +28,4 @@ public interface Backend {
* Check if this backend is supported.
*/
boolean isSupported();
@Nullable Pipeline pipelineShader();
}

View file

@ -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) {
}
}

View file

@ -32,7 +32,6 @@ public class Backends {
.fallback(() -> Backends.BATCHING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
.instancedArraysSupported())
.pipelineShader(Pipelines.INSTANCED_ARRAYS)
.register(Flywheel.rl("instancing"));
/**
@ -44,7 +43,6 @@ public class Backends {
.fallback(() -> Backends.INSTANCING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance()
.supportsIndirect())
.pipelineShader(Pipelines.INDIRECT)
.register(Flywheel.rl("indirect"));
public static void init() {

View file

@ -1,8 +1,6 @@
package com.jozufozu.flywheel.backend;
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.error.ErrorReporter;
import com.jozufozu.flywheel.backend.compile.FlwPrograms;
import com.jozufozu.flywheel.impl.BackendManagerImpl;
import net.minecraft.client.Minecraft;
@ -25,14 +23,7 @@ public class Loader implements ResourceManagerReloadListener {
@Override
public void onResourceManagerReload(ResourceManager manager) {
var errorReporter = new ErrorReporter();
ShaderSources sources = new ShaderSources(errorReporter, manager);
if (FlwCompiler.INSTANCE != null) {
FlwCompiler.INSTANCE.delete();
}
FlwCompiler.INSTANCE = new FlwCompiler(sources);
FlwPrograms.reload(manager);
// TODO: Move this to the impl package
BackendManagerImpl.refresh(Minecraft.getInstance().level);

View file

@ -40,7 +40,7 @@ public class Compilation {
public Compilation(GLSLVersion glslVersion, ShaderType shaderType) {
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.shaderType = shaderType;
}
@ -71,10 +71,6 @@ public class Compilation {
.append(" : enable\n");
}
public void addComponentName(ResourceLocation name) {
componentNames.add(name);
}
public void appendComponent(SourceComponent component) {
var source = component.source();
@ -85,12 +81,12 @@ public class Compilation {
.toString()));
}
fullSource.append(source)
.append('\n');
fullSource.append(source);
componentNames.add(component.name());
}
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) {
@ -98,7 +94,7 @@ public class Compilation {
int lines = StringUtil.countLines(generatedCode);
// all generated code is put in file 0,
var out = "#line " + generatedLines + ' ' + 0;
var out = '\n' + "#line " + generatedLines + ' ' + 0;
generatedLines += lines;
@ -123,12 +119,13 @@ public class Compilation {
@NotNull
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()
.map(ResourceLocation::toString)
.map(s -> s.replaceAll("/", "_")
.replaceAll(":", "\\$"))
.collect(Collectors.joining(";"));
return shaderType.name + glslVersion + ';' + components;
return shaderType.name + glslVersion + ';' /*+ components*/;
}
private static void dumpSource(String source, String fileName) {

View file

@ -24,7 +24,7 @@ public class CompileUtil {
public static final Pattern matType = Pattern.compile("^mat([234])(?:x([234]))?$");
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) {

View file

@ -1,6 +0,0 @@
package com.jozufozu.flywheel.backend.compile;
import com.jozufozu.flywheel.api.instance.InstanceType;
public record CullingContext(InstanceType<?> instanceType) {
}

View file

@ -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);
}
}

View file

@ -10,14 +10,14 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.Flywheel;
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.uniform.ShaderUniforms;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.compile.FlwPrograms.PipelineProgramKey;
import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline;
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlProgram;
@ -30,78 +30,164 @@ import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.util.StringUtil;
import net.minecraft.resources.ResourceLocation;
public class FlwCompiler {
private final long compileStart = System.nanoTime();
public static FlwCompiler INSTANCE;
final long compileStart = System.nanoTime();
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 fragmentMaterialComponent;
private final UniformComponent uniformComponent;
private final PipelineContextSet pipelineContexts;
private final CullingContextSet cullingContexts;
private final Map<PipelineProgramKey, GlProgram> pipelinePrograms = new HashMap<>();
private final Map<InstanceType<?>, GlProgram> cullingPrograms = new HashMap<>();
final ShaderCompiler shaderCompiler;
final Map<PipelineContext, GlProgram> pipelinePrograms = new HashMap<>();
final Map<InstanceType<?>, GlProgram> cullingPrograms = new HashMap<>();
final List<FailedCompilation> errors = new ArrayList<>();
public FlwCompiler(ShaderSources sources, ImmutableList<PipelineProgramKey> pipelineKeys, ImmutableList<InstanceType<?>> cullingKeys) {
this.sources = sources;
public FlwCompiler(ShaderSources sources) {
this.shaderCompiler = ShaderCompiler.builder()
this.pipelineKeys = pipelineKeys;
this.cullingKeys = cullingKeys;
shaderCompiler = ShaderCompiler.builder()
.errorConsumer(errors::add)
.build();
this.sources = sources;
this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
.materialSources(MaterialIndices.getAllVertexShaders())
.adapt(FnSignature.ofVoid("flw_materialVertex"))
.switchOn(GlslExpr.variable("flw_materialVertexID"))
.switchOn(GlslExpr.variable("_flw_materialVertexID"))
.build(sources);
this.fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter"))
fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter"))
.materialSources(MaterialIndices.getAllFragmentShaders())
.adapt(FnSignature.ofVoid("flw_materialFragment"))
.adapt(FnSignature.create()
.returnType("bool")
.name("flw_discardPredicate")
.arg("vec4", "color")
.build(), GlslExpr.literal(false))
.adapt(FnSignature.create()
.returnType("vec4")
.name("flw_fogFilter")
.arg("vec4", "color")
.build(), GlslExpr.variable("color"))
.switchOn(GlslExpr.variable("flw_materialFragmentID"))
.build(sources);
this.uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms"))
.name("flw_discardPredicate")
.arg("vec4", "color")
.build(), GlslExpr.literal(false))
.adapt(FnSignature.create()
.returnType("vec4")
.name("flw_fogFilter")
.arg("vec4", "color")
.build(), GlslExpr.variable("color"))
.switchOn(GlslExpr.variable("_flw_materialFragmentID"))
.build(sources);
uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms"))
.sources(ShaderUniforms.REGISTRY.getAll()
.stream()
.map(ShaderUniforms::uniformShader)
.toList())
.toList())
.build(sources);
}
this.pipelineContexts = PipelineContextSet.create();
this.cullingContexts = CullingContextSet.create();
public FlwPrograms compile() {
doCompilation();
finish();
return new FlwPrograms(pipelinePrograms, cullingPrograms);
}
private void doCompilation() {
for (var ctx : pipelineContexts.all()) {
compilePipelineContext(ctx);
for (var key : pipelineKeys) {
GlProgram glProgram = compilePipelineProgram(key);
if (glProgram != null) {
pipelinePrograms.put(key, glProgram);
}
}
for (var ctx : cullingContexts.all()) {
compileComputeCuller(ctx);
for (var key : cullingKeys) {
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() {
long compileEnd = System.nanoTime();
int programCount = pipelineContexts.size() + InstanceType.REGISTRY.getAll().size();
int programCount = pipelineKeys.size() + cullingKeys.size();
int shaderCount = shaderCompiler.shaderCount();
int errorCount = errors.size();
var elapsed = StringUtil.formatTime(compileEnd - compileStart);
@ -112,94 +198,16 @@ public class FlwCompiler {
var details = errors.stream()
.map(FailedCompilation::getMessage)
.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() {
pipelinePrograms.values()
.forEach(GlProgram::delete);
cullingPrograms.values()
.forEach(GlProgram::delete);
shaderCompiler.delete();
}
public GlProgram getPipelineProgram(VertexType vertexType, InstanceType<?> instanceType, Context contextShader, Pipeline pipelineShader) {
return pipelinePrograms.get(new PipelineContext(vertexType, instanceType, contextShader, pipelineShader));
private static final class Files {
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);
}
}

View file

@ -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) {
}
}

View file

@ -61,6 +61,8 @@ public class MaterialAdapterComponent implements SourceComponent {
.body(body -> generateAdapter(body, adaptedFunction));
}
builder.blankLine();
return builder.build();
}

View file

@ -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) {
}

View file

@ -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);
}
}

View file

@ -41,6 +41,8 @@ public class UniformComponent implements SourceComponent {
.name("FLWUniforms")
.member("flywheel_uniforms", "flywheel");
builder.blankLine();
return builder.build();
}

View file

@ -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);
}
}
}

View file

@ -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.backend.engine.indirect.IndirectComponent;
import com.jozufozu.flywheel.backend.engine.instancing.InstancedArraysComponent;
import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.lib.pipeline.SimplePipeline;
import net.minecraft.resources.ResourceLocation;
public class Pipelines {
public static final SimplePipeline INSTANCED_ARRAYS = SimplePipeline.builder()
public final class Pipelines {
public static final Pipeline INSTANCED_ARRAYS = Pipeline.builder()
.glslVersion(GLSLVersion.V420)
.vertex(Files.INSTANCED_ARRAYS_DRAW)
.fragment(Files.DRAW_FRAGMENT)
.assemblerFactory(InstancedArraysComponent::new)
.assembler(InstancedArraysComponent::new)
.build();
public static final SimplePipeline INDIRECT = SimplePipeline.builder()
public static final Pipeline INDIRECT = Pipeline.builder()
.glslVersion(GLSLVersion.V460)
.vertex(Files.INDIRECT_DRAW)
.fragment(Files.DRAW_FRAGMENT)
.assemblerFactory(IndirectComponent::new)
.assembler(IndirectComponent::new)
.build();
public static final List<Pipeline> ALL = List.of(INSTANCED_ARRAYS, INDIRECT);
public static void init() {
}
public static class Files {
public static final ResourceLocation DRAW_FRAGMENT = Flywheel.rl("pipeline/draw.frag");
public static final ResourceLocation INSTANCED_ARRAYS_DRAW = Flywheel.rl("pipeline/instanced_arrays_draw.vert");
public static final ResourceLocation INDIRECT_DRAW = Flywheel.rl("pipeline/indirect_draw.vert");
public static final ResourceLocation INDIRECT_CULL = Flywheel.rl("pipeline/indirect_cull.glsl");
public static final class Files {
public static final ResourceLocation INSTANCED_ARRAYS_DRAW = Flywheel.rl("internal/instanced_arrays_draw.vert");
public static final ResourceLocation INDIRECT_DRAW = Flywheel.rl("internal/indirect_draw.vert");
public static final ResourceLocation DRAW_FRAGMENT = Flywheel.rl("internal/draw.frag");
public static final ResourceLocation UTIL_TYPES = Flywheel.rl("util/types.glsl");
}
}

View file

@ -7,8 +7,8 @@ import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.instance.InstanceType;
import com.jozufozu.flywheel.api.layout.LayoutItem;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.compile.pipeline.Pipeline;
import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines;
import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile;
@ -57,6 +57,7 @@ public class IndirectComponent implements SourceComponent {
var builder = new GlslBuilder();
builder.define("FlwInstance", STRUCT_NAME);
builder.define("FlwPackedInstance", PACKED_STRUCT_NAME);
builder.blankLine();
var packed = builder.struct();
builder.blankLine();
@ -74,11 +75,13 @@ public class IndirectComponent implements SourceComponent {
builder.function()
.signature(FnSignature.create()
.returnType(STRUCT_NAME)
.name("flw_unpackInstance")
.name("_flw_unpackInstance")
.arg(PACKED_STRUCT_NAME, UNPACK_ARG)
.build())
.body(this::generateUnpackingBody);
builder.blankLine();
return builder.build();
}

View file

@ -15,8 +15,8 @@ import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.InstanceType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.compile.FlwPrograms;
import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines;
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.lib.context.Contexts;
@ -62,8 +62,8 @@ public class IndirectCullingGroup<I extends Instance> {
.quads2Tris(2048).glBuffer;
setupVertexArray();
compute = FlwCompiler.INSTANCE.getCullingProgram(instanceType);
draw = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, instanceType, Contexts.WORLD, Pipelines.INDIRECT);
compute = FlwPrograms.get().getCullingProgram(instanceType);
draw = FlwPrograms.get().getPipelineProgram(vertexType, instanceType, Contexts.WORLD, Pipelines.INDIRECT);
}
private void setupVertexArray() {

View file

@ -6,7 +6,7 @@ import java.util.List;
import com.jozufozu.flywheel.Flywheel;
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.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock;
@ -16,7 +16,7 @@ import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import net.minecraft.resources.ResourceLocation;
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 final List<LayoutItem> layoutItems;
@ -45,13 +45,15 @@ public class InstancedArraysComponent implements SourceComponent {
var builder = new GlslBuilder();
builder.define("FlwInstance", STRUCT_NAME);
builder.blankLine();
int i = baseIndex;
for (var field : layoutItems) {
builder.vertexInput()
.binding(i)
.type(field.type()
.typeName())
.name(field.name() + ATTRIBUTE_SUFFIX);
.name(ATTRIBUTE_PREFIX + field.name());
i += field.type()
.attributeCount();
@ -70,15 +72,17 @@ public class InstancedArraysComponent implements SourceComponent {
// unpacking function
builder.function()
.signature(FnSignature.of(STRUCT_NAME, "flw_unpackInstance"))
.signature(FnSignature.of(STRUCT_NAME, "_flw_unpackInstance"))
.body(this::generateUnpackingBody);
builder.blankLine();
return builder.build();
}
private void generateUnpackingBody(GlslBlock b) {
var fields = layoutItems.stream()
.map(it -> new GlslExpr.Variable(it.name() + ATTRIBUTE_SUFFIX))
.map(it -> new GlslExpr.Variable(ATTRIBUTE_PREFIX + it.name()))
.toList();
b.ret(GlslExpr.call(STRUCT_NAME, fields));
}

View file

@ -13,8 +13,8 @@ import com.jozufozu.flywheel.api.instance.Instancer;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.task.Plan;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.compile.FlwPrograms;
import com.jozufozu.flywheel.backend.compile.pipeline.Pipelines;
import com.jozufozu.flywheel.backend.engine.AbstractEngine;
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
import com.jozufozu.flywheel.gl.GlStateTracker;
@ -106,7 +106,7 @@ public class InstancingEngine extends AbstractEngine {
var vertexType = desc.vertexType();
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);
var uniformLocation = program.getUniformLocation("_flw_materialID_instancing");

View file

@ -93,7 +93,7 @@ public interface GlslExpr {
public String prettyPrint() {
var args = this.args.stream()
.map(GlslExpr::prettyPrint)
.collect(Collectors.joining(","));
.collect(Collectors.joining(", "));
return name + "(" + args + ")";
}

View file

@ -22,7 +22,6 @@ public class GlslFn implements GlslBuilder.Declaration {
return """
%s {
%s
}
""".formatted(signature.fullDeclaration(), StringUtil.indent(body.prettyPrint(), 4));
}""".formatted(signature.fullDeclaration(), StringUtil.indent(body.prettyPrint(), 4));
}
}

View file

@ -5,6 +5,7 @@ import java.util.List;
import java.util.stream.Collectors;
import com.jozufozu.flywheel.util.Pair;
import com.jozufozu.flywheel.util.StringUtil;
public class GlslStruct implements GlslBuilder.Declaration {
@ -25,11 +26,11 @@ public class GlslStruct implements GlslBuilder.Declaration {
.collect(Collectors.joining("\n"));
}
@Override
public String prettyPrint() {
return """
struct %s {
%s
};
""".formatted(name, buildFields().indent(4));
};""".formatted(name, StringUtil.indent(buildFields(), 4));
}
}

View file

@ -20,8 +20,7 @@ public class GlslUniformBlock implements GlslBuilder.Declaration {
return """
layout(%s, binding = %d) uniform %s {
%s
};
""".formatted(qualifier, binding, name, StringUtil.indent(formatMembers(), 4));
};""".formatted(qualifier, binding, name, StringUtil.indent(formatMembers(), 4));
}
private String formatMembers() {

View file

@ -8,7 +8,6 @@ import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.glsl.span.Span;
public class ShaderFunction {
// https://regexr.com/60n3d
public static final Pattern PATTERN = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{");
@ -86,11 +85,10 @@ public class ShaderFunction {
@Override
public String toString() {
String p = parameters.stream()
.map(variable -> variable.type)
.map(Span::get)
.collect(Collectors.joining(","));
.collect(Collectors.joining(", "));
return type + " " + name + "(" + p + ")";
}

View file

@ -4,12 +4,9 @@ import java.util.function.BooleanSupplier;
import java.util.function.Function;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@ -20,14 +17,12 @@ public class SimpleBackend implements Backend {
private final Function<LevelAccessor, Engine> engineFactory;
private final Supplier<Backend> fallback;
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.engineFactory = engineFactory;
this.fallback = fallback;
this.isSupported = isSupported;
this.pipelineShader = pipelineShader;
}
public static Builder builder() {
@ -59,17 +54,11 @@ public class SimpleBackend implements Backend {
return isSupported.getAsBoolean();
}
@Override
public @Nullable Pipeline pipelineShader() {
return pipelineShader;
}
public static class Builder {
private Component engineMessage;
private Function<LevelAccessor, Engine> engineFactory;
private Supplier<Backend> fallback = BackendManager::getOffBackend;
private BooleanSupplier isSupported;
private Pipeline pipelineShader;
public Builder engineMessage(Component engineMessage) {
this.engineMessage = engineMessage;
@ -91,13 +80,8 @@ public class SimpleBackend implements Backend {
return this;
}
public Builder pipelineShader(Pipeline pipelineShader) {
this.pipelineShader = pipelineShader;
return this;
}
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));
}
}
}

View file

@ -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);
}
}
}

View file

@ -24,6 +24,7 @@ public class StringUtil {
private static final NumberFormat THREE_DECIMAL_PLACES = new DecimalFormat("#0.000");
// FIXME: this method should count trailing newlines
public static int countLines(String s) {
return (int) s.lines()
.count();

View file

@ -1,4 +0,0 @@
#ifdef COMPUTE_SHADER
uint flw_objectID;
uint flw_batchID;
#endif

View file

@ -13,7 +13,7 @@ in vec4 flw_var1;
in vec4 flw_var2;
in vec4 flw_var3;
flat in uint flw_materialFragmentID;
flat in uint _flw_materialFragmentID;
//

View file

@ -1,5 +1,5 @@
#ifdef VERTEX_SHADER
uint flw_materialVertexID;
uint _flw_materialVertexID;
out vec4 flw_vertexPos;
out vec4 flw_vertexColor;
@ -14,5 +14,5 @@ out vec4 flw_var0;
out vec4 flw_var1;
out vec4 flw_var2;
out vec4 flw_var3;
flat out uint flw_materialFragmentID;
flat out uint _flw_materialFragmentID;
#endif

View file

@ -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);
}
*/

View file

@ -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.));
}

View file

@ -1,5 +0,0 @@
out vec4 fragColor;
void main() {
fragColor = vec4(1.0, 1.0, 1.0, 0.2);
}

View file

@ -1,5 +0,0 @@
layout(location = 0) in vec3 worldPos;
void main() {
gl_Position = flywheel.viewProjection * vec4(worldPos, 1.0);
}

View file

@ -1,8 +1,8 @@
#define FLW_SUBGROUP_SIZE 32
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
#use "flywheel:api/cull.glsl"
#use "flywheel:util/types.glsl"
#use "flywheel:pipeline/indirect_draw_command.glsl"
#use "flywheel:internal/indirect_draw_command.glsl"
// populated by instancers
layout(std430, binding = 0) restrict readonly buffer ObjectBuffer {
@ -21,6 +21,9 @@ layout(std430, binding = 3) restrict buffer DrawCommands {
MeshDrawCommand drawCommands[];
};
uint flw_objectID;
uint flw_batchID;
// 83 - 27 = 56 spirv instruction results
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);
@ -36,7 +39,7 @@ bool isVisible() {
float radius;
unpackBoundingSphere(sphere, center, radius);
FlwInstance object = flw_unpackInstance(objects[flw_objectID]);
FlwInstance object = _flw_unpackInstance(objects[flw_objectID]);
flw_transformBoundingSphere(object, center, radius);
return testSphere(center, radius);

View file

@ -1,5 +1,5 @@
#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 {
FlwPackedInstance objects[];
@ -20,10 +20,10 @@ layout(std430, binding = 3) restrict readonly buffer DrawCommands {
void main() {
uint instanceIndex = objectIDs[gl_BaseInstance + gl_InstanceID];
uint batchID = batchIDs[instanceIndex];
FlwInstance i = flw_unpackInstance(objects[instanceIndex]);
FlwInstance i = _flw_unpackInstance(objects[instanceIndex]);
flw_materialVertexID = drawCommands[batchID].vertexMaterialID;
flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID;
_flw_materialVertexID = drawCommands[batchID].vertexMaterialID;
_flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID;
flw_layoutVertex();
flw_instanceVertex(i);

View file

@ -5,10 +5,10 @@ uniform uvec2 _flw_materialID_instancing;
void main() {
flw_layoutVertex();
flw_materialVertexID = _flw_materialID_instancing.x;
flw_materialFragmentID = _flw_materialID_instancing.y;
_flw_materialVertexID = _flw_materialID_instancing.x;
_flw_materialFragmentID = _flw_materialID_instancing.y;
FlwInstance i = flw_unpackInstance();
FlwInstance i = _flw_unpackInstance();
flw_instanceVertex(i);
flw_materialVertex();
flw_contextVertex();

View file

@ -1,12 +1,12 @@
struct FLWPackedPlanes {
vec4 xyX;// <nx.x, px.x, ny.x, py.x>
vec4 xyY;// <nx.y, px.y, ny.y, py.y>
vec4 xyZ;// <nx.z, px.z, ny.z, py.z>
vec4 xyW;// <nx.w, px.w, ny.w, py.w>
vec2 zX;// <nz.x, pz.x>
vec2 zY;// <nz.y, pz.y>
vec2 zZ;// <nz.z, pz.z>
vec2 zW;// <nz.w, pz.w>
vec4 xyX; // <nx.x, px.x, ny.x, py.x>
vec4 xyY; // <nx.y, px.y, ny.y, py.y>
vec4 xyZ; // <nx.z, px.z, ny.z, py.z>
vec4 xyW; // <nx.w, px.w, ny.w, py.w>
vec2 zX; // <nz.x, pz.x>
vec2 zY; // <nz.y, pz.y>
vec2 zZ; // <nz.z, pz.z>
vec2 zW; // <nz.w, pz.w>
};
struct flywheel_uniforms {