diff --git a/src/main/java/com/jozufozu/flywheel/api/context/Context.java b/src/main/java/com/jozufozu/flywheel/api/context/Context.java index d4eb459ee..93b9dd92e 100644 --- a/src/main/java/com/jozufozu/flywheel/api/context/Context.java +++ b/src/main/java/com/jozufozu/flywheel/api/context/Context.java @@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.core.source.FileResolution; public interface Context { - void setup(GlProgram program); + void onProgramLink(GlProgram program); FileResolution vertexShader(); diff --git a/src/main/java/com/jozufozu/flywheel/api/context/ContextShader.java b/src/main/java/com/jozufozu/flywheel/api/context/ContextShader.java index 1a74be173..e908a6ae1 100644 --- a/src/main/java/com/jozufozu/flywheel/api/context/ContextShader.java +++ b/src/main/java/com/jozufozu/flywheel/api/context/ContextShader.java @@ -3,11 +3,14 @@ package com.jozufozu.flywheel.api.context; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.core.source.FileResolution; -public record ContextShader(GlProgram.Factory factory, FileResolution vertexShader, - FileResolution fragmentShader) implements Context { +public record ContextShader(FileResolution vertexShader, FileResolution fragmentShader) implements Context { @Override - public void setup(GlProgram program) { - + public void onProgramLink(GlProgram program) { + program.bind(); + program.setSamplerBinding("flw_diffuseTex", 0); + program.setSamplerBinding("flw_overlayTex", 1); + program.setSamplerBinding("flw_lightTex", 2); + GlProgram.unbind(); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java index 59b496b78..edc21b543 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java @@ -2,8 +2,6 @@ package com.jozufozu.flywheel.backend.gl.shader; import static org.lwjgl.opengl.GL20.*; -import org.jetbrains.annotations.NotNull; - import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.core.uniform.UniformBuffer; @@ -15,7 +13,6 @@ public class GlProgram extends GlObject { setHandle(handle); } - // TODO: Programs bind the uniform buffers they need, no more GlProgram inheritance public void bind() { // TODO: bind textures? UniformBuffer.getInstance() @@ -48,17 +45,13 @@ public class GlProgram extends GlObject { * * @param name The name of the sampler uniform. * @param binding The index of the texture unit. - * @return The sampler uniform's index. - * @throws NullPointerException If no uniform exists with the given name. */ - public int setSamplerBinding(String name, int binding) { + public void setSamplerBinding(String name, int binding) { int samplerUniform = getUniformLocation(name); if (samplerUniform >= 0) { glUniform1i(samplerUniform, binding); } - - return samplerUniform; } @Override @@ -66,11 +59,4 @@ public class GlProgram extends GlObject { glDeleteProgram(handle); } - /** - * A factory interface to create a {@link GlProgram}. - */ - public interface Factory { - - @NotNull GlProgram create(int handle); - } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FlwCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FlwCompiler.java index 32d077f7a..ccde358de 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FlwCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/FlwCompiler.java @@ -145,7 +145,7 @@ public class FlwCompiler { var glProgram = link(vertex.handle(), fragment.handle()); ctx.contextShader() - .setup(glProgram); + .onProgramLink(glProgram); pipelinePrograms.put(ctx, glProgram); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java index f99a6d799..2c9f5f7d1 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java @@ -1,22 +1,7 @@ package com.jozufozu.flywheel.backend.instancing.indirect; import static org.lwjgl.opengl.GL45.glCreateBuffers; -import static org.lwjgl.opengl.GL46.GL_DRAW_INDIRECT_BUFFER; -import static org.lwjgl.opengl.GL46.GL_DYNAMIC_STORAGE_BIT; -import static org.lwjgl.opengl.GL46.GL_MAP_FLUSH_EXPLICIT_BIT; -import static org.lwjgl.opengl.GL46.GL_MAP_PERSISTENT_BIT; -import static org.lwjgl.opengl.GL46.GL_MAP_WRITE_BIT; -import static org.lwjgl.opengl.GL46.GL_SHADER_STORAGE_BUFFER; -import static org.lwjgl.opengl.GL46.glBindBuffer; -import static org.lwjgl.opengl.GL46.glCopyNamedBufferSubData; -import static org.lwjgl.opengl.GL46.glDeleteBuffers; -import static org.lwjgl.opengl.GL46.glFlushMappedNamedBufferRange; -import static org.lwjgl.opengl.GL46.glNamedBufferStorage; -import static org.lwjgl.opengl.GL46.nglBindBuffersRange; -import static org.lwjgl.opengl.GL46.nglCreateBuffers; -import static org.lwjgl.opengl.GL46.nglDeleteBuffers; -import static org.lwjgl.opengl.GL46.nglMapNamedBufferRange; -import static org.lwjgl.opengl.GL46.nglNamedBufferSubData; +import static org.lwjgl.opengl.GL46.*; import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.Pointer; @@ -30,7 +15,7 @@ public class IndirectBuffers { public static final long PTR_SIZE = Pointer.POINTER_SIZE; // DRAW COMMAND - public static final long DRAW_COMMAND_STRIDE = 36; + public static final long DRAW_COMMAND_STRIDE = 44; public static final long DRAW_COMMAND_OFFSET = 0; // BITS @@ -180,15 +165,16 @@ public class IndirectBuffers { FlwMemoryTracker._freeGPUMemory(maxDrawCount * DRAW_COMMAND_STRIDE); } - public void bindAll() { - bindN(BUFFER_COUNT); + public void bindForCompute() { + multiBind(BUFFER_COUNT); } - public void bindObjectAndTarget() { - bindN(2); + public void bindForDraw() { + multiBind(BUFFER_COUNT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, draw); } - private void bindN(int bufferCount) { + private void multiBind(int bufferCount) { if (bufferCount > BUFFER_COUNT) { throw new IllegalArgumentException("Can't bind more than " + BUFFER_COUNT + " buffers"); } @@ -197,10 +183,6 @@ public class IndirectBuffers { nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, bufferCount, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); } - void bindIndirectBuffer() { - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, draw); - } - void flushBatchIDs(long length) { glFlushMappedNamedBufferRange(batch, 0, length); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java index d77a07e7a..5ac29a0ec 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java @@ -3,18 +3,11 @@ package com.jozufozu.flywheel.backend.instancing.indirect; import static org.lwjgl.opengl.GL42.GL_COMMAND_BARRIER_BIT; import static org.lwjgl.opengl.GL42.glMemoryBarrier; import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BARRIER_BIT; -import static org.lwjgl.opengl.GL46.glBindVertexArray; -import static org.lwjgl.opengl.GL46.glCreateVertexArrays; -import static org.lwjgl.opengl.GL46.glDeleteVertexArrays; -import static org.lwjgl.opengl.GL46.glDispatchCompute; -import static org.lwjgl.opengl.GL46.glEnableVertexArrayAttrib; -import static org.lwjgl.opengl.GL46.glVertexArrayElementBuffer; -import static org.lwjgl.opengl.GL46.glVertexArrayVertexBuffer; +import static org.lwjgl.opengl.GL46.*; import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.instancing.compile.FlwCompiler; @@ -26,7 +19,6 @@ public class IndirectCullingGroup { private static final int BARRIER_BITS = GL_SHADER_STORAGE_BARRIER_BIT | GL_COMMAND_BARRIER_BIT; - final StructWriter storageBufferWriter; final GlProgram compute; final GlProgram draw; private final VertexType vertexType; @@ -47,7 +39,6 @@ public class IndirectCullingGroup { IndirectCullingGroup(StructType structType, VertexType vertexType) { this.vertexType = vertexType; - storageBufferWriter = structType.getWriter(); objectStride = structType.getLayout() .getStride(); @@ -116,7 +107,7 @@ public class IndirectCullingGroup { uploadIndirectCommands(); compute.bind(); - buffers.bindAll(); + buffers.bindForCompute(); var groupCount = (instanceCountThisFrame + 31) >> 5; // ceil(instanceCount / 32) glDispatchCompute(groupCount, 1, 1); @@ -130,8 +121,7 @@ public class IndirectCullingGroup { draw.bind(); glBindVertexArray(vertexArray); - buffers.bindObjectAndTarget(); - buffers.bindIndirectBuffer(); + buffers.bindForDraw(); memoryBarrier(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectDraw.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectDraw.java index c4d3cbaea..1985198d0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectDraw.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectDraw.java @@ -4,6 +4,7 @@ import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.core.ComponentRegistry; public final class IndirectDraw { final IndirectInstancer instancer; @@ -11,12 +12,18 @@ public final class IndirectDraw { final Material material; int baseInstance = -1; + final int vertexMaterialID; + final int fragmentMaterialID; + boolean needsFullWrite = true; IndirectDraw(IndirectInstancer instancer, Material material, IndirectMeshPool.BufferedMesh mesh) { this.instancer = instancer; this.material = material; this.mesh = mesh; + + this.vertexMaterialID = ComponentRegistry.materials.getVertexID(material); + this.fragmentMaterialID = ComponentRegistry.materials.getFragmentID(material); } public void prepare(int baseInstance) { @@ -48,5 +55,8 @@ public final class IndirectDraw { MemoryUtil.memPutInt(ptr + 16, baseInstance); // baseInstance boundingSphere.getToAddress(ptr + 20); // boundingSphere + MemoryUtil.memPutInt(ptr + 36, vertexMaterialID); // vertexMaterialID + MemoryUtil.memPutInt(ptr + 40, fragmentMaterialID); // fragmentMaterialID + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectDrawSet.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectDrawSet.java index 5bf8c18fc..277087995 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectDrawSet.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectDrawSet.java @@ -10,6 +10,7 @@ import java.util.List; import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.util.Textures; public class IndirectDrawSet { @@ -37,6 +38,7 @@ public class IndirectDrawSet { continue; } material.setup(); + Textures.bindActiveTextures(); glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, i * stride, 1, stride); material.clear(); } diff --git a/src/main/java/com/jozufozu/flywheel/core/ComponentRegistry.java b/src/main/java/com/jozufozu/flywheel/core/ComponentRegistry.java index 0d11d1d04..b18d46ded 100644 --- a/src/main/java/com/jozufozu/flywheel/core/ComponentRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/core/ComponentRegistry.java @@ -1,13 +1,6 @@ package com.jozufozu.flywheel.core; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.jetbrains.annotations.Nullable; @@ -18,8 +11,6 @@ import com.jozufozu.flywheel.api.uniform.UniformProvider; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.source.FileResolution; -import it.unimi.dsi.fastutil.objects.Reference2IntMap; -import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; import net.minecraft.resources.ResourceLocation; public class ComponentRegistry { @@ -93,8 +84,8 @@ public class ComponentRegistry { public T add(T material) { materials.add(material); - vertexSources.register(material, material.getVertexShader()); - fragmentSources.register(material, material.getFragmentShader()); + vertexSources.register(material.getVertexShader()); + fragmentSources.register(material.getFragmentShader()); return material; } @@ -113,15 +104,21 @@ public class ComponentRegistry { return fragmentSources.sourceView; } + public int getVertexID(Material material) { + return vertexSources.orderedSources.indexOf(material.getVertexShader()); + } + + public int getFragmentID(Material material) { + return fragmentSources.orderedSources.indexOf(material.getFragmentShader()); + } + private static class MaterialSources { private final Set registered = new HashSet<>(); private final List orderedSources = new ArrayList<>(); - private final Reference2IntMap material2ID = new Reference2IntOpenHashMap<>(); private final List sourceView = Collections.unmodifiableList(orderedSources); - public void register(Material material, FileResolution vertexShader) { + public void register(FileResolution vertexShader) { if (registered.add(vertexShader)) { - material2ID.put(material, orderedSources.size()); orderedSources.add(vertexShader); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/Components.java b/src/main/java/com/jozufozu/flywheel/core/Components.java index 6f137b8e8..9e81348f6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Components.java +++ b/src/main/java/com/jozufozu/flywheel/core/Components.java @@ -4,7 +4,6 @@ import java.util.function.BiConsumer; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.context.ContextShader; -import com.jozufozu.flywheel.core.crumbling.CrumblingProgram; import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.SourceChecks; import com.jozufozu.flywheel.core.source.SourceFile; @@ -19,9 +18,9 @@ import net.minecraft.resources.ResourceLocation; public class Components { - public static final FlwUniformProvider UNIFORM_PROVIDER = ComponentRegistry.register(new FlwUniformProvider()); - public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(WorldProgram::new, Files.WORLD_VERTEX, Files.WORLD_FRAGMENT)); - public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(CrumblingProgram::new, Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT)); + public static final FlwUniformProvider UNIFORM_PROVIDER = ComponentRegistry.register(new FlwUniformProvider()); + public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT)); + public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT)); public static void init() { Files.init(); diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldProgram.java b/src/main/java/com/jozufozu/flywheel/core/WorldProgram.java deleted file mode 100644 index 4d53fb194..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/WorldProgram.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.jozufozu.flywheel.core; - -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -public class WorldProgram extends GlProgram { - - // TODO: sampler registry? - protected int diffuseTex; - protected int overlayTex; - protected int lightTex; - - public WorldProgram(int handle) { - super(handle); - - bind(); - registerSamplers(); - unbind(); - } - - protected void registerSamplers() { - diffuseTex = setSamplerBinding("flw_diffuseTex", 0); - overlayTex = setSamplerBinding("flw_overlayTex", 1); - lightTex = setSamplerBinding("flw_lightTex", 2); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java deleted file mode 100644 index f5be39ec6..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingProgram.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.jozufozu.flywheel.core.crumbling; - -import com.jozufozu.flywheel.core.WorldProgram; - -public class CrumblingProgram extends WorldProgram { - public CrumblingProgram(int handle) { - super(handle); - } - - @Override - protected void registerSamplers() { - diffuseTex = setSamplerBinding("flw_diffuseTex", 0); - } -} diff --git a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl b/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl index fe8efd6f7..0362e33da 100644 --- a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl +++ b/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl @@ -2,16 +2,7 @@ layout(local_size_x = FLW_SUBGROUP_SIZE) in; #use "flywheel:api/cull.glsl" #use "flywheel:util/types.glsl" - -struct MeshDrawCommand { - uint indexCount; - uint instanceCount; - uint firstIndex; - uint vertexOffset; - uint baseInstance; - - BoundingSphere boundingSphere; -}; +#use "flywheel:pipeline/indirect_draw_command.glsl" // populated by instancers layout(std430, binding = 0) restrict readonly buffer ObjectBuffer { diff --git a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw.vert b/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw.vert index 2a29b662b..84abac66d 100644 --- a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw.vert +++ b/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw.vert @@ -1,4 +1,5 @@ #use "flywheel:api/vertex.glsl" +#use "flywheel:pipeline/indirect_draw_command.glsl" layout(std430, binding = 0) restrict readonly buffer ObjectBuffer { FlwPackedInstance objects[]; @@ -8,9 +9,22 @@ layout(std430, binding = 1) restrict readonly buffer TargetBuffer { uint objectIDs[]; }; +layout(std430, binding = 2) restrict readonly buffer BatchBuffer { + uint batchIDs[]; +}; + +layout(std430, binding = 3) restrict readonly buffer DrawCommands { + MeshDrawCommand drawCommands[]; +}; + void main() { uint instanceIndex = objectIDs[gl_BaseInstance + gl_InstanceID]; + uint batchID = batchIDs[instanceIndex]; FlwInstance i = flw_unpackInstance(objects[instanceIndex]); + + flw_materialVertexID = drawCommands[batchID].vertexMaterialID; + flw_materialFragmentID = drawCommands[batchID].fragmentMaterialID; + flw_layoutVertex(); flw_instanceVertex(i); flw_materialVertex(); diff --git a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw_command.glsl b/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw_command.glsl new file mode 100644 index 000000000..6699bd126 --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_draw_command.glsl @@ -0,0 +1,13 @@ +#use "flywheel:util/types.glsl" + +struct MeshDrawCommand { + uint indexCount; + uint instanceCount; + uint firstIndex; + uint vertexOffset; + uint baseInstance; + + BoundingSphere boundingSphere; + uint vertexMaterialID; + uint fragmentMaterialID; +};