mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-07 12:56:31 +01:00
Finally have time off
- Attempt at componentizing ShaderCompiler, starting with Includer - Begin refactoring uniform providers - Context as an interface - Separate ContextSet objects for Pipeline shaders and Culling shaders - Inline ProgramAssembler - Replace StringUtil#trimEnd with String#stripTrailing - Add StringUtil#trimPrefix and #trimSuffix
This commit is contained in:
parent
ef568d22f7
commit
9a746f700d
26 changed files with 437 additions and 221 deletions
12
src/main/java/com/jozufozu/flywheel/api/context/Context.java
Normal file
12
src/main/java/com/jozufozu/flywheel/api/context/Context.java
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package com.jozufozu.flywheel.api.context;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
|
||||||
|
public interface Context {
|
||||||
|
void setup(GlProgram program);
|
||||||
|
|
||||||
|
FileResolution vertexShader();
|
||||||
|
|
||||||
|
FileResolution fragmentShader();
|
||||||
|
}
|
|
@ -3,6 +3,20 @@ package com.jozufozu.flywheel.api.context;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
|
||||||
public record ContextShader(GlProgram.Factory factory, FileResolution vertexShader, FileResolution fragmentShader) {
|
public record ContextShader(GlProgram.Factory factory, FileResolution vertexShader,
|
||||||
|
FileResolution fragmentShader) implements Context {
|
||||||
|
@Override
|
||||||
|
public void setup(GlProgram program) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileResolution vertexShader() {
|
||||||
|
return vertexShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileResolution fragmentShader() {
|
||||||
|
return fragmentShader;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,16 @@ public interface UniformProvider {
|
||||||
|
|
||||||
FileResolution uniformShader();
|
FileResolution uniformShader();
|
||||||
|
|
||||||
ActiveUniformProvider activate(long ptr, Notifier notifier);
|
ActiveUniformProvider activate(long ptr);
|
||||||
|
|
||||||
interface ActiveUniformProvider {
|
interface ActiveUniformProvider {
|
||||||
void delete();
|
void delete();
|
||||||
|
|
||||||
void poll();
|
/**
|
||||||
}
|
* Poll the provider for changes.
|
||||||
|
*
|
||||||
interface Notifier {
|
* @return {@code true} if the provider updated its backing store.
|
||||||
void signalChanged();
|
*/
|
||||||
|
boolean poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class GlProgram extends GlObject {
|
||||||
setHandle(handle);
|
setHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Programs bind the uniform buffers they need
|
// TODO: Programs bind the uniform buffers they need, no more GlProgram inheritance
|
||||||
public void bind() {
|
public void bind() {
|
||||||
ProgramManager.glUseProgram(handle());
|
ProgramManager.glUseProgram(handle());
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,8 @@ public class Compilation {
|
||||||
.toString()));
|
.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fullSource.append(source);
|
fullSource.append(source)
|
||||||
|
.append('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
private String sourceHeader(SourceFile sourceFile) {
|
private String sourceHeader(SourceFile sourceFile) {
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.compile;
|
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
|
||||||
|
import static org.lwjgl.opengl.GL20.GL_TRUE;
|
||||||
|
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
|
||||||
|
import static org.lwjgl.opengl.GL20.glGetProgrami;
|
||||||
|
import static org.lwjgl.opengl.GL20.glLinkProgram;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -7,6 +13,7 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||||
|
@ -17,9 +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()
|
return version.getVersionLine() + type.getDefineStatement() + '\n';
|
||||||
+ type.getDefineStatement()
|
|
||||||
+ '\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getElementCount(String type) {
|
public static int getElementCount(String type) {
|
||||||
|
@ -53,10 +58,31 @@ public class CompileUtil {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String generateDebugName(SourceFile... stages) {
|
public static String generateDebugName(SourceFile... stages) {
|
||||||
return Stream.of(stages)
|
return Stream.of(stages)
|
||||||
.map(SourceFile::toString)
|
.map(SourceFile::toString)
|
||||||
.collect(Collectors.joining(" -> "));
|
.collect(Collectors.joining(" -> "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the program info log for errors.
|
||||||
|
*
|
||||||
|
* @param handle The handle of the program to check.
|
||||||
|
*/
|
||||||
|
public static void checkLinkLog(int handle) {
|
||||||
|
glLinkProgram(handle);
|
||||||
|
|
||||||
|
String log = glGetProgramInfoLog(handle);
|
||||||
|
|
||||||
|
if (!log.isEmpty()) {
|
||||||
|
Backend.LOGGER.debug("Program link log: " + log);
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = glGetProgrami(handle, GL_LINK_STATUS);
|
||||||
|
|
||||||
|
if (result != GL_TRUE) {
|
||||||
|
throw new RuntimeException("Shader program linking failed, see log for details");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
|
|
||||||
|
public record CullingContext(StructType<?> structType) {
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
|
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||||
|
|
||||||
|
public class CullingContextSet {
|
||||||
|
static CullingContextSet create() {
|
||||||
|
var builder = new CullingContextSet();
|
||||||
|
for (StructType<?> structType : ComponentRegistry.structTypes) {
|
||||||
|
builder.add(structType);
|
||||||
|
}
|
||||||
|
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(StructType<?> structType) {
|
||||||
|
var ctx = new CullingContext(structType);
|
||||||
|
|
||||||
|
contexts.add(ctx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import com.jozufozu.flywheel.core.source.SourceLines;
|
||||||
import com.jozufozu.flywheel.core.source.error.ErrorBuilder;
|
import com.jozufozu.flywheel.core.source.error.ErrorBuilder;
|
||||||
import com.jozufozu.flywheel.core.source.span.Span;
|
import com.jozufozu.flywheel.core.source.span.Span;
|
||||||
import com.jozufozu.flywheel.util.ConsoleColors;
|
import com.jozufozu.flywheel.util.ConsoleColors;
|
||||||
|
import com.jozufozu.flywheel.util.StringUtil;
|
||||||
|
|
||||||
public class FailedCompilation {
|
public class FailedCompilation {
|
||||||
private static final Pattern ERROR_LINE = Pattern.compile("(\\d+)\\((\\d+)\\) : (.*)");
|
private static final Pattern ERROR_LINE = Pattern.compile("(\\d+)\\((\\d+)\\) : (.*)");
|
||||||
|
@ -49,7 +50,8 @@ public class FailedCompilation {
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
int fileId = Integer.parseInt(matcher.group(1));
|
int fileId = Integer.parseInt(matcher.group(1));
|
||||||
int lineNo = Integer.parseInt(matcher.group(2));
|
int lineNo = Integer.parseInt(matcher.group(2));
|
||||||
var msg = matcher.group(3);
|
var msg = StringUtil.trimPrefix(matcher.group(3), "error")
|
||||||
|
.stripLeading();
|
||||||
|
|
||||||
if (fileId == 0) {
|
if (fileId == 0) {
|
||||||
return interpretGeneratedError(lineNo, msg);
|
return interpretGeneratedError(lineNo, msg);
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.compile;
|
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.glAttachShader;
|
||||||
|
import static org.lwjgl.opengl.GL20.glCreateProgram;
|
||||||
|
import static org.lwjgl.opengl.GL20.glLinkProgram;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,9 +25,7 @@ import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
import com.jozufozu.flywheel.backend.instancing.indirect.IndirectComponent;
|
import com.jozufozu.flywheel.backend.instancing.indirect.IndirectComponent;
|
||||||
import com.jozufozu.flywheel.core.BackendTypes;
|
|
||||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||||
import com.jozufozu.flywheel.core.Components;
|
|
||||||
import com.jozufozu.flywheel.core.Pipelines;
|
import com.jozufozu.flywheel.core.Pipelines;
|
||||||
import com.jozufozu.flywheel.core.SourceComponent;
|
import com.jozufozu.flywheel.core.SourceComponent;
|
||||||
import com.jozufozu.flywheel.core.pipeline.SimplePipeline;
|
import com.jozufozu.flywheel.core.pipeline.SimplePipeline;
|
||||||
|
@ -41,7 +43,9 @@ public class FlwCompiler {
|
||||||
private final ShaderSources sources;
|
private final ShaderSources sources;
|
||||||
private final MaterialAdapterComponent vertexMaterialComponent;
|
private final MaterialAdapterComponent vertexMaterialComponent;
|
||||||
private final MaterialAdapterComponent fragmentMaterialComponent;
|
private final MaterialAdapterComponent fragmentMaterialComponent;
|
||||||
private final List<PipelineContext> pipelineContexts;
|
|
||||||
|
private final PipelineContextSet pipelineContexts;
|
||||||
|
private final CullingContextSet cullingContexts;
|
||||||
|
|
||||||
final ShaderCompiler shaderCompiler;
|
final ShaderCompiler shaderCompiler;
|
||||||
final Multimap<Set<UniformProvider>, PipelineContext> uniformProviderGroups = ArrayListMultimap.create();
|
final Multimap<Set<UniformProvider>, PipelineContext> uniformProviderGroups = ArrayListMultimap.create();
|
||||||
|
@ -50,7 +54,10 @@ public class FlwCompiler {
|
||||||
final List<FailedCompilation> errors = new ArrayList<>();
|
final List<FailedCompilation> errors = new ArrayList<>();
|
||||||
|
|
||||||
public FlwCompiler(ShaderSources sources) {
|
public FlwCompiler(ShaderSources sources) {
|
||||||
this.shaderCompiler = new ShaderCompiler(errors::add);
|
this.shaderCompiler = ShaderCompiler.builder()
|
||||||
|
.errorConsumer(errors::add)
|
||||||
|
.build();
|
||||||
|
|
||||||
this.sources = sources;
|
this.sources = sources;
|
||||||
this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
|
this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
|
||||||
.materialSources(ComponentRegistry.materials.vertexSources())
|
.materialSources(ComponentRegistry.materials.vertexSources())
|
||||||
|
@ -73,21 +80,24 @@ public class FlwCompiler {
|
||||||
.switchOn(GlslExpr.variable("flw_materialFragmentID"))
|
.switchOn(GlslExpr.variable("flw_materialFragmentID"))
|
||||||
.build(sources);
|
.build(sources);
|
||||||
|
|
||||||
this.pipelineContexts = buildPipelineSet();
|
this.pipelineContexts = PipelineContextSet.create();
|
||||||
|
this.cullingContexts = CullingContextSet.create();
|
||||||
|
|
||||||
// TODO: analyze uniform providers and group them into sets; break up this ctor
|
doCompilation();
|
||||||
|
|
||||||
for (PipelineContext context : pipelineContexts) {
|
|
||||||
compilePipelineContext(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (StructType<?> type : ComponentRegistry.structTypes) {
|
|
||||||
compileComputeCuller(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void doCompilation() {
|
||||||
|
for (var ctx : pipelineContexts.all()) {
|
||||||
|
compilePipelineContext(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var ctx : cullingContexts.all()) {
|
||||||
|
compileComputeCuller(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void finish() {
|
private void finish() {
|
||||||
long compileEnd = System.nanoTime();
|
long compileEnd = System.nanoTime();
|
||||||
int programCount = pipelineContexts.size() + ComponentRegistry.structTypes.size();
|
int programCount = pipelineContexts.size() + ComponentRegistry.structTypes.size();
|
||||||
|
@ -132,22 +142,31 @@ public class FlwCompiler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pipelinePrograms.put(ctx, ctx.contextShader()
|
var glProgram = link(vertex.handle(), fragment.handle());
|
||||||
.factory()
|
ctx.contextShader()
|
||||||
.create(new ProgramAssembler().attachShader(vertex)
|
.setup(glProgram);
|
||||||
.attachShader(fragment)
|
pipelinePrograms.put(ctx, glProgram);
|
||||||
.link()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compileComputeCuller(StructType<?> structType) {
|
private void compileComputeCuller(CullingContext ctx) {
|
||||||
var result = shaderCompiler.compile(GLSLVersion.V460, ShaderType.COMPUTE, getComputeComponents(structType));
|
var computeComponents = getComputeComponents(ctx.structType());
|
||||||
|
var result = shaderCompiler.compile(GLSLVersion.V460, ShaderType.COMPUTE, computeComponents);
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cullingPrograms.put(structType, new GlProgram(new ProgramAssembler().attachShader(result)
|
cullingPrograms.put(ctx.structType(), link(result.handle()));
|
||||||
.link()));
|
}
|
||||||
|
|
||||||
|
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) {
|
private ImmutableList<SourceComponent> getVertexComponents(PipelineContext ctx) {
|
||||||
|
@ -189,16 +208,4 @@ public class FlwCompiler {
|
||||||
return ImmutableList.of(instanceAssembly, instance, pipeline);
|
return ImmutableList.of(instanceAssembly, instance, pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<PipelineContext> buildPipelineSet() {
|
|
||||||
ImmutableList.Builder<PipelineContext> builder = ImmutableList.builder();
|
|
||||||
for (SimplePipeline pipelineShader : BackendTypes.availablePipelineShaders()) {
|
|
||||||
for (StructType<?> structType : ComponentRegistry.structTypes) {
|
|
||||||
for (VertexType vertexType : ComponentRegistry.vertexTypes) {
|
|
||||||
// TODO: context ubershaders, or not?
|
|
||||||
builder.add(new PipelineContext(vertexType, structType, Components.WORLD, pipelineShader));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.jozufozu.flywheel.core.SourceComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A component of a ShaderCompiler, responsible for expanding root sources into the complete set of included sources.
|
||||||
|
*/
|
||||||
|
public interface Includer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand the given root sources into the complete set of included sources.
|
||||||
|
* <p> Each unique source will be seen exactly once.
|
||||||
|
*
|
||||||
|
* @param rootSources The root sources to expand.
|
||||||
|
* @param out A consumer to which all sources should be passed in the order they should be included.
|
||||||
|
*/
|
||||||
|
void expand(ImmutableList<SourceComponent> rootSources, Consumer<SourceComponent> out);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.context.ContextShader;
|
||||||
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.core.BackendTypes;
|
||||||
|
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||||
|
import com.jozufozu.flywheel.core.Components;
|
||||||
|
import com.jozufozu.flywheel.core.pipeline.SimplePipeline;
|
||||||
|
|
||||||
|
public class PipelineContextSet {
|
||||||
|
static PipelineContextSet create() {
|
||||||
|
var builder = new PipelineContextSet();
|
||||||
|
for (SimplePipeline pipelineShader : BackendTypes.availablePipelineShaders()) {
|
||||||
|
for (StructType<?> structType : ComponentRegistry.structTypes) {
|
||||||
|
for (VertexType vertexType : ComponentRegistry.vertexTypes) {
|
||||||
|
builder.add(vertexType, structType, Components.WORLD, pipelineShader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<PipelineContext> contexts = new ArrayList<>();
|
||||||
|
private final List<PipelineContext> contextView = Collections.unmodifiableList(contexts);
|
||||||
|
|
||||||
|
PipelineContextSet() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PipelineContext> all() {
|
||||||
|
return contextView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return contexts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add(VertexType vertexType, StructType<?> structType, ContextShader world, SimplePipeline pipelineShader) {
|
||||||
|
var ctx = new PipelineContext(vertexType, structType, world, pipelineShader);
|
||||||
|
|
||||||
|
|
||||||
|
contexts.add(ctx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.compile;
|
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL11.GL_TRUE;
|
|
||||||
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
|
|
||||||
import static org.lwjgl.opengl.GL20.glAttachShader;
|
|
||||||
import static org.lwjgl.opengl.GL20.glCreateProgram;
|
|
||||||
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
|
|
||||||
import static org.lwjgl.opengl.GL20.glGetProgrami;
|
|
||||||
import static org.lwjgl.opengl.GL20.glLinkProgram;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public class ProgramAssembler {
|
|
||||||
private final int program;
|
|
||||||
|
|
||||||
public ProgramAssembler() {
|
|
||||||
this.program = glCreateProgram();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Links the attached shaders to this program.
|
|
||||||
*/
|
|
||||||
public int link() {
|
|
||||||
glLinkProgram(this.program);
|
|
||||||
|
|
||||||
String log = glGetProgramInfoLog(this.program);
|
|
||||||
|
|
||||||
if (!log.isEmpty()) {
|
|
||||||
Backend.LOGGER.debug("Program link log: " + log);
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = glGetProgrami(this.program, GL_LINK_STATUS);
|
|
||||||
|
|
||||||
if (result != GL_TRUE) {
|
|
||||||
throw new RuntimeException("Shader program linking failed, see log for details");
|
|
||||||
}
|
|
||||||
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProgramAssembler attachShader(GlShader glShader) {
|
|
||||||
glAttachShader(this.program, glShader.handle());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.jozufozu.flywheel.core.SourceComponent;
|
||||||
|
|
||||||
|
public class RecursiveIncluder implements Includer {
|
||||||
|
|
||||||
|
public static final RecursiveIncluder INSTANCE = new RecursiveIncluder();
|
||||||
|
|
||||||
|
private RecursiveIncluder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void expand(ImmutableList<SourceComponent> rootSources, Consumer<SourceComponent> out) {
|
||||||
|
var included = depthFirstInclude(rootSources);
|
||||||
|
included.forEach(out);
|
||||||
|
rootSources.forEach(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LinkedHashSet<SourceComponent> depthFirstInclude(ImmutableList<SourceComponent> root) {
|
||||||
|
var included = new LinkedHashSet<SourceComponent>(); // linked to preserve order
|
||||||
|
for (var component : root) {
|
||||||
|
recursiveDepthFirstInclude(included, component);
|
||||||
|
}
|
||||||
|
return included;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void recursiveDepthFirstInclude(Set<SourceComponent> included, SourceComponent component) {
|
||||||
|
for (var include : component.included()) {
|
||||||
|
recursiveDepthFirstInclude(included, include);
|
||||||
|
}
|
||||||
|
included.addAll(component.included());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,8 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.compile;
|
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -15,13 +13,18 @@ import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
import com.jozufozu.flywheel.core.SourceComponent;
|
import com.jozufozu.flywheel.core.SourceComponent;
|
||||||
|
import com.jozufozu.flywheel.util.FlwUtil;
|
||||||
|
|
||||||
public class ShaderCompiler {
|
public class ShaderCompiler {
|
||||||
private final Map<ShaderKey, CompilationResult> shaderCache = new HashMap<>();
|
private final Map<ShaderKey, CompilationResult> shaderCache = new HashMap<>();
|
||||||
private final Consumer<FailedCompilation> errorConsumer;
|
private final Consumer<FailedCompilation> errorConsumer;
|
||||||
|
private final CompilationFactory factory;
|
||||||
|
private final Includer includer;
|
||||||
|
|
||||||
public ShaderCompiler(Consumer<FailedCompilation> errorConsumer) {
|
public ShaderCompiler(Consumer<FailedCompilation> errorConsumer, CompilationFactory factory, Includer includer) {
|
||||||
this.errorConsumer = errorConsumer;
|
this.errorConsumer = errorConsumer;
|
||||||
|
this.factory = factory;
|
||||||
|
this.includer = includer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int shaderCount() {
|
public int shaderCount() {
|
||||||
|
@ -36,7 +39,7 @@ public class ShaderCompiler {
|
||||||
return cached.unwrap();
|
return cached.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
CompilationResult out = compileUncached(glslVersion, shaderType, sourceComponents);
|
CompilationResult out = compileUncached(factory.create(glslVersion, shaderType), sourceComponents);
|
||||||
shaderCache.put(key, out);
|
shaderCache.put(key, out);
|
||||||
return unwrapAndReportError(out);
|
return unwrapAndReportError(out);
|
||||||
}
|
}
|
||||||
|
@ -60,40 +63,51 @@ public class ShaderCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static CompilationResult compileUncached(GLSLVersion glslVersion, ShaderType shaderType, ImmutableList<SourceComponent> sourceComponents) {
|
private CompilationResult compileUncached(Compilation ctx, ImmutableList<SourceComponent> sourceComponents) {
|
||||||
var ctx = new Compilation(glslVersion, shaderType);
|
|
||||||
ctx.enableExtension("GL_ARB_explicit_attrib_location");
|
ctx.enableExtension("GL_ARB_explicit_attrib_location");
|
||||||
ctx.enableExtension("GL_ARB_conservative_depth");
|
ctx.enableExtension("GL_ARB_conservative_depth");
|
||||||
|
|
||||||
for (var include : depthFirstInclude(sourceComponents)) {
|
includer.expand(sourceComponents, ctx::appendComponent);
|
||||||
ctx.appendComponent(include);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var component : sourceComponents) {
|
|
||||||
ctx.appendComponent(component);
|
|
||||||
ctx.addComponentName(component.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.compile();
|
return ctx.compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<SourceComponent> depthFirstInclude(ImmutableList<SourceComponent> root) {
|
|
||||||
var included = new LinkedHashSet<SourceComponent>(); // linked to preserve order
|
|
||||||
for (var component : root) {
|
|
||||||
recursiveDepthFirstInclude(included, component);
|
|
||||||
}
|
|
||||||
return included;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void recursiveDepthFirstInclude(Set<SourceComponent> included, SourceComponent component) {
|
|
||||||
for (var include : component.included()) {
|
|
||||||
recursiveDepthFirstInclude(included, include);
|
|
||||||
}
|
|
||||||
included.addAll(component.included());
|
|
||||||
}
|
|
||||||
|
|
||||||
private record ShaderKey(GLSLVersion glslVersion, ShaderType shaderType,
|
private record ShaderKey(GLSLVersion glslVersion, ShaderType shaderType,
|
||||||
ImmutableList<SourceComponent> sourceComponents) {
|
ImmutableList<SourceComponent> sourceComponents) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface CompilationFactory {
|
||||||
|
Compilation create(GLSLVersion version, ShaderType shaderType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private Consumer<FailedCompilation> errorConsumer = FlwUtil::noop;
|
||||||
|
private CompilationFactory factory = Compilation::new;
|
||||||
|
private Includer includer = RecursiveIncluder.INSTANCE;
|
||||||
|
|
||||||
|
public Builder errorConsumer(Consumer<FailedCompilation> errorConsumer) {
|
||||||
|
this.errorConsumer = errorConsumer;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder compilationFactory(CompilationFactory factory) {
|
||||||
|
this.factory = factory;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder includer(Includer includer) {
|
||||||
|
this.includer = includer;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderCompiler build() {
|
||||||
|
return new ShaderCompiler(errorConsumer, factory, includer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.core.source.span.CharPos;
|
import com.jozufozu.flywheel.core.source.span.CharPos;
|
||||||
import com.jozufozu.flywheel.util.StringUtil;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
import it.unimi.dsi.fastutil.ints.IntList;
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
@ -102,7 +101,8 @@ public class SourceLines implements CharSequence {
|
||||||
int start = lines.getInt(i - 1);
|
int start = lines.getInt(i - 1);
|
||||||
int end = lines.getInt(i);
|
int end = lines.getInt(i);
|
||||||
|
|
||||||
builder.add(StringUtil.trimEnd(source.substring(start, end)));
|
builder.add(source.substring(start, end)
|
||||||
|
.stripTrailing());
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -11,6 +11,10 @@ public class GlslBuilder {
|
||||||
add(new Define(name, value));
|
add(new Define(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void undef(String key) {
|
||||||
|
add(new Undef(key));
|
||||||
|
}
|
||||||
|
|
||||||
public GlslStruct struct() {
|
public GlslStruct struct() {
|
||||||
return add(new GlslStruct());
|
return add(new GlslStruct());
|
||||||
}
|
}
|
||||||
|
@ -32,6 +36,10 @@ public class GlslBuilder {
|
||||||
elements.add(Separators.BLANK_LINE);
|
elements.add(Separators.BLANK_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void _addRaw(String sourceString) {
|
||||||
|
elements.add(() -> sourceString);
|
||||||
|
}
|
||||||
|
|
||||||
public String build() {
|
public String build() {
|
||||||
return elements.stream()
|
return elements.stream()
|
||||||
.map(Declaration::prettyPrint)
|
.map(Declaration::prettyPrint)
|
||||||
|
@ -65,4 +73,11 @@ public class GlslBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record Undef(String name) implements Declaration {
|
||||||
|
@Override
|
||||||
|
public String prettyPrint() {
|
||||||
|
return "#undef " + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,18 +22,16 @@ public class FogProvider implements UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActiveUniformProvider activate(long ptr, Notifier notifier) {
|
public ActiveUniformProvider activate(long ptr) {
|
||||||
return new Active(ptr, notifier);
|
return new Active(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Active implements ActiveUniformProvider {
|
public static class Active implements ActiveUniformProvider {
|
||||||
|
|
||||||
private final long ptr;
|
private final long ptr;
|
||||||
private final Notifier notifier;
|
|
||||||
|
|
||||||
public Active(long ptr, Notifier notifier) {
|
public Active(long ptr) {
|
||||||
this.ptr = ptr;
|
this.ptr = ptr;
|
||||||
this.notifier = notifier;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,9 +39,9 @@ public class FogProvider implements UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void poll() {
|
public boolean poll() {
|
||||||
if (!FOG_UPDATE) {
|
if (!FOG_UPDATE) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var color = RenderSystem.getShaderFogColor();
|
var color = RenderSystem.getShaderFogColor();
|
||||||
|
@ -57,9 +55,9 @@ public class FogProvider implements UniformProvider {
|
||||||
MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape()
|
MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape()
|
||||||
.getIndex());
|
.getIndex());
|
||||||
|
|
||||||
notifier.signalChanged();
|
|
||||||
|
|
||||||
FOG_UPDATE = false;
|
FOG_UPDATE = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,18 +31,17 @@ public class FrustumProvider implements UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActiveUniformProvider activate(long ptr, Notifier notifier) {
|
public ActiveUniformProvider activate(long ptr) {
|
||||||
return new Active(ptr, notifier);
|
return new Active(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Active implements ActiveUniformProvider, Consumer<BeginFrameEvent> {
|
static class Active implements ActiveUniformProvider, Consumer<BeginFrameEvent> {
|
||||||
|
|
||||||
private final long ptr;
|
private final long ptr;
|
||||||
private final Notifier notifier;
|
private boolean dirty = true;
|
||||||
|
|
||||||
public Active(long ptr, Notifier notifier) {
|
public Active(long ptr) {
|
||||||
this.ptr = ptr;
|
this.ptr = ptr;
|
||||||
this.notifier = notifier;
|
|
||||||
MinecraftForge.EVENT_BUS.addListener(this);
|
MinecraftForge.EVENT_BUS.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +51,12 @@ public class FrustumProvider implements UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void poll() {
|
public boolean poll() {
|
||||||
|
if (dirty) {
|
||||||
|
dirty = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,7 +81,7 @@ public class FrustumProvider implements UniformProvider {
|
||||||
|
|
||||||
shiftedCuller.getJozuPackedPlanes(ptr);
|
shiftedCuller.getJozuPackedPlanes(ptr);
|
||||||
|
|
||||||
notifier.signalChanged();
|
dirty = true;
|
||||||
CAPTURE = false;
|
CAPTURE = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class UniformBuffer {
|
||||||
private static final boolean PO2_ALIGNMENT = RenderMath.isPowerOf2(OFFSET_ALIGNMENT);
|
private static final boolean PO2_ALIGNMENT = RenderMath.isPowerOf2(OFFSET_ALIGNMENT);
|
||||||
|
|
||||||
private static UniformBuffer instance;
|
private static UniformBuffer instance;
|
||||||
private final List<Allocated> allocatedProviders;
|
private final AllocatedProviderSet providerSet;
|
||||||
|
|
||||||
public static UniformBuffer getInstance() {
|
public static UniformBuffer getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
|
@ -32,50 +32,19 @@ public class UniformBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final GlBuffer buffer;
|
private final GlBuffer buffer;
|
||||||
private final MemoryBlock data;
|
|
||||||
|
|
||||||
private final BitSet changedBytes;
|
|
||||||
|
|
||||||
private UniformBuffer() {
|
private UniformBuffer() {
|
||||||
buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER);
|
buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER);
|
||||||
|
providerSet = new AllocatedProviderSet(ComponentRegistry.getAllUniformProviders());
|
||||||
Collection<UniformProvider> providers = ComponentRegistry.getAllUniformProviders();
|
|
||||||
|
|
||||||
var builder = ImmutableList.<Allocated>builder();
|
|
||||||
int totalBytes = 0;
|
|
||||||
int index = 0;
|
|
||||||
for (UniformProvider provider : providers) {
|
|
||||||
int size = align16(provider.byteSize());
|
|
||||||
|
|
||||||
builder.add(new Allocated(provider, totalBytes, size, index));
|
|
||||||
|
|
||||||
totalBytes = alignUniformBuffer(totalBytes + size);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
allocatedProviders = builder.build();
|
|
||||||
|
|
||||||
data = MemoryBlock.mallocTracked(totalBytes);
|
|
||||||
changedBytes = new BitSet(totalBytes);
|
|
||||||
|
|
||||||
for (Allocated p : allocatedProviders) {
|
|
||||||
p.updatePtr(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sync() {
|
public void sync() {
|
||||||
allocatedProviders.forEach(Allocated::pollActive);
|
providerSet.sync();
|
||||||
if (changedBytes.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: upload only changed bytes
|
buffer.upload(providerSet.data);
|
||||||
changedBytes.clear();
|
|
||||||
|
|
||||||
buffer.upload(data);
|
|
||||||
|
|
||||||
int handle = buffer.handle();
|
int handle = buffer.handle();
|
||||||
for (Allocated p : allocatedProviders) {
|
for (Allocated p : providerSet.allocatedProviders) {
|
||||||
GL32.glBindBufferRange(GL32.GL_UNIFORM_BUFFER, p.index, handle, p.offset, p.size);
|
GL32.glBindBufferRange(GL32.GL_UNIFORM_BUFFER, p.index, handle, p.offset, p.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +62,7 @@ public class UniformBuffer {
|
||||||
return (numToRound + 16 - 1) & -16;
|
return (numToRound + 16 - 1) & -16;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Allocated implements UniformProvider.Notifier {
|
private static class Allocated {
|
||||||
private final UniformProvider provider;
|
private final UniformProvider provider;
|
||||||
private final int offset;
|
private final int offset;
|
||||||
private final int size;
|
private final int size;
|
||||||
|
@ -107,20 +76,11 @@ public class UniformBuffer {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void signalChanged() {
|
|
||||||
changedBytes.set(offset, offset + size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePtr(MemoryBlock bufferBase) {
|
private void updatePtr(MemoryBlock bufferBase) {
|
||||||
if (activeProvider != null) {
|
if (activeProvider != null) {
|
||||||
activeProvider.delete();
|
activeProvider.delete();
|
||||||
}
|
}
|
||||||
activeProvider = provider.activate(bufferBase.ptr() + offset, this);
|
activeProvider = provider.activate(bufferBase.ptr() + offset);
|
||||||
}
|
|
||||||
|
|
||||||
public UniformProvider provider() {
|
|
||||||
return provider;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int offset() {
|
public int offset() {
|
||||||
|
@ -135,9 +95,46 @@ public class UniformBuffer {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pollActive() {
|
public boolean maybePoll() {
|
||||||
if (activeProvider != null) {
|
return activeProvider != null && activeProvider.poll();
|
||||||
activeProvider.poll();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AllocatedProviderSet {
|
||||||
|
private final List<Allocated> allocatedProviders;
|
||||||
|
|
||||||
|
private final MemoryBlock data;
|
||||||
|
|
||||||
|
private final BitSet changedBytes;
|
||||||
|
|
||||||
|
private AllocatedProviderSet(final Collection<UniformProvider> providers) {
|
||||||
|
var builder = ImmutableList.<Allocated>builder();
|
||||||
|
int totalBytes = 0;
|
||||||
|
int index = 0;
|
||||||
|
for (UniformProvider provider : providers) {
|
||||||
|
int size = align16(provider.byteSize());
|
||||||
|
|
||||||
|
builder.add(new Allocated(provider, totalBytes, size, index));
|
||||||
|
|
||||||
|
totalBytes = alignUniformBuffer(totalBytes + size);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
allocatedProviders = builder.build();
|
||||||
|
|
||||||
|
data = MemoryBlock.mallocTracked(totalBytes);
|
||||||
|
changedBytes = new BitSet(totalBytes);
|
||||||
|
|
||||||
|
for (Allocated p : allocatedProviders) {
|
||||||
|
p.updatePtr(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sync() {
|
||||||
|
for (Allocated p : allocatedProviders) {
|
||||||
|
if (p.maybePoll()) {
|
||||||
|
changedBytes.set(p.offset(), p.offset() + p.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,17 +32,16 @@ public class ViewProvider implements UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActiveUniformProvider activate(long ptr, Notifier notifier) {
|
public ActiveUniformProvider activate(long ptr) {
|
||||||
return new Active(ptr, notifier);
|
return new Active(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Active implements ActiveUniformProvider, Consumer<BeginFrameEvent> {
|
public static class Active implements ActiveUniformProvider, Consumer<BeginFrameEvent> {
|
||||||
private final long ptr;
|
private final long ptr;
|
||||||
private final Notifier notifier;
|
private boolean dirty = true;
|
||||||
|
|
||||||
public Active(long ptr, Notifier notifier) {
|
public Active(long ptr) {
|
||||||
this.ptr = ptr;
|
this.ptr = ptr;
|
||||||
this.notifier = notifier;
|
|
||||||
MinecraftForge.EVENT_BUS.addListener(this);
|
MinecraftForge.EVENT_BUS.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +51,12 @@ public class ViewProvider implements UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void poll() {
|
public boolean poll() {
|
||||||
|
if (dirty) {
|
||||||
|
dirty = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -85,7 +89,7 @@ public class ViewProvider implements UniformProvider {
|
||||||
MemoryUtil.memPutFloat(ptr + 72, camZ);
|
MemoryUtil.memPutFloat(ptr + 72, camZ);
|
||||||
MemoryUtil.memPutInt(ptr + 76, constantAmbientLight);
|
MemoryUtil.memPutInt(ptr + 76, constantAmbientLight);
|
||||||
|
|
||||||
notifier.signalChanged();
|
dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,11 @@ public class FlwUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <R> Stream<R> mapValues(Map<?, R> map) {
|
public static <R> Stream<R> mapValues(Map<?, R> map) {
|
||||||
return map.values().stream();
|
return map.values()
|
||||||
|
.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void noop(T object) {
|
||||||
|
// noop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,13 +64,20 @@ public class StringUtil {
|
||||||
.collect(Collectors.joining(", ")) + ')';
|
.collect(Collectors.joining(", ")) + ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String trimEnd(String value) {
|
public static String trimPrefix(String s, String prefix) {
|
||||||
int len = value.length();
|
if (s.startsWith(prefix)) {
|
||||||
int st = 0;
|
return s.substring(prefix.length());
|
||||||
while ((st < len) && Character.isWhitespace(value.charAt(len - 1))) {
|
} else {
|
||||||
len--;
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String trimSuffix(String s, String prefix) {
|
||||||
|
if (s.endsWith(prefix)) {
|
||||||
|
return s.substring(0, s.length() - prefix.length());
|
||||||
|
} else {
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
return value.substring(0, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// TODO: Transform uniform shaders
|
// TODO: inject FLW_UNIFORM_BINDING definitions
|
||||||
vec4 flw_fogColor;
|
layout(std140, binding = FLW_UNIFORM_BINDING) uniform flw_fog {
|
||||||
vec2 flw_fogRange;
|
vec4 flw_fogColor;
|
||||||
int flw_fogShape;
|
vec2 flw_fogRange;
|
||||||
|
int flw_fogShape;
|
||||||
|
};
|
||||||
|
|
|
@ -9,4 +9,6 @@ struct FLWPackedPlanes {
|
||||||
vec2 zW; // <nz.w, pz.w>
|
vec2 zW; // <nz.w, pz.w>
|
||||||
};
|
};
|
||||||
|
|
||||||
FLWPackedPlanes flw_planes;
|
layout(std140, binding = FLW_UNIFORM_BINDING) uniform FLWFrustum {
|
||||||
|
FLWPackedPlanes flw_planes;
|
||||||
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
mat4 flw_viewProjection;
|
layout(std140, binding = FLW_UNIFORM_BINDING) uniform flw_view {
|
||||||
vec4 flw_cameraPos;
|
mat4 flw_viewProjection;
|
||||||
int flw_constantAmbientLight;
|
vec4 flw_cameraPos;
|
||||||
|
int flw_constantAmbientLight;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue