diff --git a/gradle.properties b/gradle.properties index 95019e8cf..79c69ac95 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ minecraft_version = 1.18.2 forge_version = 40.1.68 # build dependency versions -forgegradle_version = 5.1.+ +forgegradle_version = 5.1.53 mixingradle_version = 0.7-SNAPSHOT mixin_version = 0.8.5 librarian_version = 1.+ diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java index 3463c7cc5..ba6922888 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java @@ -38,6 +38,8 @@ public interface StructType { StorageBufferWriter getStorageBufferWriter(); + FileResolution getIndirectShader(); + public interface VertexTransformer { void transform(MutableVertexList vertexList, S struct, ClientLevel level); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 20c6f1b62..b48077615 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -54,8 +54,7 @@ public class Backend { } public static void refresh() { - // TODO: Revert when done testing - TYPE = BackendType.INDIRECT; // chooseEngine(); + TYPE = chooseEngine(); } public static boolean isOn() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java b/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java index 3ae01a15d..972962dc3 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java @@ -39,7 +39,7 @@ public class GlCompat { instancedArrays = getLatest(InstancedArrays.class, caps); bufferStorage = getLatest(BufferStorage.class, caps); - supportsIndirect = caps.OpenGL46; + supportsIndirect = true; amd = _isAmdWindows(); } 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 new file mode 100644 index 000000000..6f32d02c4 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java @@ -0,0 +1,134 @@ +package com.jozufozu.flywheel.backend.instancing.indirect; + +import static org.lwjgl.opengl.GL46.*; + +import org.lwjgl.system.MemoryUtil; +import org.lwjgl.system.Pointer; + +public class IndirectBuffers { + public static final int BUFFER_COUNT = 4; + public static final long INT_SIZE = Integer.BYTES; + 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_OFFSET = 0; + + // BITS + private static final int SUB_DATA_BITS = GL_DYNAMIC_STORAGE_BIT; + private static final int PERSISTENT_BITS = GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT; + private static final int MAP_BITS = PERSISTENT_BITS | GL_MAP_FLUSH_EXPLICIT_BIT; + private static final int GPU_ONLY_BITS = 0; + + // OFFSETS + private static final long OFFSET_OFFSET = BUFFER_COUNT * INT_SIZE; + private static final long SIZE_OFFSET = OFFSET_OFFSET + BUFFER_COUNT * PTR_SIZE; + private static final long BUFFERS_SIZE_BYTES = SIZE_OFFSET + BUFFER_COUNT * PTR_SIZE; + + private static final long OBJECT_SIZE_OFFSET = SIZE_OFFSET; + private static final long TARGET_SIZE_OFFSET = OBJECT_SIZE_OFFSET + PTR_SIZE; + private static final long BATCH_SIZE_OFFSET = TARGET_SIZE_OFFSET + PTR_SIZE; + private static final long DRAW_SIZE_OFFSET = BATCH_SIZE_OFFSET + PTR_SIZE; + + final long buffers; + final long objectStride; + int object; + int target; + int batch; + int draw; + + long objectPtr; + long batchPtr; + long drawPtr; + + int maxObjectCount; + int maxDrawCount; + + IndirectBuffers(long objectStride) { + this.objectStride = objectStride; + this.buffers = MemoryUtil.nmemAlloc(BUFFERS_SIZE_BYTES); + + if (this.buffers == MemoryUtil.NULL) { + throw new OutOfMemoryError(); + } + + MemoryUtil.memSet(this.buffers, 0, BUFFERS_SIZE_BYTES); + } + + void createBuffers() { + nglCreateBuffers(4, buffers); + object = MemoryUtil.memGetInt(buffers); + target = MemoryUtil.memGetInt(buffers + 4); + batch = MemoryUtil.memGetInt(buffers + 8); + draw = MemoryUtil.memGetInt(buffers + 12); + } + + void updateCounts(int objectCount, int drawCount) { + + if (objectCount > maxObjectCount) { + createObjectStorage(objectCount); + } + if (drawCount > maxDrawCount) { + createDrawStorage(drawCount); + } + + long objectSize = objectStride * objectCount; + long targetSize = INT_SIZE * objectCount; + long drawSize = DRAW_COMMAND_STRIDE * drawCount; + + MemoryUtil.memPutAddress(buffers + OBJECT_SIZE_OFFSET, objectSize); + MemoryUtil.memPutAddress(buffers + TARGET_SIZE_OFFSET, targetSize); + MemoryUtil.memPutAddress(buffers + BATCH_SIZE_OFFSET, targetSize); + MemoryUtil.memPutAddress(buffers + DRAW_SIZE_OFFSET, drawSize); + } + + void createObjectStorage(int objectCount) { + var objectSize = objectStride * objectCount; + var targetSize = INT_SIZE * objectCount; + + glNamedBufferStorage(object, objectSize, PERSISTENT_BITS); + glNamedBufferStorage(target, targetSize, GPU_ONLY_BITS); + glNamedBufferStorage(batch, targetSize, PERSISTENT_BITS); + + objectPtr = nglMapNamedBufferRange(object, 0, objectSize, MAP_BITS); + batchPtr = nglMapNamedBufferRange(batch, 0, targetSize, MAP_BITS); + maxObjectCount = objectCount; + } + + void createDrawStorage(int drawCount) { + var drawSize = DRAW_COMMAND_STRIDE * drawCount; + glNamedBufferStorage(draw, drawSize, SUB_DATA_BITS); + drawPtr = MemoryUtil.nmemAlloc(drawSize); + // drawPtr = nglMapNamedBufferRange(draw, 0, drawSize, MAP_BITS); + maxDrawCount = drawCount; + } + + public void bindAll() { + bindN(BUFFER_COUNT); + } + + public void bindObjectAndTarget() { + bindN(2); + } + + private void bindN(int bufferCount) { + nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, bufferCount, buffers, buffers + OFFSET_OFFSET, buffers + SIZE_OFFSET); + } + + void bindIndirectBuffer() { + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, draw); + } + + void flushBatchIDs(long length) { + glFlushMappedNamedBufferRange(batch, 0, length); + } + + void flushObjects(long length) { + glFlushMappedNamedBufferRange(object, 0, length); + } + + void flushDrawCommands(long length) { + nglNamedBufferSubData(draw, 0, length, drawPtr); + // glFlushMappedNamedBufferRange(this.draw, 0, length); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java index c47c9c59d..5b4a61d2e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java @@ -70,12 +70,14 @@ public class IndirectEngine implements Engine { @Override public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) { - var groups = renderLists.get(stage); + if (stage != RenderStage.AFTER_SOLID_TERRAIN) { + return; + } setup(); - for (var group : groups) { - group.submit(); + for (IndirectList list : renderLists.lists.values()) { + list.submit(stage); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectInstancer.java index bcc09acf2..561bfe3db 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectInstancer.java @@ -41,30 +41,6 @@ public class IndirectInstancer extends AbstractInstance anyToRemove = false; } - void writeAll(final StructWriter writer) { - anyToUpdate = false; - - for (var instance : data) { - writer.write(instance); - } - } - - void writeChanged(final StructWriter writer) { - if (!anyToUpdate) { - return; - } - - anyToUpdate = false; - - final int size = data.size(); - - if (size == 0) { - return; - } - - writeChangedUnchecked(writer); - } - @Override public void delete() { // noop diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectList.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectList.java index c5b982471..90bfe5777 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectList.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectList.java @@ -5,12 +5,15 @@ import static org.lwjgl.opengl.GL46.*; import java.util.ArrayList; import java.util.List; -import org.lwjgl.system.MemoryStack; +import org.jetbrains.annotations.NotNull; import org.lwjgl.system.MemoryUtil; +import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.struct.StorageBufferWriter; import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.instancing.PipelineCompiler; import com.jozufozu.flywheel.core.Components; @@ -18,76 +21,37 @@ import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.QuadConverter; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.uniform.UniformBuffer; -import com.jozufozu.flywheel.core.vertex.Formats; public class IndirectList { - private static final long DRAW_COMMAND_STRIDE = 36; - private static final long DRAW_COMMAND_OFFSET = 0; - final StorageBufferWriter storageBufferWriter; final GlProgram compute; final GlProgram draw; - private final StructType type; - private final long maxObjectCount; + private final StructType structType; + private final VertexType vertexType; private final long objectStride; - private final int maxBatchCount; - private final long objectClientStorage; - private final long batchIDClientStorage; - private final int elementBuffer; - /** - * Stores raw instance data per-object. - */ - int objectBuffer; - int targetBuffer; - int batchBuffer; - - /** - * Stores drawIndirect structs. - */ - int drawBuffer; - int debugBuffer; + final IndirectBuffers buffers; final IndirectMeshPool meshPool; + private final int elementBuffer; int vertexArray; - final int[] shaderStorageBuffers = new int[5]; - final List> batches = new ArrayList<>(); - IndirectList(StructType structType) { - type = structType; - storageBufferWriter = type.getStorageBufferWriter(); - - if (storageBufferWriter == null) { - throw new NullPointerException(); - } - - glCreateBuffers(shaderStorageBuffers); - objectBuffer = shaderStorageBuffers[0]; - targetBuffer = shaderStorageBuffers[1]; - batchBuffer = shaderStorageBuffers[2]; - drawBuffer = shaderStorageBuffers[3]; - debugBuffer = shaderStorageBuffers[4]; - meshPool = new IndirectMeshPool(Formats.BLOCK, 1024); - - // FIXME: Resizable buffers - maxObjectCount = 64 * 64 * 64; - maxBatchCount = 64; + IndirectList(StructType structType, VertexType vertexType) { + this.structType = structType; + this.vertexType = vertexType; + storageBufferWriter = this.structType.getStorageBufferWriter(); objectStride = storageBufferWriter.getAlignment(); - int persistentBits = GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT; - glNamedBufferStorage(objectBuffer, objectStride * maxObjectCount, persistentBits); - glNamedBufferStorage(targetBuffer, 4 * maxObjectCount, 0); - glNamedBufferStorage(batchBuffer, 4 * maxObjectCount, persistentBits); - glNamedBufferStorage(drawBuffer, DRAW_COMMAND_STRIDE * maxBatchCount, GL_DYNAMIC_STORAGE_BIT); - glNamedBufferStorage(debugBuffer, 4 * maxObjectCount, 0); + buffers = new IndirectBuffers(objectStride); + buffers.createBuffers(); + buffers.createObjectStorage(64 * 64 * 64); + buffers.createDrawStorage(64); - int mapBits = persistentBits | GL_MAP_FLUSH_EXPLICIT_BIT; - objectClientStorage = nglMapNamedBufferRange(objectBuffer, 0, objectStride * maxObjectCount, mapBits); - batchIDClientStorage = nglMapNamedBufferRange(batchBuffer, 0, 4 * maxObjectCount, mapBits); + meshPool = new IndirectMeshPool(vertexType, 1024); vertexArray = glCreateVertexArrays(); @@ -95,14 +59,15 @@ public class IndirectList { .quads2Tris(2048).buffer.handle(); setupVertexArray(); - compute = ComputeCullerCompiler.INSTANCE.get(Components.Files.ORIENTED_INDIRECT); - draw = PipelineCompiler.INSTANCE.get(new PipelineCompiler.Context(Formats.BLOCK, Materials.BELL, Components.Files.ORIENTED_INDIRECT, Components.WORLD, Components.INDIRECT)); + var indirectShader = this.structType.getIndirectShader(); + compute = ComputeCullerCompiler.INSTANCE.get(indirectShader); + draw = PipelineCompiler.INSTANCE.get(new PipelineCompiler.Context(vertexType, Materials.CHEST, indirectShader, Components.WORLD, Components.INDIRECT)); } private void setupVertexArray() { glVertexArrayElementBuffer(vertexArray, elementBuffer); - var meshLayout = Formats.BLOCK.getLayout(); + var meshLayout = vertexType.getLayout(); var meshAttribs = meshLayout.getAttributeCount(); var attributes = meshLayout.getAttributes(); @@ -118,17 +83,23 @@ public class IndirectList { } } - public void add(Mesh mesh, IndirectInstancer instancer) { - batches.add(new Batch<>(instancer, meshPool.alloc(mesh))); + public void add(IndirectInstancer instancer, Material material, Mesh mesh) { + batches.add(new Batch<>(instancer, material, meshPool.alloc(mesh))); } - void submit() { + void submit(RenderStage stage) { + if (batches.isEmpty()) { + return; + } int instanceCountThisFrame = calculateTotalInstanceCount(); if (instanceCountThisFrame == 0) { return; } + // TODO: Sort meshes by material and draw many contiguous sections of the draw indirect buffer, + // adjusting uniforms/textures accordingly + buffers.updateCounts(instanceCountThisFrame, batches.size()); meshPool.uploadAll(); uploadInstanceData(); uploadIndirectCommands(); @@ -136,39 +107,38 @@ public class IndirectList { UniformBuffer.getInstance().sync(); dispatchCompute(instanceCountThisFrame); - issueMemoryBarrier(); + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); dispatchDraw(); } private void dispatchDraw() { draw.bind(); - Materials.BELL.setup(); glVertexArrayElementBuffer(vertexArray, elementBuffer); glBindVertexArray(vertexArray); - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawBuffer); - glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, DRAW_COMMAND_OFFSET, batches.size(), (int) DRAW_COMMAND_STRIDE); - Materials.BELL.clear(); - } + buffers.bindIndirectBuffer(); - private static void issueMemoryBarrier() { - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + final int stride = (int) IndirectBuffers.DRAW_COMMAND_STRIDE; + long offset = 0; + for (Batch batch : batches) { + + batch.material.setup(); + glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, offset, 1, stride); + batch.material.clear(); + offset += stride; + } } private void dispatchCompute(int instanceCount) { compute.bind(); - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, objectBuffer, 0, instanceCount * objectStride); - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, targetBuffer, 0, instanceCount * 4L); - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 2, batchBuffer, 0, instanceCount * 4L); - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 3, drawBuffer, 0, batches.size() * DRAW_COMMAND_STRIDE); - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 4, debugBuffer, 0, instanceCount * 4L); + buffers.bindAll(); - var groupCount = (instanceCount + 31) >> 5; // ceil(totalInstanceCount / 32) + var groupCount = (instanceCount + 31) >> 5; // ceil(instanceCount / 32) glDispatchCompute(groupCount, 1, 1); } private void uploadInstanceData() { - long objectPtr = objectClientStorage; - long batchIDPtr = batchIDClientStorage; + long objectPtr = buffers.objectPtr; + long batchIDPtr = buffers.batchPtr; int baseInstance = 0; int batchID = 0; for (var batch : batches) { @@ -181,27 +151,23 @@ public class IndirectList { // write batchID MemoryUtil.memPutInt(batchIDPtr, batchID); - batchIDPtr += 4; + batchIDPtr += IndirectBuffers.INT_SIZE; } baseInstance += batch.instancer.instanceCount; batchID++; } - glFlushMappedNamedBufferRange(objectBuffer, 0, objectPtr - objectClientStorage); - glFlushMappedNamedBufferRange(batchBuffer, 0, batchIDPtr - batchIDClientStorage); + buffers.flushObjects(objectPtr - buffers.objectPtr); + buffers.flushBatchIDs(batchIDPtr - buffers.batchPtr); } private void uploadIndirectCommands() { - try (var stack = MemoryStack.stackPush()) { - long size = batches.size() * DRAW_COMMAND_STRIDE; - long basePtr = stack.nmalloc((int) size); - long writePtr = basePtr; - for (Batch batch : batches) { - batch.writeIndirectCommand(writePtr); - writePtr += DRAW_COMMAND_STRIDE; - } - nglNamedBufferSubData(drawBuffer, 0, size, basePtr); + long writePtr = buffers.drawPtr; + for (Batch batch : batches) { + batch.writeIndirectCommand(writePtr); + writePtr += IndirectBuffers.DRAW_COMMAND_STRIDE; } + buffers.flushDrawCommands(writePtr - buffers.drawPtr); } private int calculateTotalInstanceCount() { @@ -216,10 +182,12 @@ public class IndirectList { private static final class Batch { final IndirectInstancer instancer; final IndirectMeshPool.BufferedMesh mesh; - int baseInstance; + final Material material; + int baseInstance = -1; - private Batch(IndirectInstancer instancer, IndirectMeshPool.BufferedMesh mesh) { + private Batch(IndirectInstancer instancer, Material material, IndirectMeshPool.BufferedMesh mesh) { this.instancer = instancer; + this.material = material; this.mesh = mesh; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectMeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectMeshPool.java index b88fb380e..1ae8f1722 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectMeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectMeshPool.java @@ -77,6 +77,8 @@ public class IndirectMeshPool { baseVertex += model.mesh.getVertexCount(); } + clientStorage.rewind(); + glNamedBufferSubData(vbo, 0, clientStorage); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/InstancedModel.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/InstancedModel.java index e3faeb739..dfa76f2c8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/InstancedModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/InstancedModel.java @@ -21,7 +21,7 @@ public class InstancedModel { for (var entry : materialMeshMap.entrySet()) { var material = entry.getKey(); var mesh = entry.getValue(); - renderLists.add(material.getRenderStage(), type, mesh, instancer); + renderLists.add(instancer, material, mesh); return; // TODO: support multiple meshes per model } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/RenderLists.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/RenderLists.java index 38ecfc8f6..1d823e0fb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/RenderLists.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/RenderLists.java @@ -1,40 +1,24 @@ package com.jozufozu.flywheel.backend.instancing.indirect; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; import java.util.HashMap; -import java.util.List; import java.util.Map; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ImmutableListMultimap; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ListMultimap; -import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.model.Mesh; +import com.jozufozu.flywheel.util.Pair; public class RenderLists { - public final Map, IndirectList>> renderLists = new EnumMap<>(RenderStage.class); - - public Collection> get(RenderStage stage) { - var renderList = renderLists.get(stage); - if (renderList == null) { - return Collections.emptyList(); - } - return renderList.values(); - } + public final Map, VertexType>, IndirectList> lists = new HashMap<>(); @SuppressWarnings("unchecked") - public void add(RenderStage stage, StructType type, Mesh mesh, IndirectInstancer instancer) { - var indirectList = (IndirectList) renderLists.computeIfAbsent(stage, $ -> new HashMap<>()) - .computeIfAbsent(type, IndirectList::new); + public void add(IndirectInstancer instancer, Material material, Mesh mesh) { + var indirectList = (IndirectList) lists.computeIfAbsent(Pair.of(instancer.structType, mesh.getVertexType()), + p -> new IndirectList<>(p.first(), p.second())); - indirectList.add(mesh, instancer); + indirectList.add(instancer, material, mesh); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedStorageWriter.java b/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedStorageWriter.java new file mode 100644 index 000000000..70619bdd1 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedStorageWriter.java @@ -0,0 +1,31 @@ +package com.jozufozu.flywheel.core.structs.model; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.api.struct.StorageBufferWriter; +import com.jozufozu.flywheel.util.extension.MatrixExtension; + +public class TransformedStorageWriter implements StorageBufferWriter { + + public static final TransformedStorageWriter INSTANCE = new TransformedStorageWriter(); + + private TransformedStorageWriter() { + } + + @Override + public void write(long ptr, TransformedPart instance) { + MatrixExtension.writeUnsafe(instance.model, ptr); + MatrixExtension.writeUnsafe(instance.normal, ptr + 64); + MemoryUtil.memPutByte(ptr + 112, instance.r); + MemoryUtil.memPutByte(ptr + 113, instance.g); + MemoryUtil.memPutByte(ptr + 114, instance.b); + MemoryUtil.memPutByte(ptr + 115, instance.a); + MemoryUtil.memPutShort(ptr + 116, instance.skyLight); + MemoryUtil.memPutShort(ptr + 118, instance.blockLight); + } + + @Override + public int getAlignment() { + return 128; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedType.java b/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedType.java index c754bc1ab..86b727125 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedType.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedType.java @@ -36,7 +36,7 @@ public class TransformedType implements StructType { @Override public StorageBufferWriter getStorageBufferWriter() { - return null; // TODO + return TransformedStorageWriter.INSTANCE; } @Override @@ -44,6 +44,11 @@ public class TransformedType implements StructType { return Components.Files.TRANSFORMED; } + @Override + public FileResolution getIndirectShader() { + return Components.Files.TRANSFORMED_INDIRECT; + } + @Override public VertexTransformer getVertexTransformer() { return (vertexList, struct, level) -> { diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java index be6fbfa28..5bf956fa1 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java @@ -47,6 +47,11 @@ public class OrientedType implements StructType { return Components.Files.ORIENTED; } + @Override + public FileResolution getIndirectShader() { + return Components.Files.ORIENTED_INDIRECT; + } + @Override public VertexTransformer getVertexTransformer() { return (vertexList, struct, level) -> { diff --git a/src/main/java/com/jozufozu/flywheel/util/extension/MatrixExtension.java b/src/main/java/com/jozufozu/flywheel/util/extension/MatrixExtension.java index 4dd0ac116..d1e7253af 100644 --- a/src/main/java/com/jozufozu/flywheel/util/extension/MatrixExtension.java +++ b/src/main/java/com/jozufozu/flywheel/util/extension/MatrixExtension.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.util.extension; import java.nio.ByteBuffer; +import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; /** @@ -24,4 +25,8 @@ public interface MatrixExtension { static void writeUnsafe(Matrix4f matrix, long ptr) { ((MatrixExtension) (Object) matrix).flywheel$writeUnsafe(ptr); } + + static void writeUnsafe(Matrix3f matrix, long ptr) { + ((MatrixExtension) (Object) matrix).flywheel$writeUnsafe(ptr); + } } diff --git a/src/main/resources/assets/flywheel/flywheel/instance/transformed_indirect.glsl b/src/main/resources/assets/flywheel/flywheel/instance/transformed_indirect.glsl index 1ae709e24..0fbf19511 100644 --- a/src/main/resources/assets/flywheel/flywheel/instance/transformed_indirect.glsl +++ b/src/main/resources/assets/flywheel/flywheel/instance/transformed_indirect.glsl @@ -1,6 +1,6 @@ #use "flywheel:api/vertex.glsl" -#define FLW_INSTANCE_STRUCT Instance +#define FLW_INSTANCE_STRUCT Instance struct Instance { mat4 pose; mat3 normal; 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 170df512a..b1706edf0 100644 --- a/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl +++ b/src/main/resources/assets/flywheel/flywheel/pipeline/indirect_cull.glsl @@ -31,24 +31,11 @@ layout(std430, binding = 3) restrict buffer DrawCommands { MeshDrawCommand drawCommands[]; }; -layout(std430, binding = 4) restrict writeonly buffer DebugVisibility { - uint objectVisibilityBits[]; -}; - // 83 - 27 = 56 spirv instruction results bool testSphere(vec3 center, float radius) { bvec4 xyInside = greaterThanEqual(fma(flw_planes.xyX, center.xxxx, fma(flw_planes.xyY, center.yyyy, fma(flw_planes.xyZ, center.zzzz, flw_planes.xyW))), -radius.xxxx); bvec2 zInside = greaterThanEqual(fma(flw_planes.zX, center.xx, fma(flw_planes.zY, center.yy, fma(flw_planes.zZ, center.zz, flw_planes.zW))), -radius.xx); - uint debug = uint(xyInside.x); - debug |= uint(xyInside.y) << 1; - debug |= uint(xyInside.z) << 2; - debug |= uint(xyInside.w) << 3; - debug |= uint(zInside.x) << 4; - debug |= uint(zInside.y) << 5; - - objectVisibilityBits[flw_objectID] = debug; - return all(xyInside) && all(zInside); }